首先起点肯定是app调用了屏幕旋转
####1.app中调用屏幕旋转
Activity.setRequestedOrientation()
494 /** @hide */
495 @IntDef(prefix = { "SCREEN_ORIENTATION_" }, value = {
496 SCREEN_ORIENTATION_UNSET,
497 SCREEN_ORIENTATION_UNSPECIFIED,
498 SCREEN_ORIENTATION_LANDSCAPE,
499 SCREEN_ORIENTATION_PORTRAIT,
500 SCREEN_ORIENTATION_USER,
501 SCREEN_ORIENTATION_BEHIND,
502 SCREEN_ORIENTATION_SENSOR,
503 SCREEN_ORIENTATION_NOSENSOR,
504 SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
505 SCREEN_ORIENTATION_SENSOR_PORTRAIT,
506 SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
507 SCREEN_ORIENTATION_REVERSE_PORTRAIT,
508 SCREEN_ORIENTATION_FULL_SENSOR,
509 SCREEN_ORIENTATION_USER_LANDSCAPE,
510 SCREEN_ORIENTATION_USER_PORTRAIT,
511 SCREEN_ORIENTATION_FULL_USER,
512 SCREEN_ORIENTATION_LOCKED
513 })
一共有如下的几种方式。
2.Activity->setrequestedorientation
5927 public void setRequestedOrientation(@ActivityInfo.ScreenOrientation int requestedOrientation) {
5928 if (mParent == null) {
5929 try {
5930 ActivityManager.getService().setRequestedOrientation(
5931 mToken, requestedOrientation);
5932 } catch (RemoteException e) {
5933 // Empty
5934 }
5935 } else {
5936 mParent.setRequestedOrientation(requestedOrientation);
5937 }
5938 }
####3. AMS->setRequestedOrientation
5739 @Override
5740 public void setRequestedOrientation(IBinder token, int requestedOrientation) {
5741 synchronized (this) {
5742 ActivityRecord r = ActivityRecord.isInStackLocked(token);
5743 if (r == null) {
5744 return;
5745 }
5746 final long origId = Binder.clearCallingIdentity();
5747 try {
5748 r.setRequestedOrientation(requestedOrientation);
5749 } finally {
5750 Binder.restoreCallingIdentity(origId);
5751 }
5752 }
5753 }
4.activityrecord->setRequestedOrientation
2414 void setRequestedOrientation(int requestedOrientation) {
2415 final int displayId = getDisplayId();
2416 final Configuration displayConfig =
2417 mStackSupervisor.getDisplayOverrideConfiguration(displayId);
2418
2419 final Configuration config = mWindowContainerController.setOrientation(requestedOrientation,
2420 displayId, displayConfig, mayFreezeScreenLocked(app));
2421 if (config != null) {
2422 frozenBeforeDestroy = true;//此时是需要进行截图处理的
2423 if (!service.updateDisplayOverrideConfigurationLocked(config, this,
2424 false /* deferResume */, displayId)) {
2425 mStackSupervisor.resumeFocusedStackTopActivityLocked();
2426 }
2427 }
2428 service.mTaskChangeNotificationController.notifyActivityRequestedOrientationChanged(
2429 task.taskId, requestedOrientation);
2430 }
5. AppWindowContainerController->setorientation
280 public Configuration setOrientation(int requestedOrientation, int displayId,
281 Configuration displayConfig, boolean freezeScreenIfNeeded) {
282 synchronized(mWindowMap) {
283 if (mContainer == null) {
284 Slog.w(TAG_WM,
285 "Attempted to set orientation of non-existing app token: " + mToken);
286 return null;
287 }
288
289 mContainer.setOrientation(requestedOrientation);
290
291 final IBinder binder = freezeScreenIfNeeded ? mToken.asBinder() : null;
292 return mService.updateOrientationFromAppTokens(displayConfig, binder, displayId);
293
294 }
295 }
####6.WindowManagerService->updateOrientationFromAppTokens
2405 @Override
2406 public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
2407 IBinder freezeThisOneIfNeeded, int displayId) {
2408 return updateOrientationFromAppTokens(currentConfig, freezeThisOneIfNeeded, displayId,
2409 false /* forceUpdate */);
2410 }
2411
2412 public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
2413 IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) {
2414 if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
2415 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2416 }
2417
2418 final Configuration config;
2419 final long ident = Binder.clearCallingIdentity();
2420 try {
2421 synchronized(mWindowMap) {
2422 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
2423 displayId, forceUpdate);
2424 }
2425 } finally {
2426 Binder.restoreCallingIdentity(ident);
2427 }
2428
2429 return config;
2430 }
7. wms->updateOrientationFromAppTokensLocked
2432 private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
2433 IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) {
2434 if (!mDisplayReady) {
2435 return null;
2436 }
2437 Configuration config = null;
2438
2439 if (updateOrientationFromAppTokensLocked(displayId, forceUpdate)) {
2440 // If we changed the orientation but mOrientationChangeComplete is already true,
2441 // we used seamless rotation, and we don't need to freeze the screen.
2442 if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
2443 final AppWindowToken atoken = mRoot.getAppWindowToken(freezeThisOneIfNeeded);
2444 if (atoken != null) {
2445 atoken.startFreezingScreen();
2446 }
2447 }
2448 config = computeNewConfigurationLocked(displayId);
2449
2450 } else if (currentConfig != null) {
2451 // No obvious action we need to take, but if our current state mismatches the activity
2452 // manager's, update it, disregarding font scale, which should remain set to the value
2453 // of the previous configuration.
2454 // Here we're calling Configuration#unset() instead of setToDefaults() because we need
2455 // to keep override configs clear of non-empty values (e.g. fontSize).
2456 mTempConfiguration.unset();
2457 mTempConfiguration.updateFrom(currentConfig);
2458 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2459 displayContent.computeScreenConfiguration(mTempConfiguration);
2460 if (currentConfig.diff(mTempConfiguration) != 0) {
2461 mWaitingForConfig = true;
2462 displayContent.setLayoutNeeded();
2463 int anim[] = new int[2];
2464 mPolicy.selectRotationAnimationLw(anim);
2465
2466 startFreezingDisplayLocked(anim[0], anim[1], displayContent);
2467 config = new Configuration(mTempConfiguration);
2468 }
2469 }
2470
2471 return config;
2472 }
8.wms->updateOrientationFromAppTokensLocked
2490 boolean updateOrientationFromAppTokensLocked(int displayId, boolean forceUpdate) {
2491 long ident = Binder.clearCallingIdentity();
2492 try {
2493 final DisplayContent dc = mRoot.getDisplayContent(displayId);
2494 final int req = dc.getOrientation();
2495 if (req != dc.getLastOrientation() || forceUpdate) {
2496 dc.setLastOrientation(req);
2497 //send a message to Policy indicating orientation change to take
2498 //action like disabling/enabling sensors etc.,
2499 // TODO(multi-display): Implement policy for secondary displays.
2500 if (dc.isDefaultDisplay) {
2501 mPolicy.setCurrentOrientationLw(req);
2502 }
2503 return dc.updateRotationUnchecked(forceUpdate);
2504 }
2505 return false;
2506 } finally {
2507 Binder.restoreCallingIdentity(ident);
2508 }
2509 }
9.displaycontent->updaterotationunchedked
然后就到了比较重要的updaterotationuncheckedlocked
964 boolean updateRotationUnchecked(boolean forceUpdate) {
...
1076 if (!rotateSeamlessly) {//先将屏幕截图
1077 mService.startFreezingDisplayLocked(anim[0], anim[1], this);
1078 // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
1079 screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
1080 mDisplayId);
1081 } else {
1082 // The screen rotation animation uses a screenshot to freeze the screen
1083 // while windows resize underneath.
1084 // When we are rotating seamlessly, we allow the elements to transition
1085 // to their rotated state independently and without a freeze required.
1086 screenRotationAnimation = null;
1087
1088 mService.startSeamlessRotation();
1089 }
...
1138 forAllWindows(w -> {
1139 if (w.mHasSurface && !rotateSeamlessly) {
1140 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
1141 w.setOrientationChanging(true);
1142 mService.mRoot.mOrientationChangeComplete = false;
1143 w.mLastFreezeDuration = 0;
1144 }
1145 w.mReportOrientationChanged = true;
1146 }, true /* traverseTopToBottom */);
1147
10.wms->startFreezingDisplayLocked
5829 void startFreezingDisplayLocked(int exitAnim, int enterAnim,
5830 DisplayContent displayContent) {
...
5879 if (CUSTOM_SCREEN_ROTATION && displayContent.isDefaultDisplay) {
5880 mExitAnimId = exitAnim;
5881 mEnterAnimId = enterAnim;
5882 ScreenRotationAnimation screenRotationAnimation =
5883 mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId);
5884 if (screenRotationAnimation != null) {
5885 screenRotationAnimation.kill();
5886 }
5887
5888 // Check whether the current screen contains any secure content.
5889 boolean isSecure = displayContent.hasSecureWindowOnScreen();
5890
5891 displayContent.updateDisplayInfo();//创建了转屏的动画,其实就是截屏
5892 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
5893 mPolicy.isDefaultOrientationForced(), isSecure,
5894 this);
5895 mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
5896 screenRotationAnimation);
5897 }
...
####11.ScreenRotationAnimation
229
230 public ScreenRotationAnimation(Context context, DisplayContent displayContent,
231 boolean forceDefaultOrientation, boolean isSecure, WindowManagerService service) {
...
268 final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
269 try {
270 mSurfaceControl = displayContent.makeOverlay()
271 .setName("ScreenshotSurface")
272 .setSize(mWidth, mHeight)
273 .setSecure(isSecure)
274 .build();
275
276 // capture a screenshot into the surface we just created
277 // TODO(multidisplay): we should use the proper display
278 final int displayId = SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN;
279 final IBinder displayHandle = SurfaceControl.getBuiltInDisplay(displayId);
280 // This null check below is to guard a race condition where WMS didn't have a chance to
281 // respond to display disconnection before handling rotation , that surfaceflinger may
282 // return a null handle here because it doesn't think that display is valid anymore.
283 if (displayHandle != null) {
284 Surface sur = new Surface();
285 sur.copyFrom(mSurfaceControl);
286 SurfaceControl.screenshot(displayHandle, sur);//通过jni去进行屏幕的screenshot
287 t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
288 t.setAlpha(mSurfaceControl, 0);
289 t.show(mSurfaceControl);
290 sur.destroy();
291 } else {
292 Slog.w(TAG, "Built-in display " + displayId + " is null.");
293 }
294 } catch (OutOfResourcesException e) {
295 Slog.w(TAG, "Unable to allocate freeze surface", e);
296 }
297
298 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
299 " FREEZE " + mSurfaceControl + ": CREATE");
300 setRotation(t, originalRotation);
301 t.apply();
302 }
好的,现在截图已经准备好了,让我们回到第9步继续往下走.第九步就是需要将所有的后台标记成已经完成才能继续下一步的动作。现在重新回到第7步,然后继续往下走。
12.appwindowtoken->startfreezingscreen
这个时候需要将当前的app界面进行freezing
1117 void startFreezingScreen() {
1118 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
1119 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
1120 + hiddenRequested);
1121 if (!hiddenRequested) {
1122 if (!mFreezingScreen) {
1123 mFreezingScreen = true;
1124 mService.registerAppFreezeListener(this);
1125 mService.mAppsFreezingScreen++;
1126 if (mService.mAppsFreezingScreen == 1) {
1127 mService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1128 mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1129 mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
1130 }
1131 }
1132 final int count = mChildren.size();
1133 for (int i = 0; i < count; i++) {
1134 final WindowState w = mChildren.get(i);
1135 w.onStartFreezingScreen();
1136 }
1137 }
1138 }
这时候所有的界面都freeze了,那么回到第四步中
13.ams->updatedisplayoverrideconfigurationlocked
23038 private boolean updateDisplayOverrideConfigurationLocked(Configuration values,
23039 ActivityRecord starting, boolean deferResume, int displayId,
23040 UpdateConfigurationResult result) {
23041 int changes = 0;
23042 boolean kept = true;
23043
23044 if (mWindowManager != null) {
23045 mWindowManager.deferSurfaceLayout();
23046 }
23047 try {
23048 if (values != null) {
23049 if (displayId == DEFAULT_DISPLAY) {
23050 // Override configuration of the default display duplicates global config, so
23051 // we're calling global config update instead for default display. It will also
23052 // apply the correct override config.
23053 changes = updateGlobalConfigurationLocked(values, false /* initLocale */,
23054 false /* persistent */, UserHandle.USER_NULL /* userId */, deferResume);
23055 } else {
23056 changes = performDisplayOverrideConfigUpdate(values, deferResume, displayId);
23057 }
23058 }
23059
23060 kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
23061 } finally {
23062 if (mWindowManager != null) {
23063 mWindowManager.continueSurfaceLayout();
23064 }
23065 }
23066
23067 if (result != null) {
23068 result.changes = changes;
23069 result.activityRelaunched = !kept;
23070 }
23071 return kept;
23072 }
14.ams->ensureconfigandvisibilityafterupdate
23109 /** Applies latest configuration and/or visibility updates if needed. */
23110 private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
23111 boolean kept = true;
23112 final ActivityStack mainStack = mStackSupervisor.getFocusedStack();
23113 // mainStack is null during startup.
23114 if (mainStack != null) {
23115 if (changes != 0 && starting == null) {
23116 // If the configuration changed, and the caller is not already
23117 // in the process of starting an activity, then find the top
23118 // activity to check if its configuration needs to change.
23119 starting = mainStack.topRunningActivityLocked();
23120 }
23121
23122 if (starting != null) {
23123 kept = starting.ensureActivityConfiguration(changes,
23124 false /* preserveWindow */);
23125 // And we need to make sure at this point that all other activities
23126 // are made visible with the correct configuration.
23127 mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes,
23128 !PRESERVE_WINDOWS);
23129 }
23130 }
23131
23132 return kept;
23133 }
15.activitystacksupervisor->ensureactivitiesvisisblelocked
3756 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
3757 boolean preserveWindows, boolean notifyClients) {
3758 getKeyguardController().beginActivityVisibilityUpdate();
3759 try {
3760 // First the front stacks. In case any are not fullscreen and are in front of home.
3761 for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
3762 final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
3763 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
3764 final ActivityStack stack = display.getChildAt(stackNdx);
3765 stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
3766 notifyClients);
3767 }
3768 }
3769 } finally {
3770 getKeyguardController().endActivityVisibilityUpdate();
3771 }
3772 }
16.activitystack->ensureactivityvisiblelocked
1869 final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
1870 boolean preserveWindows, boolean notifyClients) {
1871 mTopActivityOccludesKeyguard = false;
1872 mTopDismissingKeyguardActivity = null;
1873 mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
1874 try {
1875 ActivityRecord top = topRunningActivityLocked();
1876 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top
1877 + " configChanges=0x" + Integer.toHexString(configChanges));
1878 if (top != null) {
1879 checkTranslucentActivityWaiting(top);
1880 }
1881
1882 // If the top activity is not fullscreen, then we need to
1883 // make sure any activities under it are now visible.
1884 boolean aboveTop = top != null;
1885 final boolean stackShouldBeVisible = shouldBeVisible(starting);
1886 boolean behindFullscreenActivity = !stackShouldBeVisible;
1887 boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
1888 && (isInStackLocked(starting) == null);
1889 final boolean isTopNotPinnedStack =
1890 isAttached() && getDisplay().isTopNotPinnedStack(this);
1891 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1892 final TaskRecord task = mTaskHistory.get(taskNdx);
1893 final ArrayList<ActivityRecord> activities = task.mActivities;
1894 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1895 final ActivityRecord r = activities.get(activityNdx);
1896 if (r.finishing) {
1897 continue;
1898 }
1899 final boolean isTop = r == top;
1900 if (aboveTop && !isTop) {
1901 continue;
1902 }
1903 aboveTop = false;
1904
1905 // Check whether activity should be visible without Keyguard influence
1906 final boolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard(
1907 behindFullscreenActivity);
1908 r.visibleIgnoringKeyguard = visibleIgnoringKeyguard;
1909
1910 // Now check whether it's really visible depending on Keyguard state.
1911 final boolean reallyVisible = checkKeyguardVisibility(r,
1912 visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
1913 if (visibleIgnoringKeyguard) {
1914 behindFullscreenActivity = updateBehindFullscreen(!stackShouldBeVisible,
1915 behindFullscreenActivity, r);
1916 }
1917 if (reallyVisible) {
1918 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
1919 + " finishing=" + r.finishing + " state=" + r.getState());
1920 // First: if this is not the current activity being started, make
1921 // sure it matches the current configuration.
1922 if (r != starting && notifyClients) {
1923 r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows,
1924 true /* ignoreStopState */);
1925 }
1926
1927 if (r.app == null || r.app.thread == null) {
1928 if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
1929 resumeNextActivity, r)) {
1930 if (activityNdx >= activities.size()) {
1931 // Record may be removed if its process needs to restart.
1932 activityNdx = activities.size() - 1;
1933 } else {
1934 resumeNextActivity = false;
1935 }
1936 }
1937 } else if (r.visible) {
1938 // If this activity is already visible, then there is nothing to do here.
1939 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
1940 "Skipping: already visible at " + r);
1941
1942 if (r.mClientVisibilityDeferred && notifyClients) {
1943 r.makeClientVisible();
1944 }
1945
1946 if (r.handleAlreadyVisible()) {
1947 resumeNextActivity = false;
1948 }
1949 } else {
1950 r.makeVisibleIfNeeded(starting, notifyClients);
1951 }
1952 // Aggregate current change flags.
1953 configChanges |= r.configChangeFlags;
1954 } else {
1955 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
1956 + " finishing=" + r.finishing + " state=" + r.getState()
1957 + " stackShouldBeVisible=" + stackShouldBeVisible
1958 + " behindFullscreenActivity=" + behindFullscreenActivity
1959 + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
1960 makeInvisible(r);
1961 }
1962 }
1963 final int windowingMode = getWindowingMode();
1964 if (windowingMode == WINDOWING_MODE_FREEFORM) {
1965 // The visibility of tasks and the activities they contain in freeform stack are
1966 // determined individually unlike other stacks where the visibility or fullscreen
1967 // status of an activity in a previous task affects other.
1968 behindFullscreenActivity = !stackShouldBeVisible;
1969 } else if (isActivityTypeHome()) {
1970 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
1971 + " stackShouldBeVisible=" + stackShouldBeVisible
1972 + " behindFullscreenActivity=" + behindFullscreenActivity);
1973 // No other task in the home stack should be visible behind the home activity.
1974 // Home activities is usually a translucent activity with the wallpaper behind
1975 // them. However, when they don't have the wallpaper behind them, we want to
1976 // show activities in the next application stack behind them vs. another
1977 // task in the home stack like recents.
1978 behindFullscreenActivity = true;
1979 }
1980 }
1981
1982 if (mTranslucentActivityWaiting != null &&
1983 mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
1984 // Nothing is getting drawn or everything was already visible, don't wait for timeout.
1985 notifyActivityDrawnLocked(null);
1986 }
1987 } finally {
1988 mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate();
1989 }
1990 }
1991
17.activityrecord->handlealreadyvisible
1857 boolean handleAlreadyVisible() {
1858 stopFreezingScreenLocked(false);
1859 try {
1860 if (returningOptions != null) {
1861 app.thread.scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
1862 }
1863 } catch(RemoteException e) {
1864 }
1865 return mState == RESUMED;
1866 }
这个时候就可以解除锁定了。
现在让我们回到第13步继续往下走。
####18.wms->continuesurfacelayout
2907 public void continueSurfaceLayout() {
2908 synchronized (mWindowMap) {
2909 mWindowPlacerLocked.continueLayout();
2910 }
2911 }
19.windowsurfaceplacer->continueLayout
133 void continueLayout() {
134 mDeferDepth--;
135 if (mDeferDepth <= 0) {
136 performSurfacePlacement();
137 }
138 }
####20.windowsurfaceplacer->performsurfaceplacement
148 final void performSurfacePlacement(boolean force) {
149 if (mDeferDepth > 0 && !force) {
150 return;
151 }
152 int loopCount = 6;
153 do {
154 mTraversalScheduled = false;
155 performSurfacePlacementLoop();
156 mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
157 loopCount--;
158 } while (mTraversalScheduled && loopCount > 0);
159 mService.mRoot.mWallpaperActionPending = false;
160 }
21.windowsurfaceplacer->performsurfaceplacementloop
162 private void performSurfacePlacementLoop() {
163 if (mInLayout) {
164 if (DEBUG) {
165 throw new RuntimeException("Recursive call!");
166 }
167 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
168 + Debug.getCallers(3));
169 return;
170 }
171
172 if (mService.mWaitingForConfig) {
173 // Our configuration has changed (most likely rotation), but we
174 // don't yet have the complete configuration to report to
175 // applications. Don't do any window layout until we have it.
176 return;
177 }
178
179 if (!mService.mDisplayReady) {
180 // Not yet initialized, nothing to do.
181 return;
182 }
183
184 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
185 mInLayout = true;
186
187 boolean recoveringMemory = false;
188 if (!mService.mForceRemoves.isEmpty()) {
189 recoveringMemory = true;
190 // Wait a little bit for things to settle down, and off we go.
191 while (!mService.mForceRemoves.isEmpty()) {
192 final WindowState ws = mService.mForceRemoves.remove(0);
193 Slog.i(TAG, "Force removing: " + ws);
194 ws.removeImmediately();
195 }
196 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
197 Object tmp = new Object();
198 synchronized (tmp) {
199 try {
200 tmp.wait(250);
201 } catch (InterruptedException e) {
202 }
203 }
204 }
205
206 try {
207 mService.mRoot.performSurfacePlacement(recoveringMemory);
208
209 mInLayout = false;
210
211 if (mService.mRoot.isLayoutNeeded()) {
212 if (++mLayoutRepeatCount < 6) {
213 requestTraversal();
214 } else {
215 Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
216 mLayoutRepeatCount = 0;
217 }
218 } else {
219 mLayoutRepeatCount = 0;
220 }
221
222 if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
223 mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
224 mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
225 }
226 } catch (RuntimeException e) {
227 mInLayout = false;
228 Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
229 }
230
231 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
232 }
22.rootwindowcontainer->performsurfaceplacement
559 void performSurfacePlacement(boolean recoveringMemory) {
...
595 try {
596 applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh);
597 } catch (RuntimeException e) {
598 Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
599 } finally {
600 mService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
601 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
602 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
603 }
23.rootwindowcontainer->applysurfacechangestransaction
826 private void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw,
827 int defaultDh) {
828 mHoldScreenWindow = null;
829 mObscuringWindow = null;
830
831 // TODO(multi-display): Support these features on secondary screens.
832 if (mService.mWatermark != null) {
833 mService.mWatermark.positionSurface(defaultDw, defaultDh);
834 }
835 if (mService.mStrictModeFlash != null) {
836 mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
837 }
838 if (mService.mCircularDisplayMask != null) {
839 mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
840 mService.getDefaultDisplayRotation());
841 }
842 if (mService.mEmulatorDisplayOverlay != null) {
843 mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
844 mService.getDefaultDisplayRotation());
845 }
846
847 boolean focusDisplayed = false;
848
849 final int count = mChildren.size();
850 for (int j = 0; j < count; ++j) {
851 final DisplayContent dc = mChildren.get(j);
852 focusDisplayed |= dc.applySurfaceChangesTransaction(recoveringMemory);
853 }
854
855 if (focusDisplayed) {
856 mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
857 }
858
859 // Give the display manager a chance to adjust properties like display rotation if it needs
860 // to.
861 mService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
862 SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
863 }
####24.displaycontent->applySurfaceChangesTransaction
2857 boolean applySurfaceChangesTransaction(boolean recoveringMemory) {
2858
2859 final int dw = mDisplayInfo.logicalWidth;
2860 final int dh = mDisplayInfo.logicalHeight;
2861 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
2862
2863 mTmpUpdateAllDrawn.clear();
2864
2865 int repeats = 0;
2866 do {
2867 repeats++;
2868 if (repeats > 6) {
2869 Slog.w(TAG, "Animation repeat aborted after too many iterations");
2870 clearLayoutNeeded();
2871 break;
2872 }
2873
2874 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
2875 pendingLayoutChanges);
2876
2877 // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid
2878 // the wallpaper window jumping across displays.
2879 // Remove check for default display when there will be support for multiple wallpaper
2880 // targets (on different displays).
2881 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
2882 mWallpaperController.adjustWallpaperWindows(this);
2883 }
2884
2885 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
2886 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
2887 if (mService.updateOrientationFromAppTokensLocked(mDisplayId)) {
2888 setLayoutNeeded();
2889 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
2890 }
2891 }
2892
2893 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
2894 setLayoutNeeded();
2895 }
2896
2897 // FIRST LOOP: Perform a layout, if needed.
2898 if (repeats < LAYOUT_REPEAT_THRESHOLD) {
2899 performLayout(repeats == 1, false /* updateInputWindows */);
2900 } else {
2901 Slog.w(TAG, "Layout repeat skipped after too many iterations");
2902 }
2903
2904 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
2905 pendingLayoutChanges = 0;
2906
2907 if (isDefaultDisplay) {
2908 mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
2909 forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
2910 pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
2911 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
2912 "after finishPostLayoutPolicyLw", pendingLayoutChanges);
2913 }
2914 } while (pendingLayoutChanges != 0);
2915
2916 mTmpApplySurfaceChangesTransactionState.reset();
2917
2918 mTmpRecoveringMemory = recoveringMemory;
2919 forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
2920 prepareSurfaces();
2921
2922 mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
2923 mTmpApplySurfaceChangesTransactionState.displayHasContent,
2924 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
2925 mTmpApplySurfaceChangesTransactionState.preferredModeId,
2926 true /* inTraversal, must call performTraversalInTrans... below */);
2927
2928 final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
2929 if (wallpaperVisible != mLastWallpaperVisible) {
2930 mLastWallpaperVisible = wallpaperVisible;
2931 mService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this);
2932 }
2933
2934 while (!mTmpUpdateAllDrawn.isEmpty()) {
2935 final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
2936 // See if any windows have been drawn, so they (and others associated with them)
2937 // can now be shown.
2938 atoken.updateAllDrawn();
2939 }
2940
2941 return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
2942 }