From 4fce75d572b7e8587430f543fad2b4d9ad735b3a Mon Sep 17 00:00:00 2001 From: Eugene Susla Date: Tue, 10 Dec 2019 09:51:58 -0800 Subject: [PATCH] Update USER_SENSITIVE flags on app install and optimize it This also parallelizes flag updating. Currently, the broadcast listener is disabled, due to test flake, so it will not update on app install/changes Bug: 141311767 Test: - on first boot go to permissions screen, and ensure system apps categorization makes sense - install app that requests location, and ensure it's not listed as system app in permission screen Change-Id: I37ea4b196313fe9fa71150c21e7cca591067d572 --- api/system-current.txt | 2 +- .../permission/IPermissionController.aidl | 2 +- .../PermissionControllerManager.java | 17 +++++- .../PermissionControllerService.java | 18 ++++-- .../policy/PermissionPolicyService.java | 61 ++++++++++++++++++- 5 files changed, 89 insertions(+), 11 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 88aa2a7b1e358..eb47306069fb7 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8940,7 +8940,7 @@ package android.permission { method @BinderThread public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map>, boolean, int, @NonNull String, @NonNull java.util.function.Consumer>>); method @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer); method @BinderThread public void onStageAndApplyRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable); - method @BinderThread public void onUpdateUserSensitivePermissionFlags(); + method @BinderThread public void onUpdateUserSensitivePermissionFlags(int, @NonNull Runnable); field public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService"; } diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl index 0483514e6297e..f011395425411 100644 --- a/core/java/android/permission/IPermissionController.aidl +++ b/core/java/android/permission/IPermissionController.aidl @@ -42,6 +42,6 @@ oneway interface IPermissionController { void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName, String packageName, String permission, int grantState, in AndroidFuture callback); void grantOrUpgradeDefaultRuntimePermissions(in AndroidFuture callback); - void updateUserSensitive(in AndroidFuture callback); void notifyOneTimePermissionSessionTimeout(String packageName); + void updateUserSensitiveForApp(int uid, in AndroidFuture callback); } diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java index 2a1857fd00277..f08e3d25632b5 100644 --- a/core/java/android/permission/PermissionControllerManager.java +++ b/core/java/android/permission/PermissionControllerManager.java @@ -46,6 +46,7 @@ import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.Bundle; import android.os.Handler; +import android.os.Process; import android.os.UserHandle; import android.util.ArrayMap; import android.util.Log; @@ -626,14 +627,26 @@ public final class PermissionControllerManager { } /** - * @see PermissionControllerService#onUpdateUserSensitive() + * @see PermissionControllerManager#updateUserSensitiveForApp * @hide */ public void updateUserSensitive() { + updateUserSensitiveForApp(Process.INVALID_UID); + } + + /** + * @see PermissionControllerService#onUpdateUserSensitiveForApp + * @hide + */ + public void updateUserSensitiveForApp(int uid) { mRemoteService.postAsync(service -> { AndroidFuture future = new AndroidFuture<>(); - service.updateUserSensitive(future); + service.updateUserSensitiveForApp(uid, future); return future; + }).whenComplete((res, err) -> { + if (err != null) { + Log.e(TAG, "Error updating user_sensitive flags for uid " + uid, err); + } }); } diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java index 263b2c7a4ac75..4a42230ad15af 100644 --- a/core/java/android/permission/PermissionControllerService.java +++ b/core/java/android/permission/PermissionControllerService.java @@ -218,11 +218,14 @@ public abstract class PermissionControllerService extends Service { * Called by system to update the * {@link PackageManager}{@code .FLAG_PERMISSION_USER_SENSITIVE_WHEN_*} flags for permissions. *

- * This is typically when creating a new user or upgrading either system or - * permission controller package. + * + * If uid is -1, updates the permission flags for all packages. + * + * Typically called by the system when a new app is installed or updated or when creating a + * new user or upgrading either system or permission controller package. */ @BinderThread - public void onUpdateUserSensitivePermissionFlags() { + public void onUpdateUserSensitivePermissionFlags(int uid, @NonNull Runnable callback) { throw new AbstractMethodError("Must be overridden in implementing class"); } @@ -459,11 +462,14 @@ public abstract class PermissionControllerService extends Service { } @Override - public void updateUserSensitive(AndroidFuture callback) { + public void updateUserSensitiveForApp(int uid, @NonNull AndroidFuture callback) { Preconditions.checkNotNull(callback, "callback cannot be null"); - onUpdateUserSensitivePermissionFlags(); - callback.complete(null); + try { + onUpdateUserSensitivePermissionFlags(uid, () -> callback.complete(null)); + } catch (Exception e) { + callback.completeExceptionally(e); + } } @Override diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java index d589353cf3a04..161f30449a520 100644 --- a/services/core/java/com/android/server/policy/PermissionPolicyService.java +++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java @@ -32,6 +32,7 @@ import android.app.AppOpsManager; import android.app.AppOpsManagerInternal; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -173,6 +174,65 @@ public final class PermissionPolicyService extends SystemService { } catch (RemoteException doesNotHappen) { Slog.wtf(LOG_TAG, "Cannot set up app-ops listener"); } + + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); + intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); + intentFilter.addDataScheme("package"); + + + /* TODO ntmyren: enable receiver when test flakes are fixed + getContext().registerReceiverAsUser(new BroadcastReceiver() { + final List mUserSetupUids = new ArrayList<>(200); + final Map mPermControllerManagers = + new HashMap<>(); + + @Override + public void onReceive(Context context, Intent intent) { + boolean hasSetupRun = true; + try { + hasSetupRun = Settings.Secure.getInt(getContext().getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE) != 0; + } catch (Settings.SettingNotFoundException e) { + // Ignore error, assume setup has run + } + int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + // If there is no valid package for the given UID, return immediately + if (packageManagerInternal.getPackage(uid) == null) { + return; + } + + if (hasSetupRun) { + if (!mUserSetupUids.isEmpty()) { + synchronized (mUserSetupUids) { + for (int i = mUserSetupUids.size() - 1; i >= 0; i--) { + updateUid(mUserSetupUids.get(i)); + } + mUserSetupUids.clear(); + } + } + updateUid(uid); + } else { + synchronized (mUserSetupUids) { + if (!mUserSetupUids.contains(uid)) { + mUserSetupUids.add(uid); + } + } + } + } + + private void updateUid(int uid) { + UserHandle user = UserHandle.getUserHandleForUid(uid); + PermissionControllerManager manager = mPermControllerManagers.get(user); + if (manager == null) { + manager = new PermissionControllerManager( + getUserContext(getContext(), user), FgThread.getHandler()); + mPermControllerManagers.put(user, manager); + } + manager.updateUserSensitiveForApp(uid); + } + }, UserHandle.ALL, intentFilter, null, null); + */ } /** @@ -182,7 +242,6 @@ public final class PermissionPolicyService extends SystemService { * {@link AppOpsManager#sOpToSwitch share an op} to control the access. * * @param permission The permission - * * @return The op that controls the access of the permission */ private static int getSwitchOp(@NonNull String permission) {