Merge "Allow input during remote animation if the app is fully trusted" into tm-dev am: 6717425404

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18330767

Change-Id: Ib30b733fc0d354dc682ff82bdd17decef7bb277c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Chris Li
2022-05-13 00:28:03 +00:00
committed by Automerger Merge Worker
4 changed files with 77 additions and 13 deletions

View File

@@ -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 =

View File

@@ -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;
}
@@ -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));
}
/**

View File

@@ -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)) {

View File

@@ -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);
@@ -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);
@@ -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) {