From 513346d8f58e13999133872478a966ea4262701f Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Wed, 27 Jan 2016 10:55:01 -0800 Subject: [PATCH 1/3] Don't allow non-dockable activities/tasks in docked stack. Prevent activities and tasks that are not resizeable and don't support crop windows resize mode from going into the docked stack. Bug: 26774816 Change-Id: I1fd23114685be15908e80e8bc5a0216d8bfd049e --- .../com/android/server/am/ActivityRecord.java | 10 ++++++++ .../com/android/server/am/ActivityStack.java | 3 +-- .../server/am/ActivityStackSupervisor.java | 25 ++++++++++++++++--- .../android/server/am/ActivityStarter.java | 20 +++++++++------ .../com/android/server/am/TaskRecord.java | 4 +++ 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 133ac385260ef..ed26e0ce6b189 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -18,6 +18,7 @@ package com.android.server.am; import static android.app.ActivityManager.StackId; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; +import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS; import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; @@ -759,10 +760,19 @@ final class ActivityRecord { return !isHomeActivity() && ActivityInfo.isResizeableMode(info.resizeMode); } + boolean isResizeableOrForced() { + return !isHomeActivity() && (isResizeable() || service.mForceResizableActivities); + } + boolean supportsPictureInPicture() { return !isHomeActivity() && info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE; } + boolean canGoInDockedStack() { + return !isHomeActivity() + && (isResizeableOrForced() || info.resizeMode == RESIZE_MODE_CROP_WINDOWS); + } + boolean isAlwaysFocusable() { return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0; } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index dac0f7d0bd0fb..b9b2bb6a06ae5 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1414,8 +1414,7 @@ final class ActivityStack { // task in the focus stack doesn't support any form of resizing. final ActivityRecord r = focusedStack.topRunningActivityLocked(); final TaskRecord task = r != null ? r.task : null; - return task == null || task.isResizeable() || task.inCropWindowsResizeMode() - ? STACK_VISIBLE : STACK_INVISIBLE; + return task == null || task.canGoInDockedStack() ? STACK_VISIBLE : STACK_INVISIBLE; } // Find the first stack below focused stack that actually got something visible. diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 1660ddafc4f02..828cb53b9a534 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1723,7 +1723,9 @@ public final class ActivityStackSupervisor implements DisplayListener { stackId = task.getLaunchStackId(); } if (stackId != task.stack.mStackId) { - moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason); + final ActivityStack stack = moveTaskToStackUncheckedLocked( + task, stackId, ON_TOP, !FORCE_FOCUS, reason); + stackId = stack.mStackId; // moveTaskToStackUncheckedLocked() should already placed the task on top, // still need moveTaskToFrontLocked() below for any transition settings. } @@ -2133,7 +2135,12 @@ public final class ActivityStackSupervisor implements DisplayListener { private boolean restoreRecentTaskLocked(TaskRecord task, int stackId) { if (stackId == INVALID_STACK_ID) { stackId = task.getLaunchStackId(); + } else if (stackId == DOCKED_STACK_ID && !task.canGoInDockedStack()) { + // Preferred stack is the docked stack, but the task can't go in the docked stack. + // Put it in the fullscreen stack. + stackId = FULLSCREEN_WORKSPACE_STACK_ID; } + if (task.stack != null) { // Task has already been restored once. See if we need to do anything more if (task.stack.mStackId == stackId) { @@ -2169,8 +2176,7 @@ public final class ActivityStackSupervisor implements DisplayListener { * Moves the specified task record to the input stack id. * WARNING: This method performs an unchecked/raw move of the task and * can leave the system in an unstable state if used incorrectly. - * Use {@link #moveTaskToStackLocked} to perform safe task movement - * to a stack. + * Use {@link #moveTaskToStackLocked} to perform safe task movement to a stack. * @param task Task to move. * @param stackId Id of stack to move task to. * @param toTop True if the task should be placed at the top of the stack. @@ -2191,6 +2197,18 @@ public final class ActivityStackSupervisor implements DisplayListener { && (prevStack.topRunningActivityLocked() == r); final int resizeMode = task.mResizeMode; + + if (stackId == DOCKED_STACK_ID && resizeMode == RESIZE_MODE_UNRESIZEABLE) { + // We don't allow moving a unresizeable task to the docked stack since the docked + // stack is used for split-screen mode and will cause things like the docked divider to + // show up. We instead leave the task in its current stack or move it to the fullscreen + // stack if it isn't currently in a stack. + stackId = (prevStack != null) ? prevStack.mStackId : FULLSCREEN_WORKSPACE_STACK_ID; + // TODO: display toast that activity doesn't support multi-window mode. + Slog.w(TAG, "Can not move unresizeable task=" + task + + " to docked stack. Moving to stackId=" + stackId + " instead."); + } + // Temporarily disable resizeablility of task we are moving. We don't want it to be resized // if a docked stack is created below which will lead to the stack we are moving from and // its resizeable tasks being resized. @@ -2238,6 +2256,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } final ActivityStack stack = moveTaskToStackUncheckedLocked( task, stackId, toTop, forceFocus, "moveTaskToStack:" + reason); + stackId = stack.mStackId; if (!animate) { stack.mNoAnimActivities.add(topActivity); diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 22b846246b7e1..76f3516269bb5 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1484,8 +1484,9 @@ class ActivityStarter { mInTask.updateOverrideConfiguration(mLaunchBounds); int stackId = mInTask.getLaunchStackId(); if (stackId != mInTask.stack.mStackId) { - mSupervisor.moveTaskToStackUncheckedLocked( + final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked( mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront"); + stackId = stack.mStackId; } if (StackId.resizeStackWithLaunchBounds(stackId)) { mSupervisor.resizeStackLocked(stackId, mLaunchBounds, @@ -1627,10 +1628,9 @@ class ActivityStarter { // If the freeform or docked stack has focus, and the activity to be launched is resizeable, // we can also put it in the focused stack. final int focusedStackId = mSupervisor.mFocusedStack.mStackId; - final boolean canUseFocusedStack = - focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID - || focusedStackId == DOCKED_STACK_ID - || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeable()); + final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID + || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack()) + || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced()); if (canUseFocusedStack && (!newTask || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) { if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, @@ -1666,6 +1666,10 @@ class ActivityStarter { if (isValidLaunchStackId(launchStackId, r)) { return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP); + } else if (launchStackId == DOCKED_STACK_ID) { + // The preferred launch stack is the docked stack, but it isn't a valid launch stack + // for this activity, so we put the activity in the fullscreen stack. + return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP); } if (!launchToSideAllowed || (launchFlags & FLAG_ACTIVITY_LAUNCH_TO_SIDE) == 0) { @@ -1701,9 +1705,11 @@ class ActivityStarter { return false; } - final boolean resizeable = r.isResizeable() || mService.mForceResizableActivities; + if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) { + return true; + } - if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !resizeable) { + if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !r.isResizeableOrForced()) { return false; } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index c14cfefbccacd..be97c5a7657f7 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -943,6 +943,10 @@ final class TaskRecord { return !isResizeable() && mResizeMode == RESIZE_MODE_CROP_WINDOWS; } + boolean canGoInDockedStack() { + return isResizeable() || inCropWindowsResizeMode(); + } + /** * Find the activity in the history stack within the given task. Returns * the index within the history at which it's found, or < 0 if not found. From b9b16a74e5543b7b707e55a7382bbe82d300e2e5 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Wed, 27 Jan 2016 12:24:44 -0800 Subject: [PATCH 2/3] Display warning toast when we try to launch unresizeable app in split-screen Bug: 26774816 Change-Id: Ia85d9d89758041661391018f04feb6f8db4e56d9 --- core/res/res/values/strings.xml | 6 +- core/res/res/values/symbols.xml | 3 +- .../server/am/ActivityStackSupervisor.java | 19 +++-- .../android/server/am/ActivityStarter.java | 8 +- .../core/java/com/android/server/wm/Task.java | 78 ++++++++++++------- .../server/wm/WindowManagerService.java | 5 +- 6 files changed, 74 insertions(+), 45 deletions(-) diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 26421fb59ebb9..52bddd87a8c0d 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4003,8 +4003,10 @@ Ask for password before unpinning - - App is not resizeable, scroll it with two fingers. + + App is not resizeable, scroll it with two fingers. + + App does not support split-screen. Installed by your administrator diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 74ca8a5a3ee43..5c7225e94cfb6 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -610,7 +610,8 @@ - + + diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 828cb53b9a534..7359859604b98 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2204,7 +2204,6 @@ public final class ActivityStackSupervisor implements DisplayListener { // show up. We instead leave the task in its current stack or move it to the fullscreen // stack if it isn't currently in a stack. stackId = (prevStack != null) ? prevStack.mStackId : FULLSCREEN_WORKSPACE_STACK_ID; - // TODO: display toast that activity doesn't support multi-window mode. Slog.w(TAG, "Can not move unresizeable task=" + task + " to docked stack. Moving to stackId=" + stackId + " instead."); } @@ -2254,6 +2253,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // during the relaunch. If we end up not doing any relaunch, we clear the flags later. mWindowManager.setReplacingWindow(topActivity.appToken, animate); } + final int preferredLaunchStackId = stackId; final ActivityStack stack = moveTaskToStackUncheckedLocked( task, stackId, toTop, forceFocus, "moveTaskToStack:" + reason); stackId = stack.mStackId; @@ -2286,9 +2286,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); resumeFocusedStackTopActivityLocked(); - if (!task.isResizeable() && isStackDockedInEffect(stackId)) { - showNonResizeableDockToast(taskId); - } + showNonResizeableDockToastIfNeeded(task, preferredLaunchStackId, stackId); } boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect bounds) { @@ -3240,8 +3238,17 @@ public final class ActivityStackSupervisor implements DisplayListener { } } - void showNonResizeableDockToast(int taskId) { - mWindowManager.scheduleShowNonResizeableDockToast(taskId); + void showNonResizeableDockToastIfNeeded( + TaskRecord task, int preferredStackId, int actualStackId) { + if (!isStackDockedInEffect(actualStackId) && preferredStackId != DOCKED_STACK_ID) { + return; + } + + if (!task.canGoInDockedStack() || task.inCropWindowsResizeMode()) { + // Display warning toast if we tried to put a non-dockable task in the docked stack or + // the task is running in cropped window mode. + mWindowManager.scheduleShowNonResizeableDockToast(task.taskId); + } } void showLockTaskToast() { diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 76f3516269bb5..4015c088c6e19 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1004,10 +1004,10 @@ class ActivityStarter { } mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); - if (!mStartActivity.task.isResizeable() - && mSupervisor.isStackDockedInEffect(mTargetStack.mStackId)) { - mSupervisor.showNonResizeableDockToast(mStartActivity.task.taskId); - } + final int preferredLaunchStackId = + (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID; + mSupervisor.showNonResizeableDockToastIfNeeded( + mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId); return START_SUCCESS; } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 4f59c62b5c409..c542ff616d701 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -19,9 +19,11 @@ package com.android.server.wm; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.HOME_STACK_ID; +import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION; import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS; +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; @@ -41,12 +43,14 @@ import android.util.Slog; import android.view.DisplayInfo; import android.view.Surface; +import com.android.internal.R; import com.android.server.EventLogTags; import java.io.PrintWriter; import java.util.ArrayList; class Task implements DimLayer.DimLayerUser { + static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM; // Return value from {@link setBounds} indicating no change was made to the Task bounds. static final int BOUNDS_CHANGE_NONE = 0; // Return value from {@link setBounds} indicating the position of the Task bounds changed. @@ -129,35 +133,51 @@ class Task implements DimLayer.DimLayerUser { mShowNonResizeableDockToast = false; + if (isResizeable()) { + Slog.wtf(TAG, + "Trying to show non-resizeable toast when task is resizeable task=" + this); + return; + } + + if (mResizeMode == RESIZE_MODE_UNRESIZEABLE) { + final String text = + mService.mContext.getString(R.string.dock_non_resizeble_failed_to_dock_text); + mService.mH.obtainMessage(SHOW_NON_RESIZEABLE_DOCK_TOAST, 0, 0, text).sendToTarget(); + return; + } + final int dockSide = mStack.getDockSide(); + if (!inCropWindowsResizeMode() || dockSide == DOCKED_INVALID) { + return; + } + int xOffset = 0; int yOffset = 0; - if (dockSide != DOCKED_INVALID) { - mStack.getBounds(mTmpRect); + mStack.getBounds(mTmpRect); - if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) { - // The toast was originally placed at the bottom and centered. To place it - // at the bottom-center of the stack, we offset it horizontally by the diff - // between the center of the stack bounds vs. the center of the screen. - displayContent.getLogicalDisplayRect(mTmpRect2); - xOffset = mTmpRect.centerX() - mTmpRect2.centerX(); - } else if (dockSide == DOCKED_TOP) { - // The toast was originally placed at the bottom and centered. To place it - // at the bottom center of the top stack, we offset it vertically by the diff - // between the bottom of the stack bounds vs. the bottom of the content rect. - // - // Note here we use the content rect instead of the display rect, as we want - // the toast's distance to the dock divider (when it's placed at the top half) - // to be the same as it's distance to the top of the navigation bar (when it's - // placed at the bottom). + if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) { + // The toast was originally placed at the bottom and centered. To place it at the + // bottom-center of the stack, we offset it horizontally by the diff between the center + // of the stack bounds vs. the center of the screen. + displayContent.getLogicalDisplayRect(mTmpRect2); + xOffset = mTmpRect.centerX() - mTmpRect2.centerX(); + } else if (dockSide == DOCKED_TOP) { + // The toast was originally placed at the bottom and centered. To place it at the bottom + // center of the top stack, we offset it vertically by the diff between the bottom of + // the stack bounds vs. the bottom of the content rect. + // + // Note here we use the content rect instead of the display rect, as we want the toast's + // distance to the dock divider (when it's placed at the top half) to be the same as + // it's distance to the top of the navigation bar (when it's placed at the bottom). - // We don't adjust for DOCKED_BOTTOM case since it's already at the bottom. - displayContent.getContentRect(mTmpRect2); - yOffset = mTmpRect2.bottom - mTmpRect.bottom; - } - mService.mH.obtainMessage( - SHOW_NON_RESIZEABLE_DOCK_TOAST, xOffset, yOffset).sendToTarget(); + // We don't adjust for DOCKED_BOTTOM case since it's already at the bottom. + displayContent.getContentRect(mTmpRect2); + yOffset = mTmpRect2.bottom - mTmpRect.bottom; } + final String text = + mService.mContext.getString(R.string.dock_cropped_windows_text); + mService.mH.obtainMessage(SHOW_NON_RESIZEABLE_DOCK_TOAST, + xOffset, yOffset, text).sendToTarget(); } void addAppToken(int addPos, AppWindowToken wtoken, int resizeMode, boolean homeTask) { @@ -190,11 +210,11 @@ class Task implements DimLayer.DimLayerUser { void removeLocked() { if (hasAppTokensAlive() && mStack.isAnimating()) { - if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: deferring removing taskId=" + mTaskId); + if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId); mDeferRemoval = true; return; } - if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: removing taskId=" + mTaskId); + if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId); EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask"); mDeferRemoval = false; DisplayContent content = getDisplayContent(); @@ -209,7 +229,7 @@ class Task implements DimLayer.DimLayerUser { if (stack == mStack) { return; } - if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: removing taskId=" + mTaskId + if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: removing taskId=" + mTaskId + " from stack=" + mStack); EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask"); if (mStack != null) { @@ -220,7 +240,7 @@ class Task implements DimLayer.DimLayerUser { void positionTaskInStack(TaskStack stack, int position, Rect bounds, Configuration config) { if (mStack != null && stack != mStack) { - if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskInStack: removing taskId=" + mTaskId + if (DEBUG_STACK) Slog.i(TAG, "positionTaskInStack: removing taskId=" + mTaskId + " from stack=" + mStack); EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask"); mStack.removeTask(this); @@ -566,7 +586,7 @@ class Task implements DimLayer.DimLayerUser { for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { final WindowState win = windows.get(winNdx); if (!resizingWindows.contains(win)) { - if (DEBUG_RESIZE) Slog.d(TAG_WM, "resizeWindows: Resizing " + win); + if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + win); resizingWindows.add(win); } } @@ -578,7 +598,7 @@ class Task implements DimLayer.DimLayerUser { final ArrayList windows = mAppTokens.get(activityNdx).allAppWindows; for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { final WindowState win = windows.get(winNdx); - if (DEBUG_RESIZE) Slog.d(TAG_WM, "moveWindows: Moving " + win); + if (DEBUG_RESIZE) Slog.d(TAG, "moveWindows: Moving " + win); win.mMovedByResize = true; } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f93b495b6446d..849fc3321d2af 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -8126,9 +8126,8 @@ public class WindowManagerService extends IWindowManager.Stub } break; case SHOW_NON_RESIZEABLE_DOCK_TOAST: { - final Toast toast = Toast.makeText(mContext, - mContext.getString(R.string.dock_non_resizeble_text), - Toast.LENGTH_LONG); + final Toast toast = Toast.makeText( + mContext, (String) msg.obj, Toast.LENGTH_LONG); final int gravity = toast.getGravity(); final int xOffset = toast.getXOffset() + msg.arg1; final int yOffset = toast.getYOffset() + msg.arg2; From 21b6058fff4fb2448394b4b4ea3ae28e44c0f69d Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Wed, 27 Jan 2016 12:34:16 -0800 Subject: [PATCH 3/3] Added isDockable field to RunningTaskInfo Allows the caller to know if the task can go in the docked stack. Bug: 26774816 Change-Id: I96fdf9b4df0ac87d84492e1504baac3ca0767d37 --- core/java/android/app/ActivityManager.java | 14 ++++++++++++++ .../android/server/am/ActivityManagerService.java | 1 + .../java/com/android/server/am/ActivityStack.java | 1 + 3 files changed, 16 insertions(+) diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 90feab4327b72..82170d1ac60fe 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1195,6 +1195,12 @@ public class ActivityManager { */ public Rect bounds; + /** + * True if the task can go in the docked stack. + * @hide + */ + public boolean isDockable; + public RecentTaskInfo() { } @@ -1238,6 +1244,7 @@ public class ActivityManager { } else { dest.writeInt(0); } + dest.writeInt(isDockable ? 1 : 0); } public void readFromParcel(Parcel source) { @@ -1260,6 +1267,7 @@ public class ActivityManager { numActivities = source.readInt(); bounds = source.readInt() > 0 ? Rect.CREATOR.createFromParcel(source) : null; + isDockable = source.readInt() == 1; } public static final Creator CREATOR @@ -1444,6 +1452,12 @@ public class ActivityManager { */ public long lastActiveTime; + /** + * True if the task can go in the docked stack. + * @hide + */ + public boolean isDockable; + public RunningTaskInfo() { } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 69cc39b3d3786..978e69c9140a0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8591,6 +8591,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (tr.mBounds != null) { rti.bounds = new Rect(tr.mBounds); } + rti.isDockable = tr.canGoInDockedStack(); ActivityRecord base = null; ActivityRecord top = null; diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index b9b2bb6a06ae5..7de254ef94829 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -4542,6 +4542,7 @@ final class ActivityStack { } ci.numActivities = numActivities; ci.numRunning = numRunning; + ci.isDockable = task.canGoInDockedStack(); list.add(ci); } }