Loading services/core/java/com/android/server/wm/AppTransitionController.java +7 −2 Original line number Diff line number Diff line Loading @@ -663,11 +663,16 @@ public class AppTransitionController { "Override with TaskFragment remote animation for transit=%s", AppTransition.appTransitionOldToString(transit)); final int organizerUid = mDisplayContent.mAtmService.mTaskFragmentOrganizerController .getTaskFragmentOrganizerUid(organizer); final boolean shouldDisableInputForRemoteAnimation = !task.isFullyTrustedEmbedding( organizerUid); final RemoteAnimationController remoteAnimationController = mDisplayContent.mAppTransition.getRemoteAnimationController(); if (remoteAnimationController != null) { if (shouldDisableInputForRemoteAnimation && remoteAnimationController != null) { // We are going to use client-driven animation, Disable all input on activity windows // during the animation to ensure it is safe to allow client to animate the surfaces. // during the animation (unless it is fully trusted) to ensure it is safe to allow // client to animate the surfaces. // This is needed for all activity windows in the animation Task. remoteAnimationController.setOnRemoteAnimationReady(() -> { final Consumer<ActivityRecord> updateActivities = Loading services/core/java/com/android/server/wm/TaskFragment.java +24 −9 Original line number Diff line number Diff line Loading @@ -562,13 +562,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { * @param uid uid of the TaskFragment organizer. */ boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a, int uid) { if (UserHandle.getAppId(uid) == SYSTEM_UID) { // The system is trusted to embed other apps securely and for all users. return true; } if (uid == a.getUid()) { // Activities from the same UID can be embedded freely by the host. if (isFullyTrustedEmbedding(a, uid)) { return true; } Loading @@ -586,14 +580,35 @@ class TaskFragment extends WindowContainer<WindowContainer> { knownActivityEmbeddingCerts); } /** * It is fully trusted for embedding in the system app or embedding in the same app. This is * different from {@link #isAllowedToBeEmbeddedInTrustedMode()} since there may be a small * chance for a previous trusted app to start doing something bad. */ private static boolean isFullyTrustedEmbedding(@NonNull ActivityRecord a, int uid) { // The system is trusted to embed other apps securely and for all users. return UserHandle.getAppId(uid) == SYSTEM_UID // Activities from the same UID can be embedded freely by the host. || uid == a.getUid(); } /** * Checks if all activities in the task fragment are embedded as fully trusted. * @see #isFullyTrustedEmbedding(ActivityRecord, int) * @param uid uid of the TaskFragment organizer. */ boolean isFullyTrustedEmbedding(int uid) { // Traverse all activities to see if any of them are not fully trusted embedding. return !forAllActivities(r -> !isFullyTrustedEmbedding(r, uid)); } /** * Checks if all activities in the task fragment are allowed to be embedded in trusted mode. * @see #isAllowedToEmbedActivityInTrustedMode(ActivityRecord) */ boolean isAllowedToBeEmbeddedInTrustedMode() { // Traverse all activities to see if any of them are not in the trusted mode. final Predicate<ActivityRecord> callback = r -> !isAllowedToEmbedActivityInTrustedMode(r); return !forAllActivities(callback); return !forAllActivities(r -> !isAllowedToEmbedActivityInTrustedMode(r)); } /** Loading services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +5 −0 Original line number Diff line number Diff line Loading @@ -378,6 +378,11 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr } } int getTaskFragmentOrganizerUid(ITaskFragmentOrganizer organizer) { final TaskFragmentOrganizerState state = validateAndGetState(organizer); return state.mOrganizerUid; } void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) { final TaskFragmentOrganizerState state = validateAndGetState(organizer); if (!state.addTaskFragment(taskFragment)) { Loading services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +41 −2 Original line number Diff line number Diff line Loading @@ -1128,6 +1128,41 @@ public class AppTransitionControllerTest extends WindowTestsBase { verify(activity).setDropInputMode(DropInputMode.NONE); } /** * We don't need to drop input for fully trusted embedding (system app, and embedding in the * same app). This will allow users to do fast tapping. */ @Test public void testOverrideTaskFragmentAdapter_noInputProtectedForFullyTrustedAnimation() { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); // Create a TaskFragment with only trusted embedded activity final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) .setParentTask(task) .createActivityCount(1) .setOrganizer(organizer) .build(); final ActivityRecord activity = taskFragment.getChildAt(0).asActivityRecord(); prepareActivityForAppTransition(activity); final int uid = mAtm.mTaskFragmentOrganizerController.getTaskFragmentOrganizerUid( getITaskFragmentOrganizer(organizer)); doReturn(true).when(task).isFullyTrustedEmbedding(uid); spyOn(mDisplayContent.mAppTransition); // Prepare and start transition. prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment); mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); // The animation will be animated remotely by client, but input should not be dropped for // fully trusted. assertTrue(remoteAnimationRunner.isAnimationStarted()); verify(activity, never()).setDropInputForAnimation(true); verify(activity, never()).setDropInputMode(DropInputMode.ALL); } @Test public void testTransitionGoodToGoForTaskFragments() { final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); Loading Loading @@ -1197,8 +1232,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { TestRemoteAnimationRunner remoteAnimationRunner) { final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter( remoteAnimationRunner, 10, 1); final ITaskFragmentOrganizer iOrganizer = ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder()); final ITaskFragmentOrganizer iOrganizer = getITaskFragmentOrganizer(organizer); final RemoteAnimationDefinition definition = new RemoteAnimationDefinition(); definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, adapter); definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, adapter); Loading @@ -1208,6 +1242,11 @@ public class AppTransitionControllerTest extends WindowTestsBase { definition); } private static ITaskFragmentOrganizer getITaskFragmentOrganizer( TaskFragmentOrganizer organizer) { return ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder()); } private void prepareAndTriggerAppTransition(@Nullable ActivityRecord openingActivity, @Nullable ActivityRecord closingActivity, @Nullable TaskFragment changingTaskFragment) { if (openingActivity != null) { Loading Loading
services/core/java/com/android/server/wm/AppTransitionController.java +7 −2 Original line number Diff line number Diff line Loading @@ -663,11 +663,16 @@ public class AppTransitionController { "Override with TaskFragment remote animation for transit=%s", AppTransition.appTransitionOldToString(transit)); final int organizerUid = mDisplayContent.mAtmService.mTaskFragmentOrganizerController .getTaskFragmentOrganizerUid(organizer); final boolean shouldDisableInputForRemoteAnimation = !task.isFullyTrustedEmbedding( organizerUid); final RemoteAnimationController remoteAnimationController = mDisplayContent.mAppTransition.getRemoteAnimationController(); if (remoteAnimationController != null) { if (shouldDisableInputForRemoteAnimation && remoteAnimationController != null) { // We are going to use client-driven animation, Disable all input on activity windows // during the animation to ensure it is safe to allow client to animate the surfaces. // during the animation (unless it is fully trusted) to ensure it is safe to allow // client to animate the surfaces. // This is needed for all activity windows in the animation Task. remoteAnimationController.setOnRemoteAnimationReady(() -> { final Consumer<ActivityRecord> updateActivities = Loading
services/core/java/com/android/server/wm/TaskFragment.java +24 −9 Original line number Diff line number Diff line Loading @@ -562,13 +562,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { * @param uid uid of the TaskFragment organizer. */ boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a, int uid) { if (UserHandle.getAppId(uid) == SYSTEM_UID) { // The system is trusted to embed other apps securely and for all users. return true; } if (uid == a.getUid()) { // Activities from the same UID can be embedded freely by the host. if (isFullyTrustedEmbedding(a, uid)) { return true; } Loading @@ -586,14 +580,35 @@ class TaskFragment extends WindowContainer<WindowContainer> { knownActivityEmbeddingCerts); } /** * It is fully trusted for embedding in the system app or embedding in the same app. This is * different from {@link #isAllowedToBeEmbeddedInTrustedMode()} since there may be a small * chance for a previous trusted app to start doing something bad. */ private static boolean isFullyTrustedEmbedding(@NonNull ActivityRecord a, int uid) { // The system is trusted to embed other apps securely and for all users. return UserHandle.getAppId(uid) == SYSTEM_UID // Activities from the same UID can be embedded freely by the host. || uid == a.getUid(); } /** * Checks if all activities in the task fragment are embedded as fully trusted. * @see #isFullyTrustedEmbedding(ActivityRecord, int) * @param uid uid of the TaskFragment organizer. */ boolean isFullyTrustedEmbedding(int uid) { // Traverse all activities to see if any of them are not fully trusted embedding. return !forAllActivities(r -> !isFullyTrustedEmbedding(r, uid)); } /** * Checks if all activities in the task fragment are allowed to be embedded in trusted mode. * @see #isAllowedToEmbedActivityInTrustedMode(ActivityRecord) */ boolean isAllowedToBeEmbeddedInTrustedMode() { // Traverse all activities to see if any of them are not in the trusted mode. final Predicate<ActivityRecord> callback = r -> !isAllowedToEmbedActivityInTrustedMode(r); return !forAllActivities(callback); return !forAllActivities(r -> !isAllowedToEmbedActivityInTrustedMode(r)); } /** Loading
services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +5 −0 Original line number Diff line number Diff line Loading @@ -378,6 +378,11 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr } } int getTaskFragmentOrganizerUid(ITaskFragmentOrganizer organizer) { final TaskFragmentOrganizerState state = validateAndGetState(organizer); return state.mOrganizerUid; } void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) { final TaskFragmentOrganizerState state = validateAndGetState(organizer); if (!state.addTaskFragment(taskFragment)) { Loading
services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +41 −2 Original line number Diff line number Diff line Loading @@ -1128,6 +1128,41 @@ public class AppTransitionControllerTest extends WindowTestsBase { verify(activity).setDropInputMode(DropInputMode.NONE); } /** * We don't need to drop input for fully trusted embedding (system app, and embedding in the * same app). This will allow users to do fast tapping. */ @Test public void testOverrideTaskFragmentAdapter_noInputProtectedForFullyTrustedAnimation() { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); // Create a TaskFragment with only trusted embedded activity final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) .setParentTask(task) .createActivityCount(1) .setOrganizer(organizer) .build(); final ActivityRecord activity = taskFragment.getChildAt(0).asActivityRecord(); prepareActivityForAppTransition(activity); final int uid = mAtm.mTaskFragmentOrganizerController.getTaskFragmentOrganizerUid( getITaskFragmentOrganizer(organizer)); doReturn(true).when(task).isFullyTrustedEmbedding(uid); spyOn(mDisplayContent.mAppTransition); // Prepare and start transition. prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment); mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); // The animation will be animated remotely by client, but input should not be dropped for // fully trusted. assertTrue(remoteAnimationRunner.isAnimationStarted()); verify(activity, never()).setDropInputForAnimation(true); verify(activity, never()).setDropInputMode(DropInputMode.ALL); } @Test public void testTransitionGoodToGoForTaskFragments() { final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); Loading Loading @@ -1197,8 +1232,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { TestRemoteAnimationRunner remoteAnimationRunner) { final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter( remoteAnimationRunner, 10, 1); final ITaskFragmentOrganizer iOrganizer = ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder()); final ITaskFragmentOrganizer iOrganizer = getITaskFragmentOrganizer(organizer); final RemoteAnimationDefinition definition = new RemoteAnimationDefinition(); definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, adapter); definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, adapter); Loading @@ -1208,6 +1242,11 @@ public class AppTransitionControllerTest extends WindowTestsBase { definition); } private static ITaskFragmentOrganizer getITaskFragmentOrganizer( TaskFragmentOrganizer organizer) { return ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder()); } private void prepareAndTriggerAppTransition(@Nullable ActivityRecord openingActivity, @Nullable ActivityRecord closingActivity, @Nullable TaskFragment changingTaskFragment) { if (openingActivity != null) { Loading