Task.java revision 0429f3522bca5bb86378dd3f013f995484ddbed6
1b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner/*
2b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner * Copyright (C) 2013 The Android Open Source Project
3b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner *
4b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner * Licensed under the Apache License, Version 2.0 (the "License");
5b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner * you may not use this file except in compliance with the License.
6b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner * You may obtain a copy of the License at
7b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner *
8b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner *      http://www.apache.org/licenses/LICENSE-2.0
9b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner *
10b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner * Unless required by applicable law or agreed to in writing, software
11b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner * distributed under the License is distributed on an "AS IS" BASIS,
12b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner * See the License for the specific language governing permissions and
14b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner * limitations under the License.
15b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner */
16b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner
17b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautnerpackage com.android.server.wm;
18b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner
193797c22ea16e932329ebffdc7e7ce09f9ecd9545Wale Ogunwaleimport static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
203797c22ea16e932329ebffdc7e7ce09f9ecd9545Wale Ogunwaleimport static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
213797c22ea16e932329ebffdc7e7ce09f9ecd9545Wale Ogunwaleimport static android.app.ActivityManager.StackId.HOME_STACK_ID;
22b15758ab7a6481717d0d29612e870d7241061c31Chong Zhangimport static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
231ed0d89e7e9a28a5dd52fdc40425466efd8d08efWale Ogunwaleimport static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
240bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynskiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
250bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynskiimport static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
260bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynskiimport static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
271ed0d89e7e9a28a5dd52fdc40425466efd8d08efWale Ogunwaleimport static com.android.server.wm.WindowManagerService.H.RESIZE_TASK;
28c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhangimport static com.android.server.wm.WindowManagerService.H.SHOW_NON_RESIZEABLE_DOCK_TOAST;
29c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhangimport static android.view.WindowManager.DOCKED_INVALID;
30c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhangimport static android.view.WindowManager.DOCKED_LEFT;
31c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhangimport static android.view.WindowManager.DOCKED_RIGHT;
32c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhangimport static android.view.WindowManager.DOCKED_TOP;
3399db1863a84364339fc5dc9142f15910cdd96ed8Wale Ogunwale
343797c22ea16e932329ebffdc7e7ce09f9ecd9545Wale Ogunwaleimport android.app.ActivityManager.StackId;
35e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwaleimport android.content.res.Configuration;
36e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwaleimport android.graphics.Rect;
372c2549c5f44b712dbbf66a69d91f07d6f5336ee6Craig Mautnerimport android.util.EventLog;
3842bf39edbdad19f51497938d0a3469dd772f19e8Craig Mautnerimport android.util.Slog;
39e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwaleimport android.view.DisplayInfo;
40e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwaleimport android.view.Surface;
41e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
42e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautnerimport com.android.server.EventLogTags;
432c2549c5f44b712dbbf66a69d91f07d6f5336ee6Craig Mautner
44e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwaleimport java.io.PrintWriter;
45e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwaleimport java.util.ArrayList;
46e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
47e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwaleclass Task implements DimLayer.DimLayerUser {
482cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale    // Return value from {@link setBounds} indicating no change was made to the Task bounds.
492cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale    static final int BOUNDS_CHANGE_NONE = 0;
502cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale    // Return value from {@link setBounds} indicating the position of the Task bounds changed.
512cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale    static final int BOUNDS_CHANGE_POSITION = 1;
522cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale    // Return value from {@link setBounds} indicating the size of the Task bounds changed.
532cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale    static final int BOUNDS_CHANGE_SIZE = 1 << 1;
542cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale
55c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    TaskStack mStack;
5605d6272bad2d707b488a6f8784ce8aea5e25b110Craig Mautner    final AppTokenList mAppTokens = new AppTokenList();
5783162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner    final int mTaskId;
58ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner    final int mUserId;
599ef471f7f2f59de032d7cb9c3c7241486109979eCraig Mautner    boolean mDeferRemoval = false;
60e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner    final WindowManagerService mService;
61b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner
62e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    // Content limits relative to the DisplayContent this sits in.
63e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    private Rect mBounds = new Rect();
640429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi    final Rect mPreparedFrozenBounds = new Rect();
65e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
66dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi    // Bounds used to calculate the insets.
67dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi    private final Rect mTempInsetBounds = new Rect();
68dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi
69e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    // Device rotation as of the last time {@link #mBounds} was set.
70e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    int mRotation;
71e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
72e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    // Whether mBounds is fullscreen
73e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    private boolean mFullscreen = true;
74e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
75e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    // Contains configurations settings that are different from the global configuration due to
76e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    // stack specific operations. E.g. {@link #setBounds}.
77e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    Configuration mOverrideConfig;
78e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
79e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    // For comparison with DisplayContent bounds.
80e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    private Rect mTmpRect = new Rect();
81e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    // For handling display rotations.
82e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    private Rect mTmpRect2 = new Rect();
83e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
84b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    // Whether the task is resizeable
85b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    private boolean mResizeable;
86b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang
87c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang    // Whether we need to show toast about the app being non-resizeable when it becomes visible.
88c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang    // This flag is set when a non-resizeable task is docked (or side-by-side). It's cleared
89c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang    // after we show the toast.
90c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang    private boolean mShowNonResizeableDockToast;
91c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang
923005e75585dcda30b64603e320e0711b583624ddChong Zhang    // Whether the task is currently being drag-resized
933005e75585dcda30b64603e320e0711b583624ddChong Zhang    private boolean mDragResizing;
943005e75585dcda30b64603e320e0711b583624ddChong Zhang
95ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski    Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
96ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski            Configuration config) {
9783162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        mTaskId = taskId;
98c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        mStack = stack;
99ac6f843c917b68ea8805711965b149a9338e3a0eCraig Mautner        mUserId = userId;
100e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner        mService = service;
101ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski        setBounds(bounds, config);
102c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    }
103c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
104c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    DisplayContent getDisplayContent() {
105c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        return mStack.getDisplayContent();
106c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    }
107c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
108c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang    void setShowNonResizeableDockToast() {
109c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        mShowNonResizeableDockToast = true;
110c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang    }
111c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang
112c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang    void scheduleShowNonResizeableDockToastIfNeeded() {
113c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        if (!mShowNonResizeableDockToast) {
114c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang            return;
115c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        }
116c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        final DisplayContent displayContent = mStack.getDisplayContent();
117c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        // If docked stack is not yet visible, we don't want to show the toast yet,
118c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        // since we need the visible rect of the docked task to position the toast.
119c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        if (displayContent == null || displayContent.getDockedStackLocked() == null) {
120c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang            return;
121c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        }
122c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang
123c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        mShowNonResizeableDockToast = false;
124c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang
125c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        final int dockSide = mStack.getDockSide();
126c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        int xOffset = 0;
127c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        int yOffset = 0;
128c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        if (dockSide != DOCKED_INVALID) {
129c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang            mStack.getBounds(mTmpRect);
130c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang            displayContent.getLogicalDisplayRect(mTmpRect2);
131c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang
132c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang            if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
133c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang                xOffset = mTmpRect.centerX() - mTmpRect2.centerX();
134c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang            } else if (dockSide == DOCKED_TOP) {
135c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang                // We don't adjust for DOCKED_BOTTOM case since it's already at the bottom.
136c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang                yOffset = mTmpRect2.bottom - mTmpRect.bottom;
137c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang            }
138c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang            mService.mH.obtainMessage(
139c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang                    SHOW_NON_RESIZEABLE_DOCK_TOAST, xOffset, yOffset).sendToTarget();
140c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang        }
141c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang    }
142c806d90e656a24dc8f50ef0d3f8bc99b9ac65afeChong Zhang
143c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    void addAppToken(int addPos, AppWindowToken wtoken) {
14442bf39edbdad19f51497938d0a3469dd772f19e8Craig Mautner        final int lastPos = mAppTokens.size();
14583162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        if (addPos >= lastPos) {
14683162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner            addPos = lastPos;
14783162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        } else {
14883162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner            for (int pos = 0; pos < lastPos && pos < addPos; ++pos) {
14983162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner                if (mAppTokens.get(pos).removed) {
15083162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner                    // addPos assumes removed tokens are actually gone.
15183162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner                    ++addPos;
15283162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner                }
15301f79cf91610ec9f85345ea6eeae50ea2f28578fCraig Mautner            }
15442bf39edbdad19f51497938d0a3469dd772f19e8Craig Mautner        }
155c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        mAppTokens.add(addPos, wtoken);
15683162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        wtoken.mTask = this;
15742bf39edbdad19f51497938d0a3469dd772f19e8Craig Mautner        mDeferRemoval = false;
158c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    }
159c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner
160e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner    void removeLocked() {
161e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner        if (!mAppTokens.isEmpty() && mStack.isAnimating()) {
1620bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynski            if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: deferring removing taskId=" + mTaskId);
163e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner            mDeferRemoval = true;
164e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner            return;
165e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner        }
1660bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynski        if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: removing taskId=" + mTaskId);
16783162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
168e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner        mDeferRemoval = false;
1690689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski        DisplayContent content = getDisplayContent();
1700689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski        if (content != null) {
171112eb8c1f76fff6a670d7c5f85e8c3d656cd3aa8Chong Zhang            content.mDimLayerController.removeDimLayerUser(this);
1720689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski        }
173e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner        mStack.removeTask(this);
17483162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        mService.mTaskIdToTask.delete(mTaskId);
175e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner    }
176e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner
17753a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale    void moveTaskToStack(TaskStack stack, boolean toTop) {
17853a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale        if (stack == mStack) {
17953a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale            return;
18053a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale        }
1810bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynski        if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: removing taskId=" + mTaskId
18253a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale                + " from stack=" + mStack);
183000957cef387dc7d08fc6563e2221e9023194984Wale Ogunwale        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
18453a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale        if (mStack != null) {
18553a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale            mStack.removeTask(this);
18653a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale        }
18753a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale        stack.addTask(this, toTop);
18853a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale    }
18953a29a90f35f72462c0d6ad650921d5566c1f8f0Wale Ogunwale
190935e50292e1404dc5f1705b2a1719cdaee3072b0Wale Ogunwale    void positionTaskInStack(TaskStack stack, int position, Rect bounds, Configuration config) {
191ddc1cb2c15549ed23dce9d416680a009fa6ae23cWale Ogunwale        if (mStack != null && stack != mStack) {
1920bd180d8880b3d1b9677f154c034a2af840b4796Filip Gruszczynski            if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskInStack: removing taskId=" + mTaskId
193ddc1cb2c15549ed23dce9d416680a009fa6ae23cWale Ogunwale                    + " from stack=" + mStack);
194ddc1cb2c15549ed23dce9d416680a009fa6ae23cWale Ogunwale            EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
195ddc1cb2c15549ed23dce9d416680a009fa6ae23cWale Ogunwale            mStack.removeTask(this);
196ddc1cb2c15549ed23dce9d416680a009fa6ae23cWale Ogunwale        }
197ddc1cb2c15549ed23dce9d416680a009fa6ae23cWale Ogunwale        stack.positionTask(this, position, showForAllUsers());
198935e50292e1404dc5f1705b2a1719cdaee3072b0Wale Ogunwale        setBounds(bounds, config);
199ddc1cb2c15549ed23dce9d416680a009fa6ae23cWale Ogunwale    }
200ddc1cb2c15549ed23dce9d416680a009fa6ae23cWale Ogunwale
201c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner    boolean removeAppToken(AppWindowToken wtoken) {
20242bf39edbdad19f51497938d0a3469dd772f19e8Craig Mautner        boolean removed = mAppTokens.remove(wtoken);
203c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        if (mAppTokens.size() == 0) {
2040429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi            EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeAppToken: last token");
205e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner            if (mDeferRemoval) {
206e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner                removeLocked();
207e3119b7d353e71d1f94ddff932b722b4d285931eCraig Mautner            }
208c00204b4d14d49a0417b44ca21aee4f0d4c466e0Craig Mautner        }
20983162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        wtoken.mTask = null;
21083162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        /* Leave mTaskId for now, it might be useful for debug
21183162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        wtoken.mTaskId = -1;
21283162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner         */
21342bf39edbdad19f51497938d0a3469dd772f19e8Craig Mautner        return removed;
214b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner    }
2155d9c7be84d9628c1cf199fcf9015942835c4671bCraig Mautner
216cbd84af39a329890013b0c3b6763280ba2ad78c9Craig Mautner    void setSendingToBottom(boolean toBottom) {
217cbd84af39a329890013b0c3b6763280ba2ad78c9Craig Mautner        for (int appTokenNdx = 0; appTokenNdx < mAppTokens.size(); appTokenNdx++) {
218cbd84af39a329890013b0c3b6763280ba2ad78c9Craig Mautner            mAppTokens.get(appTokenNdx).sendingToBottom = toBottom;
219cbd84af39a329890013b0c3b6763280ba2ad78c9Craig Mautner        }
220cbd84af39a329890013b0c3b6763280ba2ad78c9Craig Mautner    }
221cbd84af39a329890013b0c3b6763280ba2ad78c9Craig Mautner
222ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski    /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
2232cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale    int setBounds(Rect bounds, Configuration config) {
224ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski        if (config == null) {
225ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski            config = Configuration.EMPTY;
226b34a7ad1af54132b6b046ab8f768e0ffb81cf581Wale Ogunwale        }
227ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski        if (bounds == null && !Configuration.EMPTY.equals(config)) {
228ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski            throw new IllegalArgumentException("null bounds but non empty configuration: "
229ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski                    + config);
230b34a7ad1af54132b6b046ab8f768e0ffb81cf581Wale Ogunwale        }
231ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski        if (bounds != null && Configuration.EMPTY.equals(config)) {
232ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski            throw new IllegalArgumentException("non null bounds, but empty configuration");
233b34a7ad1af54132b6b046ab8f768e0ffb81cf581Wale Ogunwale        }
234e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        boolean oldFullscreen = mFullscreen;
235e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        int rotation = Surface.ROTATION_0;
236e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        final DisplayContent displayContent = mStack.getDisplayContent();
237e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        if (displayContent != null) {
238e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            displayContent.getLogicalDisplayRect(mTmpRect);
239e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            rotation = displayContent.getDisplayInfo().rotation;
240e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            if (bounds == null) {
241e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale                bounds = mTmpRect;
242e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale                mFullscreen = true;
243e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            } else {
244e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale                mFullscreen = mTmpRect.equals(bounds);
245e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            }
246e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        }
247e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
248e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        if (bounds == null) {
249e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            // Can't set to fullscreen if we don't have a display to get bounds from...
2502cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale            return BOUNDS_CHANGE_NONE;
251e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        }
252e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
2532cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale            return BOUNDS_CHANGE_NONE;
2542cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale        }
2552cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale
2562cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale        int boundsChange = BOUNDS_CHANGE_NONE;
25748a87a542684bcfd4d5356c7489f9f5f37510c71Chong Zhang        if (mBounds.left != bounds.left || mBounds.top != bounds.top) {
2582cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale            boundsChange |= BOUNDS_CHANGE_POSITION;
2592cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale        }
2602cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale        if (mBounds.width() != bounds.width() || mBounds.height() != bounds.height()) {
2612cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale            boundsChange |= BOUNDS_CHANGE_SIZE;
262e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        }
263e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
264e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        mBounds.set(bounds);
265e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        mRotation = rotation;
2660689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski        if (displayContent != null) {
267112eb8c1f76fff6a670d7c5f85e8c3d656cd3aa8Chong Zhang            displayContent.mDimLayerController.updateDimLayer(this);
2680689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski        }
269ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski        mOverrideConfig = mFullscreen ? Configuration.EMPTY : config;
2702cc92f55c0257cdc837585b36987c610fb0a8251Wale Ogunwale        return boundsChange;
271e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    }
272e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
273dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi    /**
274dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi     * Sets the bounds used to calculate the insets. See
275dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi     * {@link android.app.IActivityManager#resizeDockedStack} why this is needed.
276dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi     */
277dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi    void setTempInsetBounds(Rect tempInsetBounds) {
278dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi        if (tempInsetBounds != null) {
279dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi            mTempInsetBounds.set(tempInsetBounds);
280dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi        } else {
281dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi            mTempInsetBounds.setEmpty();
282dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi        }
283dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi    }
284dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi
285dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi    /**
286dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi     * Gets the bounds used to calculate the insets. See
287dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi     * {@link android.app.IActivityManager#resizeDockedStack} why this is needed.
288dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi     */
289dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi    void getTempInsetBounds(Rect out) {
290dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi        out.set(mTempInsetBounds);
291dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi    }
292dc249c4ae7c7838928f53f151bfda8a6817b8784Jorim Jaggi
293b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    void setResizeable(boolean resizeable) {
294b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        mResizeable = resizeable;
295b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    }
296b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang
297b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    boolean isResizeable() {
298b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        return mResizeable;
299b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    }
300b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang
30187b21722c2336490ecf8b66f6acfc46ce8cc6f46Chong Zhang    boolean resizeLocked(Rect bounds, Configuration configuration, boolean forced) {
3023005e75585dcda30b64603e320e0711b583624ddChong Zhang        int boundsChanged = setBounds(bounds, configuration);
30387b21722c2336490ecf8b66f6acfc46ce8cc6f46Chong Zhang        if (forced) {
3043005e75585dcda30b64603e320e0711b583624ddChong Zhang            boundsChanged |= BOUNDS_CHANGE_SIZE;
3053005e75585dcda30b64603e320e0711b583624ddChong Zhang        }
3063005e75585dcda30b64603e320e0711b583624ddChong Zhang        if (boundsChanged == BOUNDS_CHANGE_NONE) {
3073005e75585dcda30b64603e320e0711b583624ddChong Zhang            return false;
3083005e75585dcda30b64603e320e0711b583624ddChong Zhang        }
3093005e75585dcda30b64603e320e0711b583624ddChong Zhang        if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
3103005e75585dcda30b64603e320e0711b583624ddChong Zhang            resizeWindows();
311bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang        } else {
312bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang            moveWindows();
3133005e75585dcda30b64603e320e0711b583624ddChong Zhang        }
3143005e75585dcda30b64603e320e0711b583624ddChong Zhang        return true;
3153005e75585dcda30b64603e320e0711b583624ddChong Zhang    }
3163005e75585dcda30b64603e320e0711b583624ddChong Zhang
3170429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi    /**
3180429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi     * Prepares the task bounds to be frozen with the current size. See
3190429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi     * {@link AppWindowToken#freezeBounds}.
3200429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi     */
3210429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi    void prepareFreezingBounds() {
3220429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi        mPreparedFrozenBounds.set(mBounds);
3230429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi    }
3240429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi
325b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    boolean scrollLocked(Rect bounds) {
326b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        // shift the task bound if it doesn't fully cover the stack area
327b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        mStack.getDimBounds(mTmpRect);
328b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        if (mService.mCurConfiguration.orientation == ORIENTATION_LANDSCAPE) {
329b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            if (bounds.left > mTmpRect.left) {
330b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                bounds.left = mTmpRect.left;
331b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                bounds.right = mTmpRect.left + mBounds.width();
332b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            } else if (bounds.right < mTmpRect.right) {
333b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                bounds.left = mTmpRect.right - mBounds.width();
334b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                bounds.right = mTmpRect.right;
335b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            }
336b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        } else {
337b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            if (bounds.top > mTmpRect.top) {
338b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                bounds.top = mTmpRect.top;
339b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                bounds.bottom = mTmpRect.top + mBounds.height();
340b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            } else if (bounds.bottom < mTmpRect.bottom) {
341b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                bounds.top = mTmpRect.bottom - mBounds.height();
342b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                bounds.bottom = mTmpRect.bottom;
343b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            }
344b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        }
345b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang
346b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        if (bounds.equals(mBounds)) {
347b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            return false;
348b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        }
349b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        // Normal setBounds() does not allow non-null bounds for fullscreen apps.
350b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        // We only change bounds for the scrolling case without change it size,
351b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        // on resizing path we should still want the validation.
352b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        mBounds.set(bounds);
353b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
354b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
355b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
356b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                final WindowState win = windows.get(winNdx);
357b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                win.mXOffset = bounds.left;
358b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                win.mYOffset = bounds.top;
359b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang            }
360b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        }
361b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        return true;
362b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    }
363b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang
364f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale    /** Return true if the current bound can get outputted to the rest of the system as-is. */
365f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale    private boolean useCurrentBounds() {
366f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        final DisplayContent displayContent = mStack.getDisplayContent();
367f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        if (mFullscreen
3683797c22ea16e932329ebffdc7e7ce09f9ecd9545Wale Ogunwale                || !StackId.isTaskResizeableByDockedStack(mStack.mStackId)
369f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale                || displayContent == null
370f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale                || displayContent.getDockedStackLocked() != null) {
371f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale            return true;
372f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        }
373f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        return false;
374f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale    }
375f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale
3764c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang    /** Original bounds of the task if applicable, otherwise fullscreen rect. */
3770689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski    public void getBounds(Rect out) {
378f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        if (useCurrentBounds()) {
379f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale            // No need to adjust the output bounds if fullscreen or the docked stack is visible
380f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale            // since it is already what we want to represent to the rest of the system.
381f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale            out.set(mBounds);
382f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale            return;
383f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        }
384f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale
385f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
386f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
387f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        // system.
388f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        mStack.getDisplayContent().getLogicalDisplayRect(out);
389e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    }
390e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
3914c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang    /**
3924c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     * Calculate the maximum visible area of this task. If the task has only one app,
3934c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     * the result will be visible frame of that app. If the task has more than one apps,
3944c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     * we search from top down if the next app got different visible area.
3954c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     *
3964c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     * This effort is to handle the case where some task (eg. GMail composer) might pop up
3974c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     * a dialog that's different in size from the activity below, in which case we should
3984c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     * be dimming the entire task area behind the dialog.
3994c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     *
4004c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     * @param out Rect containing the max visible bounds.
4014c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     * @return true if the task has some visible app windows; false otherwise.
4024c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang     */
4034c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang    boolean getMaxVisibleBounds(Rect out) {
4044c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        boolean foundTop = false;
4054c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        for (int i = mAppTokens.size() - 1; i >= 0; i--) {
406d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang            final AppWindowToken token = mAppTokens.get(i);
407d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang            // skip hidden (or about to hide) apps
408d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang            if (token.mIsExiting || token.clientHidden || token.hiddenRequested) {
409d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang                continue;
410d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang            }
411d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang            final WindowState win = token.findMainWindow();
4124c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            if (win == null) {
4134c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang                continue;
4144c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            }
4154c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            if (!foundTop) {
4164c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang                out.set(win.mVisibleFrame);
4174c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang                foundTop = true;
4184c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang                continue;
4194c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            }
4204c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            if (win.mVisibleFrame.left < out.left) {
4214c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang                out.left = win.mVisibleFrame.left;
4224c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            }
4234c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            if (win.mVisibleFrame.top < out.top) {
4244c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang                out.top = win.mVisibleFrame.top;
4254c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            }
4264c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            if (win.mVisibleFrame.right > out.right) {
4274c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang                out.right = win.mVisibleFrame.right;
4284c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            }
4294c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            if (win.mVisibleFrame.bottom > out.bottom) {
4304c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang                out.bottom = win.mVisibleFrame.bottom;
4314c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            }
4324c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        }
4334c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        return foundTop;
4344c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang    }
4354c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang
4364c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang    /** Bounds of the task to be used for dimming, as well as touch related tests. */
4374c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang    @Override
4384c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang    public void getDimBounds(Rect out) {
4394c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        if (useCurrentBounds()) {
4404c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            if (inFreeformWorkspace() && getMaxVisibleBounds(out)) {
4414c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang                return;
4424c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            }
4434c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang
4444c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            out.set(mBounds);
4454c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang            return;
4464c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        }
4474c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang
4484c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
4494c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
4504c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        // system.
4514c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang        mStack.getDisplayContent().getLogicalDisplayRect(out);
4524c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang    }
4534c9ba52acad52f1c1087415e04b2a17614707e40Chong Zhang
4543005e75585dcda30b64603e320e0711b583624ddChong Zhang    void setDragResizing(boolean dragResizing) {
4553005e75585dcda30b64603e320e0711b583624ddChong Zhang        mDragResizing = dragResizing;
4563005e75585dcda30b64603e320e0711b583624ddChong Zhang    }
4573005e75585dcda30b64603e320e0711b583624ddChong Zhang
4583005e75585dcda30b64603e320e0711b583624ddChong Zhang    boolean isDragResizing() {
4593005e75585dcda30b64603e320e0711b583624ddChong Zhang        return mDragResizing;
4603005e75585dcda30b64603e320e0711b583624ddChong Zhang    }
4613005e75585dcda30b64603e320e0711b583624ddChong Zhang
462e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    void updateDisplayInfo(final DisplayContent displayContent) {
463e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        if (displayContent == null) {
464e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            return;
465e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        }
466e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        if (mFullscreen) {
467ebcc875f10f05db7365cd8afbf4e9425221ab14dFilip Gruszczynski            setBounds(null, Configuration.EMPTY);
468e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            return;
469e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        }
470e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        final int newRotation = displayContent.getDisplayInfo().rotation;
471e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        if (mRotation == newRotation) {
472e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            return;
473e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        }
474e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
475e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        // Device rotation changed. We don't want the task to move around on the screen when
476e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        // this happens, so update the task bounds so it stays in the same place.
4779474421a56c8bf66086a9d253013687eb5207331Wale Ogunwale        mTmpRect2.set(mBounds);
4789474421a56c8bf66086a9d253013687eb5207331Wale Ogunwale        displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
4791ed0d89e7e9a28a5dd52fdc40425466efd8d08efWale Ogunwale        if (setBounds(mTmpRect2, mOverrideConfig) != BOUNDS_CHANGE_NONE) {
4801ed0d89e7e9a28a5dd52fdc40425466efd8d08efWale Ogunwale            // Post message to inform activity manager of the bounds change simulating
4811ed0d89e7e9a28a5dd52fdc40425466efd8d08efWale Ogunwale            // a one-way call. We do this to prevent a deadlock between window manager
48244bc4daff31d2d6f632695008a0e5f5272ff4f56Filip Gruszczynski            // lock and activity manager lock been held. Only tasks within the freeform stack
48344bc4daff31d2d6f632695008a0e5f5272ff4f56Filip Gruszczynski            // are resizeable independently of their stack resizing.
48444bc4daff31d2d6f632695008a0e5f5272ff4f56Filip Gruszczynski            if (mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
48544bc4daff31d2d6f632695008a0e5f5272ff4f56Filip Gruszczynski                mService.mH.sendMessage(mService.mH.obtainMessage(
48644bc4daff31d2d6f632695008a0e5f5272ff4f56Filip Gruszczynski                        RESIZE_TASK, mTaskId, RESIZE_MODE_SYSTEM_SCREEN_ROTATION, mBounds));
48744bc4daff31d2d6f632695008a0e5f5272ff4f56Filip Gruszczynski            }
4881ed0d89e7e9a28a5dd52fdc40425466efd8d08efWale Ogunwale        }
489e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    }
490e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
491e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    void resizeWindows() {
492e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
493e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
494e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
495e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
496e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale                final WindowState win = windows.get(winNdx);
497e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale                if (!resizingWindows.contains(win)) {
498bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang                    if (DEBUG_RESIZE) Slog.d(TAG_WM, "resizeWindows: Resizing " + win);
499e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale                    resizingWindows.add(win);
500e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale                }
501e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale            }
502e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        }
503e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    }
504e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
505bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang    void moveWindows() {
506bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang        for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
507bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang            final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
508bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
509bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang                final WindowState win = windows.get(winNdx);
510bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang                if (DEBUG_RESIZE) Slog.d(TAG_WM, "moveWindows: Moving " + win);
511bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang                win.mMovedByResize = true;
512bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang            }
513bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang        }
514bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang    }
515bd0d937303ae54d8a5bb5f08080c4164302daefcChong Zhang
516c28098f69b8ba5d3039ecd0fa154e880f4613843Winson    /**
517c28098f69b8ba5d3039ecd0fa154e880f4613843Winson     * Cancels any running app transitions associated with the task.
518c28098f69b8ba5d3039ecd0fa154e880f4613843Winson     */
519c28098f69b8ba5d3039ecd0fa154e880f4613843Winson    void cancelTaskWindowTransition() {
520c28098f69b8ba5d3039ecd0fa154e880f4613843Winson        for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
521c28098f69b8ba5d3039ecd0fa154e880f4613843Winson            mAppTokens.get(activityNdx).mAppAnimator.clearAnimation();
522c28098f69b8ba5d3039ecd0fa154e880f4613843Winson        }
523c28098f69b8ba5d3039ecd0fa154e880f4613843Winson    }
524c28098f69b8ba5d3039ecd0fa154e880f4613843Winson
52513d30660ef6da2d924e4fc943ccd187767ee0cd2Winson    /**
52613d30660ef6da2d924e4fc943ccd187767ee0cd2Winson     * Cancels any running thumbnail transitions associated with the task.
52713d30660ef6da2d924e4fc943ccd187767ee0cd2Winson     */
52813d30660ef6da2d924e4fc943ccd187767ee0cd2Winson    void cancelTaskThumbnailTransition() {
52913d30660ef6da2d924e4fc943ccd187767ee0cd2Winson        for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
53013d30660ef6da2d924e4fc943ccd187767ee0cd2Winson            mAppTokens.get(activityNdx).mAppAnimator.clearThumbnail();
53113d30660ef6da2d924e4fc943ccd187767ee0cd2Winson        }
53213d30660ef6da2d924e4fc943ccd187767ee0cd2Winson    }
53313d30660ef6da2d924e4fc943ccd187767ee0cd2Winson
5346dfdfd6741c5a3dd8d8a49ddbd6ee5dfe2fd292dWale Ogunwale    boolean showForAllUsers() {
5353fcb4a89750d6df42f850021cd754500fc084086Wale Ogunwale        final int tokensCount = mAppTokens.size();
5366dfdfd6741c5a3dd8d8a49ddbd6ee5dfe2fd292dWale Ogunwale        return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers;
5373fcb4a89750d6df42f850021cd754500fc084086Wale Ogunwale    }
5383fcb4a89750d6df42f850021cd754500fc084086Wale Ogunwale
539db20b5f7a1fdb847f2266df0fbae6046dc95c757Chong Zhang    boolean inHomeStack() {
540db20b5f7a1fdb847f2266df0fbae6046dc95c757Chong Zhang        return mStack != null && mStack.mStackId == HOME_STACK_ID;
541db20b5f7a1fdb847f2266df0fbae6046dc95c757Chong Zhang    }
542db20b5f7a1fdb847f2266df0fbae6046dc95c757Chong Zhang
54309b21efb97d539543259b33e2da9d4c7a41966c8Chong Zhang    boolean inFreeformWorkspace() {
54409b21efb97d539543259b33e2da9d4c7a41966c8Chong Zhang        return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
54509b21efb97d539543259b33e2da9d4c7a41966c8Chong Zhang    }
54609b21efb97d539543259b33e2da9d4c7a41966c8Chong Zhang
547955b2fc732382022959889e90694801c36b8a71aFilip Gruszczynski    boolean inDockedWorkspace() {
548955b2fc732382022959889e90694801c36b8a71aFilip Gruszczynski        return mStack != null && mStack.mStackId == DOCKED_STACK_ID;
549955b2fc732382022959889e90694801c36b8a71aFilip Gruszczynski    }
550955b2fc732382022959889e90694801c36b8a71aFilip Gruszczynski
551b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    boolean isResizeableByDockedStack() {
552b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        return mStack != null && getDisplayContent().getDockedStackLocked() != null &&
553b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang                StackId.isTaskResizeableByDockedStack(mStack.mStackId);
554b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    }
555b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang
556b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    /**
557b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang     * Whether the task should be treated as if it's docked. Returns true if the task
558b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang     * is currently in docked workspace, or it's side-by-side to a docked task.
559b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang     */
560b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    boolean isDockedInEffect() {
561b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang        return inDockedWorkspace() || isResizeableByDockedStack();
562b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang    }
563b15758ab7a6481717d0d29612e870d7241061c31Chong Zhang
564d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang    WindowState getTopVisibleAppMainWindow() {
565d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang        final AppWindowToken token = getTopVisibleAppToken();
566d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang        return token != null ? token.findMainWindow() : null;
5679184ec686072e9343c9dd73cf45324e5e89e042fChong Zhang    }
568bef461f6129044bc092f0c3693bfc122d1acb6d1Chong Zhang
569d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang    AppWindowToken getTopVisibleAppToken() {
570d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang        for (int i = mAppTokens.size() - 1; i >= 0; i--) {
571d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang            final AppWindowToken token = mAppTokens.get(i);
572d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang            // skip hidden (or about to hide) apps
573d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang            if (!token.mIsExiting && !token.clientHidden && !token.hiddenRequested) {
574d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang                return token;
575d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang            }
576d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang        }
577d8ceb85512f8dc2dac6ef07fc72f89a75095e3d7Chong Zhang        return null;
578bef461f6129044bc092f0c3693bfc122d1acb6d1Chong Zhang    }
5799184ec686072e9343c9dd73cf45324e5e89e042fChong Zhang
5805d9c7be84d9628c1cf199fcf9015942835c4671bCraig Mautner    @Override
581e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    public boolean isFullscreen() {
582f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        if (useCurrentBounds()) {
583f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale            return mFullscreen;
584f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        }
585f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
586f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
587f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        // system.
588f175e8a6d0d3f3ce6be94bde451e6e03f67d0705Wale Ogunwale        return true;
589e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    }
590e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
591e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    @Override
592e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    public DisplayInfo getDisplayInfo() {
593e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale        return mStack.getDisplayContent().getDisplayInfo();
594e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    }
595e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
596e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    @Override
5975d9c7be84d9628c1cf199fcf9015942835c4671bCraig Mautner    public String toString() {
59883162a90278d9d52d8fca7ee20ba314b452261deCraig Mautner        return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
5995d9c7be84d9628c1cf199fcf9015942835c4671bCraig Mautner    }
600e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale
6010689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski    @Override
6020689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski    public String toShortString() {
6030689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski        return "Task=" + mTaskId;
6040689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski    }
6050689ae903628f12ff073376b655b9d972533796bFilip Gruszczynski
606e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    public void printTo(String prefix, PrintWriter pw) {
60756b88afcbdd190e8448fd17db91f2bf94e00c1faWale Ogunwale        pw.print(prefix); pw.print("taskId="); pw.println(mTaskId);
60856b88afcbdd190e8448fd17db91f2bf94e00c1faWale Ogunwale            pw.print(prefix + prefix); pw.print("mFullscreen="); pw.println(mFullscreen);
60956b88afcbdd190e8448fd17db91f2bf94e00c1faWale Ogunwale            pw.print(prefix + prefix); pw.print("mBounds="); pw.println(mBounds.toShortString());
61056b88afcbdd190e8448fd17db91f2bf94e00c1faWale Ogunwale            pw.print(prefix + prefix); pw.print("mdr="); pw.println(mDeferRemoval);
61156b88afcbdd190e8448fd17db91f2bf94e00c1faWale Ogunwale            pw.print(prefix + prefix); pw.print("appTokens="); pw.println(mAppTokens);
6120429f3522bca5bb86378dd3f013f995484ddbed6Jorim Jaggi            pw.print(prefix + prefix); pw.print("mTempInsetBounds="); pw.println(mTempInsetBounds);
613e4a0c5722b1d8db95dfc842d716452dbbf02c86dWale Ogunwale    }
614b1fd65c0ff5784b90d765edb7e3c3115d767dff0Craig Mautner}
615