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

Commit 388f1da6 authored by Chris Li's avatar Chris Li Committed by Automerger Merge Worker
Browse files

Merge "Disable all input on ActivityRecord during untrusted animation" into tm-dev am: a3e1134c

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

Change-Id: I59e222a005f6ce8e39dc89a88af393737fe4b818
parents bfbcfb92 a3e1134c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -384,6 +384,7 @@ message ActivityRecordProto {
    optional float min_aspect_ratio = 33;
    optional bool provides_max_bounds = 34;
    optional bool enable_recents_screenshot = 35;
    optional int32 last_drop_input_mode = 36;
}

/* represents WindowToken */
+6 −0
Original line number Diff line number Diff line
@@ -613,6 +613,12 @@
      "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",
+19 −4
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ import static com.android.server.wm.ActivityRecordProto.IN_SIZE_COMPAT_MODE;
import static com.android.server.wm.ActivityRecordProto.IS_ANIMATING;
import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START;
import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN;
import static com.android.server.wm.ActivityRecordProto.LAST_DROP_INPUT_MODE;
import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
import static com.android.server.wm.ActivityRecordProto.MIN_ASPECT_RATIO;
import static com.android.server.wm.ActivityRecordProto.NAME;
@@ -786,6 +787,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    /** The last set {@link DropInputMode} for this activity surface. */
    @DropInputMode
    private int mLastDropInputMode = DropInputMode.NONE;
    /** Whether the input to this activity will be dropped during the current playing animation. */
    private boolean mIsInputDroppedForAnimation;

    /**
     * If it is non-null, it requires all activities who have the same starting data to be drawn
@@ -1567,6 +1570,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    }

    /** Sets if all input will be dropped as a protection during the client-driven animation. */
    void setDropInputForAnimation(boolean isInputDroppedForAnimation) {
        if (mIsInputDroppedForAnimation == isInputDroppedForAnimation) {
            return;
        }
        mIsInputDroppedForAnimation = isInputDroppedForAnimation;
        updateUntrustedEmbeddingInputProtection();
    }

    /**
     * Sets to drop input when obscured to activity if it is embedded in untrusted mode.
     *
@@ -1576,11 +1588,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
     * all untrusted activities.
     */
    private void updateUntrustedEmbeddingInputProtection() {
        final SurfaceControl sc = getSurfaceControl();
        if (sc == null) {
        if (getSurfaceControl() == null) {
            return;
        }
        if (isEmbeddedInUntrustedMode()) {
        if (mIsInputDroppedForAnimation) {
            // Disable all input during the animation.
            setDropInputMode(DropInputMode.ALL);
        } else if (isEmbeddedInUntrustedMode()) {
            // Set drop input to OBSCURED when untrusted embedded.
            setDropInputMode(DropInputMode.OBSCURED);
        } else {
@@ -1591,7 +1605,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

    @VisibleForTesting
    void setDropInputMode(@DropInputMode int mode) {
        if (mLastDropInputMode != mode && getSurfaceControl() != null) {
        if (mLastDropInputMode != mode) {
            mLastDropInputMode = mode;
            mWmService.mTransactionFactory.get()
                    .setDropInputMode(getSurfaceControl(), mode)
@@ -9299,6 +9313,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // permission to access the device configs.
        proto.write(PROVIDES_MAX_BOUNDS, providesMaxBounds());
        proto.write(ENABLE_RECENTS_SCREENSHOT, mEnableRecentsScreenshot);
        proto.write(LAST_DROP_INPUT_MODE, mLastDropInputMode);
    }

    @Override
+38 −8
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
@@ -541,12 +542,13 @@ public class AppTransitionController {
    }

    /**
     * Finds the common {@link android.window.TaskFragmentOrganizer} that organizes all app windows
     * in the current transition.
     * @return {@code null} if there is no such organizer, or if there are more than one.
     * Finds the common parent {@link Task} that is parent of all embedded app windows in the
     * current transition.
     * @return {@code null} if app windows in the transition are not children of the same Task, or
     *         if none of the app windows is embedded.
     */
    @Nullable
    private ITaskFragmentOrganizer findTaskFragmentOrganizerForAllWindows() {
    private Task findParentTaskForAllEmbeddedWindows() {
        mTempTransitionWindows.clear();
        mTempTransitionWindows.addAll(mDisplayContent.mClosingApps);
        mTempTransitionWindows.addAll(mDisplayContent.mOpeningApps);
@@ -600,13 +602,22 @@ public class AppTransitionController {
            leafTask = task;
        }
        mTempTransitionWindows.clear();
        if (leafTask == null) {
            return null;
        return leafTask;
    }

    /**
     * Finds the common {@link android.window.TaskFragmentOrganizer} that organizes all embedded
     * {@link TaskFragment} belong to the given {@link Task}.
     * @return {@code null} if there is no such organizer, or if there are more than one.
     */
    @Nullable
    private ITaskFragmentOrganizer findTaskFragmentOrganizer(@Nullable Task task) {
        if (task == null) {
            return null;
        }
        // We don't support remote animation for Task with multiple TaskFragmentOrganizers.
        final ITaskFragmentOrganizer[] organizer = new ITaskFragmentOrganizer[1];
        final boolean hasMultipleOrganizers = leafTask.forAllLeafTaskFragments(taskFragment -> {
        final boolean hasMultipleOrganizers = task.forAllLeafTaskFragments(taskFragment -> {
            final ITaskFragmentOrganizer tfOrganizer = taskFragment.getTaskFragmentOrganizer();
            if (tfOrganizer == null) {
                return false;
@@ -638,7 +649,8 @@ public class AppTransitionController {
            return false;
        }

        final ITaskFragmentOrganizer organizer = findTaskFragmentOrganizerForAllWindows();
        final Task task = findParentTaskForAllEmbeddedWindows();
        final ITaskFragmentOrganizer organizer = findTaskFragmentOrganizer(task);
        final RemoteAnimationDefinition definition = organizer != null
                ? mDisplayContent.mAtmService.mTaskFragmentOrganizerController
                    .getRemoteAnimationDefinition(organizer)
@@ -653,6 +665,24 @@ public class AppTransitionController {
        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                "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.
            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);
        }
        return true;
    }

+19 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
@@ -49,6 +50,7 @@ import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.function.Consumer;

/**
 * Helper class to run app animations in a remote process.
@@ -72,6 +74,8 @@ class RemoteAnimationController implements DeathRecipient {
    private FinishedCallback mFinishedCallback;
    private boolean mCanceled;
    private boolean mLinkedToDeathOfRunner;
    @Nullable
    private Runnable mOnRemoteAnimationReady;

    RemoteAnimationController(WindowManagerService service, DisplayContent displayContent,
            RemoteAnimationAdapter remoteAnimationAdapter, Handler handler) {
@@ -101,6 +105,11 @@ class RemoteAnimationController implements DeathRecipient {
        return adapters;
    }

    /** Sets callback to run before starting remote animation. */
    void setOnRemoteAnimationReady(@Nullable Runnable onRemoteAnimationReady) {
        mOnRemoteAnimationReady = onRemoteAnimationReady;
    }

    /**
     * Called when the transition is ready to be started, and all leashes have been set up.
     */
@@ -133,6 +142,11 @@ class RemoteAnimationController implements DeathRecipient {
            return;
        }

        if (mOnRemoteAnimationReady != null) {
            mOnRemoteAnimationReady.run();
            mOnRemoteAnimationReady = null;
        }

        // Create the remote wallpaper animation targets (if any)
        final RemoteAnimationTarget[] wallpaperTargets = createWallpaperAnimations();

@@ -292,6 +306,10 @@ class RemoteAnimationController implements DeathRecipient {
                mService.closeSurfaceTransaction("RemoteAnimationController#finished");
            }
        }
        // Reset input for all activities when the remote animation is finished.
        final Consumer<ActivityRecord> updateActivities =
                activity -> activity.setDropInputForAnimation(false);
        mDisplayContent.forAllActivities(updateActivities);
        setRunningRemoteAnimation(false);
        ProtoLog.i(WM_DEBUG_REMOTE_ANIMATIONS, "Finishing remote animation");
    }
@@ -303,6 +321,7 @@ class RemoteAnimationController implements DeathRecipient {
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to notify cancel", e);
        }
        mOnRemoteAnimationReady = null;
    }

    private void releaseFinishedCallback() {
Loading