Support creating docked stack at top/left/bottom/right half of screen
Change-Id: Id8d6f639ed67baadb856ce84a20af8929e04cb2e
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index eeae20f..9ef51c8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -452,6 +452,22 @@
*/
public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;
+ /**
+ * Input parameter to {@link android.app.IActivityManager#moveTaskToDockedStack} which
+ * specifies the position of the created docked stack at the top half of the screen if
+ * in portrait mode or at the left half of the screen if in landscape mode.
+ * @hide
+ */
+ public static final int DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT = 0;
+
+ /**
+ * Input parameter to {@link android.app.IActivityManager#moveTaskToDockedStack} which
+ * specifies the position of the created docked stack at the bottom half of the screen if
+ * in portrait mode or at the right half of the screen if in landscape mode.
+ * @hide
+ */
+ public static final int DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT = 1;
+
/** @hide */
public int getFrontActivityScreenCompatMode() {
try {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index d1c73bc..d79716c 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -743,6 +743,16 @@
return true;
}
+ case MOVE_TASK_TO_DOCKED_STACK_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int taskId = data.readInt();
+ int createMode = data.readInt();
+ boolean toTop = data.readInt() != 0;
+ moveTaskToDockedStack(taskId, createMode, toTop);
+ reply.writeNoException();
+ return true;
+ }
+
case RESIZE_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int stackId = data.readInt();
@@ -3510,6 +3520,21 @@
reply.recycle();
}
@Override
+ public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop)
+ throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(taskId);
+ data.writeInt(createMode);
+ data.writeInt(toTop ? 1 : 0);
+ mRemote.transact(MOVE_TASK_TO_DOCKED_STACK_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+ @Override
public void resizeStack(int stackId, Rect r) throws RemoteException
{
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 66fa796..3b30d71 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -140,6 +140,8 @@
public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
public void moveTaskBackwards(int task) throws RemoteException;
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
+ public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop)
+ throws RemoteException;
public void resizeStack(int stackId, Rect bounds) throws RemoteException;
public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException;
public List<StackInfo> getAllStackInfos() throws RemoteException;
@@ -888,4 +890,5 @@
int GET_ACTIVITY_STACK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 343;
int MOVE_ACTIVITY_TO_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 344;
int REPORT_SIZE_CONFIGURATIONS = IBinder.FIRST_CALL_TRANSACTION + 345;
+ int MOVE_TASK_TO_DOCKED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 346;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 14376d1..dc6f3d6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19,7 +19,6 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.app.ActivityManager.HOME_STACK_ID;
import static android.app.ActivityManager.INVALID_STACK_ID;
@@ -215,7 +214,6 @@
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.Trace;
import android.os.UpdateLock;
import android.os.UserHandle;
import android.os.UserManager;
@@ -9053,6 +9051,35 @@
}
}
+ /**
+ * Moves the input task to the docked stack.
+ *
+ * @param taskId Id of task to move.
+ * @param createMode The mode the docked stack should be created in if it doesn't exist
+ * already. See
+ * {@link android.app.ActivityManager#DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT}
+ * and
+ * {@link android.app.ActivityManager#DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT}
+ * @param toTop If the task and stack should be moved to the top.
+ */
+ @Override
+ public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop) {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "moveTaskToDockedStack()");
+ synchronized (this) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToDockedStack: moving task=" + taskId
+ + " to createMode=" + createMode + " toTop=" + toTop);
+ mWindowManager.setDockedStackCreateMode(createMode);
+ mStackSupervisor.moveTaskToStackLocked(
+ taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
@Override
public void resizeStack(int stackId, Rect bounds) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 7901bee..876e9aa 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -16,8 +16,9 @@
package com.android.server.wm;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static com.android.server.wm.WindowManagerService.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
@@ -154,8 +155,11 @@
// event handler for the last finishInputEvent()!
mService.mH.sendEmptyMessage(H.FINISH_TASK_POSITIONING);
if (mCurrentDimSide != CTRL_NONE) {
- mService.mActivityManager.moveTaskToStack(
- mTaskId, DOCKED_STACK_ID, true /*toTop*/);
+ final int createMode = mCurrentDimSide == CTRL_LEFT
+ ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+ : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+ mService.mActivityManager.moveTaskToDockedStack(
+ mTaskId, createMode, true /*toTop*/);
}
}
handled = true;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index ae3bb9b..1e6fab6 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -353,11 +353,13 @@
private static void getInitialDockedStackBounds(
Rect displayRect, Rect outBounds, int stackId) {
// Docked stack start off occupying half the screen space.
- // TODO(multi-window): Need to support the selecting which half of the screen the
- // docked stack uses for snapping windows to the edge of the screen.
final boolean splitHorizontally = displayRect.width() > displayRect.height();
+ final boolean topOrLeftCreateMode =
+ WindowManagerService.sDockedStackCreateMode == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+ final boolean placeTopOrLeft = (stackId == DOCKED_STACK_ID && topOrLeftCreateMode)
+ || (stackId != DOCKED_STACK_ID && !topOrLeftCreateMode);
outBounds.set(displayRect);
- if (stackId == DOCKED_STACK_ID) {
+ if (placeTopOrLeft) {
if (splitHorizontally) {
outBounds.right = displayRect.centerX();
} else {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 69440b8..8719ddb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,6 +16,34 @@
package com.android.server.wm;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+
+import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
+
import android.Manifest;
import android.animation.ValueAnimator;
import android.app.ActivityManagerNative;
@@ -110,9 +138,7 @@
import android.view.WindowManagerPolicy.PointerEventListener;
import android.view.animation.Animation;
-import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
import com.android.internal.app.IAssistScreenshotReceiver;
-import com.android.internal.app.IBatteryStats;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -149,31 +175,6 @@
import java.util.Iterator;
import java.util.List;
-import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
-import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
-import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
-import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
@@ -458,6 +459,8 @@
private boolean mKeyguardWaitingForActivityDrawn;
+ static int sDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+
class RotationWatcher {
IRotationWatcher watcher;
IBinder.DeathRecipient deathRecipient;
@@ -4448,6 +4451,12 @@
}
}
+ public void setDockedStackCreateMode(int mode) {
+ synchronized (mWindowMap) {
+ sDockedStackCreateMode = mode;
+ }
+ }
+
/**
* Create a new TaskStack and place it on a DisplayContent.
* @param stackId The unique identifier of the new stack.