Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56f38d1c authored by Chris Li's avatar Chris Li Committed by Automerger Merge Worker
Browse files

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

parents 06206bb9 67174254
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -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 =
+24 −9
Original line number Diff line number Diff line
@@ -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));
    }

    /**
+5 −0
Original line number Diff line number Diff line
@@ -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)) {
+41 −2
Original line number Diff line number Diff line
@@ -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) {