Merge "Restrict Admin grant of sensors-related permissions" into sc-dev

This commit is contained in:
Eran Messeri
2021-02-17 18:34:53 +00:00
committed by Android (Google) Code Review
7 changed files with 216 additions and 39 deletions

View File

@@ -8959,6 +8959,16 @@ package android.os.storage {
package android.permission {
public final class AdminPermissionControlParams implements android.os.Parcelable {
method public boolean canAdminGrantSensorsPermissions();
method public int describeContents();
method public int getGrantState();
method @NonNull public String getGranteePackageName();
method @NonNull public String getPermission();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.permission.AdminPermissionControlParams> CREATOR;
}
public final class PermissionControllerManager {
method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void applyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void getRuntimePermissionBackup(@NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>);
@@ -8990,7 +9000,8 @@ package android.permission {
method @Deprecated @BinderThread public void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
method @BinderThread public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String, @NonNull Runnable);
method @BinderThread public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.util.List<java.lang.String>>>);
method @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @Deprecated @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @BinderThread public void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull android.permission.AdminPermissionControlParams, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @BinderThread public void onStageAndApplyRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
method @BinderThread public void onUpdateUserSensitivePermissionFlags(int, @NonNull java.util.concurrent.Executor, @NonNull Runnable);
method @BinderThread public void onUpdateUserSensitivePermissionFlags(int, @NonNull Runnable);

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2021, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.permission;
parcelable AdminPermissionControlParams;

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.permission;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static com.android.internal.util.Preconditions.checkArgument;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.admin.DevicePolicyManager;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.Preconditions;
/**
* A data object representing an admin's request to control a certain permission
* for a certain app.
* This class is processed by the Permission Controller's
* setRuntimePermissionGrantStateByDeviceAdmin method.
*
* @hide
*/
@SystemApi
public final class AdminPermissionControlParams implements Parcelable {
// The package to grant/deny the permission to.
private final @NonNull String mGranteePackageName;
// The permission to grant/deny.
private final @NonNull String mPermission;
// The grant state (granted/denied/default).
private final @DevicePolicyManager.PermissionGrantState int mGrantState;
// Whether the admin can grant sensors-related permissions.
private final boolean mCanAdminGrantSensorsPermissions;
/**
* @hide
* A new instance is only created by the framework, so the constructor need not be visible
* as system API.
*/
public AdminPermissionControlParams(@NonNull String granteePackageName,
@NonNull String permission,
int grantState, boolean canAdminGrantSensorsPermissions) {
Preconditions.checkStringNotEmpty(granteePackageName, "Package name must not be empty.");
Preconditions.checkStringNotEmpty(permission, "Permission must not be empty.");
checkArgument(grantState == PERMISSION_GRANT_STATE_GRANTED
|| grantState == PERMISSION_GRANT_STATE_DENIED
|| grantState == PERMISSION_GRANT_STATE_DEFAULT);
mGranteePackageName = granteePackageName;
mPermission = permission;
mGrantState = grantState;
mCanAdminGrantSensorsPermissions = canAdminGrantSensorsPermissions;
}
public static final @NonNull Creator<AdminPermissionControlParams> CREATOR =
new Creator<AdminPermissionControlParams>() {
@Override
public AdminPermissionControlParams createFromParcel(Parcel in) {
String granteePackageName = in.readString();
String permission = in.readString();
int grantState = in.readInt();
boolean mayAdminGrantSensorPermissions = in.readBoolean();
return new AdminPermissionControlParams(granteePackageName, permission,
grantState, mayAdminGrantSensorPermissions);
}
@Override
public AdminPermissionControlParams[] newArray(int size) {
return new AdminPermissionControlParams[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mGranteePackageName);
dest.writeString(mPermission);
dest.writeInt(mGrantState);
dest.writeBoolean(mCanAdminGrantSensorsPermissions);
}
/** Returns the name of the package the permission applies to */
public @NonNull String getGranteePackageName() {
return mGranteePackageName;
}
/** Returns the permission name */
public @NonNull String getPermission() {
return mPermission;
}
/** Returns the grant state */
public int getGrantState() {
return mGrantState;
}
/**
* return true if the admin may control grants of permissions related to sensors.
*/
public boolean canAdminGrantSensorsPermissions() {
return mCanAdminGrantSensorsPermissions;
}
@Override
public String toString() {
return String.format(
"Grantee %s Permission %s state: %d admin grant of sensors permissions: %b",
mGranteePackageName, mPermission, mGrantState, mCanAdminGrantSensorsPermissions);
}
}

View File

@@ -20,6 +20,7 @@ import android.os.RemoteCallback;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.permission.AdminPermissionControlParams;
import com.android.internal.infra.AndroidFuture;
/**
@@ -39,8 +40,8 @@ oneway interface IPermissionController {
void countPermissionApps(in List<String> permissionNames, int flags,
in AndroidFuture callback);
void getPermissionUsages(boolean countSystem, long numMillis, in AndroidFuture callback);
void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName, String packageName,
String permission, int grantState, in AndroidFuture callback);
void setRuntimePermissionGrantStateByDeviceAdminFromParams(String callerPackageName,
in AdminPermissionControlParams params, in AndroidFuture callback);
void grantOrUpgradeDefaultRuntimePermissions(in AndroidFuture callback);
void notifyOneTimePermissionSessionTimeout(String packageName);
void updateUserSensitiveForApp(int uid, in AndroidFuture callback);

View File

@@ -16,13 +16,9 @@
package android.permission;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static android.permission.PermissionControllerService.SERVICE_INTERFACE;
import static com.android.internal.util.FunctionalUtils.uncheckExceptions;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkArgumentNonnegative;
import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
import static com.android.internal.util.Preconditions.checkFlagsArgument;
@@ -39,7 +35,6 @@ import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.app.admin.DevicePolicyManager.PermissionGrantState;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -70,6 +65,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -323,11 +319,11 @@ public final class PermissionControllerManager {
/**
* Set the runtime permission state from a device admin.
* This variant takes into account whether the admin may or may not grant sensors-related
* permissions.
*
* @param callerPackageName The package name of the admin requesting the change
* @param packageName Package the permission belongs to
* @param permission Permission to change
* @param grantState State to set the permission into
* @param params Information about the permission being granted.
* @param executor Executor to run the {@code callback} on
* @param callback The callback
*
@@ -338,30 +334,27 @@ public final class PermissionControllerManager {
Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY},
conditional = true)
public void setRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName,
@NonNull String packageName, @NonNull String permission,
@PermissionGrantState int grantState, @NonNull @CallbackExecutor Executor executor,
@NonNull AdminPermissionControlParams params,
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<Boolean> callback) {
checkStringNotEmpty(callerPackageName);
checkStringNotEmpty(packageName);
checkStringNotEmpty(permission);
checkArgument(grantState == PERMISSION_GRANT_STATE_GRANTED
|| grantState == PERMISSION_GRANT_STATE_DENIED
|| grantState == PERMISSION_GRANT_STATE_DEFAULT);
checkNotNull(executor);
checkNotNull(callback);
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
Objects.requireNonNull(params, "Admin control params must not be null.");
mRemoteService.postAsync(service -> {
AndroidFuture<Boolean> setRuntimePermissionGrantStateResult = new AndroidFuture<>();
service.setRuntimePermissionGrantStateByDeviceAdmin(
callerPackageName, packageName, permission, grantState,
service.setRuntimePermissionGrantStateByDeviceAdminFromParams(
callerPackageName, params,
setRuntimePermissionGrantStateResult);
return setRuntimePermissionGrantStateResult;
}).whenCompleteAsync((setRuntimePermissionGrantStateResult, err) -> {
final long token = Binder.clearCallingIdentity();
try {
if (err != null) {
Log.e(TAG, "Error setting permissions state for device admin " + packageName,
err);
Log.e(TAG,
"Error setting permissions state for device admin "
+ callerPackageName, err);
callback.accept(false);
} else {
callback.accept(Boolean.TRUE.equals(setRuntimePermissionGrantStateResult));

View File

@@ -16,9 +16,7 @@
package android.permission;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static android.permission.PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED;
import static android.permission.PermissionControllerManager.COUNT_WHEN_SYSTEM;
@@ -259,6 +257,8 @@ public abstract class PermissionControllerService extends Service {
}
/**
* @deprecated See {@link #onSetRuntimePermissionGrantStateByDeviceAdmin(String,
* AdminPermissionControlParams, Consumer)}.
* Set the runtime permission state from a device admin.
*
* @param callerPackageName The package name of the admin requesting the change
@@ -267,12 +267,27 @@ public abstract class PermissionControllerService extends Service {
* @param grantState State to set the permission into
* @param callback Callback waiting for whether the state could be set or not
*/
@Deprecated
@BinderThread
public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(
@NonNull String callerPackageName, @NonNull String packageName,
@NonNull String permission, @PermissionGrantState int grantState,
@NonNull Consumer<Boolean> callback);
/**
* Set the runtime permission state from a device admin.
*
* @param callerPackageName The package name of the admin requesting the change
* @param params Parameters of admin request.
* @param callback Callback waiting for whether the state could be set or not
*/
@BinderThread
public void onSetRuntimePermissionGrantStateByDeviceAdmin(
@NonNull String callerPackageName, @NonNull AdminPermissionControlParams params,
@NonNull Consumer<Boolean> callback) {
throw new AbstractMethodError("Must be overridden in implementing class");
}
/**
* Called when a package is considered inactive based on the criteria given by
* {@link PermissionManager#startOneTimePermissionSession(String, long, int, int)}.
@@ -468,32 +483,26 @@ public abstract class PermissionControllerService extends Service {
}
@Override
public void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName,
String packageName, String permission, int grantState,
public void setRuntimePermissionGrantStateByDeviceAdminFromParams(
String callerPackageName, AdminPermissionControlParams params,
AndroidFuture callback) {
checkStringNotEmpty(callerPackageName);
checkStringNotEmpty(packageName);
checkStringNotEmpty(permission);
checkArgument(grantState == PERMISSION_GRANT_STATE_GRANTED
|| grantState == PERMISSION_GRANT_STATE_DENIED
|| grantState == PERMISSION_GRANT_STATE_DEFAULT);
checkNotNull(callback);
if (grantState == PERMISSION_GRANT_STATE_DENIED) {
if (params.getGrantState() == PERMISSION_GRANT_STATE_DENIED) {
enforceSomePermissionsGrantedToCaller(
Manifest.permission.GRANT_RUNTIME_PERMISSIONS);
}
if (grantState == PERMISSION_GRANT_STATE_DENIED) {
if (params.getGrantState() == PERMISSION_GRANT_STATE_DENIED) {
enforceSomePermissionsGrantedToCaller(
Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
}
enforceSomePermissionsGrantedToCaller(
Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
checkNotNull(callback);
onSetRuntimePermissionGrantStateByDeviceAdmin(callerPackageName,
packageName, permission, grantState, callback::complete);
params, callback::complete);
}
@Override

View File

@@ -247,6 +247,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.permission.AdminPermissionControlParams;
import android.permission.IPermissionManager;
import android.permission.PermissionControllerManager;
import android.provider.CalendarContract;
@@ -7891,6 +7892,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updateDeviceOwnerLocked();
setDeviceOwnershipSystemPropertyLocked();
//TODO(b/180371154): when provisionFullyManagedDevice is used in tests, remove this
// hard-coded default value setting.
if (isAdb(caller)) {
activeAdmin.mAdminCanGrantSensorsPermissions = true;
mPolicyCache.setAdminCanGrantSensorsPermissions(userId, true);
saveSettingsLocked(userId);
}
mInjector.binderWithCleanCallingIdentity(() -> {
// Restrict adding a managed profile when a device owner is set on the device.
// That is to prevent the co-existence of a managed profile and a device owner
@@ -12643,9 +12652,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
|| grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
|| grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT) {
AdminPermissionControlParams permissionParams =
new AdminPermissionControlParams(packageName, permission, grantState,
canAdminGrantSensorsPermissionsForUser(caller.getUserId()));
mInjector.getPermissionControllerManager(caller.getUserHandle())
.setRuntimePermissionGrantStateByDeviceAdmin(caller.getPackageName(),
packageName, permission, grantState, mContext.getMainExecutor(),
permissionParams, mContext.getMainExecutor(),
(permissionWasSet) -> {
if (isPostQAdmin && !permissionWasSet) {
callback.sendResult(null);