Merge "Update USER_SENSITIVE flags on app install and optimize it" into rvc-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 51f3425..bd6040c 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8943,7 +8943,7 @@
     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 @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 0483514..f011395 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -42,6 +42,6 @@
     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 2a1857f..f08e3d25 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -46,6 +46,7 @@
 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 @@
     }
 
     /**
-     * @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<Void> 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 263b2c7..4a42230 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -218,11 +218,14 @@
      * Called by system to update the
      * {@link PackageManager}{@code .FLAG_PERMISSION_USER_SENSITIVE_WHEN_*} flags for permissions.
      * <p>
-     * 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 @@
             }
 
             @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 d589353..161f304 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.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 @@
         } 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<Integer> mUserSetupUids = new ArrayList<>(200);
+            final Map<UserHandle, PermissionControllerManager> 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 @@
      * {@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) {