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

Commit 7590443d authored by Jiaming Liu's avatar Jiaming Liu Committed by Android (Google) Code Review
Browse files

Merge "Enforce cross-uid touch pass-though opt-in" into main

parents 01f7df4f e5a39510
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4919,6 +4919,7 @@ package android.app {
    method public int getPendingIntentBackgroundActivityStartMode();
    method public int getPendingIntentCreatorBackgroundActivityStartMode();
    method public int getSplashScreenStyle();
    method @FlaggedApi("com.android.window.flags.touch_pass_through_opt_in") public boolean isAllowPassThroughOnTouchOutside();
    method @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed();
    method public boolean isShareIdentityEnabled();
    method public static android.app.ActivityOptions makeBasic();
@@ -4932,6 +4933,7 @@ package android.app {
    method public static android.app.ActivityOptions makeTaskLaunchBehind();
    method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
    method public void requestUsageTimeReport(android.app.PendingIntent);
    method @FlaggedApi("com.android.window.flags.touch_pass_through_opt_in") public void setAllowPassThroughOnTouchOutside(boolean);
    method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle);
    method public android.app.ActivityOptions setLaunchBounds(@Nullable android.graphics.Rect);
    method public android.app.ActivityOptions setLaunchDisplayId(int);
+44 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
import static android.view.Display.INVALID_DISPLAY;
import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -453,6 +454,10 @@ public class ActivityOptions extends ComponentOptions {
    private static final String KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE =
            "android.activity.pendingIntentCreatorBackgroundActivityStartMode";

    /** See {@link #setAllowPassThroughOnTouchOutside(boolean)}. */
    private static final String KEY_ALLOW_PASS_THROUGH_ON_TOUCH_OUTSIDE =
            "android.activity.allowPassThroughOnTouchOutside";

    /**
     * @see #setLaunchCookie
     * @hide
@@ -554,6 +559,7 @@ public class ActivityOptions extends ComponentOptions {
    private int mPendingIntentCreatorBackgroundActivityStartMode =
            MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
    private boolean mDisableStartingWindow;
    private boolean mAllowPassThroughOnTouchOutside;

    /**
     * Create an ActivityOptions specifying a custom animation to run when
@@ -1416,6 +1422,7 @@ public class ActivityOptions extends ComponentOptions {
                KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE,
                MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED);
        mDisableStartingWindow = opts.getBoolean(KEY_DISABLE_STARTING_WINDOW);
        mAllowPassThroughOnTouchOutside = opts.getBoolean(KEY_ALLOW_PASS_THROUGH_ON_TOUCH_OUTSIDE);
        mAnimationAbortListener = IRemoteCallback.Stub.asInterface(
                opts.getBinder(KEY_ANIM_ABORT_LISTENER));
    }
@@ -1839,6 +1846,39 @@ public class ActivityOptions extends ComponentOptions {
                && mLaunchIntoPipParams.isLaunchIntoPip();
    }

    /**
     * Returns whether the source activity allows the overlaying activities from the to-be-launched
     * app to pass through touch events to it when touches fall outside the content window.
     *
     * @see #setAllowPassThroughOnTouchOutside(boolean)
     */
    @FlaggedApi(com.android.window.flags.Flags.FLAG_TOUCH_PASS_THROUGH_OPT_IN)
    public boolean isAllowPassThroughOnTouchOutside() {
        return mAllowPassThroughOnTouchOutside;
    }

    /**
     * Sets whether the source activity allows the overlaying activities from the to-be-launched
     * app to pass through touch events to it when touches fall outside the content window.
     *
     * <p> By default, touches that fall on a translucent non-touchable area of an overlaying
     * activity window are blocked from passing through to the activity below (source activity),
     * unless the overlaying activity is from the same UID as the source activity. The source
     * activity may use this method to opt in and allow the overlaying activities from the
     * to-be-launched app to pass through touches to itself. The source activity needs to ensure
     * that it trusts the overlaying activity and its content is not vulnerable to UI redressing
     * attacks. The flag is ignored if the context calling
     * {@link Context#startActivity(Intent, Bundle)} is not an activity.
     *
     * <p> For backward compatibility, apps with target SDK 35 and below may still receive
     * pass-through touches without opt-in if the cross-uid activity is launched by the source
     * activity.
     */
    @FlaggedApi(com.android.window.flags.Flags.FLAG_TOUCH_PASS_THROUGH_OPT_IN)
    public void setAllowPassThroughOnTouchOutside(boolean allowed) {
        mAllowPassThroughOnTouchOutside = allowed;
    }

    /** @hide */
    public int getLaunchActivityType() {
        return mLaunchActivityType;
@@ -2520,6 +2560,10 @@ public class ActivityOptions extends ComponentOptions {
        if (mDisableStartingWindow) {
            b.putBoolean(KEY_DISABLE_STARTING_WINDOW, mDisableStartingWindow);
        }
        if (mAllowPassThroughOnTouchOutside) {
            b.putBoolean(KEY_ALLOW_PASS_THROUGH_ON_TOUCH_OUTSIDE,
                    mAllowPassThroughOnTouchOutside);
        }
        b.putBinder(KEY_ANIM_ABORT_LISTENER,
                mAnimationAbortListener != null ? mAnimationAbortListener.asBinder() : null);
        return b;
+4 −1
Original line number Diff line number Diff line
@@ -2154,7 +2154,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
        mAtmService.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, packageName);

        mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord);
        final boolean appOptInTouchPassThrough =
                options != null && options.isAllowPassThroughOnTouchOutside();
        mActivityRecordInputSink = new ActivityRecordInputSink(
                this, sourceRecord, appOptInTouchPassThrough);

        mAppActivityEmbeddingSplitsEnabled = isAppActivityEmbeddingSplitsEnabled();
        mAllowUntrustedEmbeddingStateSharing = getAllowUntrustedEmbeddingStateSharingProperty();
+33 −2
Original line number Diff line number Diff line
@@ -16,13 +16,18 @@

package com.android.server.wm;

import android.app.ActivityOptions;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.os.Build;
import android.os.InputConfig;
import android.view.InputWindowHandle;
import android.view.SurfaceControl;
import android.view.WindowManager;

import com.android.window.flags.Flags;

/**
 * Creates a InputWindowHandle that catches all touches that would otherwise pass through an
 * Activity.
@@ -35,6 +40,21 @@ class ActivityRecordInputSink {
    @ChangeId
    static final long ENABLE_TOUCH_OPAQUE_ACTIVITIES = 194480991L;

    // TODO(b/369605358) Update EnabledSince when SDK 36 version code is available.
    /**
     * If the app's target SDK is 36+, pass-through touches from a cross-uid overlaying activity is
     * blocked by default. The activity may opt in to receive pass-through touches using
     * {@link ActivityOptions#setAllowPassThroughOnTouchOutside}, which allows the to-be-launched
     * cross-uid overlaying activity and other activities in that app to pass through touches. The
     * activity needs to ensure that it trusts the overlaying app and its content is not vulnerable
     * to UI redressing attacks.
     *
     * @see ActivityOptions#setAllowPassThroughOnTouchOutside
     */
    @ChangeId
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT)
    static final long ENABLE_OVERLAY_TOUCH_PASS_THROUGH_OPT_IN_ENFORCEMENT = 358129114L;

    private final ActivityRecord mActivityRecord;
    private final boolean mIsCompatEnabled;
    private final String mName;
@@ -42,13 +62,24 @@ class ActivityRecordInputSink {
    private InputWindowHandleWrapper mInputWindowHandleWrapper;
    private SurfaceControl mSurfaceControl;

    ActivityRecordInputSink(ActivityRecord activityRecord, ActivityRecord sourceRecord) {
    ActivityRecordInputSink(ActivityRecord activityRecord, ActivityRecord sourceRecord,
            boolean appOptInTouchPassThrough) {
        mActivityRecord = activityRecord;
        mIsCompatEnabled = CompatChanges.isChangeEnabled(ENABLE_TOUCH_OPAQUE_ACTIVITIES,
                mActivityRecord.getUid());
        mName = Integer.toHexString(System.identityHashCode(this)) + " ActivityRecordInputSink "
                + mActivityRecord.mActivityComponent.flattenToShortString();
        if (sourceRecord != null) {

        if (sourceRecord == null) {
            return;
        }
        // If the source activity has target sdk 36+, it is required to opt in to receive
        // pass-through touches from the overlaying activity.
        final boolean isTouchPassThroughOptInEnforced = CompatChanges.isChangeEnabled(
                ENABLE_OVERLAY_TOUCH_PASS_THROUGH_OPT_IN_ENFORCEMENT,
                sourceRecord.getUid());
        if (!Flags.touchPassThroughOptIn() || !isTouchPassThroughOptInEnforced
                || appOptInTouchPassThrough) {
            sourceRecord.mAllowedTouchUid = mActivityRecord.getUid();
        }
    }
+2 −0
Original line number Diff line number Diff line
@@ -308,6 +308,8 @@ public class ActivityOptionsTest {
                    // KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE
                case "android.activity.launchCookie": // KEY_LAUNCH_COOKIE
                case "android:activity.animAbortListener": // KEY_ANIM_ABORT_LISTENER
                case "android.activity.allowPassThroughOnTouchOutside":
                    // KEY_ALLOW_PASS_THROUGH_ON_TOUCH_OUTSIDE
                    // Existing keys

                    break;