From b8728418305038741e8635898502171be7098384 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Thu, 2 Sep 2021 13:34:06 -0600 Subject: [PATCH] Remove ActivityRecord#okToShowLocked ActivityRecord#showToCurrentUser also checks show-for-all-users flag and current user/profile, so replace it by showToCurrentUser() that will be consistent with the condition for window. This eliminates unnecessary clearing binder identity and massive invocations to StorageManagerService that acquires another lock. In general the check becomes 10x faster. The encryption check was added in commit 8558ec7. Since start process is changed to async, and the lock in handling user switch and activities are separated, the recursive restart case no longer happens. So it can be removed now. Bug: 193661576 Test: atest RootWindowContainerTests Test: Create a profile user with credential. Launch some activities of the profile user. Invoke UserManager#evictCredentialEncryptionKey and observe there should be no crash and exception from apps. Change-Id: If088cf1712c7f784826ccbcf6c38aeff84f22e7e --- .../com/android/server/wm/ActivityRecord.java | 21 +++------------ .../android/server/wm/ActivityStarter.java | 2 +- .../server/wm/ActivityTaskSupervisor.java | 6 ----- .../server/wm/RootWindowContainer.java | 2 +- .../core/java/com/android/server/wm/Task.java | 4 +-- .../com/android/server/wm/TaskFragment.java | 1 - .../android/server/wm/WindowContainer.java | 1 + .../server/wm/RootWindowContainerTests.java | 26 +++++++++---------- .../server/wm/SystemServicesTestRule.java | 1 - 9 files changed, 20 insertions(+), 44 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 9dc0cfc8c2827..d7c3e7067e94a 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -285,7 +285,6 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; -import android.os.storage.StorageManager; import android.service.contentcapture.ActivityEvent; import android.service.dreams.DreamActivity; import android.service.dreams.DreamManagerInternal; @@ -730,7 +729,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // TODO: rename to mNoDisplay @VisibleForTesting boolean noDisplay; - boolean mShowForAllUsers; + final boolean mShowForAllUsers; // TODO: Make this final int mTargetSdk; @@ -5305,7 +5304,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void updateVisibilityIgnoringKeyguard(boolean behindFullscreenActivity) { visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind) - && okToShowLocked(); + && showToCurrentUser(); } boolean shouldBeVisible() { @@ -6342,22 +6341,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return this; } - /** Checks whether the activity should be shown for current user. */ - public boolean okToShowLocked() { - // We cannot show activities when the device is locked and the application is not - // encryption aware. - if (!StorageManager.isUserKeyUnlocked(mUserId) - && !info.applicationInfo.isEncryptionAware()) { - return false; - } - - return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0 - || (mTaskSupervisor.isCurrentProfileLocked(mUserId) - && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */)); - } - boolean canBeTopRunning() { - return !finishing && okToShowLocked(); + return !finishing && showToCurrentUser(); } /** diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index af5382721dee9..ab97094c0e6a7 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2357,7 +2357,7 @@ class ActivityStarter { // of this in the record so that we can skip it when trying to find // the top running activity. mDoResume = doResume; - if (!doResume || !r.okToShowLocked() || mLaunchTaskBehind) { + if (!doResume || !r.showToCurrentUser() || mLaunchTaskBehind) { r.delayedResume = true; mDoResume = false; } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index ea242bb284953..e6aa4fcccaa26 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -1872,12 +1872,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget(); } - /** Checks whether the userid is a profile of the current user. */ - boolean isCurrentProfileLocked(int userId) { - if (userId == mRootWindowContainer.mCurrentUser) return true; - return mService.mAmInternal.isCurrentProfile(userId); - } - /** * Processes the activities to be stopped or destroyed. This should be called when the resumed * activities are idle or drawn. diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 079868d0dec14..6c2322b6d7e53 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1965,7 +1965,7 @@ class RootWindowContainer extends WindowContainer private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r, WindowProcessController app, ActivityRecord top) { - if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null + if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard || r.app != null || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) { return false; } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 567936d2108a5..7bdb1a090c1a6 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -5159,7 +5159,7 @@ class Task extends TaskFragment { } final ActivityRecord prev = baseTask.getActivity( - a -> a.mStartingData != null && a.okToShowLocked()); + a -> a.mStartingData != null && a.showToCurrentUser()); r.showStartingWindow(prev, newTask, isTaskSwitch, true /* startActivity */, sourceRecord); } @@ -5530,7 +5530,7 @@ class Task extends TaskFragment { // Don't refocus if invisible to current user final ActivityRecord top = tr.getTopNonFinishingActivity(); - if (top == null || !top.okToShowLocked()) { + if (top == null || !top.showToCurrentUser()) { positionChildAtTop(tr); if (top != null) { mTaskSupervisor.mRecentTasks.add(top.getTask()); diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 1b72826fba9b0..43af139889f24 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -655,7 +655,6 @@ class TaskFragment extends WindowContainer { * @param includingEmbeddedTask whether the activity in a task that being embedded from this * one should be included. * @see #topRunningActivity(boolean, boolean) - * @see ActivityRecord#okToShowLocked() */ ActivityRecord getTopNonFinishingActivity(boolean includeOverlays, boolean includingEmbeddedTask) { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index aec7cab2a1ec9..2882a23910663 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -1380,6 +1380,7 @@ class WindowContainer extends ConfigurationContainer< } } + /** Returns whether the window should be shown for current user. */ boolean showToCurrentUser() { return true; } diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index f2eb709b4bb8a..4069f0f41d905 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -1008,33 +1008,31 @@ public class RootWindowContainerTests extends WindowTestsBase { @Test public void testLockAllProfileTasks() { - // Make an activity visible with the user id set to 0 - final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); - final int taskId = task.mTaskId; - final ActivityRecord activity = task.getTopMostActivity(); + final int profileUid = UserHandle.PER_USER_RANGE + UserHandle.MIN_SECONDARY_USER_ID; + final int profileUserId = UserHandle.getUserId(profileUid); + // Create an activity belonging to the profile user. + final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true) + .setUid(profileUid).build(); + final Task task = activity.getTask(); - // Create another activity on top and the user id is 1 - final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task) - .setUid(UserHandle.PER_USER_RANGE + 1).build(); - doReturn(true).when(topActivity).okToShowLocked(); + // Create another activity belonging to current user on top. + final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build(); topActivity.intent.setAction(Intent.ACTION_MAIN); // Make sure the listeners will be notified for putting the task to locked state TaskChangeNotificationController controller = mAtm.getTaskChangeNotificationController(); spyOn(controller); - mWm.mRoot.lockAllProfileTasks(0); - verify(controller).notifyTaskProfileLocked(eq(taskId), eq(0)); + mWm.mRoot.lockAllProfileTasks(profileUserId); + verify(controller).notifyTaskProfileLocked(eq(task.mTaskId), eq(profileUserId)); // Create the work lock activity on top of the task - final ActivityRecord workLockActivity = new ActivityBuilder(mAtm).setTask(task) - .setUid(UserHandle.PER_USER_RANGE + 1).build(); - doReturn(true).when(workLockActivity).okToShowLocked(); + final ActivityRecord workLockActivity = new ActivityBuilder(mAtm).setTask(task).build(); workLockActivity.intent.setAction(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER); doReturn(workLockActivity.mActivityComponent).when(mAtm).getSysUiServiceComponentLocked(); // Make sure the listener won't be notified again. clearInvocations(controller); - mWm.mRoot.lockAllProfileTasks(0); + mWm.mRoot.lockAllProfileTasks(profileUserId); verify(controller, never()).notifyTaskProfileLocked(anyInt(), anyInt()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index 8e7ba4bc3293f..5bc45d7c3d170 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -271,7 +271,6 @@ public class SystemServicesTestRule implements TestRule { doNothing().when(amInternal).cleanUpServices(anyInt(), any(), any()); doReturn(UserHandle.USER_SYSTEM).when(amInternal).getCurrentUserId(); doReturn(TEST_USER_PROFILE_IDS).when(amInternal).getCurrentProfileIds(); - doReturn(true).when(amInternal).isCurrentProfile(anyInt()); doReturn(true).when(amInternal).isUserRunning(anyInt(), anyInt()); doReturn(true).when(amInternal).hasStartedUserState(anyInt()); doReturn(false).when(amInternal).shouldConfirmCredentials(anyInt());