1c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner/* 2c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * Copyright (C) 2013 The Android Open Source Project 3c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * 4c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * Licensed under the Apache License, Version 2.0 (the "License"); 5c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * you may not use this file except in compliance with the License. 6c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * You may obtain a copy of the License at 7c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * 8c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * http://www.apache.org/licenses/LICENSE-2.0 9c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * 10c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * Unless required by applicable law or agreed to in writing, software 11c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * distributed under the License is distributed on an "AS IS" BASIS, 12c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * See the License for the specific language governing permissions and 14c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner * limitations under the License. 15c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner */ 16c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner 17c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautnerpackage com.android.server.wm; 18c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner 19f0ac5c87f2a4a7ee8148a7b8d02b55e439ab130cCraig Mautnerimport static com.android.server.wm.WindowManagerService.DEBUG_TASK_MOVEMENT; 20f0ac5c87f2a4a7ee8148a7b8d02b55e439ab130cCraig Mautnerimport static com.android.server.wm.WindowManagerService.TAG; 21f0ac5c87f2a4a7ee8148a7b8d02b55e439ab130cCraig Mautner 2205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautnerimport android.graphics.Rect; 23f0ac5c87f2a4a7ee8148a7b8d02b55e439ab130cCraig Mautnerimport android.os.Debug; 242c2549c5f44b712dbbf66a69d91f07d6f5336ee6Craig Mautnerimport android.util.EventLog; 25f0ac5c87f2a4a7ee8148a7b8d02b55e439ab130cCraig Mautnerimport android.util.Slog; 2605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautnerimport android.util.TypedValue; 272c2549c5f44b712dbbf66a69d91f07d6f5336ee6Craig Mautnerimport com.android.server.EventLogTags; 2805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 2900af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautnerimport java.io.PrintWriter; 30c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautnerimport java.util.ArrayList; 31c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner 32c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautnerpublic class TaskStack { 3305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner /** Amount of time in milliseconds to animate the dim surface from one value to another, 3405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner * when no window animation is driving it. */ 3505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner private static final int DEFAULT_DIM_DURATION = 200; 3605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 3700af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner /** Unique identifier */ 38c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner final int mStackId; 3900af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner 4005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner /** The service */ 4105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner private final WindowManagerService mService; 4205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 4300af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner /** The display this stack sits under. */ 44df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner private DisplayContent mDisplayContent; 4500af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner 4600af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner /** The Tasks that define this stack. Oldest Tasks are at the bottom. The ordering must match 4700af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner * mTaskHistory in the ActivityStack with the same mStackId */ 482c2549c5f44b712dbbf66a69d91f07d6f5336ee6Craig Mautner private final ArrayList<Task> mTasks = new ArrayList<Task>(); 4900af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner 50b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner /** For comparison with DisplayContent bounds. */ 51b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner private Rect mTmpRect = new Rect(); 52b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner 53b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner /** Content limits relative to the DisplayContent this sits in. */ 54b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner private Rect mBounds = new Rect(); 55b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner 56b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner /** Whether mBounds is fullscreen */ 57b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner private boolean mFullscreen = true; 58c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner 5905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner /** Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND} */ 60b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner private DimLayer mDimLayer; 6105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 6205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner /** The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer. */ 6305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner WindowStateAnimator mDimWinAnimator; 6405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 6505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */ 66df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner DimLayer mAnimationBackgroundSurface; 6705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 6805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner /** The particular window with an Animation with non-zero background color. */ 6905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner WindowStateAnimator mAnimationBackgroundAnimator; 7005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 7105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner /** Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the end 7205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner * then stop any dimming. */ 7305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner boolean mDimmingTag; 7405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 75dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner /** Application tokens that are exiting, but still on screen for animations. */ 76dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner final AppTokenList mExitingAppTokens = new AppTokenList(); 77dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner 7895da1087ed3c7b9983b571bc5409827ae390f15fCraig Mautner /** Detach this stack from its display when animation completes. */ 7995da1087ed3c7b9983b571bc5409827ae390f15fCraig Mautner boolean mDeferDetach; 8095da1087ed3c7b9983b571bc5409827ae390f15fCraig Mautner 81df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner TaskStack(WindowManagerService service, int stackId) { 8205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mService = service; 83c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner mStackId = stackId; 84bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner // TODO: remove bounds from log, they are always 0. 85bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top, 86bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner mBounds.right, mBounds.bottom); 87c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner } 88c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner 89c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner DisplayContent getDisplayContent() { 90c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner return mDisplayContent; 91c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner } 92c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner 93d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner ArrayList<Task> getTasks() { 94d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner return mTasks; 95d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner } 96d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner 97b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner void resizeWindows() { 98bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner final boolean underStatusBar = mBounds.top == 0; 99bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner 100bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner final ArrayList<WindowState> resizingWindows = mService.mResizingWindows; 101bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { 102bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens; 103bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 104bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows; 105bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 106bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner final WindowState win = windows.get(winNdx); 107bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner if (!resizingWindows.contains(win)) { 108bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner if (WindowManagerService.DEBUG_RESIZE) Slog.d(TAG, 109bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner "setBounds: Resizing " + win); 110bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner resizingWindows.add(win); 111bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 112bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner win.mUnderStatusBar = underStatusBar; 113bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 114bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 115bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 116bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 117bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner 118bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner boolean setBounds(Rect bounds) { 119b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner boolean oldFullscreen = mFullscreen; 120b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner if (mDisplayContent != null) { 121b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner mDisplayContent.getLogicalDisplayRect(mTmpRect); 122b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner mFullscreen = mTmpRect.equals(bounds); 123b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner } 124b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner 125b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner if (mBounds.equals(bounds) && oldFullscreen == mFullscreen) { 126bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner return false; 127bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 128bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner 129bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner mDimLayer.setBounds(bounds); 130bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner mAnimationBackgroundSurface.setBounds(bounds); 131bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner mBounds.set(bounds); 132bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner 133bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner return true; 134bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 135bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner 136bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner void getBounds(Rect out) { 137b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner out.set(mBounds); 138b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner } 139b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner 140b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner void updateDisplayInfo() { 141b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner if (mFullscreen && mDisplayContent != null) { 142b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner mDisplayContent.getLogicalDisplayRect(mTmpRect); 143b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner setBounds(mTmpRect); 144bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 145bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 146bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner 147bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner boolean isFullscreen() { 148b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner return mFullscreen; 149d5d5d0f4b8c75c9ed4fea320b4f31740b88dd37eCraig Mautner } 150d5d5d0f4b8c75c9ed4fea320b4f31740b88dd37eCraig Mautner 1511bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner boolean isAnimating() { 1521bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { 1531bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens; 1541bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1551bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows; 1561bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 157bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator; 1587c9ee19cbd0360a62dc4322169afc1b0b9c9e022Craig Mautner if (winAnimator.isAnimating() || winAnimator.mWin.mExiting) { 1591bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner return true; 1601bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner } 1611bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner } 1621bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner } 1631bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner } 1641bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner return false; 1651bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner } 1661bf2b873470d2ba8a4ac218da73516cc2b20aa76Craig Mautner 16700af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner /** 16800af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner * Put a Task in this stack. Used for adding and moving. 16900af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner * @param task The task to add. 17000af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner * @param toTop Whether to add it to the top or bottom. 17100af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner */ 172bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner void addTask(Task task, boolean toTop) { 173ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner int stackNdx; 174ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner if (!toTop) { 175ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner stackNdx = 0; 176ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner } else { 177ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner stackNdx = mTasks.size(); 178e0d50cc15be2c8aa9e4a4aa6cf34cc7cf23c9109Craig Mautner if (!mService.isCurrentProfileLocked(task.mUserId)) { 179ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner // Place the task below all current user tasks. 180ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner while (--stackNdx >= 0) { 181e0d50cc15be2c8aa9e4a4aa6cf34cc7cf23c9109Craig Mautner if (!mService.isCurrentProfileLocked(mTasks.get(stackNdx).mUserId)) { 182ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner break; 183ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner } 184ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner } 185e0d50cc15be2c8aa9e4a4aa6cf34cc7cf23c9109Craig Mautner // Put it above first non-current user task. 186ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner ++stackNdx; 187ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner } 188ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner } 189ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "addTask: task=" + task + " toTop=" + toTop 190ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner + " pos=" + stackNdx); 191ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner mTasks.add(stackNdx, task); 192ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner 193967212cb542e6eeb308678367b53381bff984c31Craig Mautner task.mStack = this; 194bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner mDisplayContent.moveStack(this, true); 195dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, stackNdx); 196c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner } 197c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner 198bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner void moveTaskToTop(Task task) { 199f0ac5c87f2a4a7ee8148a7b8d02b55e439ab130cCraig Mautner if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToTop: task=" + task + " Callers=" 200f0ac5c87f2a4a7ee8148a7b8d02b55e439ab130cCraig Mautner + Debug.getCallers(6)); 201d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner mTasks.remove(task); 202bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner addTask(task, true); 203d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner } 204d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner 205bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner void moveTaskToBottom(Task task) { 206f0ac5c87f2a4a7ee8148a7b8d02b55e439ab130cCraig Mautner if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToBottom: task=" + task); 207d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner mTasks.remove(task); 208bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner addTask(task, false); 209d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner } 210d9a22881fda77e208f54f893a804d0001d27a27eCraig Mautner 21100af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner /** 21204a0ea60ac7e20369e63edc4f3f8cedf8425a439Craig Mautner * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the 21304a0ea60ac7e20369e63edc4f3f8cedf8425a439Craig Mautner * back. 21400af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner * @param task The Task to delete. 21500af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner */ 216de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner void removeTask(Task task) { 217f0ac5c87f2a4a7ee8148a7b8d02b55e439ab130cCraig Mautner if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "removeTask: task=" + task); 218de4ef020ec5c3acdc90c4ba43011dda20d98d4ddCraig Mautner mTasks.remove(task); 219df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner if (mDisplayContent != null) { 220df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner if (mTasks.isEmpty()) { 221df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner mDisplayContent.moveStack(this, false); 222df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner } 223df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner mDisplayContent.layoutNeeded = true; 22404a0ea60ac7e20369e63edc4f3f8cedf8425a439Craig Mautner } 225c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner } 226c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner 227df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner void attachDisplayContent(DisplayContent displayContent) { 228df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner if (mDisplayContent != null) { 229df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner throw new IllegalStateException("attachDisplayContent: Already attached"); 230df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner } 231df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner 232df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner mDisplayContent = displayContent; 233df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner mDimLayer = new DimLayer(mService, this, displayContent); 234df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner mAnimationBackgroundSurface = new DimLayer(mService, this, displayContent); 235b660b9d8cf6b951b85a35599d636c470795e9a1aCraig Mautner updateDisplayInfo(); 236df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner } 237df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner 238dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner void detachDisplay() { 239df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId); 240bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner 241bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner boolean doAnotherLayoutPass = false; 242dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { 243bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner final AppTokenList appWindowTokens = mTasks.get(taskNdx).mAppTokens; 244bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) { 245bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows; 246bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) { 247bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner mService.removeWindowInnerLocked(null, appWindows.get(winNdx)); 248bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner doAnotherLayoutPass = true; 249bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner } 250bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner } 251dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner } 252bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner if (doAnotherLayoutPass) { 253bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner mService.requestTraversalLocked(); 254bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner } 255bc2a6dff1f0edfb2856377fbdb6378158621bd16Craig Mautner 25605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mAnimationBackgroundSurface.destroySurface(); 257df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner mAnimationBackgroundSurface = null; 25805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimLayer.destroySurface(); 259df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner mDimLayer = null; 260df88d73092c62a1a3cd2b2056ca63ae2e70cc238Craig Mautner mDisplayContent = null; 26100af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner } 26200af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner 26305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner void resetAnimationBackgroundAnimator() { 26405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mAnimationBackgroundAnimator = null; 26505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mAnimationBackgroundSurface.hide(); 26605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 26705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 26805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner private long getDimBehindFadeDuration(long duration) { 26905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner TypedValue tv = new TypedValue(); 27005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mService.mContext.getResources().getValue( 27105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true); 27205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (tv.type == TypedValue.TYPE_FRACTION) { 27305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner duration = (long)tv.getFraction(duration, duration); 27405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) { 27505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner duration = tv.data; 27605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 27705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner return duration; 27805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 27905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 28005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner boolean animateDimLayers() { 28105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner final int dimLayer; 28205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner final float dimAmount; 28305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (mDimWinAnimator == null) { 28405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner dimLayer = mDimLayer.getLayer(); 28505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner dimAmount = 0; 28605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } else { 28705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner dimLayer = mDimWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM; 28805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner dimAmount = mDimWinAnimator.mWin.mAttrs.dimAmount; 28905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 29005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner final float targetAlpha = mDimLayer.getTargetAlpha(); 29105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (targetAlpha != dimAmount) { 29205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (mDimWinAnimator == null) { 29305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimLayer.hide(DEFAULT_DIM_DURATION); 29405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } else { 29505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner long duration = (mDimWinAnimator.mAnimating && mDimWinAnimator.mAnimation != null) 29605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner ? mDimWinAnimator.mAnimation.computeDurationHint() 29705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner : DEFAULT_DIM_DURATION; 29805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (targetAlpha > dimAmount) { 29905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner duration = getDimBehindFadeDuration(duration); 30005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 30105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimLayer.show(dimLayer, dimAmount, duration); 30205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 30305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } else if (mDimLayer.getLayer() != dimLayer) { 30405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimLayer.setLayer(dimLayer); 30505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 30605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (mDimLayer.isAnimating()) { 30705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (!mService.okToDisplay()) { 30805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner // Jump to the end of the animation. 30905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimLayer.show(); 31005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } else { 31105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner return mDimLayer.stepAnimation(); 31205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 31305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 31405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner return false; 31505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 31605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 31705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner void resetDimmingTag() { 31805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimmingTag = false; 31905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 32005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 32105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner void setDimmingTag() { 32205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimmingTag = true; 32305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 32405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 32505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner boolean testDimmingTag() { 32605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner return mDimmingTag; 32705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 32805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 32905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner boolean isDimming() { 33005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner return mDimLayer.isDimming(); 33105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 33205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 33305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner boolean isDimming(WindowStateAnimator winAnimator) { 33405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner return mDimWinAnimator == winAnimator && mDimLayer.isDimming(); 33505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 33605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 33705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) { 33805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner // Only set dim params on the highest dimmed layer. 33905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner final WindowStateAnimator existingDimWinAnimator = mDimWinAnimator; 34005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer. 34105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null 34205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner || !existingDimWinAnimator.mSurfaceShown 34305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) { 34405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimWinAnimator = newWinAnimator; 345c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner } 34605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 34705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 34805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner void stopDimmingIfNeeded() { 34905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (!mDimmingTag && isDimming()) { 35005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimWinAnimator = null; 35105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 35205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 35305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 35405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner void setAnimationBackground(WindowStateAnimator winAnimator, int color) { 35505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner int animLayer = winAnimator.mAnimLayer; 35605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (mAnimationBackgroundAnimator == null 35705d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner || animLayer < mAnimationBackgroundAnimator.mAnimLayer) { 35805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mAnimationBackgroundAnimator = winAnimator; 35905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner animLayer = mService.adjustAnimationBackground(winAnimator); 36005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mAnimationBackgroundSurface.show(animLayer - WindowManagerService.LAYER_OFFSET_DIM, 36105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner ((color >> 24) & 0xff) / 255f, 0); 36205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 36305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 36405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner 365ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner void switchUser(int userId) { 366ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner int top = mTasks.size(); 367ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner for (int taskNdx = 0; taskNdx < top; ++taskNdx) { 368ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner Task task = mTasks.get(taskNdx); 369e0d50cc15be2c8aa9e4a4aa6cf34cc7cf23c9109Craig Mautner if (mService.isCurrentProfileLocked(task.mUserId)) { 370ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner mTasks.remove(taskNdx); 371ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner mTasks.add(task); 372ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner --top; 373ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner } 374ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner } 375ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner } 376ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner 377bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner void close() { 378bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner mDimLayer.mDimSurface.destroy(); 379bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner mAnimationBackgroundSurface.mDimSurface.destroy(); 380bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner } 381bdc748af8ce62778d2ad15040ecdfada6e4635fdCraig Mautner 38200af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner public void dump(String prefix, PrintWriter pw) { 38300af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner pw.print(prefix); pw.print("mStackId="); pw.println(mStackId); 38495da1087ed3c7b9983b571bc5409827ae390f15fCraig Mautner pw.print(prefix); pw.print("mDeferDetach="); pw.println(mDeferDetach); 38500af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) { 38600af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner pw.print(prefix); pw.println(mTasks.get(taskNdx)); 38700af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner } 38805d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (mAnimationBackgroundSurface.isDimming()) { 38905d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner pw.print(prefix); pw.println("mWindowAnimationBackgroundSurface:"); 39005d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mAnimationBackgroundSurface.printTo(prefix + " ", pw); 39105d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 39205d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner if (mDimLayer.isDimming()) { 39305d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner pw.print(prefix); pw.println("mDimLayer:"); 39405d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner mDimLayer.printTo(prefix, pw); 39505d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator); 39605d290365f0b9ed781ffcb30b38a0c7c6e450e9dCraig Mautner } 397dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner if (!mExitingAppTokens.isEmpty()) { 398dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner pw.println(); 399dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner pw.println(" Exiting application tokens:"); 400dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 401dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner WindowToken token = mExitingAppTokens.get(i); 402dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner pw.print(" Exiting App #"); pw.print(i); 403dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner pw.print(' '); pw.print(token); 404dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner pw.println(':'); 405dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner token.dump(pw, " "); 406dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner } 407dc548483ae90ba26ad9e2e2cb79f4673140edb49Craig Mautner } 40800af9fe6ae0da5b716212fa754163d90b60c1ee6Craig Mautner } 4094cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner 4104cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner @Override 4114cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner public String toString() { 4124cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner return "{stackId=" + mStackId + " tasks=" + mTasks + "}"; 4134cd0c13f8f765118a24e31548c058b5029481beaCraig Mautner } 414c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner} 415