blob: 450ed2058b0d27f5f285b59f8054bd394e43764c [file] [log] [blame]
Craig Mautner59c00972012-07-30 12:10:24 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Wale Ogunwale3797c222015-10-27 14:21:58 -070019import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
Wale Ogunwale51362492016-09-08 17:49:17 -070020import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
Wale Ogunwale3797c222015-10-27 14:21:58 -070021import static android.app.ActivityManager.StackId.HOME_STACK_ID;
22import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Wale Ogunwalea77e1462016-09-28 10:09:46 -070023import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Wale Ogunwale19e452e2016-10-12 12:36:29 -070026import static android.view.Display.DEFAULT_DISPLAY;
27import static android.view.Display.FLAG_PRIVATE;
Andrii Kulian4dfb9c42016-10-11 20:06:27 -070028import static android.view.Surface.ROTATION_0;
29import static android.view.Surface.ROTATION_180;
30import static android.view.Surface.ROTATION_270;
31import static android.view.Surface.ROTATION_90;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070032import static android.view.View.GONE;
Wale Ogunwale10124582016-09-15 20:25:50 -070033import static android.view.WindowManager.DOCKED_BOTTOM;
34import static android.view.WindowManager.DOCKED_INVALID;
35import static android.view.WindowManager.DOCKED_TOP;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070036import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
37import static android.view.WindowManager.INPUT_CONSUMER_PIP;
38import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070039import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -080040import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
41import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
42import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
Wale Ogunwale494009b82016-10-21 09:01:38 -070043import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -070044import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070045import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
46import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070047import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
48import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
Wale Ogunwale494009b82016-10-21 09:01:38 -070049import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -070050import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwaleec731152016-09-08 20:18:57 -070051import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Wale Ogunwale494009b82016-10-21 09:01:38 -070052import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
Wale Ogunwaleec731152016-09-08 20:18:57 -070053import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
Wale Ogunwale494009b82016-10-21 09:01:38 -070054import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070055import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
Wale Ogunwale494009b82016-10-21 09:01:38 -070056import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070057import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
58import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
Svetoslav Ganovaa076532016-08-01 19:16:43 -070059import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
Wale Ogunwaleec731152016-09-08 20:18:57 -070060import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -070061import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070062import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
63import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -070064import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Wale Ogunwaleec731152016-09-08 20:18:57 -070065import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
Wale Ogunwale494009b82016-10-21 09:01:38 -070066import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
Wale Ogunwale10124582016-09-15 20:25:50 -070067import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -070068import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070070import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
Wale Ogunwalec69694a2016-10-18 13:51:15 -070071import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -070072import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -070073import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
Jorim Jaggife762342016-10-13 14:33:27 +020074import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070075import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
Wale Ogunwale494009b82016-10-21 09:01:38 -070076import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
Andrii Kulian839def92016-11-02 10:58:58 -070077import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
Jorim Jaggife762342016-10-13 14:33:27 +020078import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -070079import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070080import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
Wale Ogunwaleec731152016-09-08 20:18:57 -070081import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070082import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070083import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -070084import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080085import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070086import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
87import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -070088import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070089import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
90import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
91import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
92import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
Wale Ogunwale494009b82016-10-21 09:01:38 -070093import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
Wale Ogunwale19e452e2016-10-12 12:36:29 -070094import static com.android.server.wm.WindowManagerService.dipToPixel;
95import static com.android.server.wm.WindowManagerService.localLOGV;
Wale Ogunwalef7cab102016-10-25 15:25:14 -070096import static com.android.server.wm.WindowManagerService.logSurface;
Wale Ogunwale231b06e2015-09-16 12:03:09 -070097import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
Wale Ogunwale494009b82016-10-21 09:01:38 -070098import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -070099import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -0700100import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700101
Andrii Kulian3a507b52016-09-19 18:14:12 -0700102import android.annotation.NonNull;
Wale Ogunwale3797c222015-10-27 14:21:58 -0700103import android.app.ActivityManager.StackId;
Andrii Kulian441e4492016-09-29 15:25:00 -0700104import android.content.res.Configuration;
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700105import android.graphics.Bitmap;
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700106import android.graphics.Matrix;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800107import android.graphics.Rect;
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700108import android.graphics.RectF;
Craig Mautner6601b7b2013-04-29 10:29:11 -0700109import android.graphics.Region;
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100110import android.graphics.Region.Op;
Wale Ogunwaleb699ce02016-07-18 12:05:30 -0700111import android.hardware.display.DisplayManagerInternal;
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700112import android.os.Debug;
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700113import android.os.Handler;
Wale Ogunwale02319a62016-09-26 15:21:22 -0700114import android.os.IBinder;
Wale Ogunwale494009b82016-10-21 09:01:38 -0700115import android.os.RemoteException;
116import android.os.SystemClock;
Chong Zhang8e89b312015-09-09 15:09:30 -0700117import android.util.DisplayMetrics;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700118import android.util.Slog;
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700119import android.view.Display;
Craig Mautner59c00972012-07-30 12:10:24 -0700120import android.view.DisplayInfo;
Wale Ogunwaleec731152016-09-08 20:18:57 -0700121import android.view.IWindow;
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700122import android.view.InputChannel;
123import android.view.Surface;
124import android.view.SurfaceControl;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -0700125import android.view.WindowManagerPolicy;
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700126
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700127import com.android.internal.util.FastPrintWriter;
Wale Ogunwale494009b82016-10-21 09:01:38 -0700128import com.android.internal.view.IInputMethodClient;
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700129import com.android.server.input.InputWindowHandle;
Craig Mautner59c00972012-07-30 12:10:24 -0700130
Robert Carr3b716242016-08-16 16:02:21 -0700131import java.io.FileDescriptor;
Craig Mautner59c00972012-07-30 12:10:24 -0700132import java.io.PrintWriter;
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700133import java.io.StringWriter;
Craig Mautner59c00972012-07-30 12:10:24 -0700134import java.util.ArrayList;
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700135import java.util.Arrays;
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700136import java.util.Comparator;
Wale Ogunwale02319a62016-09-26 15:21:22 -0700137import java.util.HashMap;
138import java.util.Iterator;
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700139import java.util.LinkedList;
Andrii Kulian3a507b52016-09-19 18:14:12 -0700140import java.util.List;
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700141import java.util.function.BiConsumer;
142import java.util.function.Consumer;
143import java.util.function.Predicate;
Craig Mautner59c00972012-07-30 12:10:24 -0700144
Craig Mautner59c00972012-07-30 12:10:24 -0700145/**
146 * Utility class for keeping track of the WindowStates and other pertinent contents of a
147 * particular Display.
148 *
149 * IMPORTANT: No method from this class should ever be used without holding
150 * WindowManagerService.mWindowMap.
151 */
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700152class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
Wale Ogunwale824ab5c2016-10-20 09:31:56 -0700153 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
Craig Mautner59c00972012-07-30 12:10:24 -0700154
155 /** Unique identifier of this stack. */
156 private final int mDisplayId;
157
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700158 // The display only has 2 child window containers. mTaskStackContainers which contains all
159 // window containers that are related to apps (Activities) and mNonAppWindowContainers which
160 // contains all window containers not related to apps (e.g. Status bar).
161 private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
162 private final NonAppWindowContainers mNonAppWindowContainers = new NonAppWindowContainers();
163
Craig Mautner59c00972012-07-30 12:10:24 -0700164 /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
165 * from mDisplayWindows; */
Craig Mautnerdc548482014-02-05 13:35:24 -0800166 private final WindowList mWindows = new WindowList();
Craig Mautner59c00972012-07-30 12:10:24 -0700167
Wale Ogunwale02319a62016-09-26 15:21:22 -0700168 // Mapping from a token IBinder to a WindowToken object on this display.
169 private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
170
Craig Mautner59c00972012-07-30 12:10:24 -0700171 int mInitialDisplayWidth = 0;
172 int mInitialDisplayHeight = 0;
Dianne Hackborndde331c2012-08-03 14:01:57 -0700173 int mInitialDisplayDensity = 0;
Craig Mautner59c00972012-07-30 12:10:24 -0700174 int mBaseDisplayWidth = 0;
175 int mBaseDisplayHeight = 0;
Dianne Hackborndde331c2012-08-03 14:01:57 -0700176 int mBaseDisplayDensity = 0;
Jeff Brownd46747a2015-04-15 19:02:36 -0700177 boolean mDisplayScalingDisabled;
Craig Mautner2d5618c2012-10-18 13:55:47 -0700178 private final DisplayInfo mDisplayInfo = new DisplayInfo();
179 private final Display mDisplay;
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700180 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
Craig Mautner59c00972012-07-30 12:10:24 -0700181
Craig Mautner6601b7b2013-04-29 10:29:11 -0700182 Rect mBaseDisplayRect = new Rect();
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700183 private Rect mContentRect = new Rect();
Craig Mautner6601b7b2013-04-29 10:29:11 -0700184
Craig Mautner39834192012-09-02 07:47:24 -0700185 // Accessed directly by all users.
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700186 private boolean mLayoutNeeded;
Craig Mautner76a71652012-09-03 23:23:58 -0700187 int pendingLayoutChanges;
Andrii Kulian839def92016-11-02 10:58:58 -0700188 // TODO(multi-display): remove some of the usages.
Craig Mautner69b08182012-09-05 13:07:13 -0700189 final boolean isDefaultDisplay;
Craig Mautner39834192012-09-02 07:47:24 -0700190
Craig Mautnerdc548482014-02-05 13:35:24 -0800191 /** Window tokens that are in the process of exiting, but still on screen for animations. */
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700192 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800193
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800194 /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
195 * (except a future lockscreen TaskStack) moves to the top. */
Craig Mautnerde4ef022013-04-07 19:01:33 -0700196 private TaskStack mHomeStack = null;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700197
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700198 /** Detect user tapping outside of current focused task bounds .*/
199 TaskTapPointerEventListener mTapDetector;
Craig Mautnercf910b02013-04-23 11:23:27 -0700200
Craig Mautner6601b7b2013-04-29 10:29:11 -0700201 /** Detect user tapping outside of current focused stack bounds .*/
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700202 private Region mTouchExcludeRegion = new Region();
Craig Mautner6601b7b2013-04-29 10:29:11 -0700203
Craig Mautner6601b7b2013-04-29 10:29:11 -0700204 /** Save allocating when calculating rects */
Filip Gruszczynski912d9192015-12-01 16:14:04 -0800205 private final Rect mTmpRect = new Rect();
206 private final Rect mTmpRect2 = new Rect();
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700207 private final RectF mTmpRectF = new RectF();
208 private final Matrix mTmpMatrix = new Matrix();
Filip Gruszczynski912d9192015-12-01 16:14:04 -0800209 private final Region mTmpRegion = new Region();
Craig Mautner6601b7b2013-04-29 10:29:11 -0700210
Craig Mautner9d808b12013-08-06 18:00:25 -0700211 final WindowManagerService mService;
212
Craig Mautner95da1082014-02-24 17:54:35 -0800213 /** Remove this display when animation on it has completed. */
Wale Ogunwaled4a00a02016-10-10 11:29:17 -0700214 private boolean mDeferredRemoval;
Craig Mautner1bf2b872014-02-05 15:37:40 -0800215
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700216 final DockedStackDividerController mDividerControllerLocked;
Winson Chung655332c2016-10-31 13:14:28 -0700217 final PinnedStackController mPinnedStackControllerLocked;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700218
Chong Zhang112eb8c2015-11-02 11:17:00 -0800219 final DimLayerController mDimLayerController;
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700220
Filip Gruszczynskiecf67222015-12-11 15:16:36 -0800221 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
222
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700223 /** Used when rebuilding window list to keep track of windows that have been removed. */
224 private WindowState[] mRebuildTmp = new WindowState[20];
225
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700226 /**
227 * Temporary list for comparison. Always clear this after use so we don't end up with
228 * orphaned windows references
229 */
230 private final ArrayList<WindowState> mTmpWindows = new ArrayList<>();
231
232 private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
233
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700234 private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
235 new TaskForResizePointSearchResult();
236 private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult =
237 new GetWindowOnDisplaySearchResult();
238
Wale Ogunwale601a3f02016-10-17 08:39:39 -0700239 // True if this display is in the process of being removed. Used to determine if the removal of
240 // the display's direct children should be allowed.
241 private boolean mRemovingDisplay = false;
242
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700243 private final WindowLayersController mLayersController;
Wale Ogunwale0303c572016-10-20 10:16:29 -0700244 final WallpaperController mWallpaperController;
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700245 int mInputMethodAnimLayerAdjustment;
246
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800247 /**
Craig Mautner2d5618c2012-10-18 13:55:47 -0700248 * @param display May not be null.
Craig Mautnerdf88d732014-01-27 09:21:32 -0800249 * @param service You know.
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700250 * @param layersController window layer controller used to assign layer to the windows on this
251 * display.
Wale Ogunwale0303c572016-10-20 10:16:29 -0700252 * @param wallpaperController wallpaper windows controller used to adjust the positioning of the
253 * wallpaper windows in the window list.
Craig Mautner2d5618c2012-10-18 13:55:47 -0700254 */
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700255 DisplayContent(Display display, WindowManagerService service,
Wale Ogunwale0303c572016-10-20 10:16:29 -0700256 WindowLayersController layersController, WallpaperController wallpaperController) {
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700257 mDisplay = display;
258 mDisplayId = display.getDisplayId();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700259 mLayersController = layersController;
Wale Ogunwale0303c572016-10-20 10:16:29 -0700260 mWallpaperController = wallpaperController;
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700261 display.getDisplayInfo(mDisplayInfo);
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700262 display.getMetrics(mDisplayMetrics);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700263 isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
Craig Mautner9d808b12013-08-06 18:00:25 -0700264 mService = service;
Wale Ogunwalefd04d8c2015-09-30 10:09:39 -0700265 initializeDisplayBaseInfo();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800266 mDividerControllerLocked = new DockedStackDividerController(service, this);
Winson Chung655332c2016-10-31 13:14:28 -0700267 mPinnedStackControllerLocked = new PinnedStackController(service, this);
Chong Zhang112eb8c2015-11-02 11:17:00 -0800268 mDimLayerController = new DimLayerController(this);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700269
270 // These are the only direct children we should ever have and they are permanent.
271 super.addChild(mTaskStackContainers, null);
272 super.addChild(mNonAppWindowContainers, null);
Craig Mautner59c00972012-07-30 12:10:24 -0700273 }
274
275 int getDisplayId() {
276 return mDisplayId;
277 }
278
Wale Ogunwale02319a62016-09-26 15:21:22 -0700279 WindowToken getWindowToken(IBinder binder) {
280 return mTokenMap.get(binder);
281 }
282
283 AppWindowToken getAppWindowToken(IBinder binder) {
284 final WindowToken token = getWindowToken(binder);
285 if (token == null) {
286 return null;
287 }
288 return token.asAppWindowToken();
289 }
290
291 void setWindowToken(IBinder binder, WindowToken token) {
292 final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
293 if (dc != null) {
294 // We currently don't support adding a window token to the display if the display
295 // already has the binder mapped to another token. If there is a use case for supporting
296 // this moving forward we will either need to merge the WindowTokens some how or have
297 // the binder map to a list of window tokens.
298 throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this
299 + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
300 }
301 mTokenMap.put(binder, token);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700302
303 if (token.asAppWindowToken() == null) {
304 // Add non-app token to container hierarchy on the display. App tokens are added through
305 // the parent container managing them (e.g. Tasks).
306 mNonAppWindowContainers.addChild(token, null);
307 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700308 }
309
310 WindowToken removeWindowToken(IBinder binder) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700311 final WindowToken token = mTokenMap.remove(binder);
312 if (token != null && token.asAppWindowToken() == null) {
313 mNonAppWindowContainers.removeChild(token);
314 }
315 return token;
Wale Ogunwale02319a62016-09-26 15:21:22 -0700316 }
317
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700318 void removeAppToken(IBinder binder) {
319 final WindowToken token = removeWindowToken(binder);
320 if (token == null) {
321 Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
322 return;
323 }
324
325 final AppWindowToken appToken = token.asAppWindowToken();
326
327 if (appToken == null) {
328 Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
329 return;
330 }
331
332 appToken.onRemovedFromDisplay();
333 }
334
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700335 Display getDisplay() {
336 return mDisplay;
337 }
338
Craig Mautner59c00972012-07-30 12:10:24 -0700339 DisplayInfo getDisplayInfo() {
340 return mDisplayInfo;
341 }
342
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700343 DisplayMetrics getDisplayMetrics() {
344 return mDisplayMetrics;
345 }
346
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100347 DockedStackDividerController getDockedDividerController() {
348 return mDividerControllerLocked;
349 }
350
Winson Chung655332c2016-10-31 13:14:28 -0700351 PinnedStackController getPinnedStackController() {
352 return mPinnedStackControllerLocked;
353 }
354
Jeff Browna506a6e2013-06-04 00:02:38 -0700355 /**
356 * Returns true if the specified UID has access to this display.
357 */
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700358 boolean hasAccess(int uid) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700359 return mDisplay.hasAccess(uid);
360 }
361
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700362 boolean isPrivate() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700363 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
keunyounga446bf02013-06-21 19:07:57 -0700364 }
365
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700366 TaskStack getHomeStack() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700367 if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800368 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
Craig Mautnere0a38842013-12-16 16:14:02 -0800369 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700370 return mHomeStack;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700371 }
372
Chong Zhangd9d35bd2016-08-04 17:55:21 -0700373 TaskStack getStackById(int stackId) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700374 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
375 final TaskStack stack = mTaskStackContainers.get(i);
Chong Zhangd9d35bd2016-08-04 17:55:21 -0700376 if (stack.mStackId == stackId) {
377 return stack;
378 }
379 }
380 return null;
381 }
382
Andrii Kulian441e4492016-09-29 15:25:00 -0700383 @Override
384 void onConfigurationChanged(Configuration newParentConfig) {
385 super.onConfigurationChanged(newParentConfig);
386
Andrii Kulian3a507b52016-09-19 18:14:12 -0700387 // The display size information is heavily dependent on the resources in the current
388 // configuration, so we need to reconfigure it every time the configuration changes.
389 // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
390 mService.reconfigureDisplayLocked(this);
391
392 getDockedDividerController().onConfigurationChanged();
Winson Chung655332c2016-10-31 13:14:28 -0700393 getPinnedStackController().onConfigurationChanged();
Andrii Kulian441e4492016-09-29 15:25:00 -0700394 }
Andrii Kulian3a507b52016-09-19 18:14:12 -0700395
Andrii Kulian441e4492016-09-29 15:25:00 -0700396 /**
397 * Callback used to trigger bounds update after configuration change and get ids of stacks whose
398 * bounds were updated.
399 */
400 void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700401 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
402 final TaskStack stack = mTaskStackContainers.get(i);
Andrii Kulian441e4492016-09-29 15:25:00 -0700403 if (stack.updateBoundsAfterConfigChange()) {
Andrii Kulian3a507b52016-09-19 18:14:12 -0700404 changedStackList.add(stack.mStackId);
405 }
406 }
407 }
408
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700409 @Override
410 boolean fillsParent() {
411 return true;
412 }
413
414 @Override
415 boolean isVisible() {
416 return true;
417 }
418
419 @Override
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700420 void onAppTransitionDone() {
Wale Ogunwale10124582016-09-15 20:25:50 -0700421 super.onAppTransitionDone();
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700422 rebuildAppWindowList();
423 }
424
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700425 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700426 int getOrientation() {
Wale Ogunwalee6f806e2016-10-20 15:29:42 -0700427 final WindowManagerPolicy policy = mService.mPolicy;
428
429 // TODO: All the logic before the last return statement in this method should really go in
430 // #NonAppWindowContainer.getOrientation() since it is trying to decide orientation based
431 // on non-app windows. But, we can not do that until the window list is always correct in
432 // terms of z-ordering based on layers.
433 if (mService.mDisplayFrozen) {
434 if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
435 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
436 "Display is frozen, return " + mService.mLastWindowForcedOrientation);
437 // If the display is frozen, some activities may be in the middle of restarting, and
438 // thus have removed their old window. If the window has the flag to hide the lock
439 // screen, then the lock screen can re-appear and inflict its own orientation on us.
440 // Keep the orientation stable until this all settles down.
441 return mService.mLastWindowForcedOrientation;
442 } else if (policy.isKeyguardLocked()) {
443 // Use the last orientation the while the display is frozen with the keyguard
444 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
445 // window. We don't want to check the show when locked window directly though as
446 // things aren't stable while the display is frozen, for example the window could be
447 // momentarily unavailable due to activity relaunch.
448 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
449 + "return " + mService.mLastOrientation);
450 return mService.mLastOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -0700451 }
Wale Ogunwalee6f806e2016-10-20 15:29:42 -0700452 } else {
453 for (int pos = mWindows.size() - 1; pos >= 0; --pos) {
454 final WindowState win = mWindows.get(pos);
455 if (win.mAppToken != null) {
456 // We hit an application window. so the orientation will be determined by the
457 // app window. No point in continuing further.
458 break;
459 }
460 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
461 continue;
462 }
463 int req = win.mAttrs.screenOrientation;
464 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) {
465 continue;
466 }
467
468 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
469 if (policy.isKeyguardHostWindow(win.mAttrs)) {
470 mService.mLastKeyguardForcedOrientation = req;
471 }
472 return (mService.mLastWindowForcedOrientation = req);
473 }
474 mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
475
Jorim Jaggife762342016-10-13 14:33:27 +0200476 if (policy.isKeyguardShowingAndNotOccluded()) {
Wale Ogunwalee6f806e2016-10-20 15:29:42 -0700477 return mService.mLastKeyguardForcedOrientation;
478 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700479 }
480
Wale Ogunwalee6f806e2016-10-20 15:29:42 -0700481 // Top system windows are not requesting an orientation. Start searching from apps.
482 return mTaskStackContainers.getOrientation();
Wale Ogunwale51362492016-09-08 17:49:17 -0700483 }
484
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700485 void updateDisplayInfo() {
Craig Mautner722285e2012-09-07 13:55:58 -0700486 mDisplay.getDisplayInfo(mDisplayInfo);
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700487 mDisplay.getMetrics(mDisplayMetrics);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700488 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
489 mTaskStackContainers.get(i).updateDisplayInfo(null);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800490 }
Craig Mautner722285e2012-09-07 13:55:58 -0700491 }
492
Wale Ogunwalefd04d8c2015-09-30 10:09:39 -0700493 void initializeDisplayBaseInfo() {
Wale Ogunwaleb699ce02016-07-18 12:05:30 -0700494 final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
495 if (displayManagerInternal != null) {
496 // Bootstrap the default logical display from the display manager.
497 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
498 if (newDisplayInfo != null) {
499 mDisplayInfo.copyFrom(newDisplayInfo);
500 }
Wale Ogunwalefd04d8c2015-09-30 10:09:39 -0700501 }
Wale Ogunwaleb699ce02016-07-18 12:05:30 -0700502
Filip Gruszczynski608797e2015-11-12 19:08:20 -0800503 mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
504 mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
505 mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
506 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
Wale Ogunwalefd04d8c2015-09-30 10:09:39 -0700507 }
508
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700509 void getLogicalDisplayRect(Rect out) {
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700510 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
Craig Mautner4a1cb222013-12-04 16:14:06 -0800511 final int orientation = mDisplayInfo.rotation;
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700512 boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
Craig Mautner4a1cb222013-12-04 16:14:06 -0800513 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
514 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700515 int width = mDisplayInfo.logicalWidth;
Craig Mautner4a1cb222013-12-04 16:14:06 -0800516 int left = (physWidth - width) / 2;
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700517 int height = mDisplayInfo.logicalHeight;
Craig Mautner4a1cb222013-12-04 16:14:06 -0800518 int top = (physHeight - height) / 2;
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700519 out.set(left, top, left + width, top + height);
520 }
521
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700522 private void getLogicalDisplayRect(Rect out, int orientation) {
523 getLogicalDisplayRect(out);
524
525 // Rotate the Rect if needed.
526 final int currentRotation = mDisplayInfo.rotation;
527 final int rotationDelta = deltaRotation(currentRotation, orientation);
528 if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
529 createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
530 mTmpRectF.set(out);
531 mTmpMatrix.mapRect(mTmpRectF);
532 mTmpRectF.round(out);
533 }
534 }
535
Chong Zhangf66db432016-01-13 10:39:51 -0800536 void getContentRect(Rect out) {
537 out.set(mContentRect);
538 }
539
Andrii Kulian839def92016-11-02 10:58:58 -0700540 /**
541 * Adds the stack to this display.
542 * @see WindowManagerService#addStackToDisplay(int, int, boolean)
543 */
544 Rect addStackToDisplay(int stackId, boolean onTop) {
545 boolean attachedToDisplay = false;
546 TaskStack stack = mService.mStackIdToStack.get(stackId);
547 if (stack == null) {
548 if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
549 + mDisplayId);
550
551 stack = getStackById(stackId);
552 if (stack != null) {
553 // It's already attached to the display...clear mDeferRemoval and move stack to
554 // appropriate z-order on display as needed.
555 stack.mDeferRemoval = false;
556 moveStack(stack, onTop);
557 attachedToDisplay = true;
558 } else {
559 stack = new TaskStack(mService, stackId);
560 }
561
562 mService.mStackIdToStack.put(stackId, stack);
563 if (stackId == DOCKED_STACK_ID) {
564 mDividerControllerLocked.notifyDockedStackExistsChanged(true);
565 }
566 } else {
567 final DisplayContent currentDC = stack.getDisplayContent();
568 if (currentDC != null) {
569 throw new IllegalStateException("Trying to add stackId=" + stackId
570 + "to displayId=" + mDisplayId + ", but it's already attached to displayId="
571 + currentDC.getDisplayId());
572 }
573 }
574
575 if (!attachedToDisplay) {
576 mTaskStackContainers.addStackToDisplay(stack, onTop);
577 }
578
579 if (stack.getRawFullscreen()) {
580 return null;
581 }
582 final Rect bounds = new Rect();
583 stack.getRawBounds(bounds);
584 return bounds;
585 }
586
587 /** Removes the stack from the display and prepares for changing the parent. */
588 private void removeStackFromDisplay(TaskStack stack) {
589 mTaskStackContainers.removeStackFromDisplay(stack);
590 }
591
592 /** Moves the stack to this display and returns the updated bounds. */
593 Rect moveStackToDisplay(TaskStack stack) {
594 final DisplayContent currentDisplayContent = stack.getDisplayContent();
595 if (currentDisplayContent == null) {
596 throw new IllegalStateException("Trying to move stackId=" + stack.mStackId
597 + " which is not currently attached to any display");
598 }
599 if (stack.getDisplayContent().getDisplayId() == mDisplayId) {
600 throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId
601 + " to its current displayId=" + mDisplayId);
602 }
603
604 currentDisplayContent.removeStackFromDisplay(stack);
605 return addStackToDisplay(stack.mStackId, true /* onTop */);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800606 }
607
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800608 void moveStack(TaskStack stack, boolean toTop) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700609 mTaskStackContainers.moveStack(stack, toTop);
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700610 }
Wale Ogunwale1e60e0c2015-10-28 13:36:10 -0700611
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700612 @Override
613 protected void addChild(DisplayChildWindowContainer child,
614 Comparator<DisplayChildWindowContainer> comparator) {
615 throw new UnsupportedOperationException("See DisplayChildWindowContainer");
616 }
Wale Ogunwale1e60e0c2015-10-28 13:36:10 -0700617
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700618 @Override
619 protected void addChild(DisplayChildWindowContainer child, int index) {
620 throw new UnsupportedOperationException("See DisplayChildWindowContainer");
621 }
622
623 @Override
624 protected void removeChild(DisplayChildWindowContainer child) {
Wale Ogunwale601a3f02016-10-17 08:39:39 -0700625 // Only allow removal of direct children from this display if the display is in the process
626 // of been removed.
627 if (mRemovingDisplay) {
628 super.removeChild(child);
629 return;
630 }
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700631 throw new UnsupportedOperationException("See DisplayChildWindowContainer");
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800632 }
633
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700634 int taskIdFromPoint(int x, int y) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700635 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
636 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700637 final int taskId = stack.taskIdFromPoint(x, y);
638 if (taskId != -1) {
639 return taskId;
Craig Mautner967212c2013-04-13 21:10:58 -0700640 }
641 }
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800642 return -1;
Craig Mautnercf910b02013-04-23 11:23:27 -0700643 }
644
Chong Zhang8e89b312015-09-09 15:09:30 -0700645 /**
Chong Zhangd8ceb852015-11-11 14:53:41 -0800646 * Find the task whose outside touch area (for resizing) (x, y) falls within.
Chong Zhang9184ec62015-09-24 12:32:21 -0700647 * Returns null if the touch doesn't fall into a resizing area.
Chong Zhang8e89b312015-09-09 15:09:30 -0700648 */
Wale Ogunwale15ead902016-09-02 14:30:11 -0700649 Task findTaskForResizePoint(int x, int y) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700650 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700651 mTmpTaskForResizePointSearchResult.reset();
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700652 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
653 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwale3797c222015-10-27 14:21:58 -0700654 if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700655 return null;
Chong Zhang8e89b312015-09-09 15:09:30 -0700656 }
Chong Zhang9184ec62015-09-24 12:32:21 -0700657
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700658 stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult);
659 if (mTmpTaskForResizePointSearchResult.searchDone) {
660 return mTmpTaskForResizePointSearchResult.taskForResize;
Chong Zhang8e89b312015-09-09 15:09:30 -0700661 }
662 }
Chong Zhang9184ec62015-09-24 12:32:21 -0700663 return null;
Chong Zhang8e89b312015-09-09 15:09:30 -0700664 }
665
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700666 void setTouchExcludeRegion(Task focusedTask) {
Craig Mautner6601b7b2013-04-29 10:29:11 -0700667 mTouchExcludeRegion.set(mBaseDisplayRect);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700668 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700669 mTmpRect2.setEmpty();
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700670 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
671 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700672 stack.setTouchExcludeRegion(
673 focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
Craig Mautner6601b7b2013-04-29 10:29:11 -0700674 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800675 // If we removed the focused task above, add it back and only leave its
676 // outside touch area in the exclusion. TapDectector is not interested in
677 // any touch inside the focused task itself.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700678 if (!mTmpRect2.isEmpty()) {
Chong Zhangd8ceb852015-11-11 14:53:41 -0800679 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
680 }
Filip Gruszczynski912d9192015-12-01 16:14:04 -0800681 final WindowState inputMethod = mService.mInputMethodWindow;
682 if (inputMethod != null && inputMethod.isVisibleLw()) {
683 // If the input method is visible and the user is typing, we don't want these touch
684 // events to be intercepted and used to change focus. This would likely cause a
685 // disappearance of the input method.
686 inputMethod.getTouchableRegion(mTmpRegion);
687 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
688 }
Filip Gruszczynskiecf67222015-12-11 15:16:36 -0800689 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
690 WindowState win = mTapExcludedWindows.get(i);
691 win.getTouchableRegion(mTmpRegion);
692 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
693 }
Jorim Jaggife762342016-10-13 14:33:27 +0200694 if (getDockedStackLocked() != null) {
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100695 mDividerControllerLocked.getTouchRegion(mTmpRect);
Jorim Jaggi7f19cb82016-03-25 19:37:44 -0700696 mTmpRegion.set(mTmpRect);
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100697 mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
698 }
Craig Mautner1bef3892015-02-17 15:09:47 -0800699 if (mTapDetector != null) {
Chong Zhang2e2c81a2016-07-15 11:28:17 -0700700 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
Craig Mautner1bef3892015-02-17 15:09:47 -0800701 }
Craig Mautner6601b7b2013-04-29 10:29:11 -0700702 }
703
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700704 void switchUser() {
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700705 final int count = mWindows.size();
706 for (int i = 0; i < count; i++) {
707 final WindowState win = mWindows.get(i);
Craig Mautner858d8a62013-04-23 17:08:34 -0700708 if (win.isHiddenFromUserLocked()) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800709 if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win
Wale Ogunwale498e8c92015-02-13 09:42:46 -0800710 + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
Craig Mautner858d8a62013-04-23 17:08:34 -0700711 win.hideLw(false);
712 }
713 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700714
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700715 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
716 mTaskStackContainers.get(stackNdx).switchUser();
Craig Mautner858d8a62013-04-23 17:08:34 -0700717 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700718
719 rebuildAppWindowList();
Craig Mautner858d8a62013-04-23 17:08:34 -0700720 }
721
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700722 private void resetAnimationBackgroundAnimator() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700723 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
724 mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
Craig Mautner05d29032013-05-03 13:40:13 -0700725 }
726 }
727
728 boolean animateDimLayers() {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800729 return mDimLayerController.animateDimLayers();
Craig Mautner05d29032013-05-03 13:40:13 -0700730 }
731
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700732 private void resetDimming() {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800733 mDimLayerController.resetDimming();
Craig Mautner05d29032013-05-03 13:40:13 -0700734 }
735
736 boolean isDimming() {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800737 return mDimLayerController.isDimming();
Craig Mautner05d29032013-05-03 13:40:13 -0700738 }
739
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700740 private void stopDimmingIfNeeded() {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800741 mDimLayerController.stopDimmingIfNeeded();
Craig Mautner05d29032013-05-03 13:40:13 -0700742 }
743
Wale Ogunwale10124582016-09-15 20:25:50 -0700744 @Override
745 void removeIfPossible() {
746 if (isAnimating()) {
747 mDeferredRemoval = true;
748 return;
Craig Mautner2eb15342013-08-07 13:13:35 -0700749 }
Wale Ogunwale10124582016-09-15 20:25:50 -0700750 removeImmediately();
Craig Mautner2eb15342013-08-07 13:13:35 -0700751 }
752
Wale Ogunwale10124582016-09-15 20:25:50 -0700753 @Override
754 void removeImmediately() {
Wale Ogunwale601a3f02016-10-17 08:39:39 -0700755 mRemovingDisplay = true;
756 try {
757 super.removeImmediately();
758 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
759 mDimLayerController.close();
760 if (mDisplayId == DEFAULT_DISPLAY) {
761 mService.unregisterPointerEventListener(mTapDetector);
762 mService.unregisterPointerEventListener(mService.mMousePositionTracker);
763 }
764 } finally {
765 mRemovingDisplay = false;
Craig Mautner95da1082014-02-24 17:54:35 -0800766 }
Craig Mautner95da1082014-02-24 17:54:35 -0800767 }
768
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700769 /** Returns true if a removal action is still being deferred. */
Wale Ogunwale10124582016-09-15 20:25:50 -0700770 @Override
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700771 boolean checkCompleteDeferredRemoval() {
Wale Ogunwale10124582016-09-15 20:25:50 -0700772 final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
773
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700774 if (!stillDeferringRemoval && mDeferredRemoval) {
Wale Ogunwale10124582016-09-15 20:25:50 -0700775 removeImmediately();
Craig Mautner95da1082014-02-24 17:54:35 -0800776 mService.onDisplayRemoved(mDisplayId);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700777 return false;
Craig Mautner95da1082014-02-24 17:54:35 -0800778 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700779 return true;
Craig Mautner95da1082014-02-24 17:54:35 -0800780 }
781
Wale Ogunwale10124582016-09-15 20:25:50 -0700782 boolean animateForIme(float interpolatedValue, float animationTarget,
783 float dividerAnimationTarget) {
784 boolean updated = false;
785
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700786 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
787 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700788 if (stack == null || !stack.isAdjustedForIme()) {
789 continue;
790 }
791
792 if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) {
793 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
794 updated = true;
795 } else {
796 mDividerControllerLocked.mLastAnimationProgress =
797 mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue);
798 mDividerControllerLocked.mLastDividerProgress =
799 mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue);
800 updated |= stack.updateAdjustForIme(
801 mDividerControllerLocked.mLastAnimationProgress,
802 mDividerControllerLocked.mLastDividerProgress,
803 false /* force */);
804 }
805 if (interpolatedValue >= 1f) {
806 stack.endImeAdjustAnimation();
807 }
808 }
809
810 return updated;
811 }
812
813 boolean clearImeAdjustAnimation() {
814 boolean changed = false;
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700815 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
816 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700817 if (stack != null && stack.isAdjustedForIme()) {
818 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
819 changed = true;
820 }
821 }
822 return changed;
823 }
824
825 void beginImeAdjustAnimation() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700826 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
827 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700828 if (stack.isVisible() && stack.isAdjustedForIme()) {
829 stack.beginImeAdjustAnimation();
830 }
831 }
832 }
833
834 void adjustForImeIfNeeded() {
835 final WindowState imeWin = mService.mInputMethodWindow;
836 final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
837 && !mDividerControllerLocked.isImeHideRequested();
838 final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID);
839 final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
840 final int imeDockSide = (dockVisible && imeTargetStack != null) ?
841 imeTargetStack.getDockSide() : DOCKED_INVALID;
842 final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
843 final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
844 final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock();
845 final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw();
846 final boolean imeHeightChanged = imeVisible &&
847 imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
848
849 // The divider could be adjusted for IME position, or be thinner than usual,
850 // or both. There are three possible cases:
851 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
852 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
853 // - If IME is not visible, divider is not moved and is normal width.
854
855 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700856 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
857 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700858 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
859 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
860 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
861 } else {
862 stack.resetAdjustedForIme(false);
863 }
864 }
865 mDividerControllerLocked.setAdjustedForIme(
866 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
867 } else {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700868 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
869 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700870 stack.resetAdjustedForIme(!dockVisible);
871 }
872 mDividerControllerLocked.setAdjustedForIme(
873 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
874 }
Winson Chung655332c2016-10-31 13:14:28 -0700875 mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
Wale Ogunwale10124582016-09-15 20:25:50 -0700876 }
877
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700878 void setInputMethodAnimLayerAdjustment(int adj) {
879 if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
880 mInputMethodAnimLayerAdjustment = adj;
881 final WindowState imw = mService.mInputMethodWindow;
882 if (imw != null) {
883 imw.adjustAnimLayer(adj);
884 }
885 for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) {
886 final WindowState dialog = mService.mInputMethodDialogs.get(i);
887 // TODO: This and other places setting mAnimLayer can probably use WS.adjustAnimLayer,
888 // but need to make sure we are not setting things twice for child windows that are
889 // already in the list.
890 dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj;
891 if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
892 + " anim layer: " + dialog.mWinAnimator.mAnimLayer);
893 }
894 }
895
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -0700896 /**
897 * If a window that has an animation specifying a colored background and the current wallpaper
898 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
899 * suddenly disappear.
900 */
901 int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
902 for (int i = mWindows.size() - 1; i >= 0; --i) {
903 final WindowState win = mWindows.get(i);
904 if (win.mIsWallpaper && win.isVisibleNow()) {
905 return win.mWinAnimator.mAnimLayer;
906 }
907 }
908 return winAnimator.mAnimLayer;
909 }
910
Wale Ogunwale10124582016-09-15 20:25:50 -0700911 void prepareFreezingTaskBounds() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700912 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
913 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwale10124582016-09-15 20:25:50 -0700914 stack.prepareFreezingTaskBounds();
915 }
916 }
917
Wale Ogunwale94744212015-09-21 19:01:47 -0700918 void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700919 getLogicalDisplayRect(mTmpRect, newRotation);
920
921 // Compute a transform matrix to undo the coordinate space transformation,
922 // and present the window at the same physical position it previously occupied.
923 final int deltaRotation = deltaRotation(newRotation, oldRotation);
924 createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
925
926 mTmpRectF.set(bounds);
927 mTmpMatrix.mapRect(mTmpRectF);
928 mTmpRectF.round(bounds);
Wale Ogunwale94744212015-09-21 19:01:47 -0700929 }
930
Wale Ogunwale4a02d812015-02-12 23:01:38 -0800931 static int deltaRotation(int oldRotation, int newRotation) {
932 int delta = newRotation - oldRotation;
933 if (delta < 0) delta += 4;
934 return delta;
935 }
936
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700937 private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700938 Matrix outMatrix) {
939 // For rotations without Z-ordering we don't need the target rectangle's position.
940 createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
941 displayHeight, outMatrix);
942 }
943
944 static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
945 float displayWidth, float displayHeight, Matrix outMatrix) {
946 switch (rotation) {
947 case ROTATION_0:
948 outMatrix.reset();
949 break;
950 case ROTATION_270:
951 outMatrix.setRotate(270, 0, 0);
952 outMatrix.postTranslate(0, displayHeight);
953 outMatrix.postTranslate(rectTop, 0);
954 break;
955 case ROTATION_180:
956 outMatrix.reset();
957 break;
958 case ROTATION_90:
959 outMatrix.setRotate(90, 0, 0);
960 outMatrix.postTranslate(displayWidth, 0);
961 outMatrix.postTranslate(-rectTop, rectLeft);
962 break;
963 }
964 }
965
Craig Mautnera91f9e22012-09-14 16:22:08 -0700966 public void dump(String prefix, PrintWriter pw) {
967 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
968 final String subPrefix = " " + prefix;
969 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
970 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
971 pw.print("dpi");
972 if (mInitialDisplayWidth != mBaseDisplayWidth
973 || mInitialDisplayHeight != mBaseDisplayHeight
974 || mInitialDisplayDensity != mBaseDisplayDensity) {
975 pw.print(" base=");
976 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
977 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
978 }
Jeff Brownd46747a2015-04-15 19:02:36 -0700979 if (mDisplayScalingDisabled) {
980 pw.println(" noscale");
981 }
Craig Mautnera91f9e22012-09-14 16:22:08 -0700982 pw.print(" cur=");
983 pw.print(mDisplayInfo.logicalWidth);
984 pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
985 pw.print(" app=");
986 pw.print(mDisplayInfo.appWidth);
987 pw.print("x"); pw.print(mDisplayInfo.appHeight);
988 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
989 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
990 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
991 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700992 pw.println(subPrefix + "deferred=" + mDeferredRemoval
993 + " mLayoutNeeded=" + mLayoutNeeded);
Wale Ogunwaleb429e682016-01-06 12:36:34 -0800994
Craig Mautnerdc548482014-02-05 13:35:24 -0800995 pw.println();
Jorim Jaggiad5d2842016-11-01 18:22:53 -0700996 pw.println(prefix + "Application tokens in top down Z order:");
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700997 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
998 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwaleb429e682016-01-06 12:36:34 -0800999 stack.dump(prefix + " ", pw);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001000 }
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001001
Craig Mautnerdc548482014-02-05 13:35:24 -08001002 pw.println();
1003 if (!mExitingTokens.isEmpty()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001004 pw.println();
1005 pw.println(" Exiting tokens:");
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001006 for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001007 final WindowToken token = mExitingTokens.get(i);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001008 pw.print(" Exiting #"); pw.print(i);
1009 pw.print(' '); pw.print(token);
1010 pw.println(':');
1011 token.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08001012 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07001013 }
Craig Mautner59c00972012-07-30 12:10:24 -07001014 pw.println();
Jorim Jaggiad5d2842016-11-01 18:22:53 -07001015 mDimLayerController.dump(prefix, pw);
Jorim Jaggi31f71702016-05-04 16:43:04 -07001016 pw.println();
Jorim Jaggiad5d2842016-11-01 18:22:53 -07001017 mDividerControllerLocked.dump(prefix, pw);
Winson Chung655332c2016-10-31 13:14:28 -07001018 pw.println();
Jorim Jaggiad5d2842016-11-01 18:22:53 -07001019 mPinnedStackControllerLocked.dump(prefix, pw);
Wale Ogunwalec69694a2016-10-18 13:51:15 -07001020
1021 if (mInputMethodAnimLayerAdjustment != 0) {
1022 pw.println(subPrefix
1023 + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment);
1024 }
Craig Mautner59c00972012-07-30 12:10:24 -07001025 }
Craig Mautnere0a38842013-12-16 16:14:02 -08001026
1027 @Override
1028 public String toString() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001029 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001030 }
1031
1032 String getName() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001033 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
Craig Mautnere0a38842013-12-16 16:14:02 -08001034 }
Filip Gruszczynski466f3212015-09-21 17:57:57 -07001035
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001036 /**
1037 * @return The docked stack, but only if it is visible, and {@code null} otherwise.
1038 */
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001039 TaskStack getDockedStackLocked() {
Wale Ogunwalee45899a2015-10-01 11:30:34 -07001040 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001041 return (stack != null && stack.isVisible()) ? stack : null;
Filip Gruszczynski466f3212015-09-21 17:57:57 -07001042 }
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -08001043
1044 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001045 * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
Jorim Jaggife762342016-10-13 14:33:27 +02001046 * visible.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001047 */
Jorim Jaggife762342016-10-13 14:33:27 +02001048 TaskStack getDockedStackIgnoringVisibility() {
1049 return mService.mStackIdToStack.get(DOCKED_STACK_ID);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001050 }
1051
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001052 /** Find the visible, touch-deliverable window under the given point */
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -08001053 WindowState getTouchableWinAtPointLocked(float xf, float yf) {
1054 WindowState touchedWin = null;
1055 final int x = (int) xf;
1056 final int y = (int) yf;
1057
1058 for (int i = mWindows.size() - 1; i >= 0; i--) {
1059 WindowState window = mWindows.get(i);
1060 final int flags = window.mAttrs.flags;
1061 if (!window.isVisibleLw()) {
1062 continue;
1063 }
1064 if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
1065 continue;
1066 }
1067
1068 window.getVisibleBounds(mTmpRect);
1069 if (!mTmpRect.contains(x, y)) {
1070 continue;
1071 }
1072
1073 window.getTouchableRegion(mTmpRegion);
1074
1075 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
1076 if (mTmpRegion.contains(x, y) || touchFlags == 0) {
1077 touchedWin = window;
1078 break;
1079 }
1080 }
1081
1082 return touchedWin;
1083 }
Jorim Jaggi6626f542016-08-22 13:08:44 -07001084
Svetoslav Ganovaa076532016-08-01 19:16:43 -07001085 boolean canAddToastWindowForUid(int uid) {
1086 // We allow one toast window per UID being shown at a time.
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001087 final int windowCount = mWindows.size();
Svetoslav Ganovaa076532016-08-01 19:16:43 -07001088 for (int i = 0; i < windowCount; i++) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001089 final WindowState window = mWindows.get(i);
Svetoslav Ganovaa076532016-08-01 19:16:43 -07001090 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
Svet Ganov62a40f82016-09-29 00:43:51 -07001091 && !window.mPermanentlyHidden && !window.mAnimatingExit
1092 && !window.mRemoveOnExit) {
Svetoslav Ganovaa076532016-08-01 19:16:43 -07001093 return false;
1094 }
1095 }
1096 return true;
1097 }
1098
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001099 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
Svetoslav Ganovaa076532016-08-01 19:16:43 -07001100 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
1101 return;
1102 }
1103 final int lostFocusUid = oldFocus.mOwnerUid;
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001104 final int windowCount = mWindows.size();
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001105 final Handler handler = mService.mH;
Svetoslav Ganovaa076532016-08-01 19:16:43 -07001106 for (int i = 0; i < windowCount; i++) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001107 final WindowState window = mWindows.get(i);
Svetoslav Ganovaa076532016-08-01 19:16:43 -07001108 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001109 if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) {
1110 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window),
Svetoslav Ganovaa076532016-08-01 19:16:43 -07001111 window.mAttrs.hideTimeoutMilliseconds);
1112 }
1113 }
1114 }
1115 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001116
1117 WindowState findFocusedWindow() {
1118 final AppWindowToken focusedApp = mService.mFocusedApp;
1119
1120 for (int i = mWindows.size() - 1; i >= 0; i--) {
1121 final WindowState win = mWindows.get(i);
1122
1123 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win
1124 + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys());
1125
1126 if (!win.canReceiveKeys()) {
1127 continue;
1128 }
1129
1130 final AppWindowToken wtoken = win.mAppToken;
1131
1132 // If this window's application has been removed, just skip it.
1133 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
1134 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
1135 + (wtoken.removed ? "removed" : "sendingToBottom"));
1136 continue;
1137 }
1138
1139 if (focusedApp == null) {
1140 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
1141 + " using new focus @ " + i + " = " + win);
1142 return win;
1143 }
1144
1145 if (!focusedApp.windowsAreFocusable()) {
1146 // Current focused app windows aren't focusable...
1147 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
1148 + " focusable using new focus @ " + i + " = " + win);
1149 return win;
1150 }
1151
1152 // Descend through all of the app tokens and find the first that either matches
1153 // win.mAppToken (return win) or mFocusedApp (return null).
1154 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
Wale Ogunwale10124582016-09-15 20:25:50 -07001155 if (focusedApp.compareTo(wtoken) > 0) {
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001156 // App stack below focused app stack. No focus for you!!!
1157 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
1158 "findFocusedWindow: Reached focused app=" + focusedApp);
1159 return null;
1160 }
1161 }
1162
1163 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ "
1164 + i + " = " + win);
1165 return win;
1166 }
1167
1168 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
1169 return null;
1170 }
Wale Ogunwaleec731152016-09-08 20:18:57 -07001171
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001172 void addAppWindowToWindowList(final WindowState win) {
Wale Ogunwaleec731152016-09-08 20:18:57 -07001173 final IWindow client = win.mClient;
1174
1175 WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken);
1176 if (!tokenWindowList.isEmpty()) {
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001177 addAppWindowExisting(win, tokenWindowList);
1178 return;
Wale Ogunwaleec731152016-09-08 20:18:57 -07001179 }
1180
1181 // No windows from this token on this display
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001182 if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
Wale Ogunwaleec731152016-09-08 20:18:57 -07001183 + client.asBinder() + " (token=" + this + ")");
1184
1185 final WindowToken wToken = win.mToken;
1186
1187 // Figure out where the window should go, based on the order of applications.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001188 mTmpGetWindowOnDisplaySearchResult.reset();
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001189 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1190 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001191 stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
1192 if (mTmpGetWindowOnDisplaySearchResult.reachedToken) {
Wale Ogunwaleec731152016-09-08 20:18:57 -07001193 // We have reach the token we are interested in. End search.
1194 break;
1195 }
1196 }
1197
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001198 WindowState pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
Wale Ogunwaleec731152016-09-08 20:18:57 -07001199
1200 // We now know the index into the apps. If we found an app window above, that gives us the
1201 // position; else we need to look some more.
1202 if (pos != null) {
1203 // Move behind any windows attached to this one.
Wale Ogunwale02319a62016-09-26 15:21:22 -07001204 final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
Wale Ogunwaleec731152016-09-08 20:18:57 -07001205 if (atoken != null) {
1206 tokenWindowList = getTokenWindowsOnDisplay(atoken);
1207 final int NC = tokenWindowList.size();
1208 if (NC > 0) {
1209 WindowState bottom = tokenWindowList.get(0);
1210 if (bottom.mSubLayer < 0) {
1211 pos = bottom;
1212 }
1213 }
1214 }
1215 addWindowToListBefore(win, pos);
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001216 return;
Wale Ogunwaleec731152016-09-08 20:18:57 -07001217 }
1218
1219 // Continue looking down until we find the first token that has windows on this display.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001220 mTmpGetWindowOnDisplaySearchResult.reset();
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001221 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1222 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001223 stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
1224 if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) {
Wale Ogunwaleec731152016-09-08 20:18:57 -07001225 // We have found a window after the token. End search.
1226 break;
1227 }
1228 }
1229
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001230 pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
Wale Ogunwaleec731152016-09-08 20:18:57 -07001231
1232 if (pos != null) {
1233 // Move in front of any windows attached to this one.
Wale Ogunwale02319a62016-09-26 15:21:22 -07001234 final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
Wale Ogunwaleec731152016-09-08 20:18:57 -07001235 if (atoken != null) {
1236 final WindowState top = atoken.getTopWindow();
1237 if (top != null && top.mSubLayer >= 0) {
1238 pos = top;
1239 }
1240 }
1241 addWindowToListAfter(win, pos);
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001242 return;
Wale Ogunwaleec731152016-09-08 20:18:57 -07001243 }
1244
1245 // Just search for the start of this layer.
1246 final int myLayer = win.mBaseLayer;
1247 int i;
1248 for (i = mWindows.size() - 1; i >= 0; --i) {
1249 final WindowState w = mWindows.get(i);
1250 // Dock divider shares the base layer with application windows, but we want to always
1251 // keep it above the application windows. The sharing of the base layer is intended
1252 // for window animations, which need to be above the dock divider for the duration
1253 // of the animation.
1254 if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
1255 break;
1256 }
1257 }
1258 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1259 "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
1260 + mWindows.size());
1261 mWindows.add(i + 1, win);
1262 mService.mWindowsChanged = true;
Wale Ogunwaleec731152016-09-08 20:18:57 -07001263 }
1264
1265 /** Adds this non-app window to the window list. */
1266 void addNonAppWindowToWindowList(WindowState win) {
1267 // Figure out where window should go, based on layer.
1268 int i;
1269 for (i = mWindows.size() - 1; i >= 0; i--) {
1270 final WindowState otherWin = mWindows.get(i);
1271 if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) {
1272 // Wallpaper wanders through the window list, for example to position itself
1273 // directly behind keyguard. Because of this it will break the ordering based on
1274 // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
1275 // we don't want the new window to appear above them. An example of this is adding
1276 // of the docked stack divider. Consider a scenario with the following ordering (top
1277 // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
1278 // to land below the assist preview, so the dock divider must ignore the wallpaper,
1279 // with which it shares the base layer.
1280 break;
1281 }
1282 }
1283
1284 i++;
1285 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1286 "Free window: Adding window " + this + " at " + i + " of " + mWindows.size());
1287 mWindows.add(i, win);
1288 mService.mWindowsChanged = true;
1289 }
1290
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -07001291 void addToWindowList(WindowState win, int index) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001292 mService.mWindowsChanged = true;
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -07001293 mWindows.add(index, win);
1294 }
1295
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001296 boolean removeFromWindowList(WindowState win) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001297 mService.mWindowsChanged = true;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001298 return mWindows.remove(win);
1299 }
1300
1301 private int removeWindowAndChildrenFromWindowList(WindowState win, int interestingPos) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001302 int wpos = mWindows.indexOf(win);
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001303 if (wpos < 0) {
1304 return interestingPos;
1305 }
1306
1307 if (wpos < interestingPos) interestingPos--;
1308 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this);
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001309 mWindows.remove(wpos);
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001310 mService.mWindowsChanged = true;
1311 int childWinCount = win.mChildren.size();
1312 while (childWinCount > 0) {
1313 childWinCount--;
1314 final WindowState cw = win.mChildren.get(childWinCount);
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001315 int cpos = mWindows.indexOf(cw);
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001316 if (cpos >= 0) {
1317 if (cpos < interestingPos) interestingPos--;
1318 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
1319 "Temp removing child at " + cpos + ": " + cw);
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001320 mWindows.remove(cpos);
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001321 }
1322 }
1323 return interestingPos;
1324 }
1325
Wale Ogunwaleec731152016-09-08 20:18:57 -07001326 void addChildWindowToWindowList(WindowState win) {
1327 final WindowState parentWindow = win.getParentWindow();
1328
1329 WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken);
1330
1331 // Figure out this window's ordering relative to the parent window.
1332 final int wCount = windowsOnSameDisplay.size();
1333 final int sublayer = win.mSubLayer;
1334 int largestSublayer = Integer.MIN_VALUE;
1335 WindowState windowWithLargestSublayer = null;
1336 int i;
1337 for (i = 0; i < wCount; i++) {
1338 WindowState w = windowsOnSameDisplay.get(i);
1339 final int wSublayer = w.mSubLayer;
1340 if (wSublayer >= largestSublayer) {
1341 largestSublayer = wSublayer;
1342 windowWithLargestSublayer = w;
1343 }
1344 if (sublayer < 0) {
1345 // For negative sublayers, we go below all windows in the same sublayer.
1346 if (wSublayer >= sublayer) {
1347 addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w);
1348 break;
1349 }
1350 } else {
1351 // For positive sublayers, we go above all windows in the same sublayer.
1352 if (wSublayer > sublayer) {
1353 addWindowToListBefore(win, w);
1354 break;
1355 }
1356 }
1357 }
1358 if (i >= wCount) {
1359 if (sublayer < 0) {
1360 addWindowToListBefore(win, parentWindow);
1361 } else {
1362 addWindowToListAfter(win,
1363 largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
1364 }
1365 }
1366 }
1367
Wale Ogunwalec69694a2016-10-18 13:51:15 -07001368 /** Updates the layer assignment of windows on this display. */
1369 void assignWindowLayers(boolean setLayoutNeeded) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001370 mLayersController.assignWindowLayers(mWindows.getReadOnly());
Wale Ogunwalec69694a2016-10-18 13:51:15 -07001371 if (setLayoutNeeded) {
1372 setLayoutNeeded();
1373 }
1374 }
1375
Wale Ogunwale0303c572016-10-20 10:16:29 -07001376 void adjustWallpaperWindows() {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001377 if (mWallpaperController.adjustWallpaperWindows(mWindows.getReadOnly())) {
Wale Ogunwale0303c572016-10-20 10:16:29 -07001378 assignWindowLayers(true /*setLayoutNeeded*/);
1379 }
1380 }
1381
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001382 /**
1383 * Z-orders the display window list so that:
1384 * <ul>
1385 * <li>Any windows that are currently below the wallpaper window stay below the wallpaper
1386 * window.
1387 * <li>Exiting application windows are at the bottom, but above the wallpaper window.
1388 * <li>All other application windows are above the exiting application windows and ordered based
1389 * on the ordering of their stacks and tasks on the display.
1390 * <li>Non-application windows are at the very top.
1391 * </ul>
1392 * <p>
1393 * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window
1394 * surface layering is done in {@link WindowLayersController}.
1395 */
1396 void rebuildAppWindowList() {
1397 int count = mWindows.size();
1398 int i;
1399 int lastBelow = -1;
1400 int numRemoved = 0;
1401
1402 if (mRebuildTmp.length < count) {
1403 mRebuildTmp = new WindowState[count + 10];
1404 }
1405
1406 // First remove all existing app windows.
1407 i = 0;
1408 while (i < count) {
1409 final WindowState w = mWindows.get(i);
1410 if (w.mAppToken != null) {
1411 final WindowState win = mWindows.remove(i);
1412 win.mRebuilding = true;
1413 mRebuildTmp[numRemoved] = win;
1414 mService.mWindowsChanged = true;
1415 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
1416 count--;
1417 numRemoved++;
1418 continue;
1419 } else if (lastBelow == i-1) {
1420 if (w.mAttrs.type == TYPE_WALLPAPER) {
1421 lastBelow = i;
1422 }
1423 }
1424 i++;
1425 }
1426
1427 // Keep whatever windows were below the app windows still below, by skipping them.
1428 lastBelow++;
1429 i = lastBelow;
1430
1431 // First add all of the exiting app tokens... these are no longer in the main app list,
1432 // but still have windows shown. We put them in the back because now that the animation is
1433 // over we no longer will care about them.
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001434 final int numStacks = mTaskStackContainers.size();
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001435 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001436 AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens;
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001437 int NT = exitingAppTokens.size();
1438 for (int j = 0; j < NT; j++) {
Wale Ogunwale360a8bc2016-10-10 13:25:26 -07001439 i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001440 }
1441 }
1442
1443 // And add in the still active app tokens in Z order.
1444 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001445 i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001446 }
1447
1448 i -= lastBelow;
1449 if (i != numRemoved) {
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001450 setLayoutNeeded();
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001451 Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
1452 + " windows but added " + i + " rebuildAppWindowListLocked() "
1453 + " callers=" + Debug.getCallers(10));
1454 for (i = 0; i < numRemoved; i++) {
1455 WindowState ws = mRebuildTmp[i];
1456 if (ws.mRebuilding) {
1457 StringWriter sw = new StringWriter();
1458 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
1459 ws.dump(pw, "", true);
1460 pw.flush();
1461 Slog.w(TAG_WM, "This window was lost: " + ws);
1462 Slog.w(TAG_WM, sw.toString());
1463 ws.mWinAnimator.destroySurfaceLocked();
1464 }
1465 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07001466 Slog.w(TAG_WM, "Current window hierarchy:");
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001467 dumpChildrenNames();
1468 Slog.w(TAG_WM, "Final window list:");
1469 dumpWindows();
1470 }
1471 Arrays.fill(mRebuildTmp, null);
1472 }
1473
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001474 /** Rebuilds the display's window list and does a relayout if something changed. */
1475 void rebuildAppWindowsAndLayoutIfNeeded() {
1476 mTmpWindows.clear();
1477 mTmpWindows.addAll(mWindows);
1478
1479 rebuildAppWindowList();
1480
1481 // Set displayContent.mLayoutNeeded if window order changed.
1482 final int tmpSize = mTmpWindows.size();
1483 final int winSize = mWindows.size();
1484 int tmpNdx = 0, winNdx = 0;
1485 while (tmpNdx < tmpSize && winNdx < winSize) {
1486 // Skip over all exiting windows, they've been moved out of order.
1487 WindowState tmp;
1488 do {
1489 tmp = mTmpWindows.get(tmpNdx++);
1490 } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting);
1491
1492 WindowState win;
1493 do {
1494 win = mWindows.get(winNdx++);
1495 } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting);
1496
1497 if (tmp != win) {
1498 // Window order changed.
1499 setLayoutNeeded();
1500 break;
1501 }
1502 }
1503 if (tmpNdx != winNdx) {
1504 // One list was different from the other.
1505 setLayoutNeeded();
1506 }
1507 mTmpWindows.clear();
1508
1509 if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
1510 false /*updateInputWindows*/)) {
1511 assignWindowLayers(false /* setLayoutNeeded */);
1512 }
1513
1514 mService.mInputMonitor.setUpdateInputWindowsNeededLw();
1515 mService.mWindowPlacerLocked.performSurfacePlacement();
1516 mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
1517 }
1518
1519 void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
1520 final InputConsumerImpl navInputConsumer =
1521 mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_NAVIGATION, mDisplayId);
1522 final InputConsumerImpl pipInputConsumer =
1523 mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_PIP, mDisplayId);
1524 final InputConsumerImpl wallpaperInputConsumer =
1525 mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_WALLPAPER, mDisplayId);
1526 boolean addInputConsumerHandle = navInputConsumer != null;
1527 boolean addPipInputConsumerHandle = pipInputConsumer != null;
1528 boolean addWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
1529 final Rect pipTouchableBounds = addPipInputConsumerHandle ? new Rect() : null;
1530 boolean disableWallpaperTouchEvents = false;
1531
1532 for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
1533 final WindowState child = mWindows.get(winNdx);
1534 final InputChannel inputChannel = child.mInputChannel;
1535 final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
1536 if (inputChannel == null || inputWindowHandle == null || child.mRemoved
1537 || child.isAdjustedForMinimizedDock()) {
1538 // Skip this window because it cannot possibly receive input.
1539 continue;
1540 }
1541
1542 if (addPipInputConsumerHandle
1543 && child.getStackId() == PINNED_STACK_ID
1544 && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
1545 // Update the bounds of the Pip input consumer to match the Pinned stack
1546 child.getStack().getBounds(pipTouchableBounds);
1547 pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
1548 inputMonitor.addInputWindowHandle(pipInputConsumer.mWindowHandle);
1549 addPipInputConsumerHandle = false;
1550 }
1551
1552 if (addInputConsumerHandle
1553 && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
1554 inputMonitor.addInputWindowHandle(navInputConsumer.mWindowHandle);
1555 addInputConsumerHandle = false;
1556 }
1557
1558 if (addWallpaperInputConsumerHandle) {
1559 if (child.mAttrs.type == TYPE_WALLPAPER && child.isVisibleLw()) {
1560 // Add the wallpaper input consumer above the first visible wallpaper.
1561 inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
1562 addWallpaperInputConsumerHandle = false;
1563 }
1564 }
1565
1566 final int flags = child.mAttrs.flags;
1567 final int privateFlags = child.mAttrs.privateFlags;
1568 final int type = child.mAttrs.type;
1569
1570 final boolean hasFocus = child == inputFocus;
1571 final boolean isVisible = child.isVisibleLw();
1572 if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
1573 disableWallpaperTouchEvents = true;
1574 }
1575 final boolean hasWallpaper = mWallpaperController.isWallpaperTarget(child)
1576 && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
1577 && !disableWallpaperTouchEvents;
1578
1579 // If there's a drag in progress and 'child' is a potential drop target,
1580 // make sure it's been told about the drag
1581 if (inDrag && isVisible && isDefaultDisplay) {
1582 mService.mDragState.sendDragStartedIfNeededLw(child);
1583 }
1584
1585 inputMonitor.addInputWindowHandle(
1586 inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
1587 }
1588
1589 if (addWallpaperInputConsumerHandle) {
1590 // No visible wallpaper found, add the wallpaper input consumer at the end.
1591 inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
1592 }
1593 }
1594
1595 /** Returns true if a leaked surface was destroyed */
1596 boolean destroyLeakedSurfaces() {
1597 boolean leakedSurface = false;
1598 final int numWindows = mWindows.size();
1599 for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
1600 final WindowState ws = mWindows.get(winNdx);
1601 final WindowStateAnimator wsa = ws.mWinAnimator;
1602 if (wsa.mSurfaceController == null) {
1603 continue;
1604 }
1605 if (!mService.mSessions.contains(wsa.mSession)) {
1606 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
1607 + ws + " surface=" + wsa.mSurfaceController
1608 + " token=" + ws.mToken
1609 + " pid=" + ws.mSession.mPid
1610 + " uid=" + ws.mSession.mUid);
1611 wsa.destroySurface();
1612 mService.mForceRemoves.add(ws);
1613 leakedSurface = true;
1614 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
1615 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
1616 + ws + " surface=" + wsa.mSurfaceController
1617 + " token=" + ws.mAppToken
1618 + " saved=" + ws.hasSavedSurface());
1619 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
1620 wsa.destroySurface();
1621 leakedSurface = true;
1622 }
1623 }
1624
1625 return leakedSurface;
1626 }
1627
Wale Ogunwaleec731152016-09-08 20:18:57 -07001628 /** Return the list of Windows on this display associated with the input token. */
1629 WindowList getTokenWindowsOnDisplay(WindowToken token) {
1630 final WindowList windowList = new WindowList();
1631 final int count = mWindows.size();
1632 for (int i = 0; i < count; i++) {
1633 final WindowState win = mWindows.get(i);
1634 if (win.mToken == token) {
1635 windowList.add(win);
1636 }
1637 }
1638 return windowList;
1639 }
1640
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001641 private void reAddToWindowList(WindowState win) {
1642 win.mToken.addWindow(win);
1643 // This is a hack to get all of the child windows added as well at the right position. Child
1644 // windows should be rare and this case should be rare, so it shouldn't be that big a deal.
1645 int wpos = mWindows.indexOf(win);
1646 if (wpos >= 0) {
1647 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win);
1648 mWindows.remove(wpos);
1649 mService.mWindowsChanged = true;
1650 win.reAddWindow(wpos);
1651 }
1652 }
1653
1654 void moveInputMethodDialogs(int pos) {
1655 ArrayList<WindowState> dialogs = mService.mInputMethodDialogs;
1656
1657 final int N = dialogs.size();
1658 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos);
1659 for (int i = 0; i < N; i++) {
1660 pos = removeWindowAndChildrenFromWindowList(dialogs.get(i), pos);
1661 }
1662 if (DEBUG_INPUT_METHOD) {
1663 Slog.v(TAG_WM, "Window list w/pos=" + pos);
1664 logWindowList(mWindows, " ");
1665 }
1666
1667 WindowState ime = mService.mInputMethodWindow;
1668 if (pos >= 0) {
1669 // Skip windows owned by the input method.
1670 if (ime != null) {
1671 while (pos < mWindows.size()) {
1672 WindowState wp = mWindows.get(pos);
1673 if (wp == ime || wp.getParentWindow() == ime) {
1674 pos++;
1675 continue;
1676 }
1677 break;
1678 }
1679 }
1680 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos);
1681 for (int i=0; i<N; i++) {
1682 WindowState win = dialogs.get(i);
1683 pos = win.reAddWindow(pos);
1684 }
1685 if (DEBUG_INPUT_METHOD) {
1686 Slog.v(TAG_WM, "Final window list:");
1687 logWindowList(mWindows, " ");
1688 }
1689 return;
1690 }
1691 for (int i=0; i<N; i++) {
1692 WindowState win = dialogs.get(i);
1693 reAddToWindowList(win);
1694 if (DEBUG_INPUT_METHOD) {
1695 Slog.v(TAG_WM, "No IM target, final list:");
1696 logWindowList(mWindows, " ");
1697 }
1698 }
1699 }
1700
1701 boolean moveInputMethodWindowsIfNeeded(boolean needAssignLayers) {
1702 final WindowState imWin = mService.mInputMethodWindow;
1703 final int DN = mService.mInputMethodDialogs.size();
1704 if (imWin == null && DN == 0) {
1705 return false;
1706 }
1707
1708 // TODO(multidisplay): IMEs are only supported on the default display.
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001709 int imPos = findDesiredInputMethodWindowIndex(true);
1710 if (imPos >= 0) {
1711 // In this case, the input method windows are to be placed
1712 // immediately above the window they are targeting.
1713
1714 // First check to see if the input method windows are already
1715 // located here, and contiguous.
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001716 final int N = mWindows.size();
1717 final WindowState firstImWin = imPos < N ? mWindows.get(imPos) : null;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001718
1719 // Figure out the actual input method window that should be
1720 // at the bottom of their stack.
1721 WindowState baseImWin = imWin != null ? imWin : mService.mInputMethodDialogs.get(0);
1722 final WindowState cw = baseImWin.getBottomChild();
1723 if (cw != null && cw.mSubLayer < 0) {
1724 baseImWin = cw;
1725 }
1726
1727 if (firstImWin == baseImWin) {
1728 // The windows haven't moved... but are they still contiguous?
1729 // First find the top IM window.
1730 int pos = imPos+1;
1731 while (pos < N) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001732 if (!(mWindows.get(pos)).mIsImWindow) {
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001733 break;
1734 }
1735 pos++;
1736 }
1737 pos++;
1738 // Now there should be no more input method windows above.
1739 while (pos < N) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001740 if ((mWindows.get(pos)).mIsImWindow) {
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001741 break;
1742 }
1743 pos++;
1744 }
1745 if (pos >= N) {
1746 return false;
1747 }
1748 }
1749
1750 if (imWin != null) {
1751 if (DEBUG_INPUT_METHOD) {
1752 Slog.v(TAG_WM, "Moving IM from " + imPos);
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001753 logWindowList(mWindows, " ");
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001754 }
1755 imPos = removeWindowAndChildrenFromWindowList(imWin, imPos);
1756 if (DEBUG_INPUT_METHOD) {
1757 Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":");
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001758 logWindowList(mWindows, " ");
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001759 }
1760 imWin.reAddWindow(imPos);
1761 if (DEBUG_INPUT_METHOD) {
1762 Slog.v(TAG_WM, "List after moving IM to " + imPos + ":");
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001763 logWindowList(mWindows, " ");
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001764 }
1765 if (DN > 0) moveInputMethodDialogs(imPos+1);
1766 } else {
1767 moveInputMethodDialogs(imPos);
1768 }
1769
1770 } else {
1771 // In this case, the input method windows go in a fixed layer,
1772 // because they aren't currently associated with a focus window.
1773
1774 if (imWin != null) {
1775 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos);
1776 removeWindowAndChildrenFromWindowList(imWin, 0);
1777 reAddToWindowList(imWin);
1778 if (DEBUG_INPUT_METHOD) {
1779 Slog.v(TAG_WM, "List with no IM target:");
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001780 logWindowList(mWindows, " ");
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001781 }
1782 if (DN > 0) moveInputMethodDialogs(-1);
1783 } else {
1784 moveInputMethodDialogs(-1);
1785 }
1786
1787 }
1788
1789 if (needAssignLayers) {
1790 assignWindowLayers(false /* setLayoutNeeded */);
1791 }
1792
1793 return true;
1794 }
1795
1796 /**
1797 * Dig through the WindowStates and find the one that the Input Method will target.
1798 * @param willMove
1799 * @return The index+1 in mWindows of the discovered target.
1800 */
1801 int findDesiredInputMethodWindowIndex(boolean willMove) {
1802 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1803 // same display. Or even when the current IME/target are not on the same screen as the next
1804 // IME/target. For now only look for input windows on the main screen.
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001805 WindowState w = null;
1806 int i;
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001807 for (i = mWindows.size() - 1; i >= 0; --i) {
1808 final WindowState win = mWindows.get(i);
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001809
1810 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i
1811 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1812 if (canBeImeTarget(win)) {
1813 w = win;
1814 //Slog.i(TAG_WM, "Putting input method here!");
1815
1816 // Yet more tricksyness! If this window is a "starting" window, we do actually want
1817 // to be on top of it, but it is not -really- where input will go. So if the caller
1818 // is not actually looking to move the IME, look down below for a real window to
1819 // target...
1820 if (!willMove && w.mAttrs.type == TYPE_APPLICATION_STARTING && i > 0) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001821 final WindowState wb = mWindows.get(i-1);
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001822 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1823 i--;
1824 w = wb;
1825 }
1826 }
1827 break;
1828 }
1829 }
1830
1831 // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1832
1833 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w);
1834
1835 // Now, a special case -- if the last target's window is in the process of exiting, and is
1836 // above the new target, keep on the last target to avoid flicker. Consider for example a
1837 // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it
1838 // until it is completely gone so it doesn't drop behind the dialog or its full-screen
1839 // scrim.
1840 final WindowState curTarget = mService.mInputMethodTarget;
1841 if (curTarget != null
1842 && curTarget.isDisplayedLw()
1843 && curTarget.isClosing()
1844 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1845 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001846 return mWindows.indexOf(curTarget) + 1;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001847 }
1848
1849 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target="
1850 + w + " willMove=" + willMove);
1851
1852 if (willMove && w != null) {
1853 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1854 if (token != null) {
1855
1856 // Now some fun for dealing with window animations that modify the Z order. We need
1857 // to look at all windows below the current target that are in this app, finding the
1858 // highest visible one in layering.
1859 WindowState highestTarget = null;
1860 int highestPos = 0;
1861 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001862 WindowList curWindows = token.getDisplayContent().mWindows;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001863 int pos = curWindows.indexOf(curTarget);
1864 while (pos >= 0) {
1865 WindowState win = curWindows.get(pos);
1866 if (win.mAppToken != token) {
1867 break;
1868 }
1869 if (!win.mRemoved) {
1870 if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1871 highestTarget.mWinAnimator.mAnimLayer) {
1872 highestTarget = win;
1873 highestPos = pos;
1874 }
1875 }
1876 pos--;
1877 }
1878 }
1879
1880 if (highestTarget != null) {
1881 final AppTransition appTransition = mService.mAppTransition;
1882 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
1883 + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
1884 + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1885 + " new layer=" + w.mWinAnimator.mAnimLayer);
1886
1887 if (appTransition.isTransitionSet()) {
1888 // If we are currently setting up for an animation, hold everything until we
1889 // can find out what will happen.
1890 mService.mInputMethodTargetWaitingAnim = true;
1891 mService.mInputMethodTarget = highestTarget;
1892 return highestPos + 1;
1893 } else if (highestTarget.mWinAnimator.isAnimationSet() &&
1894 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1895 // If the window we are currently targeting is involved with an animation,
1896 // and it is on top of the next target we will be over, then hold off on
1897 // moving until that is done.
1898 mService.mInputMethodTargetWaitingAnim = true;
1899 mService.mInputMethodTarget = highestTarget;
1900 return highestPos + 1;
1901 }
1902 }
1903 }
1904 }
1905
1906 //Slog.i(TAG_WM, "Placing input method @" + (i+1));
1907 if (w != null) {
1908 if (willMove) {
1909 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
1910 + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1911 mService.mInputMethodTarget = w;
1912 mService.mInputMethodTargetWaitingAnim = false;
1913 if (w.mAppToken != null) {
1914 setInputMethodAnimLayerAdjustment(
1915 w.mAppToken.mAppAnimator.animLayerAdjustment);
1916 } else {
1917 setInputMethodAnimLayerAdjustment(0);
1918 }
1919 }
1920
1921 // If the docked divider is visible, we still need to go through this whole excercise to
1922 // find the appropriate input method target (used for animations and dialog
1923 // adjustments), but for purposes of Z ordering we simply wish to place it above the
1924 // docked divider. Unless it is already above the divider.
1925 final WindowState dockedDivider = mDividerControllerLocked.getWindow();
1926 if (dockedDivider != null && dockedDivider.isVisibleLw()) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001927 int dividerIndex = mWindows.indexOf(dockedDivider);
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001928 if (dividerIndex > 0 && dividerIndex > i) {
1929 return dividerIndex + 1;
1930 }
1931 }
1932 return i+1;
1933 }
1934 if (willMove) {
1935 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
1936 + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1937 mService.mInputMethodTarget = null;
1938 setInputMethodAnimLayerAdjustment(0);
1939 }
1940 return -1;
1941 }
1942
1943 private static boolean canBeImeTarget(WindowState w) {
1944 final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1945 final int type = w.mAttrs.type;
1946
1947 if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
1948 && type != TYPE_APPLICATION_STARTING) {
1949 return false;
1950 }
1951
1952 if (DEBUG_INPUT_METHOD) {
1953 Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1954 if (!w.isVisibleOrAdding()) {
1955 Slog.i(TAG_WM, " mSurfaceController=" + w.mWinAnimator.mSurfaceController
1956 + " relayoutCalled=" + w.mRelayoutCalled
1957 + " viewVis=" + w.mViewVisibility
1958 + " policyVis=" + w.mPolicyVisibility
1959 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1960 + " parentHidden=" + w.isParentWindowHidden()
1961 + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
1962 if (w.mAppToken != null) {
1963 Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1964 }
1965 }
1966 }
1967 return w.isVisibleOrAdding();
1968 }
1969
1970 private void logWindowList(final WindowList windows, String prefix) {
1971 int N = windows.size();
1972 while (N > 0) {
1973 N--;
1974 Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N));
1975 }
1976 }
1977
1978 boolean getNeedsMenu(WindowState win, WindowManagerPolicy.WindowState bottom) {
1979 int index = -1;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001980 while (true) {
1981 if (win.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
1982 return win.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
1983 }
1984 // If we reached the bottom of the range of windows we are considering,
1985 // assume no menu is needed.
1986 if (win == bottom) {
1987 return false;
1988 }
1989 // The current window hasn't specified whether menu key is needed; look behind it.
1990 // First, we may need to determine the starting position.
1991 if (index < 0) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001992 index = mWindows.indexOf(win);
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001993 }
1994 index--;
1995 if (index < 0) {
1996 return false;
1997 }
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001998 win = mWindows.get(index);
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001999 }
2000 }
2001
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07002002 void setLayoutNeeded() {
2003 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
2004 mLayoutNeeded = true;
2005 }
2006
Wale Ogunwalef7cab102016-10-25 15:25:14 -07002007 private void clearLayoutNeeded() {
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07002008 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
2009 mLayoutNeeded = false;
2010 }
2011
2012 boolean isLayoutNeeded() {
2013 return mLayoutNeeded;
2014 }
2015
Wale Ogunwale07bcab72016-10-14 15:30:09 -07002016 private void addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
Wale Ogunwaleec731152016-09-08 20:18:57 -07002017
Wale Ogunwaleec731152016-09-08 20:18:57 -07002018 // If this application has existing windows, we simply place the new window on top of
2019 // them... but keep the starting window on top.
2020 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
2021 // Base windows go behind everything else.
2022 final WindowState lowestWindow = tokenWindowList.get(0);
2023 addWindowToListBefore(win, lowestWindow);
Wale Ogunwaleec731152016-09-08 20:18:57 -07002024 } else {
2025 final AppWindowToken atoken = win.mAppToken;
2026 final int windowListPos = tokenWindowList.size();
2027 final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
2028 if (atoken != null && lastWindow == atoken.startingWindow) {
2029 addWindowToListBefore(win, lastWindow);
Wale Ogunwaleec731152016-09-08 20:18:57 -07002030 } else {
2031 int newIdx = findIdxBasedOnAppTokens(win);
2032 // There is a window above this one associated with the same apptoken note that the
2033 // window could be a floating window that was created later or a window at the top
2034 // of the list of windows associated with this token.
2035 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2036 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
2037 + mWindows.size());
2038 mWindows.add(newIdx + 1, win);
Wale Ogunwaleec731152016-09-08 20:18:57 -07002039 mService.mWindowsChanged = true;
2040 }
2041 }
Wale Ogunwaleec731152016-09-08 20:18:57 -07002042 }
2043
2044 /** Places the first input window after the second input window in the window list. */
2045 private void addWindowToListAfter(WindowState first, WindowState second) {
2046 final int i = mWindows.indexOf(second);
2047 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2048 "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size()
2049 + " (after " + second + ")");
2050 mWindows.add(i + 1, first);
2051 mService.mWindowsChanged = true;
2052 }
2053
2054 /** Places the first input window before the second input window in the window list. */
2055 private void addWindowToListBefore(WindowState first, WindowState second) {
2056 int i = mWindows.indexOf(second);
2057 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2058 "Adding window " + this + " at " + i + " of " + mWindows.size()
2059 + " (before " + second + ")");
2060 if (i < 0) {
2061 Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows);
2062 i = 0;
2063 }
2064 mWindows.add(i, first);
2065 mService.mWindowsChanged = true;
2066 }
2067
2068 /**
2069 * This method finds out the index of a window that has the same app token as win. used for z
2070 * ordering the windows in mWindows
2071 */
2072 private int findIdxBasedOnAppTokens(WindowState win) {
2073 for(int j = mWindows.size() - 1; j >= 0; j--) {
2074 final WindowState wentry = mWindows.get(j);
2075 if(wentry.mAppToken == win.mAppToken) {
2076 return j;
2077 }
2078 }
2079 return -1;
2080 }
2081
Wale Ogunwale9adfe572016-09-08 20:43:58 -07002082 private void dumpChildrenNames() {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07002083 StringBuilder output = new StringBuilder();
2084 dumpChildrenNames(output, " ");
2085 Slog.v(TAG_WM, output.toString());
Wale Ogunwale9adfe572016-09-08 20:43:58 -07002086 }
2087
Wale Ogunwale9adfe572016-09-08 20:43:58 -07002088 private void dumpWindows() {
Wale Ogunwale10124582016-09-15 20:25:50 -07002089 Slog.v(TAG_WM, " Display #" + mDisplayId);
Wale Ogunwalef7cab102016-10-25 15:25:14 -07002090 for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
2091 Slog.v(TAG_WM, " #" + winNdx + ": " + mWindows.get(winNdx));
Wale Ogunwale9adfe572016-09-08 20:43:58 -07002092 }
2093 }
2094
Wale Ogunwale02319a62016-09-26 15:21:22 -07002095 void dumpTokens(PrintWriter pw, boolean dumpAll) {
2096 if (mTokenMap.isEmpty()) {
2097 return;
2098 }
2099 pw.println(" Display #" + mDisplayId);
2100 final Iterator<WindowToken> it = mTokenMap.values().iterator();
2101 while (it.hasNext()) {
2102 final WindowToken token = it.next();
2103 pw.print(" ");
2104 pw.print(token);
2105 if (dumpAll) {
2106 pw.println(':');
2107 token.dump(pw, " ");
2108 } else {
2109 pw.println();
2110 }
2111 }
2112 }
2113
Wale Ogunwale824ab5c2016-10-20 09:31:56 -07002114 void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
2115 final int count = mWindows.size();
2116 for (int j = 0; j < count; j++) {
2117 final WindowStateAnimator wAnim = mWindows.get(j).mWinAnimator;
2118 pw.println(subPrefix + "Window #" + j + ": " + wAnim);
2119 }
2120 }
2121
Wale Ogunwale19e452e2016-10-12 12:36:29 -07002122 void enableSurfaceTrace(FileDescriptor fd) {
2123 for (int i = mWindows.size() - 1; i >= 0; i--) {
2124 final WindowState win = mWindows.get(i);
2125 win.mWinAnimator.enableSurfaceTrace(fd);
2126 }
2127 }
2128
2129 void disableSurfaceTrace() {
2130 for (int i = mWindows.size() - 1; i >= 0; i--) {
2131 final WindowState win = mWindows.get(i);
2132 win.mWinAnimator.disableSurfaceTrace();
2133 }
2134 }
2135
Jorim Jaggife762342016-10-13 14:33:27 +02002136 /**
2137 * Starts the Keyguard exit animation on all windows that don't belong to an app token.
2138 */
2139 void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
2140 final WindowManagerPolicy policy = mService.mPolicy;
2141 for (int i = mWindows.size() - 1; i >= 0; i--) {
2142 final WindowState window = mWindows.get(i);
2143 if (window.mAppToken == null && policy.canBeHiddenByKeyguardLw(window)) {
2144 window.mWinAnimator.setAnimation(
2145 policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
2146 }
2147 }
2148 }
2149
Wale Ogunwale494009b82016-10-21 09:01:38 -07002150 boolean checkWaitingForWindows() {
2151
2152 boolean haveBootMsg = false;
2153 boolean haveApp = false;
2154 // if the wallpaper service is disabled on the device, we're never going to have
2155 // wallpaper, don't bother waiting for it
2156 boolean haveWallpaper = false;
2157 boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
2158 com.android.internal.R.bool.config_enableWallpaperService)
2159 && !mService.mOnlyCore;
2160 boolean haveKeyguard = true;
2161 final int count = mWindows.size();
2162 for (int i = 0; i < count; i++) {
2163 final WindowState w = mWindows.get(i);
2164 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
2165 return true;
2166 }
2167 if (w.isDrawnLw()) {
2168 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
2169 haveBootMsg = true;
2170 } else if (w.mAttrs.type == TYPE_APPLICATION
2171 || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
2172 haveApp = true;
2173 } else if (w.mAttrs.type == TYPE_WALLPAPER) {
2174 haveWallpaper = true;
2175 } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
2176 haveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
2177 }
2178 }
2179 }
2180
2181 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
2182 "******** booted=" + mService.mSystemBooted
2183 + " msg=" + mService.mShowingBootMessages
2184 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
2185 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
2186 + " haveKeyguard=" + haveKeyguard);
2187
2188 // If we are turning on the screen to show the boot message, don't do it until the boot
2189 // message is actually displayed.
2190 if (!mService.mSystemBooted && !haveBootMsg) {
2191 return true;
2192 }
2193
2194 // If we are turning on the screen after the boot is completed normally, don't do so until
2195 // we have the application and wallpaper.
2196 if (mService.mSystemBooted && ((!haveApp && !haveKeyguard) ||
2197 (wallpaperEnabled && !haveWallpaper))) {
2198 return true;
2199 }
2200
2201 return false;
2202 }
2203
Wale Ogunwale824ab5c2016-10-20 09:31:56 -07002204 void updateWindowsForAnimator(WindowAnimator animator) {
Wale Ogunwale0303c572016-10-20 10:16:29 -07002205 final WallpaperController wallpaperController = mWallpaperController;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -07002206 for (int i = mWindows.size() - 1; i >= 0; i--) {
2207 WindowState win = mWindows.get(i);
2208 WindowStateAnimator winAnimator = win.mWinAnimator;
Wale Ogunwale824ab5c2016-10-20 09:31:56 -07002209 if (winAnimator.hasSurface()) {
2210 final boolean wasAnimating = winAnimator.mWasAnimating;
2211 final boolean nowAnimating = winAnimator.stepAnimationLocked(animator.mCurrentTime);
2212 winAnimator.mWasAnimating = nowAnimating;
2213 animator.orAnimating(nowAnimating);
2214
2215 if (DEBUG_WALLPAPER) Slog.v(TAG,
2216 win + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
2217
2218 if (wasAnimating && !winAnimator.mAnimating
2219 && wallpaperController.isWallpaperTarget(win)) {
2220 animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
2221 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2222 if (DEBUG_LAYOUT_REPEATS) {
2223 mService.mWindowPlacerLocked.debugLayoutRepeats(
2224 "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
2225 }
2226 }
Wale Ogunwale824ab5c2016-10-20 09:31:56 -07002227 }
2228
2229 final AppWindowToken atoken = win.mAppToken;
2230 if (winAnimator.mDrawState == READY_TO_SHOW) {
2231 if (atoken == null || atoken.allDrawn) {
2232 if (win.performShowLocked()) {
2233 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
2234 if (DEBUG_LAYOUT_REPEATS) {
2235 mService.mWindowPlacerLocked.debugLayoutRepeats(
2236 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
2237 }
2238 }
2239 }
2240 }
2241 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
2242 if (appAnimator != null && appAnimator.thumbnail != null) {
2243 if (appAnimator.thumbnailTransactionSeq != animator.mAnimTransactionSequence) {
2244 appAnimator.thumbnailTransactionSeq = animator.mAnimTransactionSequence;
2245 appAnimator.thumbnailLayer = 0;
2246 }
2247 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
2248 appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
2249 }
2250 }
Wale Ogunwale824ab5c2016-10-20 09:31:56 -07002251 } // end forall windows
Wale Ogunwale824ab5c2016-10-20 09:31:56 -07002252 }
2253
2254 void updateWallpaperForAnimator(WindowAnimator animator) {
Jorim Jaggi7156b652016-10-25 08:31:58 -07002255 resetAnimationBackgroundAnimator();
2256
Wale Ogunwale824ab5c2016-10-20 09:31:56 -07002257 final WindowList windows = mWindows;
2258 WindowState detachedWallpaper = null;
2259
2260 for (int i = windows.size() - 1; i >= 0; i--) {
2261 final WindowState win = windows.get(i);
2262 final WindowStateAnimator winAnimator = win.mWinAnimator;
2263 if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
2264 continue;
2265 }
2266
2267 final int flags = win.mAttrs.flags;
2268
2269 // If this window is animating, make a note that we have an animating window and take
2270 // care of a request to run a detached wallpaper animation.
2271 if (winAnimator.mAnimating) {
2272 if (winAnimator.mAnimation != null) {
2273 if ((flags & FLAG_SHOW_WALLPAPER) != 0
2274 && winAnimator.mAnimation.getDetachWallpaper()) {
2275 detachedWallpaper = win;
2276 }
2277 final int color = winAnimator.mAnimation.getBackgroundColor();
2278 if (color != 0) {
2279 final TaskStack stack = win.getStack();
2280 if (stack != null) {
2281 stack.setAnimationBackground(winAnimator, color);
2282 }
2283 }
2284 }
2285 animator.setAnimating(true);
2286 }
2287
2288 // If this window's app token is running a detached wallpaper animation, make a note so
2289 // we can ensure the wallpaper is displayed behind it.
2290 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
2291 if (appAnimator != null && appAnimator.animation != null
2292 && appAnimator.animating) {
2293 if ((flags & FLAG_SHOW_WALLPAPER) != 0
2294 && appAnimator.animation.getDetachWallpaper()) {
2295 detachedWallpaper = win;
2296 }
2297
2298 final int color = appAnimator.animation.getBackgroundColor();
2299 if (color != 0) {
2300 final TaskStack stack = win.getStack();
2301 if (stack != null) {
2302 stack.setAnimationBackground(winAnimator, color);
2303 }
2304 }
2305 }
2306 } // end forall windows
2307
2308 if (animator.mWindowDetachedWallpaper != detachedWallpaper) {
2309 if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from "
2310 + animator.mWindowDetachedWallpaper + " to " + detachedWallpaper);
2311 animator.mWindowDetachedWallpaper = detachedWallpaper;
2312 animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
2313 }
2314 }
2315
2316 void prepareWindowSurfaces() {
2317 final int count = mWindows.size();
2318 for (int j = 0; j < count; j++) {
2319 mWindows.get(j).mWinAnimator.prepareSurfaceLocked(true);
2320 }
2321 }
2322
Wale Ogunwale494009b82016-10-21 09:01:38 -07002323 boolean inputMethodClientHasFocus(IInputMethodClient client) {
2324 // The focus for the client is the window immediately below where we would place the input
2325 // method window.
2326 int idx = findDesiredInputMethodWindowIndex(false);
2327 if (idx <= 0) {
2328 return false;
2329 }
2330
2331 WindowState imFocus = mWindows.get(idx - 1);
2332 if (DEBUG_INPUT_METHOD) {
2333 Slog.i(TAG_WM, "Desired input method target: " + imFocus);
2334 Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
2335 Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
2336 }
2337
2338 if (imFocus == null) {
2339 return false;
2340 }
2341
2342 // This may be a starting window, in which case we still want to count it as okay.
2343 if (imFocus.mAttrs.type == TYPE_APPLICATION_STARTING && imFocus.mAppToken != null) {
2344 // The client has definitely started, so it really should have a window in this app
2345 // token. Let's look for it.
2346 final WindowState w = imFocus.mAppToken.getFirstNonStartingWindow();
2347 if (w != null) {
2348 if (DEBUG_INPUT_METHOD) Slog.i(TAG_WM, "Switching to real app window: " + w);
2349 imFocus = w;
2350 }
2351 }
2352
2353 final IInputMethodClient imeClient = imFocus.mSession.mClient;
2354
2355 if (DEBUG_INPUT_METHOD) {
2356 Slog.i(TAG_WM, "IM target client: " + imeClient);
2357 if (imeClient != null) {
2358 Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder());
2359 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
2360 }
2361 }
2362
2363 return imeClient != null && imeClient.asBinder() == client.asBinder();
2364 }
2365
2366 boolean hasSecureWindowOnScreen() {
2367 for (int i = mWindows.size() - 1; i >= 0; --i) {
2368 final WindowState ws = mWindows.get(i);
2369 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
2370 return true;
2371 }
2372 }
2373 return false;
2374 }
2375
2376 void updateSystemUiVisibility(int visibility, int globalDiff) {
2377 for (int i = mWindows.size() - 1; i >= 0; --i) {
2378 final WindowState ws = mWindows.get(i);
2379 try {
2380 int curValue = ws.mSystemUiVisibility;
2381 int diff = (curValue ^ visibility) & globalDiff;
2382 int newValue = (curValue & ~diff) | (visibility & diff);
2383 if (newValue != curValue) {
2384 ws.mSeq++;
2385 ws.mSystemUiVisibility = newValue;
2386 }
2387 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
2388 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
2389 visibility, newValue, diff);
2390 }
2391 } catch (RemoteException e) {
2392 // so sorry
2393 }
2394 }
2395 }
2396
2397 void onWindowFreezeTimeout() {
2398 Slog.w(TAG_WM, "Window freeze timeout expired.");
2399 mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
2400 for (int i = mWindows.size() - 1; i >= 0; --i) {
2401 final WindowState w = mWindows.get(i);
2402 if (!w.mOrientationChanging) {
2403 continue;
2404 }
2405 w.mOrientationChanging = false;
2406 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
2407 - mService.mDisplayFreezeTime);
2408 Slog.w(TAG_WM, "Force clearing orientation change: " + w);
2409 }
2410 mService.mWindowPlacerLocked.performSurfacePlacement();
2411 }
2412
2413 void waitForAllWindowsDrawn() {
2414 final WindowManagerPolicy policy = mService.mPolicy;
2415 for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
2416 final WindowState win = mWindows.get(winNdx);
Wale Ogunwale494009b82016-10-21 09:01:38 -07002417 final boolean keyguard = policy.isKeyguardHostWindow(win.mAttrs);
Jorim Jaggife762342016-10-13 14:33:27 +02002418 if (win.isVisibleLw() && (win.mAppToken != null || keyguard)) {
Wale Ogunwale494009b82016-10-21 09:01:38 -07002419 win.mWinAnimator.mDrawState = DRAW_PENDING;
2420 // Force add to mResizingWindows.
2421 win.mLastContentInsets.set(-1, -1, -1, -1);
2422 mService.mWaitingForDrawn.add(win);
Wale Ogunwale494009b82016-10-21 09:01:38 -07002423 }
2424 }
2425 }
2426
Wale Ogunwalef7cab102016-10-25 15:25:14 -07002427 ReadOnlyWindowList getReadOnlyWindowList() {
2428 return mWindows.getReadOnly();
2429 }
2430
2431 void getWindows(WindowList output) {
2432 output.addAll(mWindows);
2433 }
2434
2435 // TODO: Super crazy long method that should be broken down...
2436 boolean applySurfaceChangesTransaction(boolean recoveringMemory) {
2437
2438 boolean focusDisplayed = false;
2439 boolean displayHasContent = false;
2440 float preferredRefreshRate = 0;
2441 int preferredModeId = 0;
2442
2443
2444 final int dw = mDisplayInfo.logicalWidth;
2445 final int dh = mDisplayInfo.logicalHeight;
2446 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
2447
2448 mTmpUpdateAllDrawn.clear();
2449
2450 int repeats = 0;
2451 do {
2452 repeats++;
2453 if (repeats > 6) {
2454 Slog.w(TAG, "Animation repeat aborted after too many iterations");
2455 clearLayoutNeeded();
2456 break;
2457 }
2458
2459 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
2460 pendingLayoutChanges);
2461
Andrii Kulian839def92016-11-02 10:58:58 -07002462 // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid
2463 // the wallpaper window jumping across displays.
2464 // Remove check for default display when there will be support for multiple wallpaper
2465 // targets (on different displays).
2466 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07002467 adjustWallpaperWindows();
2468 }
2469
2470 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
2471 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
2472 if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) {
2473 setLayoutNeeded();
Andrii Kulianb17e8692016-11-01 10:37:22 -07002474 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
Wale Ogunwalef7cab102016-10-25 15:25:14 -07002475 }
2476 }
2477
2478 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
2479 setLayoutNeeded();
2480 }
2481
2482 // FIRST LOOP: Perform a layout, if needed.
2483 if (repeats < LAYOUT_REPEAT_THRESHOLD) {
2484 performLayout(repeats == 1, false /* updateInputWindows */);
2485 } else {
2486 Slog.w(TAG, "Layout repeat skipped after too many iterations");
2487 }
2488
2489 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
2490 pendingLayoutChanges = 0;
2491
2492 if (isDefaultDisplay) {
2493 mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
2494 for (int i = mWindows.size() - 1; i >= 0; i--) {
2495 final WindowState w = mWindows.get(i);
Jorim Jaggife762342016-10-13 14:33:27 +02002496 mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
2497 mService.mInputMethodTarget);
Wale Ogunwalef7cab102016-10-25 15:25:14 -07002498 }
2499 pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
2500 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
2501 "after finishPostLayoutPolicyLw", pendingLayoutChanges);
2502 }
2503 } while (pendingLayoutChanges != 0);
2504
2505 RootWindowContainer root = mService.mRoot;
2506 boolean obscured = false;
2507 boolean syswin = false;
2508 resetDimming();
2509
2510 // Only used if default window
2511 final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
2512
2513 for (int i = mWindows.size() - 1; i >= 0; i--) {
2514 final WindowState w = mWindows.get(i);
2515 final Task task = w.getTask();
2516 final boolean obscuredChanged = w.mObscured != obscured;
2517
2518 // Update effect.
2519 w.mObscured = obscured;
2520 if (!obscured) {
2521 final boolean isDisplayed = w.isDisplayedLw();
2522
2523 if (isDisplayed && w.isObscuringFullscreen(mDisplayInfo)) {
2524 // This window completely covers everything behind it, so we want to leave all
2525 // of them as undimmed (for performance reasons).
2526 root.mObscuringWindow = w;
2527 obscured = true;
2528 }
2529
2530 displayHasContent |= root.handleNotObscuredLocked(w, obscured, syswin);
2531
2532 if (w.mHasSurface && isDisplayed) {
2533 final int type = w.mAttrs.type;
2534 if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
2535 || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
2536 syswin = true;
2537 }
2538 if (preferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) {
2539 preferredRefreshRate = w.mAttrs.preferredRefreshRate;
2540 }
2541 if (preferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) {
2542 preferredModeId = w.mAttrs.preferredDisplayModeId;
2543 }
2544 }
2545 }
2546
2547 w.applyDimLayerIfNeeded();
2548
2549 if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
2550 && mWallpaperController.isWallpaperTarget(w)) {
2551 // This is the wallpaper target and its obscured state changed... make sure the
2552 // current wallpaper's visibility has been updated accordingly.
2553 mWallpaperController.updateWallpaperVisibility();
2554 }
2555
2556 w.handleWindowMovedIfNeeded();
2557
2558 final WindowStateAnimator winAnimator = w.mWinAnimator;
2559
2560 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
2561 w.mContentChanged = false;
2562
2563 // Moved from updateWindowsAndWallpaperLocked().
2564 if (w.mHasSurface) {
2565 // Take care of the window being ready to display.
2566 final boolean committed = winAnimator.commitFinishDrawingLocked();
2567 if (isDefaultDisplay && committed) {
2568 if (w.mAttrs.type == TYPE_DREAM) {
2569 // HACK: When a dream is shown, it may at that point hide the lock screen.
2570 // So we need to redo the layout to let the phone window manager make this
2571 // happen.
2572 pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
2573 if (DEBUG_LAYOUT_REPEATS) {
2574 surfacePlacer.debugLayoutRepeats(
2575 "dream and commitFinishDrawingLocked true",
2576 pendingLayoutChanges);
2577 }
2578 }
2579 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
2580 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
2581 "First draw done in potential wallpaper target " + w);
2582 root.mWallpaperMayChange = true;
2583 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2584 if (DEBUG_LAYOUT_REPEATS) {
2585 surfacePlacer.debugLayoutRepeats(
2586 "wallpaper and commitFinishDrawingLocked true",
2587 pendingLayoutChanges);
2588 }
2589 }
2590 }
2591 if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
2592 // Updates the shown frame before we set up the surface. This is needed
2593 // because the resizing could change the top-left position (in addition to
2594 // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
2595 // position the surface.
2596 //
2597 // If an animation is being started, we can't call this method because the
2598 // animation hasn't processed its initial transformation yet, but in general
2599 // we do want to update the position if the window is animating.
2600 winAnimator.computeShownFrameLocked();
2601 }
2602 winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
2603 }
2604
2605 final AppWindowToken atoken = w.mAppToken;
2606 if (atoken != null) {
2607 final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
2608 if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
2609 mTmpUpdateAllDrawn.add(atoken);
2610 }
2611 }
2612
2613 if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
2614 && w.isDisplayedLw()) {
2615 focusDisplayed = true;
2616 }
2617
2618 w.updateResizingWindowIfNeeded();
2619 }
2620
2621 mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
2622 displayHasContent,
2623 preferredRefreshRate,
2624 preferredModeId,
2625 true /* inTraversal, must call performTraversalInTrans... below */);
2626
2627 stopDimmingIfNeeded();
2628
2629 while (!mTmpUpdateAllDrawn.isEmpty()) {
2630 final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
2631 // See if any windows have been drawn, so they (and others associated with them)
2632 // can now be shown.
2633 atoken.updateAllDrawn(this);
2634 }
2635
2636 return focusDisplayed;
2637 }
2638
2639 void performLayout(boolean initial, boolean updateInputWindows) {
2640 if (!isLayoutNeeded()) {
2641 return;
2642 }
2643 clearLayoutNeeded();
2644
2645 final int dw = mDisplayInfo.logicalWidth;
2646 final int dh = mDisplayInfo.logicalHeight;
2647
2648 int i;
2649
2650 if (DEBUG_LAYOUT) {
2651 Slog.v(TAG, "-------------------------------------");
2652 Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh);
2653 }
2654
2655 mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation,
2656 getConfiguration().uiMode);
2657 if (isDefaultDisplay) {
2658 // Not needed on non-default displays.
2659 mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
2660 mService.mScreenRect.set(0, 0, dw, dh);
2661 }
2662
2663 mService.mPolicy.getContentRectLw(mContentRect);
2664
2665 int seq = mService.mLayoutSeq + 1;
2666 if (seq < 0) seq = 0;
2667 mService.mLayoutSeq = seq;
2668
2669 boolean behindDream = false;
2670
2671 // First perform layout of any root windows (not attached to another window).
2672 int topAttached = -1;
2673 for (i = mWindows.size() - 1; i >= 0; i--) {
2674 final WindowState win = mWindows.get(i);
2675
2676 // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
2677 // wasting time and funky changes while a window is animating away.
Jorim Jaggife762342016-10-13 14:33:27 +02002678 final boolean gone = (behindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win))
Wale Ogunwalef7cab102016-10-25 15:25:14 -07002679 || win.isGoneForLayoutLw();
2680
2681 if (DEBUG_LAYOUT && !win.mLayoutAttached) {
2682 Slog.v(TAG, "1ST PASS " + win + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
2683 + " mLayoutAttached=" + win.mLayoutAttached
2684 + " screen changed=" + win.isConfigChanged());
2685 final AppWindowToken atoken = win.mAppToken;
2686 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + win.mViewVisibility
2687 + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
2688 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
2689 + " parentHidden=" + win.isParentWindowHidden());
2690 else Slog.v(TAG, " VIS: mViewVisibility=" + win.mViewVisibility
2691 + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
2692 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
2693 + " parentHidden=" + win.isParentWindowHidden());
2694 }
2695
2696 // If this view is GONE, then skip it -- keep the current frame, and let the caller know
2697 // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows,
2698 // since that means "perform layout as normal, just don't display").
2699 if (!gone || !win.mHaveFrame || win.mLayoutNeeded
2700 || ((win.isConfigChanged() || win.setReportResizeHints())
2701 && !win.isGoneForLayoutLw() &&
2702 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
2703 (win.mHasSurface && win.mAppToken != null &&
2704 win.mAppToken.layoutConfigChanges)))) {
2705 if (!win.mLayoutAttached) {
2706 if (initial) {
2707 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
2708 win.mContentChanged = false;
2709 }
2710 if (win.mAttrs.type == TYPE_DREAM) {
2711 // Don't layout windows behind a dream, so that if it does stuff like hide
2712 // the status bar we won't get a bad transition when it goes away.
2713 behindDream = true;
2714 }
2715 win.mLayoutNeeded = false;
2716 win.prelayout();
2717 mService.mPolicy.layoutWindowLw(win, null);
2718 win.mLayoutSeq = seq;
2719
2720 // Window frames may have changed. Update dim layer with the new bounds.
2721 final Task task = win.getTask();
2722 if (task != null) {
2723 mDimLayerController.updateDimLayer(task);
2724 }
2725
2726 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + win.mFrame
2727 + " mContainingFrame=" + win.mContainingFrame
2728 + " mDisplayFrame=" + win.mDisplayFrame);
2729 } else {
2730 if (topAttached < 0) topAttached = i;
2731 }
2732 }
2733 }
2734
2735 boolean attachedBehindDream = false;
2736
2737 // Now perform layout of attached windows, which usually depend on the position of the
2738 // window they are attached to. XXX does not deal with windows that are attached to windows
2739 // that are themselves attached.
2740 for (i = topAttached; i >= 0; i--) {
2741 final WindowState win = mWindows.get(i);
2742
2743 if (win.mLayoutAttached) {
2744 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame
2745 + " mViewVisibility=" + win.mViewVisibility
2746 + " mRelayoutCalled=" + win.mRelayoutCalled);
2747 // If this view is GONE, then skip it -- keep the current frame, and let the caller
2748 // know so they can ignore it if they want. (We do the normal layout for INVISIBLE
2749 // windows, since that means "perform layout as normal, just don't display").
Jorim Jaggife762342016-10-13 14:33:27 +02002750 if (attachedBehindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win)) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -07002751 continue;
2752 }
2753 if ((win.mViewVisibility != GONE && win.mRelayoutCalled) || !win.mHaveFrame
2754 || win.mLayoutNeeded) {
2755 if (initial) {
2756 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
2757 win.mContentChanged = false;
2758 }
2759 win.mLayoutNeeded = false;
2760 win.prelayout();
2761 mService.mPolicy.layoutWindowLw(win, win.getParentWindow());
2762 win.mLayoutSeq = seq;
2763 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + win.mFrame
2764 + " mContainingFrame=" + win.mContainingFrame
2765 + " mDisplayFrame=" + win.mDisplayFrame);
2766 }
2767 } else if (win.mAttrs.type == TYPE_DREAM) {
2768 // Don't layout windows behind a dream, so that if it does stuff like hide the
2769 // status bar we won't get a bad transition when it goes away.
2770 attachedBehindDream = behindDream;
2771 }
2772 }
2773
2774 // Window frames may have changed. Tell the input dispatcher about it.
2775 mService.mInputMonitor.layoutInputConsumers(dw, dh);
2776 mService.mInputMonitor.setUpdateInputWindowsNeededLw();
2777 if (updateInputWindows) {
2778 mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
2779 }
2780
2781 mService.mPolicy.finishLayoutLw();
2782 mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
2783 }
2784
2785 /**
2786 * Takes a snapshot of the display. In landscape mode this grabs the whole screen.
2787 * In portrait mode, it grabs the full screenshot.
2788 *
2789 * @param width the width of the target bitmap
2790 * @param height the height of the target bitmap
2791 * @param includeFullDisplay true if the screen should not be cropped before capture
2792 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
2793 * @param config of the output bitmap
2794 * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
2795 */
2796 Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
2797 boolean includeFullDisplay, float frameScale, Bitmap.Config config,
2798 boolean wallpaperOnly) {
2799 int dw = mDisplayInfo.logicalWidth;
2800 int dh = mDisplayInfo.logicalHeight;
2801 if (dw == 0 || dh == 0) {
2802 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
2803 + ": returning null. logical widthxheight=" + dw + "x" + dh);
2804 return null;
2805 }
2806
2807 Bitmap bm = null;
2808
2809 int maxLayer = 0;
2810 final Rect frame = new Rect();
2811 final Rect stackBounds = new Rect();
2812
2813 boolean screenshotReady;
2814 int minLayer;
2815 if (appToken == null && !wallpaperOnly) {
2816 screenshotReady = true;
2817 minLayer = 0;
2818 } else {
2819 screenshotReady = false;
2820 minLayer = Integer.MAX_VALUE;
2821 }
2822
2823 WindowState appWin = null;
2824
2825 boolean includeImeInScreenshot;
2826 synchronized(mService.mWindowMap) {
2827 final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null
2828 ? mService.mInputMethodTarget.mAppToken : null;
2829 // We only include the Ime in the screenshot if the app we are screenshoting is the IME
2830 // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
2831 // mode because the frame of the IME might not overlap with that of the app.
2832 // E.g. IME target app at the top in split-screen mode and the IME at the bottom
2833 // overlapping with the bottom app.
2834 includeImeInScreenshot = imeTargetAppToken != null
2835 && imeTargetAppToken.appToken != null
2836 && imeTargetAppToken.appToken.asBinder() == appToken
2837 && !mService.mInputMethodTarget.isInMultiWindowMode();
2838 }
2839
2840 final int aboveAppLayer = (mService.mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
2841 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
2842
2843 synchronized(mService.mWindowMap) {
2844 // Figure out the part of the screen that is actually the app.
2845 appWin = null;
2846 for (int i = mWindows.size() - 1; i >= 0; i--) {
2847 final WindowState ws = mWindows.get(i);
2848 if (!ws.mHasSurface) {
2849 continue;
2850 }
2851 if (ws.mLayer >= aboveAppLayer) {
2852 continue;
2853 }
2854 if (wallpaperOnly && !ws.mIsWallpaper) {
2855 continue;
2856 }
2857 if (ws.mIsImWindow) {
2858 if (!includeImeInScreenshot) {
2859 continue;
2860 }
2861 } else if (ws.mIsWallpaper) {
2862 // If this is the wallpaper layer and we're only looking for the wallpaper layer
2863 // then the target window state is this one.
2864 if (wallpaperOnly) {
2865 appWin = ws;
2866 }
2867
2868 if (appWin == null) {
2869 // We have not ran across the target window yet, so it is probably behind
2870 // the wallpaper. This can happen when the keyguard is up and all windows
2871 // are moved behind the wallpaper. We don't want to include the wallpaper
2872 // layer in the screenshot as it will cover-up the layer of the target
2873 // window.
2874 continue;
2875 }
2876 // Fall through. The target window is in front of the wallpaper. For this
2877 // case we want to include the wallpaper layer in the screenshot because
2878 // the target window might have some transparent areas.
2879 } else if (appToken != null) {
2880 if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
2881 // This app window is of no interest if it is not associated with the
2882 // screenshot app.
2883 continue;
2884 }
2885 appWin = ws;
2886 }
2887
2888 // Include this window.
2889
2890 final WindowStateAnimator winAnim = ws.mWinAnimator;
2891 int layer = winAnim.mSurfaceController.getLayer();
2892 if (maxLayer < layer) {
2893 maxLayer = layer;
2894 }
2895 if (minLayer > layer) {
2896 minLayer = layer;
2897 }
2898
2899 // Don't include wallpaper in bounds calculation
2900 if (!includeFullDisplay && !ws.mIsWallpaper) {
2901 final Rect wf = ws.mFrame;
2902 final Rect cr = ws.mContentInsets;
2903 int left = wf.left + cr.left;
2904 int top = wf.top + cr.top;
2905 int right = wf.right - cr.right;
2906 int bottom = wf.bottom - cr.bottom;
2907 frame.union(left, top, right, bottom);
2908 ws.getVisibleBounds(stackBounds);
2909 if (!Rect.intersects(frame, stackBounds)) {
2910 // Set frame empty if there's no intersection.
2911 frame.setEmpty();
2912 }
2913 }
2914
2915 final boolean foundTargetWs =
2916 (ws.mAppToken != null && ws.mAppToken.token == appToken)
2917 || (appWin != null && wallpaperOnly);
2918 if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
2919 screenshotReady = true;
2920 }
2921
2922 if (ws.isObscuringFullscreen(mDisplayInfo)){
2923 break;
2924 }
2925 }
2926
2927 if (appToken != null && appWin == null) {
2928 // Can't find a window to snapshot.
2929 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
2930 "Screenshot: Couldn't find a surface matching " + appToken);
2931 return null;
2932 }
2933
2934 if (!screenshotReady) {
2935 Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
2936 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
2937 appWin.mWinAnimator.mDrawState)));
2938 return null;
2939 }
2940
2941 // Screenshot is ready to be taken. Everything from here below will continue
2942 // through the bottom of the loop and return a value. We only stay in the loop
2943 // because we don't want to release the mWindowMap lock until the screenshot is
2944 // taken.
2945
2946 if (maxLayer == 0) {
2947 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
2948 + ": returning null maxLayer=" + maxLayer);
2949 return null;
2950 }
2951
2952 if (!includeFullDisplay) {
2953 // Constrain frame to the screen size.
2954 if (!frame.intersect(0, 0, dw, dh)) {
2955 frame.setEmpty();
2956 }
2957 } else {
2958 // Caller just wants entire display.
2959 frame.set(0, 0, dw, dh);
2960 }
2961 if (frame.isEmpty()) {
2962 return null;
2963 }
2964
2965 if (width < 0) {
2966 width = (int) (frame.width() * frameScale);
2967 }
2968 if (height < 0) {
2969 height = (int) (frame.height() * frameScale);
2970 }
2971
2972 // Tell surface flinger what part of the image to crop. Take the top
2973 // right part of the application, and crop the larger dimension to fit.
2974 Rect crop = new Rect(frame);
2975 if (width / (float) frame.width() < height / (float) frame.height()) {
2976 int cropWidth = (int)((float)width / (float)height * frame.height());
2977 crop.right = crop.left + cropWidth;
2978 } else {
2979 int cropHeight = (int)((float)height / (float)width * frame.width());
2980 crop.bottom = crop.top + cropHeight;
2981 }
2982
2983 // The screenshot API does not apply the current screen rotation.
2984 int rot = mDisplay.getRotation();
2985
2986 if (rot == ROTATION_90 || rot == ROTATION_270) {
2987 rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90;
2988 }
2989
2990 // Surfaceflinger is not aware of orientation, so convert our logical
2991 // crop to surfaceflinger's portrait orientation.
2992 convertCropForSurfaceFlinger(crop, rot, dw, dh);
2993
2994 if (DEBUG_SCREENSHOT) {
2995 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
2996 + maxLayer + " appToken=" + appToken);
2997 for (int i = 0; i < mWindows.size(); i++) {
2998 final WindowState win = mWindows.get(i);
2999 final WindowSurfaceController controller = win.mWinAnimator.mSurfaceController;
3000 Slog.i(TAG_WM, win + ": " + win.mLayer
3001 + " animLayer=" + win.mWinAnimator.mAnimLayer
3002 + " surfaceLayer=" + ((controller == null)
3003 ? "null" : controller.getLayer()));
3004 }
3005 }
3006
3007 final ScreenRotationAnimation screenRotationAnimation =
3008 mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
3009 final boolean inRotation = screenRotationAnimation != null &&
3010 screenRotationAnimation.isAnimating();
3011 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
3012 "Taking screenshot while rotating");
3013
3014 // We force pending transactions to flush before taking
3015 // the screenshot by pushing an empty synchronous transaction.
3016 SurfaceControl.openTransaction();
3017 SurfaceControl.closeTransactionSync();
3018
3019 bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
3020 inRotation, rot);
3021 if (bm == null) {
3022 Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
3023 + ") to layer " + maxLayer);
3024 return null;
3025 }
3026 }
3027
3028 if (DEBUG_SCREENSHOT) {
3029 // TEST IF IT's ALL BLACK
3030 int[] buffer = new int[bm.getWidth() * bm.getHeight()];
3031 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
3032 boolean allBlack = true;
3033 final int firstColor = buffer[0];
3034 for (int i = 0; i < buffer.length; i++) {
3035 if (buffer[i] != firstColor) {
3036 allBlack = false;
3037 break;
3038 }
3039 }
3040 if (allBlack) {
3041 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
3042 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
3043 (appWin != null ?
3044 appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
3045 " minLayer=" + minLayer + " maxLayer=" + maxLayer);
3046 }
3047 }
3048
3049 // Create a copy of the screenshot that is immutable and backed in ashmem.
3050 // This greatly reduces the overhead of passing the bitmap between processes.
3051 Bitmap ret = bm.createAshmemBitmap(config);
3052 bm.recycle();
3053 return ret;
3054 }
3055
3056 // TODO: Can this use createRotationMatrix()?
3057 private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
3058 if (rot == Surface.ROTATION_90) {
3059 final int tmp = crop.top;
3060 crop.top = dw - crop.right;
3061 crop.right = crop.bottom;
3062 crop.bottom = dw - crop.left;
3063 crop.left = tmp;
3064 } else if (rot == Surface.ROTATION_180) {
3065 int tmp = crop.top;
3066 crop.top = dh - crop.bottom;
3067 crop.bottom = dh - tmp;
3068 tmp = crop.right;
3069 crop.right = dw - crop.left;
3070 crop.left = dw - tmp;
3071 } else if (rot == Surface.ROTATION_270) {
3072 final int tmp = crop.top;
3073 crop.top = crop.left;
3074 crop.left = dh - crop.bottom;
3075 crop.bottom = crop.right;
3076 crop.right = dh - tmp;
3077 }
3078 }
3079
3080 void onSeamlessRotationTimeout() {
3081 boolean layoutNeeded = false;
3082 for (int i = mWindows.size() - 1; i >= 0; i--) {
3083 final WindowState w = mWindows.get(i);
3084 if (!w.mSeamlesslyRotated) {
3085 continue;
3086 }
3087 layoutNeeded = true;
3088 w.setDisplayLayoutNeeded();
3089 mService.markForSeamlessRotation(w, false);
3090 }
3091
3092 if (layoutNeeded) {
3093 mService.mWindowPlacerLocked.performSurfacePlacement();
3094 }
3095 }
3096
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07003097 static final class GetWindowOnDisplaySearchResult {
Wale Ogunwaleec731152016-09-08 20:18:57 -07003098 boolean reachedToken;
3099 WindowState foundWindow;
3100
3101 void reset() {
3102 reachedToken = false;
3103 foundWindow = null;
3104 }
3105 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07003106
3107 static final class TaskForResizePointSearchResult {
3108 boolean searchDone;
3109 Task taskForResize;
3110
3111 void reset() {
3112 searchDone = false;
3113 taskForResize = null;
3114 }
3115 }
Robert Carr3b716242016-08-16 16:02:21 -07003116
Wale Ogunwale19e452e2016-10-12 12:36:29 -07003117 /**
3118 * Base class for any direct child window container of {@link #DisplayContent} need to inherit
3119 * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
3120 * homogeneous children type which is currently required by sub-classes of
3121 * {@link WindowContainer} class.
3122 */
3123 static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
3124
3125 int size() {
3126 return mChildren.size();
3127 }
3128
3129 E get(int index) {
3130 return mChildren.get(index);
3131 }
3132
3133 @Override
3134 boolean fillsParent() {
3135 return true;
3136 }
3137
3138 @Override
3139 boolean isVisible() {
3140 return true;
Robert Carr3b716242016-08-16 16:02:21 -07003141 }
3142 }
3143
Wale Ogunwale19e452e2016-10-12 12:36:29 -07003144 /**
3145 * Window container class that contains all containers on this display relating to Apps.
3146 * I.e Activities.
3147 */
3148 private class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
3149
Andrii Kulian839def92016-11-02 10:58:58 -07003150 /**
3151 * Adds the stack to this container.
3152 * @see WindowManagerService#addStackToDisplay(int, int, boolean)
3153 */
3154 void addStackToDisplay(TaskStack stack, boolean onTop) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -07003155 if (stack.mStackId == HOME_STACK_ID) {
3156 if (mHomeStack != null) {
3157 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
3158 }
3159 mHomeStack = stack;
3160 }
3161 addChild(stack, onTop);
3162 stack.onDisplayChanged(DisplayContent.this);
Robert Carr3b716242016-08-16 16:02:21 -07003163 }
Wale Ogunwale19e452e2016-10-12 12:36:29 -07003164
Andrii Kulian839def92016-11-02 10:58:58 -07003165 /** Removes the stack from its container and prepare for changing the parent. */
3166 void removeStackFromDisplay(TaskStack stack) {
3167 removeChild(stack);
3168 stack.onRemovedFromDisplay();
3169 // TODO: remove when window list will be gone.
3170 // Manually remove records from window list and tap excluded windows list.
3171 for (int i = mWindows.size() - 1; i >= 0; --i) {
3172 final WindowState windowState = mWindows.get(i);
3173 if (stack == windowState.getStack()) {
3174 mWindows.remove(i);
3175 mTapExcludedWindows.remove(windowState);
3176 }
3177 }
3178 }
3179
Wale Ogunwale19e452e2016-10-12 12:36:29 -07003180 void moveStack(TaskStack stack, boolean toTop) {
3181 if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
3182 // This stack is always-on-top silly...
3183 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
3184 return;
3185 }
3186
3187 if (!mChildren.contains(stack)) {
3188 Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
3189 }
3190 removeChild(stack);
3191 addChild(stack, toTop);
3192 }
3193
3194 private void addChild(TaskStack stack, boolean toTop) {
3195 int addIndex = toTop ? mChildren.size() : 0;
3196
3197 if (toTop
3198 && mService.isStackVisibleLocked(PINNED_STACK_ID)
3199 && stack.mStackId != PINNED_STACK_ID) {
3200 // The pinned stack is always the top most stack (always-on-top) when it is visible.
3201 // So, stack is moved just below the pinned stack.
3202 addIndex--;
3203 TaskStack topStack = mChildren.get(addIndex);
3204 if (topStack.mStackId != PINNED_STACK_ID) {
3205 throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
3206 }
3207 }
3208 addChild(stack, addIndex);
3209 setLayoutNeeded();
3210 }
3211
Wale Ogunwalee6f806e2016-10-20 15:29:42 -07003212 @Override
3213 int getOrientation() {
3214 if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
3215 || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
3216 // Apps and their containers are not allowed to specify an orientation while the
3217 // docked or freeform stack is visible...except for the home stack/task if the
3218 // docked stack is minimized and it actually set something.
3219 if (mHomeStack != null && mHomeStack.isVisible()
3220 && mDividerControllerLocked.isMinimizedDock()) {
3221 final int orientation = mHomeStack.getOrientation();
3222 if (orientation != SCREEN_ORIENTATION_UNSET) {
3223 return orientation;
3224 }
3225 }
3226 return SCREEN_ORIENTATION_UNSPECIFIED;
3227 }
3228
3229 final int orientation = super.getOrientation();
3230 if (orientation != SCREEN_ORIENTATION_UNSET
3231 && orientation != SCREEN_ORIENTATION_BEHIND) {
3232 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3233 "App is requesting an orientation, return " + orientation);
3234 return orientation;
3235 }
3236
3237 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3238 "No app is requesting an orientation, return " + mService.mLastOrientation);
3239 // The next app has not been requested to be visible, so we keep the current orientation
3240 // to prevent freezing/unfreezing the display too early.
3241 return mService.mLastOrientation;
3242 }
Wale Ogunwale19e452e2016-10-12 12:36:29 -07003243 }
3244
3245 /**
3246 * Window container class that contains all containers on this display that are not related to
3247 * Apps. E.g. status bar.
3248 */
3249 private static class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
3250
Robert Carr3b716242016-08-16 16:02:21 -07003251 }
Craig Mautner59c00972012-07-30 12:10:24 -07003252}