Merge cherrypicks of [14554379, 14554380, 14554562, 14554565, 14554567, 14554524, 14554569, 14554525, 14554572, 14554574, 14554575, 14554577, 14554622, 14554628, 14554630, 14554631, 14554503, 14554632, 14554536, 14554633] into security-aosp-qt-release

Change-Id: I719edd3e51e12a3c70b1934c57fe02306a21a7f8
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0bb89b7..515686b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5691,6 +5691,7 @@
             final PendingIntent pi = PendingIntent.getBroadcast(getContext(),
                     REQUEST_CODE_TIMEOUT,
                     new Intent(ACTION_NOTIFICATION_TIMEOUT)
+                            .setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
                             .setData(new Uri.Builder().scheme(SCHEME_TIMEOUT)
                                     .appendPath(record.getKey()).build())
                             .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 79c86c1..128b7f77 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -618,23 +618,30 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        final int userId = UserHandle.getUserId(newPackage.applicationInfo.uid);
-        int numRequestedPermissions = newPackage.requestedPermissions.size();
-        for (int i = 0; i < numRequestedPermissions; i++) {
-            PermissionInfo permInfo = getPermissionInfo(newPackage.requestedPermissions.get(i),
-                    newPackage.packageName, 0, callingUid);
-            if (permInfo == null || !STORAGE_PERMISSIONS.contains(permInfo.name)) {
-                continue;
+
+        for (int userId: mUserManagerInt.getUserIds()) {
+            int numRequestedPermissions = newPackage.requestedPermissions.size();
+            for (int i = 0; i < numRequestedPermissions; i++) {
+                PermissionInfo permInfo = getPermissionInfo(newPackage.requestedPermissions.get(i),
+                        newPackage.packageName, 0, callingUid);
+                if (permInfo == null || !STORAGE_PERMISSIONS.contains(permInfo.name)) {
+                    continue;
+                }
+
+                EventLog.writeEvent(0x534e4554, "171430330", newPackage.applicationInfo.uid,
+                        "Revoking permission " + permInfo.name + " from package "
+                                + newPackage.packageName + " as either the sdk downgraded "
+                                + downgradedSdk + " or newly requested legacy full storage "
+                                + newlyRequestsLegacy);
+
+                try {
+                    revokeRuntimePermission(permInfo.name, newPackage.packageName,
+                            false, userId, permissionCallback);
+                } catch (IllegalStateException | SecurityException e) {
+                    Log.e(TAG, "unable to revoke " + permInfo.name + " for "
+                            + newPackage.packageName + " user " + userId, e);
+                }
             }
-
-            EventLog.writeEvent(0x534e4554, "171430330", newPackage.applicationInfo.uid,
-                    "Revoking permission " + permInfo.name + " from package "
-                            + newPackage.packageName + " as either the sdk downgraded "
-                            + downgradedSdk + " or newly requested legacy full storage "
-                            + newlyRequestsLegacy);
-
-            revokeRuntimePermission(permInfo.name, newPackage.packageName,
-                    false, userId, permissionCallback);
         }
 
     }
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 3ec461d..e785d8f 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -2111,13 +2111,14 @@
                     final List<TaskRecord> tasks = stack.getAllTasks();
                     for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
                         final TaskRecord task = tasks.get(taskNdx);
-
-                        // Check the task for a top activity belonging to userId, or returning a
-                        // result to an activity belonging to userId. Example case: a document
-                        // picker for personal files, opened by a work app, should still get locked.
-                        if (taskTopActivityIsUser(task, userId)) {
-                            mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
-                                    task.taskId, userId);
+                        for (int activityNdx = task.mActivities.size() - 1; activityNdx >= 0;
+                                activityNdx--) {
+                            final ActivityRecord activity = task.mActivities.get(activityNdx);
+                            if (!activity.finishing && activity.mUserId == userId) {
+                                mService.getTaskChangeNotificationController()
+                                        .notifyTaskProfileLocked(task.taskId, userId);
+                                break;
+                            }
                         }
                     }
                 }
@@ -2127,26 +2128,6 @@
         }
     }
 
-    /**
-     * Detects whether we should show a lock screen in front of this task for a locked user.
-     * <p>
-     * We'll do this if either of the following holds:
-     * <ul>
-     *   <li>The top activity explicitly belongs to {@param userId}.</li>
-     *   <li>The top activity returns a result to an activity belonging to {@param userId}.</li>
-     * </ul>
-     *
-     * @return {@code true} if the top activity looks like it belongs to {@param userId}.
-     */
-    private boolean taskTopActivityIsUser(TaskRecord task, @UserIdInt int userId) {
-        // To handle the case that work app is in the task but just is not the top one.
-        final ActivityRecord activityRecord = task.getTopActivity();
-        final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
-
-        return (activityRecord != null && activityRecord.mUserId == userId)
-                || (resultTo != null && resultTo.mUserId == userId);
-    }
-
     void cancelInitializingActivities() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 9750cfc..ab853ab 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -74,6 +74,7 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.AlarmManager;
 import android.app.AppOpsManager;
 import android.app.AutomaticZenRule;
 import android.app.IActivityManager;
@@ -146,6 +147,7 @@
 import com.android.server.lights.LightsManager;
 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
 import com.android.server.notification.NotificationManagerService.NotificationListeners;
+import com.android.server.pm.PackageManagerService;
 import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -242,6 +244,9 @@
     @Mock
     UserManager mUm;
 
+    @Mock
+    AlarmManager mAlarmManager;
+
     // Use a Testable subclass so we can simulate calls from the system without failing.
     private static class TestableNotificationManagerService extends NotificationManagerService {
         int countSystemChecks = 0;
@@ -337,6 +342,7 @@
         LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
         LocalServices.removeServiceForTest(ActivityManagerInternal.class);
         LocalServices.addService(ActivityManagerInternal.class, mAmi);
+        mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
 
         doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
 
@@ -548,6 +554,26 @@
     }
 
     @Test
+    public void testLimitTimeOutBroadcast() {
+        NotificationChannel channel = new NotificationChannel("id", "name",
+                NotificationManager.IMPORTANCE_HIGH);
+        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setTimeoutAfter(1);
+
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
+                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
+        NotificationRecord r = new NotificationRecord(mContext, sbn, channel);
+
+        mService.scheduleTimeoutLocked(r);
+        ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
+        verify(mAlarmManager).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture());
+        assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME,
+                captor.getValue().getIntent().getPackage());
+    }
+
+    @Test
     public void testCreateNotificationChannels_SingleChannel() throws Exception {
         final NotificationChannel channel =
                 new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 8d2c3dd..4e018c8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -59,6 +59,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.util.Pair;
 
@@ -816,6 +817,25 @@
         assertEquals(infoFake1.activityInfo.name, resolvedInfo.first.name);
     }
 
+    @Test
+    public void testLockAllProfileTasks() {
+        // Make an activity visible with the user id set to 1
+        final TaskRecord task = new TaskBuilder(mSupervisor).setStack(mFullscreenStack).build();
+        final ActivityRecord activity = new ActivityBuilder(mService).setTask(task)
+                .setUid(UserHandle.PER_USER_RANGE + 1).build();
+
+        // Create another activity on top and the user id is 2
+        final ActivityRecord topActivity = new ActivityBuilder(mService)
+                .setTask(task).setUid(UserHandle.PER_USER_RANGE + 2).build();
+
+        // Make sure the listeners will be notified for putting the task to locked state
+        TaskChangeNotificationController controller =
+                mService.getTaskChangeNotificationController();
+        spyOn(controller);
+        mService.mRootActivityContainer.lockAllProfileTasks(1);
+        verify(controller).notifyTaskProfileLocked(eq(task.taskId), eq(1));
+    }
+
     /**
      * Mock {@link RootActivityContainerTests#resolveHomeActivity} for returning consistent activity
      * info for test cases (the original implementation will resolve from the real package manager).