Disable all input on ActivityRecord during trusted animation

As a followup to ag/17258046, since we don't have any use case to
rely on handling input during animation, disable input even if it
is trusted embedding so that it could cover some edge-cases when
a previously truste host starts doing something bad.

Bug: 197364677
Test: atest WmTests:AppTransitionControllerTest
Change-Id: I7312b6ed961891c5c58adad73f660d4a18084c52
This commit is contained in:
Chris Li
2022-03-23 17:49:56 +08:00
parent a53b05ca8c
commit b4c0c4e81b
3 changed files with 53 additions and 15 deletions

View File

@@ -577,12 +577,6 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityStarter.java"
},
"-1488852351": {
"message": "Task=%d contains embedded TaskFragment in untrusted mode. Disabled all input during TaskFragment remote animation.",
"level": "DEBUG",
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
"-1483435730": {
"message": "InsetsSource setWin %s for type %s",
"level": "DEBUG",
@@ -3961,6 +3955,12 @@
"group": "WM_DEBUG_KEEP_SCREEN_ON",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
"2100457473": {
"message": "Task=%d contains embedded TaskFragment. Disabled all input during TaskFragment remote animation.",
"level": "DEBUG",
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
"2114149926": {
"message": "Not removing %s because app died while it's visible",
"level": "VERBOSE",

View File

@@ -666,22 +666,19 @@ public class AppTransitionController {
"Override with TaskFragment remote animation for transit=%s",
AppTransition.appTransitionOldToString(transit));
final boolean hasUntrustedEmbedding = task.forAllLeafTasks(
taskFragment -> !taskFragment.isAllowedToBeEmbeddedInTrustedMode());
final RemoteAnimationController remoteAnimationController =
mDisplayContent.mAppTransition.getRemoteAnimationController();
if (hasUntrustedEmbedding && remoteAnimationController != null) {
// We are going to use client-driven animation, but the Task is in untrusted embedded
// mode. We need to disable all input on activity windows during the animation to
// ensure it is safe. This is needed for all activity windows in the animation Task.
if (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.
// This is needed for all activity windows in the animation Task.
remoteAnimationController.setOnRemoteAnimationReady(() -> {
final Consumer<ActivityRecord> updateActivities =
activity -> activity.setDropInputForAnimation(true);
task.forAllActivities(updateActivities);
});
ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "Task=%d contains embedded TaskFragment in"
+ " untrusted mode. Disabled all input during TaskFragment remote animation.",
task.mTaskId);
ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "Task=%d contains embedded TaskFragment."
+ " Disabled all input during TaskFragment remote animation.", task.mTaskId);
}
return true;
}

View File

@@ -1064,6 +1064,47 @@ public class AppTransitionControllerTest extends WindowTestsBase {
verify(activity2).setDropInputMode(DropInputMode.NONE);
}
/**
* Since we don't have any use case to rely on handling input during animation, disable it even
* if it is trusted embedding so that it could cover some edge-cases when a previously trusted
* host starts doing something bad.
*/
@Test
public void testOverrideTaskFragmentAdapter_inputProtectedForTrustedAnimation() {
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
// Create a TaskFragment with only trusted embedded activity
final Task task = createTask(mDisplayContent);
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
.setParentTask(task)
.createActivityCount(1)
.setOrganizer(organizer)
.build();
final ActivityRecord activity = taskFragment.getChildAt(0).asActivityRecord();
prepareActivityForAppTransition(activity);
doReturn(true).when(taskFragment).isAllowedToEmbedActivityInTrustedMode(activity);
spyOn(mDisplayContent.mAppTransition);
// Prepare and start transition.
prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment);
mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
// The animation will be animated remotely by client and all activities are input disabled
// for untrusted animation.
assertTrue(remoteAnimationRunner.isAnimationStarted());
verify(activity).setDropInputForAnimation(true);
verify(activity).setDropInputMode(DropInputMode.ALL);
// Reset input after animation is finished.
clearInvocations(activity);
remoteAnimationRunner.finishAnimation();
verify(activity).setDropInputForAnimation(false);
verify(activity).setDropInputMode(DropInputMode.NONE);
}
@Test
public void testTransitionGoodToGoForTaskFragments() {
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);