Merge "Allow input during remote animation if the app is fully trusted" into tm-dev
This commit is contained in:
@@ -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 =
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user