From af06141f18d54f8eb48f0a59447bee7ab1930cf3 Mon Sep 17 00:00:00 2001 From: Pavel Grafov Date: Thu, 20 Apr 2023 17:53:35 +0100 Subject: [PATCH] Pass profile userId to notifyLockedProfile When the stack originates in the primary user and then a profile activity is added on top, RunningTaskInfo.userId will reflect the primary user, but this is not the user for which WorkLockActivity should be launched. With this CL profile userId is passed along the RunningTaskInfo into onTaskProfileLocked, so that WorkLockActivity is started for the right user. Bug: 279024529 Test: atest WmTests:RootWindowContainerTests SystemUITests WMShellUnitTests WMShellTest Change-Id: I7755243edf73546dc840d0107d0a6bdb695eb45d --- core/java/android/app/ITaskStackListener.aidl | 2 +- core/java/android/app/TaskStackListener.java | 12 +++++- .../common/TaskStackListenerCallback.java | 2 +- .../shell/common/TaskStackListenerImpl.java | 7 ++-- .../common/TaskStackListenerImplTest.java | 6 +-- .../system/TaskStackChangeListener.java | 2 +- .../system/TaskStackChangeListeners.java | 7 ++-- .../keyguard/WorkLockActivityController.java | 11 ++--- .../WorkLockActivityControllerTest.java | 41 ++++++++----------- .../server/wm/RootWindowContainer.java | 2 +- .../wm/TaskChangeNotificationController.java | 6 +-- .../server/wm/RootWindowContainerTests.java | 4 +- 12 files changed, 53 insertions(+), 49 deletions(-) diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl index 36e57620c9dd3..3c6ff2865d04d 100644 --- a/core/java/android/app/ITaskStackListener.aidl +++ b/core/java/android/app/ITaskStackListener.aidl @@ -137,7 +137,7 @@ oneway interface ITaskStackListener { * activities inside it belong to a managed profile user, and that user has just * been locked. */ - void onTaskProfileLocked(in ActivityManager.RunningTaskInfo taskInfo); + void onTaskProfileLocked(in ActivityManager.RunningTaskInfo taskInfo, int userId); /** * Called when a task snapshot got updated. diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java index 774bc06e1adbe..0290cee94dc35 100644 --- a/core/java/android/app/TaskStackListener.java +++ b/core/java/android/app/TaskStackListener.java @@ -154,8 +154,18 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub { } @Override + public void onTaskProfileLocked(RunningTaskInfo taskInfo, int userId) + throws RemoteException { + onTaskProfileLocked(taskInfo); + } + + /** + * @deprecated see {@link #onTaskProfileLocked(RunningTaskInfo, int)} + */ + @Deprecated @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public void onTaskProfileLocked(RunningTaskInfo taskInfo) throws RemoteException { + public void onTaskProfileLocked(RunningTaskInfo taskInfo) + throws RemoteException { } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java index 0f9260c9deaae..9abf0f6781791 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java @@ -38,7 +38,7 @@ public interface TaskStackListenerCallback { default void onTaskStackChanged() { } - default void onTaskProfileLocked(RunningTaskInfo taskInfo) { } + default void onTaskProfileLocked(RunningTaskInfo taskInfo, int userId) { } default void onTaskDisplayChanged(int taskId, int newDisplayId) { } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java index e2106e478bb3d..d8859bac471fd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java @@ -150,8 +150,8 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler. } @Override - public void onTaskProfileLocked(ActivityManager.RunningTaskInfo taskInfo) { - mMainHandler.obtainMessage(ON_TASK_PROFILE_LOCKED, taskInfo).sendToTarget(); + public void onTaskProfileLocked(ActivityManager.RunningTaskInfo taskInfo, int userId) { + mMainHandler.obtainMessage(ON_TASK_PROFILE_LOCKED, userId, 0, taskInfo).sendToTarget(); } @Override @@ -348,8 +348,9 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler. case ON_TASK_PROFILE_LOCKED: { final ActivityManager.RunningTaskInfo info = (ActivityManager.RunningTaskInfo) msg.obj; + final int userId = msg.arg1; for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onTaskProfileLocked(info); + mTaskStackListeners.get(i).onTaskProfileLocked(info, userId); } break; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java index 1347e061eb458..60ee918ee545e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java @@ -112,9 +112,9 @@ public class TaskStackListenerImplTest extends ShellTestCase { @Test public void testOnTaskProfileLocked() { ActivityManager.RunningTaskInfo info = mock(ActivityManager.RunningTaskInfo.class); - mImpl.onTaskProfileLocked(info); - verify(mCallback).onTaskProfileLocked(eq(info)); - verify(mOtherCallback).onTaskProfileLocked(eq(info)); + mImpl.onTaskProfileLocked(info, 0); + verify(mCallback).onTaskProfileLocked(eq(info), eq(0)); + verify(mOtherCallback).onTaskProfileLocked(eq(info), eq(0)); } @Test diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java index 362d7a9390d45..7cf3121957caf 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java @@ -68,7 +68,7 @@ public interface TaskStackChangeListener { onActivityLaunchOnSecondaryDisplayRerouted(); } - default void onTaskProfileLocked(RunningTaskInfo taskInfo) { } + default void onTaskProfileLocked(RunningTaskInfo taskInfo, int userId) { } default void onTaskCreated(int taskId, ComponentName componentName) { } default void onTaskRemoved(int taskId) { } default void onTaskMovedToFront(int taskId) { } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java index dd52cfbdc80f8..c613afbda5b80 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java @@ -262,8 +262,8 @@ public class TaskStackChangeListeners { } @Override - public void onTaskProfileLocked(RunningTaskInfo taskInfo) { - mHandler.obtainMessage(ON_TASK_PROFILE_LOCKED, taskInfo).sendToTarget(); + public void onTaskProfileLocked(RunningTaskInfo taskInfo, int userId) { + mHandler.obtainMessage(ON_TASK_PROFILE_LOCKED, userId, 0, taskInfo).sendToTarget(); } @Override @@ -418,8 +418,9 @@ public class TaskStackChangeListeners { } case ON_TASK_PROFILE_LOCKED: { final RunningTaskInfo info = (RunningTaskInfo) msg.obj; + final int userId = msg.arg1; for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onTaskProfileLocked(info); + mTaskStackListeners.get(i).onTaskProfileLocked(info, userId); } break; } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java index b92499eb883e9..b7ba2019777eb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java @@ -56,11 +56,11 @@ public class WorkLockActivityController { tscl.registerTaskStackListener(mLockListener); } - private void startWorkChallengeInTask(ActivityManager.RunningTaskInfo info) { + private void startWorkChallengeInTask(ActivityManager.RunningTaskInfo info, int userId) { String packageName = info.baseActivity != null ? info.baseActivity.getPackageName() : ""; Intent intent = new Intent(KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER) .setComponent(new ComponentName(mContext, WorkLockActivity.class)) - .putExtra(Intent.EXTRA_USER_ID, info.userId) + .putExtra(Intent.EXTRA_USER_ID, userId) .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) .addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP); @@ -76,10 +76,11 @@ public class WorkLockActivityController { } else { // Starting the activity inside the task failed. We can't be sure why, so to be // safe just remove the whole task if it still exists. + Log.w(TAG, "Failed to start work lock activity, will remove task=" + info.taskId); try { mIatm.removeTask(info.taskId); } catch (RemoteException e) { - Log.w(TAG, "Failed to get description for task=" + info.taskId); + Log.e(TAG, "Failed to remove task=" + info.taskId); } } } @@ -112,8 +113,8 @@ public class WorkLockActivityController { private final TaskStackChangeListener mLockListener = new TaskStackChangeListener() { @Override - public void onTaskProfileLocked(ActivityManager.RunningTaskInfo info) { - startWorkChallengeInTask(info); + public void onTaskProfileLocked(ActivityManager.RunningTaskInfo info, int userId) { + startWorkChallengeInTask(info, userId); } }; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java index b9cfc6550966c..e981d627b5828 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java @@ -25,13 +25,11 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.IActivityTaskManager; import android.app.IApplicationThread; import android.app.ProfilerInfo; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -59,13 +57,14 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidJUnit4.class) public class WorkLockActivityControllerTest extends SysuiTestCase { - private static final int USER_ID = 333; + private static final int TASK_USER_ID = 333; + private static final int PROFILE_USER_ID = 555; private static final int TASK_ID = 444; private static final ActivityManager.RunningTaskInfo TASK_INFO = new ActivityManager.RunningTaskInfo(); static { - TASK_INFO.userId = USER_ID; + TASK_INFO.userId = TASK_USER_ID; TASK_INFO.taskId = TASK_ID; } @@ -101,10 +100,10 @@ public class WorkLockActivityControllerTest extends SysuiTestCase { setActivityStartCode(TASK_ID, true /*taskOverlay*/, ActivityManager.START_SUCCESS); // And the controller receives a message saying the profile is locked, - mTaskStackListener.onTaskProfileLocked(TASK_INFO); + mTaskStackListener.onTaskProfileLocked(TASK_INFO, PROFILE_USER_ID); // The overlay should start and the task the activity started in should not be removed. - verifyStartActivity(TASK_ID, true /*taskOverlay*/); + verifyStartActivity(TASK_ID, true /*taskOverlay*/, PROFILE_USER_ID); verify(mIActivityTaskManager, never()).removeTask(anyInt() /*taskId*/); } @@ -114,11 +113,11 @@ public class WorkLockActivityControllerTest extends SysuiTestCase { setActivityStartCode(TASK_ID, true /*taskOverlay*/, ActivityManager.START_CLASS_NOT_FOUND); // And the controller receives a message saying the profile is locked, - mTaskStackListener.onTaskProfileLocked(TASK_INFO); + mTaskStackListener.onTaskProfileLocked(TASK_INFO, PROFILE_USER_ID); // The task the activity started in should be removed to prevent the locked task from // being shown. - verifyStartActivity(TASK_ID, true /*taskOverlay*/); + verifyStartActivity(TASK_ID, true /*taskOverlay*/, PROFILE_USER_ID); verify(mIActivityTaskManager).removeTask(TASK_ID); } @@ -141,12 +140,13 @@ public class WorkLockActivityControllerTest extends SysuiTestCase { eq(ActivityManager.getCurrentUser())); } - private void verifyStartActivity(int taskId, boolean taskOverlay) throws Exception { + private void verifyStartActivity(int taskId, boolean taskOverlay, int profileUserId) + throws Exception { verify(mIActivityTaskManager).startActivityAsUser( eq((IApplicationThread) null), eq((String) null), eq((String) null), - any(Intent.class), + argThat(hasUserId(profileUserId)), eq((String) null), eq((IBinder) null), eq((String) null), @@ -157,24 +157,15 @@ public class WorkLockActivityControllerTest extends SysuiTestCase { eq(ActivityManager.getCurrentUser())); } - private static ArgumentMatcher hasComponent(final Context context, - final Class activityClass) { - return new ArgumentMatcher() { - @Override - public boolean matches(Intent intent) { - return new ComponentName(context, activityClass).equals(intent.getComponent()); - } - }; + private static ArgumentMatcher hasUserId(int userId) { + return intent -> intent.getIntExtra(Intent.EXTRA_USER_ID, -1) == userId; } private static ArgumentMatcher hasOptions(final int taskId, final boolean overlay) { - return new ArgumentMatcher() { - @Override - public boolean matches(Bundle item) { - final ActivityOptions options = ActivityOptions.fromBundle(item); - return (options.getLaunchTaskId() == taskId) - && (options.getTaskOverlay() == overlay); - } + return item -> { + final ActivityOptions options = ActivityOptions.fromBundle(item); + return (options.getLaunchTaskId() == taskId) + && (options.getTaskOverlay() == overlay); }; } } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 3f4296a5eee58..d3edeaebbf996 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -3239,7 +3239,7 @@ class RootWindowContainer extends WindowContainer if (task.getActivity(activity -> !activity.finishing && activity.mUserId == userId) != null) { mService.getTaskChangeNotificationController().notifyTaskProfileLocked( - task.getTaskInfo()); + task.getTaskInfo(), userId); } }, true /* traverseTopToBottom */); } diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java index 49d064f833455..9324e29daafbb 100644 --- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java +++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java @@ -144,7 +144,7 @@ class TaskChangeNotificationController { }; private final TaskStackConsumer mNotifyTaskProfileLocked = (l, m) -> { - l.onTaskProfileLocked((RunningTaskInfo) m.obj); + l.onTaskProfileLocked((RunningTaskInfo) m.obj, m.arg1); }; private final TaskStackConsumer mNotifyTaskSnapshotChanged = (l, m) -> { @@ -467,9 +467,9 @@ class TaskChangeNotificationController { * Notify listeners that the task has been put in a locked state because one or more of the * activities inside it belong to a managed profile user that has been locked. */ - void notifyTaskProfileLocked(ActivityManager.RunningTaskInfo taskInfo) { + void notifyTaskProfileLocked(RunningTaskInfo taskInfo, int userId) { final Message msg = mHandler.obtainMessage(NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG, - taskInfo); + userId, 0, taskInfo); forAllLocalListeners(mNotifyTaskProfileLocked, msg); msg.sendToTarget(); } 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 dfc453f0f1b6b..d173ce9d522a5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -1134,7 +1134,7 @@ public class RootWindowContainerTests extends WindowTestsBase { TaskChangeNotificationController controller = mAtm.getTaskChangeNotificationController(); spyOn(controller); mWm.mRoot.lockAllProfileTasks(profileUserId); - verify(controller).notifyTaskProfileLocked(any()); + verify(controller).notifyTaskProfileLocked(any(), eq(profileUserId)); // Create the work lock activity on top of the task final ActivityRecord workLockActivity = new ActivityBuilder(mAtm).setTask(task).build(); @@ -1144,7 +1144,7 @@ public class RootWindowContainerTests extends WindowTestsBase { // Make sure the listener won't be notified again. clearInvocations(controller); mWm.mRoot.lockAllProfileTasks(profileUserId); - verify(controller, never()).notifyTaskProfileLocked(any()); + verify(controller, never()).notifyTaskProfileLocked(any(), anyInt()); } /**