diff options
| author | 2016-01-27 12:24:44 -0800 | |
|---|---|---|
| committer | 2016-01-29 12:45:30 -0800 | |
| commit | b9b16a74e5543b7b707e55a7382bbe82d300e2e5 (patch) | |
| tree | b49fc6afb4ef8713ab6474d24ad7755e0b85e746 | |
| parent | 513346d8f58e13999133872478a966ea4262701f (diff) | |
Display warning toast when we try to launch unresizeable app in split-screen
Bug: 26774816
Change-Id: Ia85d9d89758041661391018f04feb6f8db4e56d9
6 files changed, 77 insertions, 48 deletions
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 26421fb59ebb..52bddd87a8c0 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4003,8 +4003,10 @@ <string name="lock_to_app_unlock_password">Ask for password before unpinning</string> <!-- Multi-Window strings --> - <!-- Warning message when a non-resizeble tasks is docked. --> - <string name="dock_non_resizeble_text">App is not resizeable, scroll it with two fingers.</string> + <!-- Warning message when a non-resizeble tasks is docked whose display windows are cropped. --> + <string name="dock_cropped_windows_text">App is not resizeable, scroll it with two fingers.</string> + <!-- Warning message when we try to dock a non-resizeble tasks and launch it in fullscreen instead. --> + <string name="dock_non_resizeble_failed_to_dock_text">App does not support split-screen.</string> <!-- Notification shown when device owner silently installs a package [CHAR LIMIT=NONE] --> <string name="package_installed_device_owner">Installed by your administrator</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 74ca8a5a3ee4..5c7225e94cfb 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -610,7 +610,8 @@ <java-symbol type="string" name="display_manager_overlay_display_name" /> <java-symbol type="string" name="display_manager_overlay_display_secure_suffix" /> <java-symbol type="string" name="display_manager_overlay_display_title" /> - <java-symbol type="string" name="dock_non_resizeble_text" /> + <java-symbol type="string" name="dock_cropped_windows_text" /> + <java-symbol type="string" name="dock_non_resizeble_failed_to_dock_text" /> <java-symbol type="string" name="double_tap_toast" /> <java-symbol type="string" name="durationDays" /> <java-symbol type="string" name="durationDayHours" /> diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 828cb53b9a53..7359859604b9 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 76f3516269bb..4015c088c6e1 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 4f59c62b5c40..c542ff616d70 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); - - 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(); - } + 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). + + // 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<WindowState> 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 f93b495b6446..849fc3321d2a 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; |