Android屏幕旋转流程(一)

首先起点肯定是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    }