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

Commit 2dd09e2c authored by Surajit Chandra's avatar Surajit Chandra Committed by Android (Google) Code Review
Browse files

Merge "Revert "Support launching an intent based drag into split"" into main

parents 082e90ea 8f92d8e0
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -101,10 +101,6 @@
    <dimen name="split_divider_bar_width">10dp</dimen>
    <dimen name="split_divider_corner_size">42dp</dimen>

    <!-- The distance from the edge of the screen to invoke splitscreen when the user is dragging
         an intent that can be launched into split. -->
    <dimen name="drag_launchable_intent_edge_margin">48dp</dimen>

    <!-- One-Handed Mode -->
    <!-- Threshold for dragging distance to enable one-handed mode -->
    <dimen name="gestures_onehanded_drag_threshold">20dp</dimen>
+5 −3
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.protolog.common.ProtoLog;
import com.android.launcher3.icons.IconProvider;
@@ -315,11 +316,12 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll
                    return false;
                }
                // TODO(b/290391688): Also update the session data with task stack changes
                pd.dragSession = new DragSession(ActivityTaskManager.getInstance(),
                InstanceId loggerSessionId = mLogger.logStart(event);
                pd.activeDragCount++;
                pd.dragSession = new DragSession(mContext, ActivityTaskManager.getInstance(),
                        mDisplayController.getDisplayLayout(displayId), event.getClipData());
                pd.dragSession.update();
                pd.activeDragCount++;
                pd.dragLayout.prepare(pd.dragSession, mLogger.logStart(pd.dragSession));
                pd.dragLayout.prepare(pd.dragSession, loggerSessionId);
                setDropTargetWindowVisibility(pd, View.VISIBLE);
                notifyListeners(l -> {
                    l.onDragStarted();
+8 −12
Original line number Diff line number Diff line
@@ -53,21 +53,17 @@ public class DragAndDropEventLogger {
    /**
     * Logs the start of a drag.
     */
    public InstanceId logStart(DragSession session) {
        mInstanceId = session.appData != null
                ? session.appData.getParcelableExtra(ClipDescription.EXTRA_LOGGING_INSTANCE_ID,
                        InstanceId.class)
                : null;
    public InstanceId logStart(DragEvent event) {
        final ClipDescription description = event.getClipDescription();
        final ClipData data = event.getClipData();
        final ClipData.Item item = data.getItemAt(0);
        mInstanceId = item.getIntent().getParcelableExtra(
                ClipDescription.EXTRA_LOGGING_INSTANCE_ID);
        if (mInstanceId == null) {
            mInstanceId = mIdSequence.newInstanceId();
        }
        mActivityInfo = session.activityInfo;
        if (session.appData != null) {
            log(getStartEnum(session.getClipDescription()), mActivityInfo);
        } else {
            // TODO(b/255649902): Update this once we have a new enum
            log(DragAndDropUiEventEnum.GLOBAL_APP_DRAG_START_ACTIVITY, mActivityInfo);
        }
        mActivityInfo = item.getActivityInfo();
        log(getStartEnum(description), mActivityInfo);
        return mInstanceId;
    }

+14 −61
Original line number Diff line number Diff line
@@ -29,8 +29,6 @@ import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.Intent.EXTRA_SHORTCUT_ID;
import static android.content.Intent.EXTRA_TASK_ID;
import static android.content.Intent.EXTRA_USER;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;

import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -54,7 +52,6 @@ import android.content.pm.LauncherApps;
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -66,10 +63,8 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R;
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;

import java.lang.annotation.Retention;
@@ -109,9 +104,7 @@ public class DragAndDropPolicy {
    void start(DragSession session, InstanceId loggerSessionId) {
        mLoggerSessionId = loggerSessionId;
        mSession = session;
        RectF disallowHitRegion = mSession.appData != null
                ? (RectF) mSession.appData.getExtra(EXTRA_DISALLOW_HIT_REGION)
                : null;
        RectF disallowHitRegion = (RectF) mSession.dragData.getExtra(EXTRA_DISALLOW_HIT_REGION);
        if (disallowHitRegion == null) {
            mDisallowHitRegion.setEmpty();
        } else {
@@ -230,7 +223,7 @@ public class DragAndDropPolicy {
    }

    @VisibleForTesting
    void handleDrop(Target target) {
    void handleDrop(Target target, ClipData data) {
        if (target == null || !mTargets.contains(target)) {
            return;
        }
@@ -245,80 +238,40 @@ public class DragAndDropPolicy {
            mSplitScreen.onDroppedToSplit(position, mLoggerSessionId);
        }

        if (mSession.appData != null) {
            launchApp(mSession, position);
        } else {
            launchIntent(mSession, position);
        }
        final ClipDescription description = data.getDescription();
        final Intent dragData = mSession.dragData;
        startClipDescription(description, dragData, position);
    }

    /**
     * Launches an app provided by SysUI.
     */
    private void launchApp(DragSession session, @SplitPosition int position) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Launching app data at position=%d",
                position);
        final ClipDescription description = session.getClipDescription();
    private void startClipDescription(ClipDescription description, Intent intent,
            @SplitPosition int position) {
        final boolean isTask = description.hasMimeType(MIMETYPE_APPLICATION_TASK);
        final boolean isShortcut = description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT);
        final ActivityOptions baseActivityOpts = ActivityOptions.makeBasic();
        baseActivityOpts.setDisallowEnterPictureInPictureWhileLaunching(true);
        final Bundle opts = baseActivityOpts.toBundle();
        if (session.appData.hasExtra(EXTRA_ACTIVITY_OPTIONS)) {
            opts.putAll(session.appData.getBundleExtra(EXTRA_ACTIVITY_OPTIONS));
        if (intent.hasExtra(EXTRA_ACTIVITY_OPTIONS)) {
            opts.putAll(intent.getBundleExtra(EXTRA_ACTIVITY_OPTIONS));
        }
        // Put BAL flags to avoid activity start aborted.
        opts.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, true);
        opts.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION, true);
        final UserHandle user = session.appData.getParcelableExtra(EXTRA_USER);
        final UserHandle user = intent.getParcelableExtra(EXTRA_USER);

        if (isTask) {
            final int taskId = session.appData.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID);
            final int taskId = intent.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID);
            mStarter.startTask(taskId, position, opts);
        } else if (isShortcut) {
            final String packageName = session.appData.getStringExtra(EXTRA_PACKAGE_NAME);
            final String id = session.appData.getStringExtra(EXTRA_SHORTCUT_ID);
            final String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
            final String id = intent.getStringExtra(EXTRA_SHORTCUT_ID);
            mStarter.startShortcut(packageName, id, position, opts, user);
        } else {
            final PendingIntent launchIntent =
                    session.appData.getParcelableExtra(EXTRA_PENDING_INTENT);
            if (Build.IS_DEBUGGABLE) {
                if (launchIntent.isImmutable()) {
                    throw new IllegalStateException("Expected immutable app pending intent from "
                            + "SysUI");
                } else if (!user.equals(launchIntent.getCreatorUserHandle())) {
                    throw new IllegalStateException("Expected app intent's EXTRA_USER to match "
                            + "pending intent user");
                }
            }
            final PendingIntent launchIntent = intent.getParcelableExtra(EXTRA_PENDING_INTENT);
            mStarter.startIntent(launchIntent, user.getIdentifier(), null /* fillIntent */,
                    position, opts);
        }
    }

    /**
     * Launches an intent sender provided by an application.
     */
    private void launchIntent(DragSession session, @SplitPosition int position) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Launching intent at position=%d",
                position);
        final ActivityOptions baseActivityOpts = ActivityOptions.makeBasic();
        baseActivityOpts.setDisallowEnterPictureInPictureWhileLaunching(true);
        // TODO(b/255649902): Rework this so that SplitScreenController can always use the options
        // instead of a fillInIntent since it's assuming that the PendingIntent is mutable
        baseActivityOpts.setPendingIntentLaunchFlags(FLAG_ACTIVITY_NEW_TASK
                | FLAG_ACTIVITY_MULTIPLE_TASK);

        final Bundle opts = baseActivityOpts.toBundle();
        // Put BAL flags to avoid activity start aborted.
        opts.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, true);
        opts.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION, true);

        mStarter.startIntent(session.launchableIntent,
                session.launchableIntent.getCreatorUserHandle().getIdentifier(),
                null /* fillIntent */, position, opts);
    }

    /**
     * Interface for actually committing the task launches.
     */
+6 −79
Original line number Diff line number Diff line
@@ -22,8 +22,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS;
import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;

import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -40,15 +38,12 @@ import android.app.ActivityManager;
import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.view.DragEvent;
import android.view.SurfaceControl;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.WindowInsets.Type;
import android.widget.LinearLayout;
@@ -70,8 +65,7 @@ import java.util.ArrayList;
/**
 * Coordinates the visible drop targets for the current drag within a single display.
 */
public class DragLayout extends LinearLayout
        implements ViewTreeObserver.OnComputeInternalInsetsListener {
public class DragLayout extends LinearLayout {

    // While dragging the status bar is hidden.
    private static final int HIDE_STATUS_BAR_FLAGS = StatusBarManager.DISABLE_NOTIFICATION_ICONS
@@ -96,9 +90,7 @@ public class DragLayout extends LinearLayout

    private int mDisplayMargin;
    private int mDividerSize;
    private int mLaunchIntentEdgeMargin;
    private Insets mInsets = Insets.NONE;
    private Region mTouchableRegion;

    private boolean mIsShowing;
    private boolean mHasDropped;
@@ -114,11 +106,10 @@ public class DragLayout extends LinearLayout
        mStatusBarManager = context.getSystemService(StatusBarManager.class);
        mLastConfiguration.setTo(context.getResources().getConfiguration());

        final Resources res = context.getResources();
        mDisplayMargin = res.getDimensionPixelSize(R.dimen.drop_layout_display_margin);
        mDividerSize = res.getDimensionPixelSize(R.dimen.split_divider_bar_width);
        mLaunchIntentEdgeMargin =
                res.getDimensionPixelSize(R.dimen.drag_launchable_intent_edge_margin);
        mDisplayMargin = context.getResources().getDimensionPixelSize(
                R.dimen.drop_layout_display_margin);
        mDividerSize = context.getResources().getDimensionPixelSize(
                R.dimen.split_divider_bar_width);

        // Always use LTR because we assume dropZoneView1 is on the left and 2 is on the right when
        // showing the highlight.
@@ -139,66 +130,6 @@ public class DragLayout extends LinearLayout
        updateContainerMargins(mIsLeftRightSplit);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mTouchableRegion = Region.obtain();
        getViewTreeObserver().addOnComputeInternalInsetsListener(this);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
        mTouchableRegion.recycle();
    }

    @Override
    public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inOutInfo) {
        if (mSession != null && mSession.launchableIntent != null) {
            inOutInfo.touchableRegion.set(mTouchableRegion);
            inOutInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        updateTouchableRegion();
    }

    /**
     * Updates the touchable region, this should be called after any configuration changes have
     * been applied.
     */
    private void updateTouchableRegion() {
        mTouchableRegion.setEmpty();
        if (mSession != null && mSession.launchableIntent != null) {
            final int width = getMeasuredWidth();
            final int height = getMeasuredHeight();
            if (mIsLeftRightSplit) {
                mTouchableRegion.union(
                        new Rect(0, 0, mInsets.left + mLaunchIntentEdgeMargin, height));
                mTouchableRegion.union(
                        new Rect(width - mInsets.right - mLaunchIntentEdgeMargin, 0, width,
                                height));
            } else {
                mTouchableRegion.union(
                        new Rect(0, 0, width, mInsets.top + mLaunchIntentEdgeMargin));
                mTouchableRegion.union(
                        new Rect(0, height - mInsets.bottom - mLaunchIntentEdgeMargin, width,
                                height));
            }
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP,
                    "Updating drag layout width=%d height=%d touchable region=%s",
                    width, height, mTouchableRegion);

            // Reapply insets to update the touchable region
            requestApplyInsets();
        }
    }


    @Override
    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
        mInsets = insets.getInsets(Type.tappableElement() | Type.displayCutout());
@@ -233,7 +164,6 @@ public class DragLayout extends LinearLayout
            mDropZoneView2.onThemeChange();
        }
        mLastConfiguration.setTo(newConfig);
        requestLayout();
    }

    private void updateContainerMarginsForSingleTask() {
@@ -312,7 +242,6 @@ public class DragLayout extends LinearLayout
            mSplitScreenController.getStageBounds(topOrLeftBounds, bottomOrRightBounds);
            updateDropZoneSizes(topOrLeftBounds, bottomOrRightBounds);
        }
        requestLayout();
    }

    private void updateDropZoneSizesForSingleTask() {
@@ -463,7 +392,7 @@ public class DragLayout extends LinearLayout
        mHasDropped = true;

        // Process the drop
        mPolicy.handleDrop(mCurrentTarget);
        mPolicy.handleDrop(mCurrentTarget, event.getClipData());

        // Start animating the drop UI out with the drag surface
        hide(event, dropCompleteCallback);
@@ -576,7 +505,5 @@ public class DragLayout extends LinearLayout
        pw.println(innerPrefix + "mIsShowing=" + mIsShowing);
        pw.println(innerPrefix + "mHasDropped=" + mHasDropped);
        pw.println(innerPrefix + "mCurrentTarget=" + mCurrentTarget);
        pw.println(innerPrefix + "mInsets=" + mInsets);
        pw.println(innerPrefix + "mTouchableRegion=" + mTouchableRegion);
    }
}
Loading