blob: cc79178796343f640c6d5fba1e1a65ad37eb4ee0 [file] [log] [blame]
Robert Carre625fcf2017-09-01 12:36:28 -07001/*
2 * Copyright (C) 2017 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 */
Wale Ogunwalee05f5012016-09-16 16:27:29 -070016
Filip Gruszczynski4501d232015-09-02 13:00:02 -070017package com.android.server.wm;
18
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080019import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
Jorim Jaggi192086e2016-03-11 17:17:03 +010020import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080021import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Jorim Jaggi192086e2016-03-11 17:17:03 +010022import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE;
Jorim Jaggi192086e2016-03-11 17:17:03 +010023import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070024
Filip Gruszczynski4501d232015-09-02 13:00:02 -070025import android.os.Debug;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070026import android.os.Trace;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070027import android.util.Slog;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080028import android.util.SparseIntArray;
Jorim Jaggid75962e2016-05-03 15:10:03 -070029
Filip Gruszczynski24966d42015-09-05 15:00:00 -070030import java.io.PrintWriter;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070031
32/**
33 * Positions windows and their surfaces.
34 *
35 * It sets positions of windows by calculating their frames and then applies this by positioning
36 * surfaces according to these frames. Z layer is still assigned withing WindowManagerService.
37 */
38class WindowSurfacePlacer {
Filip Gruszczynskice4ec402016-01-22 11:22:47 -080039 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfacePlacer" : TAG_WM;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070040 private final WindowManagerService mService;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070041
42 private boolean mInLayout = false;
43
44 /** Only do a maximum of 6 repeated layouts. After that quit */
45 private int mLayoutRepeatCount;
46
47 static final int SET_UPDATE_ROTATION = 1 << 0;
lumark7888178a92018-09-26 13:13:37 +080048 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 2;
49 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 3;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070050
Filip Gruszczynski24966d42015-09-05 15:00:00 -070051 private boolean mTraversalScheduled;
Jorim Jaggic4025202015-10-22 16:43:34 +020052 private int mDeferDepth = 0;
Filip Gruszczynski24966d42015-09-05 15:00:00 -070053
Jorim Jaggi3878ca32017-02-02 17:13:05 -080054 private final SparseIntArray mTempTransitionReasons = new SparseIntArray();
Jorim Jaggi3dac63a2016-03-01 12:37:07 +010055
Jorim Jaggied7993b2017-03-28 18:50:01 +010056 private final Runnable mPerformSurfacePlacement;
57
Filip Gruszczynski4501d232015-09-02 13:00:02 -070058 public WindowSurfacePlacer(WindowManagerService service) {
59 mService = service;
Jorim Jaggied7993b2017-03-28 18:50:01 +010060 mPerformSurfacePlacement = () -> {
Wale Ogunwaledb485de2018-10-29 09:47:07 -070061 synchronized (mService.mGlobalLock) {
Jorim Jaggied7993b2017-03-28 18:50:01 +010062 performSurfacePlacement();
63 }
64 };
Filip Gruszczynski4501d232015-09-02 13:00:02 -070065 }
66
Jorim Jaggic4025202015-10-22 16:43:34 +020067 /**
68 * See {@link WindowManagerService#deferSurfaceLayout()}
69 */
70 void deferLayout() {
71 mDeferDepth++;
72 }
73
74 /**
75 * See {@link WindowManagerService#continueSurfaceLayout()}
76 */
77 void continueLayout() {
78 mDeferDepth--;
79 if (mDeferDepth <= 0) {
80 performSurfacePlacement();
81 }
82 }
83
Jorim Jaggi1f833082017-08-04 18:06:56 +020084 boolean isLayoutDeferred() {
85 return mDeferDepth > 0;
86 }
87
chaviw504715c2019-02-14 11:02:43 -080088 void performSurfacePlacementIfScheduled() {
89 if (mTraversalScheduled) {
90 performSurfacePlacement();
91 }
92 }
93
Filip Gruszczynski4501d232015-09-02 13:00:02 -070094 final void performSurfacePlacement() {
Jorim Jaggi02886a82016-12-06 09:10:06 -080095 performSurfacePlacement(false /* force */);
96 }
97
98 final void performSurfacePlacement(boolean force) {
99 if (mDeferDepth > 0 && !force) {
Jorim Jaggic4025202015-10-22 16:43:34 +0200100 return;
101 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700102 int loopCount = 6;
103 do {
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700104 mTraversalScheduled = false;
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700105 performSurfacePlacementLoop();
Jorim Jaggied7993b2017-03-28 18:50:01 +0100106 mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700107 loopCount--;
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700108 } while (mTraversalScheduled && loopCount > 0);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700109 mService.mRoot.mWallpaperActionPending = false;
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700110 }
111
112 private void performSurfacePlacementLoop() {
113 if (mInLayout) {
114 if (DEBUG) {
115 throw new RuntimeException("Recursive call!");
116 }
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800117 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700118 + Debug.getCallers(3));
119 return;
120 }
121
Vishnu Nairba183352018-11-21 11:16:49 -0800122 // TODO(multi-display):
123 final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
124 if (defaultDisplay.mWaitingForConfig) {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700125 // Our configuration has changed (most likely rotation), but we
126 // don't yet have the complete configuration to report to
127 // applications. Don't do any window layout until we have it.
128 return;
129 }
130
131 if (!mService.mDisplayReady) {
132 // Not yet initialized, nothing to do.
133 return;
134 }
135
136 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
137 mInLayout = true;
138
139 boolean recoveringMemory = false;
140 if (!mService.mForceRemoves.isEmpty()) {
141 recoveringMemory = true;
142 // Wait a little bit for things to settle down, and off we go.
143 while (!mService.mForceRemoves.isEmpty()) {
Wale Ogunwaleadde52e2016-07-16 13:11:55 -0700144 final WindowState ws = mService.mForceRemoves.remove(0);
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800145 Slog.i(TAG, "Force removing: " + ws);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700146 ws.removeImmediately();
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700147 }
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800148 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700149 Object tmp = new Object();
150 synchronized (tmp) {
151 try {
152 tmp.wait(250);
153 } catch (InterruptedException e) {
154 }
155 }
156 }
157
158 try {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700159 mService.mRoot.performSurfacePlacement(recoveringMemory);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700160
161 mInLayout = false;
162
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700163 if (mService.mRoot.isLayoutNeeded()) {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700164 if (++mLayoutRepeatCount < 6) {
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700165 requestTraversal();
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700166 } else {
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800167 Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700168 mLayoutRepeatCount = 0;
169 }
170 } else {
171 mLayoutRepeatCount = 0;
172 }
173
174 if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
175 mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
176 mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
177 }
178 } catch (RuntimeException e) {
179 mInLayout = false;
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800180 Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700181 }
182
183 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
184 }
185
186 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
187 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800188 Slog.v(TAG, "Layouts looping: " + msg +
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700189 ", mPendingLayoutChanges = 0x" + Integer.toHexString(pendingLayoutChanges));
190 }
191 }
192
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700193 boolean isInLayout() {
194 return mInLayout;
195 }
196
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700197 void requestTraversal() {
198 if (!mTraversalScheduled) {
199 mTraversalScheduled = true;
Jorim Jaggied7993b2017-03-28 18:50:01 +0100200 mService.mAnimationHandler.post(mPerformSurfacePlacement);
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700201 }
202 }
203
204 public void dump(PrintWriter pw, String prefix) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700205 pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled);
206 pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow);
Wale Ogunwaled4a00a02016-10-10 11:29:17 -0700207 pw.println(prefix + "mObscuringWindow=" + mService.mRoot.mObscuringWindow);
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700208 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700209}