Loading libs/WindowManager/Shell/res/values/dimen.xml +4 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,10 @@ <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> Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +3 −5 Original line number Diff line number Diff line Loading @@ -59,7 +59,6 @@ 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; Loading Loading @@ -316,12 +315,11 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll return false; } // TODO(b/290391688): Also update the session data with task stack changes InstanceId loggerSessionId = mLogger.logStart(event); pd.activeDragCount++; pd.dragSession = new DragSession(mContext, ActivityTaskManager.getInstance(), pd.dragSession = new DragSession(ActivityTaskManager.getInstance(), mDisplayController.getDisplayLayout(displayId), event.getClipData()); pd.dragSession.update(); pd.dragLayout.prepare(pd.dragSession, loggerSessionId); pd.activeDragCount++; pd.dragLayout.prepare(pd.dragSession, mLogger.logStart(pd.dragSession)); setDropTargetWindowVisibility(pd, View.VISIBLE); notifyListeners(l -> { l.onDragStarted(); Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java +12 −8 Original line number Diff line number Diff line Loading @@ -53,17 +53,21 @@ public class DragAndDropEventLogger { /** * Logs the start of a drag. */ 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); public InstanceId logStart(DragSession session) { mInstanceId = session.appData != null ? session.appData.getParcelableExtra(ClipDescription.EXTRA_LOGGING_INSTANCE_ID, InstanceId.class) : null; if (mInstanceId == null) { mInstanceId = mIdSequence.newInstanceId(); } mActivityInfo = item.getActivityInfo(); log(getStartEnum(description), mActivityInfo); 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); } return mInstanceId; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +58 −14 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ 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; Loading @@ -52,9 +54,11 @@ 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; import android.util.Log; import android.util.Slog; import androidx.annotation.IntDef; Loading @@ -63,8 +67,10 @@ 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; Loading Loading @@ -104,7 +110,9 @@ public class DragAndDropPolicy { void start(DragSession session, InstanceId loggerSessionId) { mLoggerSessionId = loggerSessionId; mSession = session; RectF disallowHitRegion = (RectF) mSession.dragData.getExtra(EXTRA_DISALLOW_HIT_REGION); RectF disallowHitRegion = mSession.appData != null ? (RectF) mSession.appData.getExtra(EXTRA_DISALLOW_HIT_REGION) : null; if (disallowHitRegion == null) { mDisallowHitRegion.setEmpty(); } else { Loading Loading @@ -223,7 +231,7 @@ public class DragAndDropPolicy { } @VisibleForTesting void handleDrop(Target target, ClipData data) { void handleDrop(Target target) { if (target == null || !mTargets.contains(target)) { return; } Loading @@ -238,40 +246,76 @@ public class DragAndDropPolicy { mSplitScreen.onDroppedToSplit(position, mLoggerSessionId); } final ClipDescription description = data.getDescription(); final Intent dragData = mSession.dragData; startClipDescription(description, dragData, position); if (mSession.appData != null) { launchApp(mSession, position); } else { launchIntent(mSession, position); } } private void startClipDescription(ClipDescription description, Intent intent, @SplitPosition int 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(); 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 (intent.hasExtra(EXTRA_ACTIVITY_OPTIONS)) { opts.putAll(intent.getBundleExtra(EXTRA_ACTIVITY_OPTIONS)); if (session.appData.hasExtra(EXTRA_ACTIVITY_OPTIONS)) { opts.putAll(session.appData.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 = intent.getParcelableExtra(EXTRA_USER); final UserHandle user = session.appData.getParcelableExtra(EXTRA_USER); if (isTask) { final int taskId = intent.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID); final int taskId = session.appData.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID); mStarter.startTask(taskId, position, opts); } else if (isShortcut) { final String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME); final String id = intent.getStringExtra(EXTRA_SHORTCUT_ID); final String packageName = session.appData.getStringExtra(EXTRA_PACKAGE_NAME); final String id = session.appData.getStringExtra(EXTRA_SHORTCUT_ID); mStarter.startShortcut(packageName, id, position, opts, user); } else { final PendingIntent launchIntent = intent.getParcelableExtra(EXTRA_PENDING_INTENT); final PendingIntent launchIntent = session.appData.getParcelableExtra(EXTRA_PENDING_INTENT); if (Build.IS_DEBUGGABLE) { if (!user.equals(launchIntent.getCreatorUserHandle())) { Log.e(TAG, "Expected app intent's EXTRA_USER to match pending intent user"); } } 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. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +79 −6 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ 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; Loading @@ -38,12 +40,15 @@ 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; Loading @@ -65,7 +70,8 @@ import java.util.ArrayList; /** * Coordinates the visible drop targets for the current drag within a single display. */ public class DragLayout extends LinearLayout { public class DragLayout extends LinearLayout implements ViewTreeObserver.OnComputeInternalInsetsListener { // While dragging the status bar is hidden. private static final int HIDE_STATUS_BAR_FLAGS = StatusBarManager.DISABLE_NOTIFICATION_ICONS Loading @@ -90,7 +96,9 @@ 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; Loading @@ -106,10 +114,11 @@ public class DragLayout extends LinearLayout { mStatusBarManager = context.getSystemService(StatusBarManager.class); mLastConfiguration.setTo(context.getResources().getConfiguration()); mDisplayMargin = context.getResources().getDimensionPixelSize( R.dimen.drop_layout_display_margin); mDividerSize = context.getResources().getDimensionPixelSize( R.dimen.split_divider_bar_width); 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); // Always use LTR because we assume dropZoneView1 is on the left and 2 is on the right when // showing the highlight. Loading @@ -130,6 +139,66 @@ 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()); Loading Loading @@ -164,6 +233,7 @@ public class DragLayout extends LinearLayout { mDropZoneView2.onThemeChange(); } mLastConfiguration.setTo(newConfig); requestLayout(); } private void updateContainerMarginsForSingleTask() { Loading Loading @@ -242,6 +312,7 @@ public class DragLayout extends LinearLayout { mSplitScreenController.getStageBounds(topOrLeftBounds, bottomOrRightBounds); updateDropZoneSizes(topOrLeftBounds, bottomOrRightBounds); } requestLayout(); } private void updateDropZoneSizesForSingleTask() { Loading Loading @@ -392,7 +463,7 @@ public class DragLayout extends LinearLayout { mHasDropped = true; // Process the drop mPolicy.handleDrop(mCurrentTarget, event.getClipData()); mPolicy.handleDrop(mCurrentTarget); // Start animating the drop UI out with the drag surface hide(event, dropCompleteCallback); Loading Loading @@ -505,5 +576,7 @@ 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
libs/WindowManager/Shell/res/values/dimen.xml +4 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,10 @@ <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> Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +3 −5 Original line number Diff line number Diff line Loading @@ -59,7 +59,6 @@ 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; Loading Loading @@ -316,12 +315,11 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll return false; } // TODO(b/290391688): Also update the session data with task stack changes InstanceId loggerSessionId = mLogger.logStart(event); pd.activeDragCount++; pd.dragSession = new DragSession(mContext, ActivityTaskManager.getInstance(), pd.dragSession = new DragSession(ActivityTaskManager.getInstance(), mDisplayController.getDisplayLayout(displayId), event.getClipData()); pd.dragSession.update(); pd.dragLayout.prepare(pd.dragSession, loggerSessionId); pd.activeDragCount++; pd.dragLayout.prepare(pd.dragSession, mLogger.logStart(pd.dragSession)); setDropTargetWindowVisibility(pd, View.VISIBLE); notifyListeners(l -> { l.onDragStarted(); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java +12 −8 Original line number Diff line number Diff line Loading @@ -53,17 +53,21 @@ public class DragAndDropEventLogger { /** * Logs the start of a drag. */ 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); public InstanceId logStart(DragSession session) { mInstanceId = session.appData != null ? session.appData.getParcelableExtra(ClipDescription.EXTRA_LOGGING_INSTANCE_ID, InstanceId.class) : null; if (mInstanceId == null) { mInstanceId = mIdSequence.newInstanceId(); } mActivityInfo = item.getActivityInfo(); log(getStartEnum(description), mActivityInfo); 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); } return mInstanceId; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +58 −14 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ 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; Loading @@ -52,9 +54,11 @@ 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; import android.util.Log; import android.util.Slog; import androidx.annotation.IntDef; Loading @@ -63,8 +67,10 @@ 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; Loading Loading @@ -104,7 +110,9 @@ public class DragAndDropPolicy { void start(DragSession session, InstanceId loggerSessionId) { mLoggerSessionId = loggerSessionId; mSession = session; RectF disallowHitRegion = (RectF) mSession.dragData.getExtra(EXTRA_DISALLOW_HIT_REGION); RectF disallowHitRegion = mSession.appData != null ? (RectF) mSession.appData.getExtra(EXTRA_DISALLOW_HIT_REGION) : null; if (disallowHitRegion == null) { mDisallowHitRegion.setEmpty(); } else { Loading Loading @@ -223,7 +231,7 @@ public class DragAndDropPolicy { } @VisibleForTesting void handleDrop(Target target, ClipData data) { void handleDrop(Target target) { if (target == null || !mTargets.contains(target)) { return; } Loading @@ -238,40 +246,76 @@ public class DragAndDropPolicy { mSplitScreen.onDroppedToSplit(position, mLoggerSessionId); } final ClipDescription description = data.getDescription(); final Intent dragData = mSession.dragData; startClipDescription(description, dragData, position); if (mSession.appData != null) { launchApp(mSession, position); } else { launchIntent(mSession, position); } } private void startClipDescription(ClipDescription description, Intent intent, @SplitPosition int 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(); 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 (intent.hasExtra(EXTRA_ACTIVITY_OPTIONS)) { opts.putAll(intent.getBundleExtra(EXTRA_ACTIVITY_OPTIONS)); if (session.appData.hasExtra(EXTRA_ACTIVITY_OPTIONS)) { opts.putAll(session.appData.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 = intent.getParcelableExtra(EXTRA_USER); final UserHandle user = session.appData.getParcelableExtra(EXTRA_USER); if (isTask) { final int taskId = intent.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID); final int taskId = session.appData.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID); mStarter.startTask(taskId, position, opts); } else if (isShortcut) { final String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME); final String id = intent.getStringExtra(EXTRA_SHORTCUT_ID); final String packageName = session.appData.getStringExtra(EXTRA_PACKAGE_NAME); final String id = session.appData.getStringExtra(EXTRA_SHORTCUT_ID); mStarter.startShortcut(packageName, id, position, opts, user); } else { final PendingIntent launchIntent = intent.getParcelableExtra(EXTRA_PENDING_INTENT); final PendingIntent launchIntent = session.appData.getParcelableExtra(EXTRA_PENDING_INTENT); if (Build.IS_DEBUGGABLE) { if (!user.equals(launchIntent.getCreatorUserHandle())) { Log.e(TAG, "Expected app intent's EXTRA_USER to match pending intent user"); } } 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. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +79 −6 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ 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; Loading @@ -38,12 +40,15 @@ 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; Loading @@ -65,7 +70,8 @@ import java.util.ArrayList; /** * Coordinates the visible drop targets for the current drag within a single display. */ public class DragLayout extends LinearLayout { public class DragLayout extends LinearLayout implements ViewTreeObserver.OnComputeInternalInsetsListener { // While dragging the status bar is hidden. private static final int HIDE_STATUS_BAR_FLAGS = StatusBarManager.DISABLE_NOTIFICATION_ICONS Loading @@ -90,7 +96,9 @@ 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; Loading @@ -106,10 +114,11 @@ public class DragLayout extends LinearLayout { mStatusBarManager = context.getSystemService(StatusBarManager.class); mLastConfiguration.setTo(context.getResources().getConfiguration()); mDisplayMargin = context.getResources().getDimensionPixelSize( R.dimen.drop_layout_display_margin); mDividerSize = context.getResources().getDimensionPixelSize( R.dimen.split_divider_bar_width); 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); // Always use LTR because we assume dropZoneView1 is on the left and 2 is on the right when // showing the highlight. Loading @@ -130,6 +139,66 @@ 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()); Loading Loading @@ -164,6 +233,7 @@ public class DragLayout extends LinearLayout { mDropZoneView2.onThemeChange(); } mLastConfiguration.setTo(newConfig); requestLayout(); } private void updateContainerMarginsForSingleTask() { Loading Loading @@ -242,6 +312,7 @@ public class DragLayout extends LinearLayout { mSplitScreenController.getStageBounds(topOrLeftBounds, bottomOrRightBounds); updateDropZoneSizes(topOrLeftBounds, bottomOrRightBounds); } requestLayout(); } private void updateDropZoneSizesForSingleTask() { Loading Loading @@ -392,7 +463,7 @@ public class DragLayout extends LinearLayout { mHasDropped = true; // Process the drop mPolicy.handleDrop(mCurrentTarget, event.getClipData()); mPolicy.handleDrop(mCurrentTarget); // Start animating the drop UI out with the drag surface hide(event, dropCompleteCallback); Loading Loading @@ -505,5 +576,7 @@ 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); } }