summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Winson Chung <winsonc@google.com> 2020-11-05 15:57:36 -0800
committer Winson Chung <winsonc@google.com> 2020-11-10 05:46:24 +0000
commit6dd73e98d77af599253ae26a2076abceaa44a78c (patch)
tree3cd64ce47cc42c6bbf65bffbdb3c9acbd2aabc7d
parente3d75ac262f7a101f56df08c2fb7ea0077fd42f9 (diff)
6/ Fix some flakey issues with dragging to split
- Ensure that the task info activity type always matches the actual task activity type (can be different than the window configuration type) - Ensure that the targets hit rects respect the insets, and that dragging out of all targets (but still within the window) will hide the last target - Work around race with launching secondary task when splitting, wait until the split screen task org has moved existing tasks to secondary split root before starting the new task, and also update the home task position when going home (b/172686383) - Add a timeout to clean up drag surfaces if SysUI crashes while mid-drag - Clean up some other calls to get activity type/win mode Bug: 169894807 Test: atest DragDropControllerTests Test: atest DragAndDropPolicyTest Test: atest SplitScreenTests Change-Id: I7ae11cc38b1e927d955798ef1056e17c9e435758
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java59
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java7
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java10
-rw-r--r--services/core/java/com/android/server/wm/DragDropController.java9
-rw-r--r--services/core/java/com/android/server/wm/DragState.java5
-rw-r--r--services/core/java/com/android/server/wm/Task.java4
13 files changed, 124 insertions, 46 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 51ddb17daa00..2d20feeb0832 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -346,15 +346,9 @@ public class ShellTaskOrganizer extends TaskOrganizer {
return mTaskListeners.get(taskListenerType);
}
- @WindowingMode
- public static int getWindowingMode(RunningTaskInfo taskInfo) {
- return taskInfo.configuration.windowConfiguration.getWindowingMode();
- }
-
@VisibleForTesting
static @TaskListenerType int taskInfoToTaskListenerType(RunningTaskInfo runningTaskInfo) {
- final int windowingMode = getWindowingMode(runningTaskInfo);
- switch (windowingMode) {
+ switch (runningTaskInfo.getWindowingMode()) {
case WINDOWING_MODE_FULLSCREEN:
return runningTaskInfo.letterboxActivityBounds != null
? TASK_LISTENER_TYPE_LETTERBOX
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index 25890bc31b3c..8a547b4477fd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -18,6 +18,7 @@ package com.android.wm.shell.draganddrop;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.ClipDescription.EXTRA_ACTIVITY_OPTIONS;
@@ -67,6 +68,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Consumer;
/**
* The policy for handling drag and drop operations to shell.
@@ -133,20 +135,20 @@ public class DragAndDropPolicy {
// TODO(b/169894807): For now, only allow splitting to the right/bottom until we
// have split pairs
mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(0, 0, w, h / 2),
+ new Rect(l, t, l + iw, t + ih / 2),
new Rect(l, t, l + iw, t + ih),
new Rect(0, 0, w, h)));
mTargets.add(new Target(TYPE_SPLIT_BOTTOM,
- new Rect(0, h / 2, w, h),
+ new Rect(l, t + ih / 2, l + iw, t + ih),
new Rect(l, t + ih / 2, l + iw, t + ih),
new Rect(0, h / 2, w, h)));
} else {
mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(0, 0, w / 2, h),
+ new Rect(l, t, l + iw / 2, t + ih),
new Rect(l, t, l + iw, t + ih),
new Rect(0, 0, w, h)));
mTargets.add(new Target(TYPE_SPLIT_RIGHT,
- new Rect(w / 2, 0, w, h),
+ new Rect(l + iw / 2, t, l + iw, t + ih),
new Rect(l + iw / 2, t, l + iw, t + ih),
new Rect(w / 2, 0, w, h)));
}
@@ -162,12 +164,12 @@ public class DragAndDropPolicy {
secondarySplitBounds.intersect(new Rect(l, t, l + iw, t + ih));
if (isVerticalSplit) {
mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(0, 0, w, secondarySplitRawBounds.top),
+ new Rect(l, t, l + iw, secondarySplitRawBounds.top),
new Rect(l, t, l + iw, t + ih),
new Rect(0, 0, w, secondarySplitRawBounds.top)));
} else {
mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(0, 0, secondarySplitRawBounds.left, h),
+ new Rect(l, t, secondarySplitRawBounds.left, t + ih),
new Rect(l, t, l + iw, t + ih),
new Rect(0, 0, w, h)));
}
@@ -178,7 +180,7 @@ public class DragAndDropPolicy {
} else {
// Otherwise only show the fullscreen target
mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(0, 0, w, h),
+ new Rect(l, t, l + iw, t + ih),
new Rect(l, t, l + iw, t + ih),
new Rect(0, 0, w, h)));
}
@@ -210,6 +212,7 @@ public class DragAndDropPolicy {
final boolean isShortcut = description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT);
final Intent dragData = mSession.dragData;
+ boolean deferAppLaunchUntilSplit = false;
if (target.type == TYPE_FULLSCREEN) {
if (mSplitScreen != null && mSplitScreen.isDividerVisible()) {
// If in split, remove split and launch fullscreen
@@ -226,20 +229,40 @@ public class DragAndDropPolicy {
// Not in split, enter split now
mStarter.enterSplitScreen(mSession.runningTaskId,
target.type == TYPE_SPLIT_LEFT || target.type == TYPE_SPLIT_TOP);
+ deferAppLaunchUntilSplit = true;
}
}
- Bundle opts = dragData.hasExtra(EXTRA_ACTIVITY_OPTIONS)
- ? dragData.getBundleExtra(EXTRA_ACTIVITY_OPTIONS)
- : null;
- if (isTask) {
- mStarter.startTask(dragData.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID), opts);
- } else if (isShortcut) {
- mStarter.startShortcut(dragData.getStringExtra(EXTRA_PACKAGE_NAME),
- dragData.getStringExtra(EXTRA_SHORTCUT_ID),
- opts, dragData.getParcelableExtra(EXTRA_USER));
+ final Runnable startAppRunnable = () -> {
+ Bundle opts = dragData.hasExtra(EXTRA_ACTIVITY_OPTIONS)
+ ? dragData.getBundleExtra(EXTRA_ACTIVITY_OPTIONS)
+ : null;
+ if (isTask) {
+ mStarter.startTask(dragData.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID), opts);
+ } else if (isShortcut) {
+ mStarter.startShortcut(dragData.getStringExtra(EXTRA_PACKAGE_NAME),
+ dragData.getStringExtra(EXTRA_SHORTCUT_ID),
+ opts, dragData.getParcelableExtra(EXTRA_USER));
+ } else {
+ mStarter.startIntent(dragData.getParcelableExtra(EXTRA_PENDING_INTENT), opts);
+ }
+ };
+ if (deferAppLaunchUntilSplit) {
+ // TODO(b/169894807): The enterSplitScreen() call above will trigger the current task
+ // into split, and we should wait for home and other tasks to be moved to
+ // split-secondary before trying to launch the new secondary task. This can be removed
+ // once we have app-pairs.
+ mSplitScreen.registerInSplitScreenListener(new Consumer<Boolean>() {
+ @Override
+ public void accept(Boolean inSplit) {
+ if (inSplit) {
+ startAppRunnable.run();
+ mSplitScreen.unregisterInSplitScreenListener(this);
+ }
+ }
+ });
} else {
- mStarter.startIntent(dragData.getParcelableExtra(EXTRA_PENDING_INTENT), opts);
+ startAppRunnable.run();
}
}
@@ -274,7 +297,7 @@ public class DragAndDropPolicy {
* Updates the session data based on the current state of the system.
*/
void update() {
- final ClipDescription description = mInitialDragData.getDescription();
+
try {
List<ActivityManager.RunningTaskInfo> tasks =
mIActivityTaskManager.getFilteredTasks(1,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index fa857cdd174c..5b7531c09a7b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -135,17 +135,25 @@ public class DragLayout extends View {
// visibility of the current region
DragAndDropPolicy.Target target = mPolicy.getTargetAtLocation(
(int) event.getX(), (int) event.getY());
- if (target != null && mCurrentTarget != target) {
+ if (mCurrentTarget != target) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Current target: %s", target);
- Interpolator boundsInterpolator = FAST_OUT_SLOW_IN;
- if (mCurrentTarget == null) {
+ if (target == null) {
+ // Animating to no target
+ mDropOutline.startVisibilityAnimation(false, LINEAR);
+ Rect finalBounds = new Rect(mCurrentTarget.drawRegion);
+ finalBounds.inset(mDisplayMargin, mDisplayMargin);
+ mDropOutline.startBoundsAnimation(finalBounds, FAST_OUT_LINEAR_IN);
+ } else if (mCurrentTarget == null) {
+ // Animating to first target
mDropOutline.startVisibilityAnimation(true, LINEAR);
Rect initialBounds = new Rect(target.drawRegion);
initialBounds.inset(mDisplayMargin, mDisplayMargin);
mDropOutline.setRegionBounds(initialBounds);
- boundsInterpolator = LINEAR_OUT_SLOW_IN;
+ mDropOutline.startBoundsAnimation(target.drawRegion, LINEAR_OUT_SLOW_IN);
+ } else {
+ // Bounds change
+ mDropOutline.startBoundsAnimation(target.drawRegion, FAST_OUT_SLOW_IN);
}
- mDropOutline.startBoundsAnimation(target.drawRegion, boundsInterpolator);
mCurrentTarget = target;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 251f8d472245..854096c1d12f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -324,8 +324,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
@Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
- if (task.configuration.windowConfiguration.getWindowingMode()
- != WINDOWING_MODE_PINNED) {
+ if (task.getWindowingMode() != WINDOWING_MODE_PINNED) {
return;
}
mTouchHandler.getMotionHelper().expandLeavePip(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
index 70b544621329..402d79c6fbd1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
@@ -398,8 +398,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
private void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean clearedTask) {
- if (task.configuration.windowConfiguration.getWindowingMode()
- != WINDOWING_MODE_PINNED) {
+ if (task.getWindowingMode() != WINDOWING_MODE_PINNED) {
return;
}
if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index cfe9b9157eaa..e55f065c1bb2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -57,6 +57,9 @@ public interface SplitScreen {
/** Registers listener that gets called whenever the existence of the divider changes. */
void registerInSplitScreenListener(Consumer<Boolean> listener);
+ /** Unregisters listener that gets called whenever the existence of the divider changes. */
+ void unregisterInSplitScreenListener(Consumer<Boolean> listener);
+
/** Registers listener that gets called whenever the split screen bounds changes. */
void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 49f11592a7fa..07af289c4f35 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -58,6 +58,7 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -85,8 +86,8 @@ public class SplitScreenController implements SplitScreen,
private final WindowManagerProxy mWindowManagerProxy;
private final TaskOrganizer mTaskOrganizer;
- private final ArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners =
- new ArrayList<>();
+ private final CopyOnWriteArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners
+ = new CopyOnWriteArrayList<>();
private final ArrayList<WeakReference<BiConsumer<Rect, Rect>>> mBoundsChangedListeners =
new ArrayList<>();
@@ -173,7 +174,7 @@ public class SplitScreenController implements SplitScreen,
@Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
- if (!wasVisible || task.configuration.windowConfiguration.getWindowingMode()
+ if (!wasVisible || task.getWindowingMode()
!= WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
|| !mSplits.isSplitScreenSupported()) {
return;
@@ -478,6 +479,17 @@ public class SplitScreenController implements SplitScreen,
}
@Override
+ public void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
+ synchronized (mDockedStackExistsListeners) {
+ for (int i = mDockedStackExistsListeners.size() - 1; i >= 0; i--) {
+ if (mDockedStackExistsListeners.get(i) == listener) {
+ mDockedStackExistsListeners.remove(i);
+ }
+ }
+ }
+ }
+
+ @Override
public void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
synchronized (mBoundsChangedListeners) {
mBoundsChangedListeners.add(new WeakReference<>(listener));
@@ -500,9 +512,7 @@ public class SplitScreenController implements SplitScreen,
}
// Note: The set of running tasks from the system is ordered by recency.
final RunningTaskInfo topRunningTask = runningTasks.get(0);
-
- final int activityType = topRunningTask.configuration.windowConfiguration
- .getActivityType();
+ final int activityType = topRunningTask.getActivityType();
if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) {
return false;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
index 64e9d6618390..5b2b38ba8189 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
@@ -23,7 +23,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.wm.shell.ShellTaskOrganizer.getWindowingMode;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
import android.app.ActivityManager.RunningTaskInfo;
@@ -42,6 +41,7 @@ import com.android.wm.shell.Transitions;
import com.android.wm.shell.common.SyncTransactionQueue;
import java.io.PrintWriter;
+import java.util.ArrayList;
class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
private static final String TAG = "SplitScreenTaskListener";
@@ -106,7 +106,7 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
return;
}
- final int winMode = getWindowingMode(taskInfo);
+ final int winMode = taskInfo.getWindowingMode();
if (winMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
ProtoLog.v(WM_SHELL_TASK_ORG,
"%s onTaskAppeared Primary taskId=%d", TAG, taskInfo.taskId);
@@ -283,6 +283,21 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
mSplitScreenController.startEnterSplit();
}
} else if (secondaryImpliesMinimize) {
+ // Workaround for b/172686383, we can't rely on the sync bounds change transaction for
+ // the home task to finish before the last updateChildTaskSurface() call even if it's
+ // queued on the sync transaction queue, so ensure that the home task surface is updated
+ // again before we minimize
+ final ArrayList<RunningTaskInfo> tasks = new ArrayList<>();
+ mSplitScreenController.getWmProxy().getHomeAndRecentsTasks(tasks,
+ mSplitScreenController.getSecondaryRoot());
+ for (int i = 0; i < tasks.size(); i++) {
+ final RunningTaskInfo taskInfo = tasks.get(i);
+ final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
+ if (leash != null) {
+ updateChildTaskSurface(taskInfo, leash, false /* firstAppeared */);
+ }
+ }
+
// Both splits are populated but the secondary split has a home/recents stack on top,
// so enter minimized mode.
mSplitScreenController.ensureMinimizedSplit();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
index c51bbeb7b6c2..0307206e2def 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
@@ -120,7 +120,7 @@ class WindowManagerProxy {
new WindowOrganizer().applyTransaction(t);
}
- private boolean getHomeAndRecentsTasks(List<ActivityManager.RunningTaskInfo> out,
+ boolean getHomeAndRecentsTasks(List<ActivityManager.RunningTaskInfo> out,
WindowContainerToken parent) {
boolean resizable = false;
List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
@@ -209,8 +209,7 @@ class WindowManagerProxy {
continue;
}
// Only move fullscreen tasks to split secondary.
- if (rootTask.configuration.windowConfiguration.getWindowingMode()
- != WINDOWING_MODE_FULLSCREEN) {
+ if (rootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
continue;
}
// Since this iterates from bottom to top, update topHomeTask for every fullscreen task
@@ -232,7 +231,7 @@ class WindowManagerProxy {
}
boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) {
- final int atype = ti.configuration.windowConfiguration.getActivityType();
+ final int atype = ti.getActivityType();
return atype == ACTIVITY_TYPE_HOME || atype == ACTIVITY_TYPE_RECENTS;
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
index affd7367f472..fad1f057267a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
@@ -35,6 +35,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -68,10 +69,13 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.function.Consumer;
/**
* Tests for the drag and drop policy.
@@ -124,6 +128,12 @@ public class DragAndDropPolicyTest {
doReturn(new Rect(50, 0, 100, 100)).when(divider)
.getNonMinimizedSplitScreenSecondaryBounds();
+ doAnswer((Answer<Void>) invocation -> {
+ Consumer<Boolean> callback = invocation.getArgument(0);
+ callback.accept(true);
+ return null;
+ }).when(mSplitScreen).registerInSplitScreenListener(any());
+
mPolicy = new DragAndDropPolicy(mContext, mIActivityTaskManager, mSplitScreen, mStarter);
mActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
mNonResizeableActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 3eac1be3ebee..627af9149fe5 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -49,6 +49,7 @@ class DragDropController {
static final int MSG_DRAG_END_TIMEOUT = 0;
static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 1;
static final int MSG_ANIMATION_END = 2;
+ static final int MSG_REMOVE_DRAG_SURFACE_TIMEOUT = 3;
/**
* Drag state per operation.
@@ -384,6 +385,14 @@ class DragDropController {
}
break;
}
+
+ case MSG_REMOVE_DRAG_SURFACE_TIMEOUT: {
+ synchronized (mService.mGlobalLock) {
+ mService.mTransactionFactory.get()
+ .reparent((SurfaceControl) msg.obj, null).apply();
+ }
+ break;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 8c80205a9e45..e7d8ad690bc4 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -23,6 +23,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.DragDropController.MSG_ANIMATION_END;
import static com.android.server.wm.DragDropController.MSG_DRAG_END_TIMEOUT;
+import static com.android.server.wm.DragDropController.MSG_REMOVE_DRAG_SURFACE_TIMEOUT;
import static com.android.server.wm.DragDropController.MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -59,6 +60,7 @@ import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
+import com.android.internal.os.SomeArgs;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.view.IDragAndDropPermissions;
import com.android.server.LocalServices;
@@ -248,6 +250,9 @@ class DragState {
if (mSurfaceControl != null) {
if (!mRelinquishDragSurface) {
mTransaction.reparent(mSurfaceControl, null).apply();
+ } else {
+ mDragDropController.sendTimeoutMessage(MSG_REMOVE_DRAG_SURFACE_TIMEOUT,
+ mSurfaceControl);
}
mSurfaceControl = null;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0b2ba8727abe..329028279126 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4072,6 +4072,10 @@ class Task extends WindowContainer<WindowContainer> {
info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
info.configuration.setTo(getConfiguration());
+ // Update to the task's current activity type and windowing mode which may differ from the
+ // window configuration
+ info.configuration.windowConfiguration.setActivityType(getActivityType());
+ info.configuration.windowConfiguration.setWindowingMode(getWindowingMode());
info.token = mRemoteToken.toWindowContainerToken();
//TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child