Robert Carr | e625fcf | 2017-09-01 12:36:28 -0700 | [diff] [blame] | 1 | /* |
| 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 Ogunwale | e05f501 | 2016-09-16 16:27:29 -0700 | [diff] [blame] | 16 | |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 17 | package com.android.server.wm; |
| 18 | |
Filip Gruszczynski | 0bd180d | 2015-12-07 15:43:52 -0800 | [diff] [blame] | 19 | import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; |
Jorim Jaggi | 192086e | 2016-03-11 17:17:03 +0100 | [diff] [blame] | 20 | import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; |
Filip Gruszczynski | 0bd180d | 2015-12-07 15:43:52 -0800 | [diff] [blame] | 21 | import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; |
Jorim Jaggi | 192086e | 2016-03-11 17:17:03 +0100 | [diff] [blame] | 22 | import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE; |
Jorim Jaggi | 192086e | 2016-03-11 17:17:03 +0100 | [diff] [blame] | 23 | import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 24 | |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 25 | import android.os.Debug; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 26 | import android.os.Trace; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 27 | import android.util.Slog; |
Jorim Jaggi | 3878ca3 | 2017-02-02 17:13:05 -0800 | [diff] [blame] | 28 | import android.util.SparseIntArray; |
Jorim Jaggi | d75962e | 2016-05-03 15:10:03 -0700 | [diff] [blame] | 29 | |
Filip Gruszczynski | 24966d4 | 2015-09-05 15:00:00 -0700 | [diff] [blame] | 30 | import java.io.PrintWriter; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 31 | |
| 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 | */ |
| 38 | class WindowSurfacePlacer { |
Filip Gruszczynski | ce4ec40 | 2016-01-22 11:22:47 -0800 | [diff] [blame] | 39 | private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfacePlacer" : TAG_WM; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 40 | private final WindowManagerService mService; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 41 | |
| 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; |
lumark | 7888178a9 | 2018-09-26 13:13:37 +0800 | [diff] [blame] | 48 | static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 2; |
| 49 | static final int SET_WALLPAPER_ACTION_PENDING = 1 << 3; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 50 | |
Filip Gruszczynski | 24966d4 | 2015-09-05 15:00:00 -0700 | [diff] [blame] | 51 | private boolean mTraversalScheduled; |
Jorim Jaggi | c402520 | 2015-10-22 16:43:34 +0200 | [diff] [blame] | 52 | private int mDeferDepth = 0; |
Filip Gruszczynski | 24966d4 | 2015-09-05 15:00:00 -0700 | [diff] [blame] | 53 | |
Jorim Jaggi | 3878ca3 | 2017-02-02 17:13:05 -0800 | [diff] [blame] | 54 | private final SparseIntArray mTempTransitionReasons = new SparseIntArray(); |
Jorim Jaggi | 3dac63a | 2016-03-01 12:37:07 +0100 | [diff] [blame] | 55 | |
Jorim Jaggi | ed7993b | 2017-03-28 18:50:01 +0100 | [diff] [blame] | 56 | private final Runnable mPerformSurfacePlacement; |
| 57 | |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 58 | public WindowSurfacePlacer(WindowManagerService service) { |
| 59 | mService = service; |
Jorim Jaggi | ed7993b | 2017-03-28 18:50:01 +0100 | [diff] [blame] | 60 | mPerformSurfacePlacement = () -> { |
Wale Ogunwale | db485de | 2018-10-29 09:47:07 -0700 | [diff] [blame] | 61 | synchronized (mService.mGlobalLock) { |
Jorim Jaggi | ed7993b | 2017-03-28 18:50:01 +0100 | [diff] [blame] | 62 | performSurfacePlacement(); |
| 63 | } |
| 64 | }; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 65 | } |
| 66 | |
Jorim Jaggi | c402520 | 2015-10-22 16:43:34 +0200 | [diff] [blame] | 67 | /** |
| 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 Jaggi | 1f83308 | 2017-08-04 18:06:56 +0200 | [diff] [blame] | 84 | boolean isLayoutDeferred() { |
| 85 | return mDeferDepth > 0; |
| 86 | } |
| 87 | |
chaviw | 504715c | 2019-02-14 11:02:43 -0800 | [diff] [blame] | 88 | void performSurfacePlacementIfScheduled() { |
| 89 | if (mTraversalScheduled) { |
| 90 | performSurfacePlacement(); |
| 91 | } |
| 92 | } |
| 93 | |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 94 | final void performSurfacePlacement() { |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 95 | performSurfacePlacement(false /* force */); |
| 96 | } |
| 97 | |
| 98 | final void performSurfacePlacement(boolean force) { |
| 99 | if (mDeferDepth > 0 && !force) { |
Jorim Jaggi | c402520 | 2015-10-22 16:43:34 +0200 | [diff] [blame] | 100 | return; |
| 101 | } |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 102 | int loopCount = 6; |
| 103 | do { |
Filip Gruszczynski | 24966d4 | 2015-09-05 15:00:00 -0700 | [diff] [blame] | 104 | mTraversalScheduled = false; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 105 | performSurfacePlacementLoop(); |
Jorim Jaggi | ed7993b | 2017-03-28 18:50:01 +0100 | [diff] [blame] | 106 | mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement); |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 107 | loopCount--; |
Filip Gruszczynski | 24966d4 | 2015-09-05 15:00:00 -0700 | [diff] [blame] | 108 | } while (mTraversalScheduled && loopCount > 0); |
Wale Ogunwale | e05f501 | 2016-09-16 16:27:29 -0700 | [diff] [blame] | 109 | mService.mRoot.mWallpaperActionPending = false; |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 110 | } |
| 111 | |
| 112 | private void performSurfacePlacementLoop() { |
| 113 | if (mInLayout) { |
| 114 | if (DEBUG) { |
| 115 | throw new RuntimeException("Recursive call!"); |
| 116 | } |
Filip Gruszczynski | ce4ec40 | 2016-01-22 11:22:47 -0800 | [diff] [blame] | 117 | Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 118 | + Debug.getCallers(3)); |
| 119 | return; |
| 120 | } |
| 121 | |
Vishnu Nair | ba18335 | 2018-11-21 11:16:49 -0800 | [diff] [blame] | 122 | // TODO(multi-display): |
| 123 | final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked(); |
| 124 | if (defaultDisplay.mWaitingForConfig) { |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 125 | // 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 Ogunwale | adde52e | 2016-07-16 13:11:55 -0700 | [diff] [blame] | 144 | final WindowState ws = mService.mForceRemoves.remove(0); |
Filip Gruszczynski | ce4ec40 | 2016-01-22 11:22:47 -0800 | [diff] [blame] | 145 | Slog.i(TAG, "Force removing: " + ws); |
Wale Ogunwale | 571771c | 2016-08-26 13:18:50 -0700 | [diff] [blame] | 146 | ws.removeImmediately(); |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 147 | } |
Filip Gruszczynski | ce4ec40 | 2016-01-22 11:22:47 -0800 | [diff] [blame] | 148 | Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 149 | Object tmp = new Object(); |
| 150 | synchronized (tmp) { |
| 151 | try { |
| 152 | tmp.wait(250); |
| 153 | } catch (InterruptedException e) { |
| 154 | } |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | try { |
Wale Ogunwale | e05f501 | 2016-09-16 16:27:29 -0700 | [diff] [blame] | 159 | mService.mRoot.performSurfacePlacement(recoveringMemory); |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 160 | |
| 161 | mInLayout = false; |
| 162 | |
Wale Ogunwale | 2b06bfc | 2016-09-28 14:17:05 -0700 | [diff] [blame] | 163 | if (mService.mRoot.isLayoutNeeded()) { |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 164 | if (++mLayoutRepeatCount < 6) { |
Filip Gruszczynski | 24966d4 | 2015-09-05 15:00:00 -0700 | [diff] [blame] | 165 | requestTraversal(); |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 166 | } else { |
Filip Gruszczynski | ce4ec40 | 2016-01-22 11:22:47 -0800 | [diff] [blame] | 167 | Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 168 | 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 Gruszczynski | ce4ec40 | 2016-01-22 11:22:47 -0800 | [diff] [blame] | 180 | Slog.wtf(TAG, "Unhandled exception while laying out windows", e); |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 181 | } |
| 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 Gruszczynski | ce4ec40 | 2016-01-22 11:22:47 -0800 | [diff] [blame] | 188 | Slog.v(TAG, "Layouts looping: " + msg + |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 189 | ", mPendingLayoutChanges = 0x" + Integer.toHexString(pendingLayoutChanges)); |
| 190 | } |
| 191 | } |
| 192 | |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 193 | boolean isInLayout() { |
| 194 | return mInLayout; |
| 195 | } |
| 196 | |
Filip Gruszczynski | 24966d4 | 2015-09-05 15:00:00 -0700 | [diff] [blame] | 197 | void requestTraversal() { |
| 198 | if (!mTraversalScheduled) { |
| 199 | mTraversalScheduled = true; |
Jorim Jaggi | ed7993b | 2017-03-28 18:50:01 +0100 | [diff] [blame] | 200 | mService.mAnimationHandler.post(mPerformSurfacePlacement); |
Filip Gruszczynski | 24966d4 | 2015-09-05 15:00:00 -0700 | [diff] [blame] | 201 | } |
| 202 | } |
| 203 | |
| 204 | public void dump(PrintWriter pw, String prefix) { |
Wale Ogunwale | e05f501 | 2016-09-16 16:27:29 -0700 | [diff] [blame] | 205 | pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled); |
| 206 | pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow); |
Wale Ogunwale | d4a00a0 | 2016-10-10 11:29:17 -0700 | [diff] [blame] | 207 | pw.println(prefix + "mObscuringWindow=" + mService.mRoot.mObscuringWindow); |
Filip Gruszczynski | 24966d4 | 2015-09-05 15:00:00 -0700 | [diff] [blame] | 208 | } |
Filip Gruszczynski | 4501d23 | 2015-09-02 13:00:02 -0700 | [diff] [blame] | 209 | } |