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

Commit 11a8f995 authored by Winson Chung's avatar Winson Chung
Browse files

Disallow drag to split depending on drag flag

- Propagate the drag flags used when starting the drag to the
  privileged drop target window so it can verify that
  DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG is specified
  before handling the drag to invoke split from a drag with a
  launch intent.

Fixes: 334934117
Test: atest DragDropControllerTests
Test: atest DragAndDropPolicyTest
Change-Id: I21f7ddf342f9db44676431accdacc2d5b6b871cd
parent 9eff245e
Loading
Loading
Loading
Loading
+22 −7
Original line number Diff line number Diff line
@@ -156,6 +156,13 @@ public class DragEvent implements Parcelable {
    private float mOffsetX;
    private float mOffsetY;

    /**
     * The View#DRAG_FLAG_* flags used to start the current drag, only provided if the target window
     * has the {@link WindowManager.LayoutParams#PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP} flag
     * and is only sent with {@link #ACTION_DRAG_STARTED} and {@link #ACTION_DROP}.
     */
    private int mFlags;

    private DragEvent mNext;
    private RuntimeException mRecycledLocation;
    private boolean mRecycled;
@@ -290,7 +297,7 @@ public class DragEvent implements Parcelable {
    private DragEvent() {
    }

    private void init(int action, float x, float y, float offsetX, float offsetY,
    private void init(int action, float x, float y, float offsetX, float offsetY, int flags,
            ClipDescription description, ClipData data, SurfaceControl dragSurface,
            IDragAndDropPermissions dragAndDropPermissions, Object localState, boolean result) {
        mAction = action;
@@ -298,6 +305,7 @@ public class DragEvent implements Parcelable {
        mY = y;
        mOffsetX = offsetX;
        mOffsetY = offsetY;
        mFlags = flags;
        mClipDescription = description;
        mClipData = data;
        mDragSurface = dragSurface;
@@ -307,19 +315,19 @@ public class DragEvent implements Parcelable {
    }

    static DragEvent obtain() {
        return DragEvent.obtain(0, 0f, 0f, 0f, 0f, null, null, null, null, null, false);
        return DragEvent.obtain(0, 0f, 0f, 0f, 0f, 0, null, null, null, null, null, false);
    }

    /** @hide */
    public static DragEvent obtain(int action, float x, float y, float offsetX, float offsetY,
            Object localState, ClipDescription description, ClipData data,
            int flags, Object localState, ClipDescription description, ClipData data,
            SurfaceControl dragSurface, IDragAndDropPermissions dragAndDropPermissions,
            boolean result) {
        final DragEvent ev;
        synchronized (gRecyclerLock) {
            if (gRecyclerTop == null) {
                ev = new DragEvent();
                ev.init(action, x, y, offsetX, offsetY, description, data, dragSurface,
                ev.init(action, x, y, offsetX, offsetY, flags, description, data, dragSurface,
                        dragAndDropPermissions, localState, result);
                return ev;
            }
@@ -331,7 +339,7 @@ public class DragEvent implements Parcelable {
        ev.mRecycled = false;
        ev.mNext = null;

        ev.init(action, x, y, offsetX, offsetY, description, data, dragSurface,
        ev.init(action, x, y, offsetX, offsetY, flags, description, data, dragSurface,
                dragAndDropPermissions, localState, result);

        return ev;
@@ -341,8 +349,8 @@ public class DragEvent implements Parcelable {
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static DragEvent obtain(DragEvent source) {
        return obtain(source.mAction, source.mX, source.mY, source.mOffsetX, source.mOffsetY,
                source.mLocalState, source.mClipDescription, source.mClipData, source.mDragSurface,
                source.mDragAndDropPermissions, source.mDragResult);
                source.mFlags, source.mLocalState, source.mClipDescription, source.mClipData,
                source.mDragSurface, source.mDragAndDropPermissions, source.mDragResult);
    }

    /**
@@ -423,6 +431,11 @@ public class DragEvent implements Parcelable {
        return mDragSurface;
    }

    /** @hide */
    public int getDragFlags() {
        return mFlags;
    }

    /** @hide */
    public IDragAndDropPermissions getDragAndDropPermissions() {
        return mDragAndDropPermissions;
@@ -571,6 +584,7 @@ public class DragEvent implements Parcelable {
        dest.writeFloat(mY);
        dest.writeFloat(mOffsetX);
        dest.writeFloat(mOffsetY);
        dest.writeInt(mFlags);
        dest.writeInt(mDragResult ? 1 : 0);
        if (mClipData == null) {
            dest.writeInt(0);
@@ -610,6 +624,7 @@ public class DragEvent implements Parcelable {
            event.mY = in.readFloat();
            event.mOffsetX = in.readFloat();
            event.mOffsetY = in.readFloat();
            event.mFlags = in.readInt();
            event.mDragResult = (in.readInt() != 0);
            if (in.readInt() != 0) {
                event.mClipData = ClipData.CREATOR.createFromParcel(in);
+1 −1
Original line number Diff line number Diff line
@@ -10263,7 +10263,7 @@ public final class ViewRootImpl implements ViewParent,
            // force DRAG_EXITED_EVENT if appropriate
            DragEvent event = DragEvent.obtain(
                    isExiting ? DragEvent.ACTION_DRAG_EXITED : DragEvent.ACTION_DRAG_LOCATION,
                    x, y, 0 /* offsetX */, 0 /* offsetY */, null/* localState */,
                    x, y, 0 /* offsetX */, 0 /* offsetY */, 0 /* flags */, null/* localState */,
                    null/* description */, null /* data */, null /* dragSurface */,
                    null /* dragAndDropPermissions */, false /* result */);
            dispatchDragEvent(event);
+2 −1
Original line number Diff line number Diff line
@@ -316,7 +316,8 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll
                }
                // TODO(b/290391688): Also update the session data with task stack changes
                pd.dragSession = new DragSession(ActivityTaskManager.getInstance(),
                        mDisplayController.getDisplayLayout(displayId), event.getClipData());
                        mDisplayController.getDisplayLayout(displayId), event.getClipData(),
                        event.getDragFlags());
                pd.dragSession.update();
                pd.activeDragCount++;
                pd.dragLayout.prepare(pd.dragSession, mLogger.logStart(pd.dragSession));
+4 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import java.util.List;
public class DragSession {
    private final ActivityTaskManager mActivityTaskManager;
    private final ClipData mInitialDragData;
    private final int mInitialDragFlags;

    final DisplayLayout displayLayout;
    // The activity info associated with the activity in the appData or the launchableIntent
@@ -62,9 +63,10 @@ public class DragSession {
    boolean dragItemSupportsSplitscreen;

    DragSession(ActivityTaskManager activityTaskManager,
            DisplayLayout dispLayout, ClipData data) {
            DisplayLayout dispLayout, ClipData data, int dragFlags) {
        mActivityTaskManager = activityTaskManager;
        mInitialDragData = data;
        mInitialDragFlags = dragFlags;
        displayLayout = dispLayout;
    }

@@ -94,6 +96,6 @@ public class DragSession {
        dragItemSupportsSplitscreen = activityInfo == null
                || ActivityInfo.isResizeableMode(activityInfo.resizeMode);
        appData = mInitialDragData.getItemAt(0).getIntent();
        launchableIntent = DragUtils.getLaunchIntent(mInitialDragData);
        launchableIntent = DragUtils.getLaunchIntent(mInitialDragData, mInitialDragFlags);
    }
}
+7 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipDescription;
import android.view.DragEvent;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -67,14 +68,18 @@ public class DragUtils {
     */
    @Nullable
    public static PendingIntent getLaunchIntent(@NonNull DragEvent dragEvent) {
        return getLaunchIntent(dragEvent.getClipData());
        return getLaunchIntent(dragEvent.getClipData(), dragEvent.getDragFlags());
    }

    /**
     * Returns a launchable intent in the given `ClipData` or `null` if there is none.
     */
    @Nullable
    public static PendingIntent getLaunchIntent(@NonNull ClipData data) {
    public static PendingIntent getLaunchIntent(@NonNull ClipData data, int dragFlags) {
        if ((dragFlags & View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG) == 0) {
            // Disallow launching the intent if the app does not want to delegate it to the system
            return null;
        }
        for (int i = 0; i < data.getItemCount(); i++) {
            final ClipData.Item item = data.getItemAt(i);
            if (item.getIntentSender() != null) {
Loading