/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
Java | 1047 lines | 807 code | 123 blank | 117 comment | 259 complexity | 223ae389e451099ef9d3f2b5ca424f5a MD5 | raw file
- package com.android.server.wm;
- import static android.app.ActivityManagerInternal.APP_TRANSITION_SAVED_SURFACE;
- import static android.app.ActivityManagerInternal.APP_TRANSITION_STARTING_WINDOW;
- import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
- import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
- import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
- import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
- import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
- import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
- import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
- import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
- import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
- import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
- import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
- import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
- import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
- import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
- import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
- import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
- import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
- import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
- import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
- import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
- import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
- import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
- import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
- import static com.android.server.wm.WindowManagerService.H.DO_TRAVERSAL;
- import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
- import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING;
- import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
- import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
- import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE;
- import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
- import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
- import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
- import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
- import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
- import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
- import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
- import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.PixelFormat;
- import android.graphics.Rect;
- import android.os.Debug;
- import android.os.PowerManager;
- import android.os.RemoteException;
- import android.os.SystemClock;
- import android.os.Trace;
- import android.provider.Settings;
- import android.util.ArraySet;
- import android.util.Slog;
- import android.view.Display;
- import android.view.DisplayInfo;
- import android.view.Surface;
- import android.view.SurfaceControl;
- import android.view.View;
- import android.view.WindowManager.LayoutParams;
- import android.view.animation.Animation;
- import com.android.server.wm.WindowManagerService.H;
- import java.io.PrintWriter;
- import java.util.ArrayList;
- /**
- * Positions windows and their surfaces.
- *
- * It sets positions of windows by calculating their frames and then applies this by positioning
- * surfaces according to these frames. Z layer is still assigned withing WindowManagerService.
- */
- class WindowSurfacePlacer {
- private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfacePlacer" : TAG_WM;
- private final WindowManagerService mService;
- private final WallpaperController mWallpaperControllerLocked;
- private boolean mInLayout = false;
- /** Only do a maximum of 6 repeated layouts. After that quit */
- private int mLayoutRepeatCount;
- static final int SET_UPDATE_ROTATION = 1 << 0;
- static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1;
- static final int SET_FORCE_HIDING_CHANGED = 1 << 2;
- static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3;
- static final int SET_TURN_ON_SCREEN = 1 << 4;
- static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5;
- boolean mWallpaperMayChange = false;
- boolean mOrientationChangeComplete = true;
- boolean mWallpaperActionPending = false;
- private boolean mWallpaperForceHidingChanged = false;
- private Object mLastWindowFreezeSource = null;
- private Session mHoldScreen = null;
- private boolean mObscured = false;
- private boolean mSyswin = false;
- private float mScreenBrightness = -1;
- private float mButtonBrightness = -1;
- private long mUserActivityTimeout = -1;
- private boolean mUpdateRotation = false;
- private final Rect mTmpStartRect = new Rect();
- private final Rect mTmpContentRect = new Rect();
- // Set to true when the display contains content to show the user.
- // When false, the display manager may choose to mirror or blank the display.
- private boolean mDisplayHasContent = false;
- // Only set while traversing the default display based on its content.
- // Affects the behavior of mirroring on secondary displays.
- private boolean mObscureApplicationContentOnSecondaryDisplays = false;
- private float mPreferredRefreshRate = 0;
- private int mPreferredModeId = 0;
- private boolean mTraversalScheduled;
- private int mDeferDepth = 0;
- private boolean mSustainedPerformanceModeEnabled = false;
- private boolean mSustainedPerformanceModeCurrent = false;
- // Following variables are for debugging screen wakelock only.
- // Last window that requires screen wakelock
- WindowState mHoldScreenWindow = null;
- // Last window that obscures all windows below
- WindowState mObsuringWindow = null;
- private static final class LayerAndToken {
- public int layer;
- public AppWindowToken token;
- }
- private final LayerAndToken mTmpLayerAndToken = new LayerAndToken();
- private final ArrayList<SurfaceControl> mPendingDestroyingSurfaces = new ArrayList<>();
- public WindowSurfacePlacer(WindowManagerService service) {
- mService = service;
- mWallpaperControllerLocked = mService.mWallpaperControllerLocked;
- }
- /**
- * See {@link WindowManagerService#deferSurfaceLayout()}
- */
- void deferLayout() {
- mDeferDepth++;
- }
- /**
- * See {@link WindowManagerService#continueSurfaceLayout()}
- */
- void continueLayout() {
- mDeferDepth--;
- if (mDeferDepth <= 0) {
- performSurfacePlacement();
- }
- }
- final void performSurfacePlacement() {
- if (mDeferDepth > 0) {
- return;
- }
- int loopCount = 6;
- do {
- mTraversalScheduled = false;
- performSurfacePlacementLoop();
- mService.mH.removeMessages(DO_TRAVERSAL);
- loopCount--;
- } while (mTraversalScheduled && loopCount > 0);
- mWallpaperActionPending = false;
- }
- private void performSurfacePlacementLoop() {
- if (mInLayout) {
- if (DEBUG) {
- throw new RuntimeException("Recursive call!");
- }
- Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
- + Debug.getCallers(3));
- return;
- }
- if (mService.mWaitingForConfig) {
- // Our configuration has changed (most likely rotation), but we
- // don't yet have the complete configuration to report to
- // applications. Don't do any window layout until we have it.
- return;
- }
- if (!mService.mDisplayReady) {
- // Not yet initialized, nothing to do.
- return;
- }
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
- mInLayout = true;
- boolean recoveringMemory = false;
- if (!mService.mForceRemoves.isEmpty()) {
- recoveringMemory = true;
- // Wait a little bit for things to settle down, and off we go.
- while (!mService.mForceRemoves.isEmpty()) {
- WindowState ws = mService.mForceRemoves.remove(0);
- Slog.i(TAG, "Force removing: " + ws);
- mService.removeWindowInnerLocked(ws);
- }
- Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
- Object tmp = new Object();
- synchronized (tmp) {
- try {
- tmp.wait(250);
- } catch (InterruptedException e) {
- }
- }
- }
- try {
- performSurfacePlacementInner(recoveringMemory);
- mInLayout = false;
- if (mService.needsLayout()) {
- if (++mLayoutRepeatCount < 6) {
- requestTraversal();
- } else {
- Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
- mLayoutRepeatCount = 0;
- }
- } else {
- mLayoutRepeatCount = 0;
- }
- if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
- mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
- mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
- }
- } catch (RuntimeException e) {
- mInLayout = false;
- Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
- }
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
- }
- void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
- if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
- Slog.v(TAG, "Layouts looping: " + msg +
- ", mPendingLayoutChanges = 0x" + Integer.toHexString(pendingLayoutChanges));
- }
- }
- // "Something has changed! Let's make it correct now."
- private void performSurfacePlacementInner(boolean recoveringMemory) {
- if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
- + Debug.getCallers(3));
- int i;
- boolean updateInputWindowsNeeded = false;
- if (mService.mFocusMayChange) {
- mService.mFocusMayChange = false;
- updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
- UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
- }
- // Initialize state of exiting tokens.
- final int numDisplays = mService.mDisplayContents.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
- for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
- displayContent.mExitingTokens.get(i).hasVisible = false;
- }
- }
- for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
- // Initialize state of exiting applications.
- final AppTokenList exitingAppTokens =
- mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
- for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
- exitingAppTokens.get(tokenNdx).hasVisible = false;
- }
- }
- mHoldScreen = null;
- mHoldScreenWindow = null;
- mObsuringWindow = null;
- mScreenBrightness = -1;
- mButtonBrightness = -1;
- mUserActivityTimeout = -1;
- mObscureApplicationContentOnSecondaryDisplays = false;
- mSustainedPerformanceModeCurrent = false;
- mService.mTransactionSequence++;
- final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
- final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
- final int defaultDw = defaultInfo.logicalWidth;
- final int defaultDh = defaultInfo.logicalHeight;
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
- SurfaceControl.openTransaction();
- try {
- applySurfaceChangesTransaction(recoveringMemory, numDisplays, defaultDw, defaultDh);
- } catch (RuntimeException e) {
- Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
- } finally {
- SurfaceControl.closeTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
- }
- final WindowList defaultWindows = defaultDisplay.getWindowList();
- // If we are ready to perform an app transition, check through
- // all of the app tokens to be shown and see if they are ready
- // to go.
- if (mService.mAppTransition.isReady()) {
- defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
- if (DEBUG_LAYOUT_REPEATS)
- debugLayoutRepeats("after handleAppTransitionReadyLocked",
- defaultDisplay.pendingLayoutChanges);
- }
- if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
- // We have finished the animation of an app transition. To do
- // this, we have delayed a lot of operations like showing and
- // hiding apps, moving apps in Z-order, etc. The app token list
- // reflects the correct Z-order, but the window list may now
- // be out of sync with it. So here we will just rebuild the
- // entire app window list. Fun!
- defaultDisplay.pendingLayoutChanges |=
- mService.handleAnimatingStoppedAndTransitionLocked();
- if (DEBUG_LAYOUT_REPEATS)
- debugLayoutRepeats("after handleAnimStopAndXitionLock",
- defaultDisplay.pendingLayoutChanges);
- }
- if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
- && !mService.mAppTransition.isReady()) {
- // At this point, there was a window with a wallpaper that
- // was force hiding other windows behind it, but now it
- // is going away. This may be simple -- just animate
- // away the wallpaper and its window -- or it may be
- // hard -- the wallpaper now needs to be shown behind
- // something that was hidden.
- defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS)
- debugLayoutRepeats("after animateAwayWallpaperLocked",
- defaultDisplay.pendingLayoutChanges);
- }
- mWallpaperForceHidingChanged = false;
- if (mWallpaperMayChange) {
- if (DEBUG_WALLPAPER_LIGHT)
- Slog.v(TAG, "Wallpaper may change! Adjusting");
- defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
- defaultDisplay.pendingLayoutChanges);
- }
- if (mService.mFocusMayChange) {
- mService.mFocusMayChange = false;
- if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
- false /*updateInputWindows*/)) {
- updateInputWindowsNeeded = true;
- defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
- }
- }
- if (mService.needsLayout()) {
- defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
- defaultDisplay.pendingLayoutChanges);
- }
- for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
- WindowState win = mService.mResizingWindows.get(i);
- if (win.mAppFreezing) {
- // Don't remove this window until rotation has completed.
- continue;
- }
- // Discard the saved surface if window size is changed, it can't be reused.
- if (win.mAppToken != null) {
- win.mAppToken.destroySavedSurfaces();
- }
- win.reportResized();
- mService.mResizingWindows.remove(i);
- }
- if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
- "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
- if (mOrientationChangeComplete) {
- if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
- mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
- mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
- mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
- }
- mService.stopFreezingDisplayLocked();
- }
- // Destroy the surface of any windows that are no longer visible.
- boolean wallpaperDestroyed = false;
- i = mService.mDestroySurface.size();
- if (i > 0) {
- do {
- i--;
- WindowState win = mService.mDestroySurface.get(i);
- win.mDestroying = false;
- if (mService.mInputMethodWindow == win) {
- mService.mInputMethodWindow = null;
- }
- if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
- wallpaperDestroyed = true;
- }
- win.destroyOrSaveSurface();
- } while (i > 0);
- mService.mDestroySurface.clear();
- }
- // Time to remove any exiting tokens?
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
- ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
- for (i = exitingTokens.size() - 1; i >= 0; i--) {
- WindowToken token = exitingTokens.get(i);
- if (!token.hasVisible) {
- exitingTokens.remove(i);
- if (token.windowType == TYPE_WALLPAPER) {
- mWallpaperControllerLocked.removeWallpaperToken(token);
- }
- }
- }
- }
- // Time to remove any exiting applications?
- for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
- // Initialize state of exiting applications.
- final AppTokenList exitingAppTokens =
- mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
- for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
- AppWindowToken token = exitingAppTokens.get(i);
- if (!token.hasVisible && !mService.mClosingApps.contains(token) &&
- (!token.mIsExiting || token.allAppWindows.isEmpty())) {
- // Make sure there is no animation running on this token,
- // so any windows associated with it will be removed as
- // soon as their animations are complete
- token.mAppAnimator.clearAnimation();
- token.mAppAnimator.animating = false;
- if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
- "performLayout: App token exiting now removed" + token);
- token.removeAppFromTaskLocked();
- }
- }
- }
- if (wallpaperDestroyed) {
- defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- defaultDisplay.layoutNeeded = true;
- }
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
- if (displayContent.pendingLayoutChanges != 0) {
- displayContent.layoutNeeded = true;
- }
- }
- // Finally update all input windows now that the window changes have stabilized.
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
- mService.setHoldScreenLocked(mHoldScreen);
- if (!mService.mDisplayFrozen) {
- if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) {
- mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
- } else {
- mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
- toBrightnessOverride(mScreenBrightness));
- }
- if (mButtonBrightness < 0
- || mButtonBrightness > 1.0f) {
- mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
- } else {
- mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
- toBrightnessOverride(mButtonBrightness));
- }
- mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
- mUserActivityTimeout);
- }
- if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
- mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
- mService.mPowerManagerInternal.powerHint(
- mService.mPowerManagerInternal.POWER_HINT_SUSTAINED_PERFORMANCE_MODE,
- (mSustainedPerformanceModeEnabled ? 1 : 0));
- }
- if (mService.mTurnOnScreen) {
- if (mService.mAllowTheaterModeWakeFromLayout
- || Settings.Global.getInt(mService.mContext.getContentResolver(),
- Settings.Global.THEATER_MODE_ON, 0) == 0) {
- if (DEBUG_VISIBILITY || DEBUG_POWER) {
- Slog.v(TAG, "Turning screen on after layout!");
- }
- mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
- "android.server.wm:TURN_ON");
- }
- mService.mTurnOnScreen = false;
- }
- if (mUpdateRotation) {
- if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
- if (mService.updateRotationUncheckedLocked(false)) {
- mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
- } else {
- mUpdateRotation = false;
- }
- }
- if (mService.mWaitingForDrawnCallback != null ||
- (mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
- !mUpdateRotation)) {
- mService.checkDrawnWindowsLocked();
- }
- final int N = mService.mPendingRemove.size();
- if (N > 0) {
- if (mService.mPendingRemoveTmp.length < N) {
- mService.mPendingRemoveTmp = new WindowState[N+10];
- }
- mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
- mService.mPendingRemove.clear();
- DisplayContentList displayList = new DisplayContentList();
- for (i = 0; i < N; i++) {
- WindowState w = mService.mPendingRemoveTmp[i];
- mService.removeWindowInnerLocked(w);
- final DisplayContent displayContent = w.getDisplayContent();
- if (displayContent != null && !displayList.contains(displayContent)) {
- displayList.add(displayContent);
- }
- }
- for (DisplayContent displayContent : displayList) {
- mService.mLayersController.assignLayersLocked(displayContent.getWindowList());
- displayContent.layoutNeeded = true;
- }
- }
- // Remove all deferred displays stacks, tasks, and activities.
- for (int displayNdx = mService.mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- mService.mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
- }
- if (updateInputWindowsNeeded) {
- mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
- }
- mService.setFocusTaskRegionLocked();
- // Check to see if we are now in a state where the screen should
- // be enabled, because the window obscured flags have changed.
- mService.enableScreenIfNeededLocked();
- mService.scheduleAnimationLocked();
- mService.mWindowPlacerLocked.destroyPendingSurfaces();
- if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
- "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
- }
- private void applySurfaceChangesTransaction(boolean recoveringMemory, int numDisplays,
- int defaultDw, int defaultDh) {
- if (mService.mWatermark != null) {
- mService.mWatermark.positionSurface(defaultDw, defaultDh);
- }
- if (mService.mStrictModeFlash != null) {
- mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
- }
- if (mService.mCircularDisplayMask != null) {
- mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
- mService.mRotation);
- }
- if (mService.mEmulatorDisplayOverlay != null) {
- mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
- mService.mRotation);
- }
- boolean focusDisplayed = false;
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
- boolean updateAllDrawn = false;
- WindowList windows = displayContent.getWindowList();
- DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final int displayId = displayContent.getDisplayId();
- final int dw = displayInfo.logicalWidth;
- final int dh = displayInfo.logicalHeight;
- final int innerDw = displayInfo.appWidth;
- final int innerDh = displayInfo.appHeight;
- final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- // Reset for each display.
- mDisplayHasContent = false;
- mPreferredRefreshRate = 0;
- mPreferredModeId = 0;
- int repeats = 0;
- do {
- repeats++;
- if (repeats > 6) {
- Slog.w(TAG, "Animation repeat aborted after too many iterations");
- displayContent.layoutNeeded = false;
- break;
- }
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
- "On entry to LockedInner", displayContent.pendingLayoutChanges);
- if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
- mWallpaperControllerLocked.adjustWallpaperWindows()) {
- mService.mLayersController.assignLayersLocked(windows);
- displayContent.layoutNeeded = true;
- }
- if (isDefaultDisplay
- && (displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
- if (mService.updateOrientationFromAppTokensLocked(true)) {
- displayContent.layoutNeeded = true;
- mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
- }
- }
- if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
- displayContent.layoutNeeded = true;
- }
- // FIRST LOOP: Perform a layout, if needed.
- if (repeats < LAYOUT_REPEAT_THRESHOLD) {
- performLayoutLockedInner(displayContent, repeats == 1,
- false /* updateInputWindows */);
- } else {
- Slog.w(TAG, "Layout repeat skipped after too many iterations");
- }
- // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
- // it is animating.
- displayContent.pendingLayoutChanges = 0;
- if (isDefaultDisplay) {
- mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
- for (int i = windows.size() - 1; i >= 0; i--) {
- WindowState w = windows.get(i);
- if (w.mHasSurface) {
- mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs,
- w.mAttachedWindow);
- }
- }
- displayContent.pendingLayoutChanges |=
- mService.mPolicy.finishPostLayoutPolicyLw();
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishPostLayoutPolicyLw",
- displayContent.pendingLayoutChanges);
- }
- } while (displayContent.pendingLayoutChanges != 0);
- mObscured = false;
- mSyswin = false;
- displayContent.resetDimming();
- // Only used if default window
- final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
- for (int i = windows.size() - 1; i >= 0; i--) {
- WindowState w = windows.get(i);
- final Task task = w.getTask();
- final boolean obscuredChanged = w.mObscured != mObscured;
- // Update effect.
- w.mObscured = mObscured;
- if (!mObscured) {
- handleNotObscuredLocked(w, displayInfo);
- }
- w.applyDimLayerIfNeeded();
- if (isDefaultDisplay && obscuredChanged
- && mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {
- // This is the wallpaper target and its obscured state
- // changed... make sure the current wallaper's visibility
- // has been updated accordingly.
- mWallpaperControllerLocked.updateWallpaperVisibility();
- }
- final WindowStateAnimator winAnimator = w.mWinAnimator;
- // If the window has moved due to its containing content frame changing, then
- // notify the listeners and optionally animate it. Simply checking a change of
- // position is not enough, because being move due to dock divider is not a trigger
- // for animation.
- if (w.hasMoved()) {
- // Frame has moved, containing content frame has also moved, and we're not
- // currently animating... let's do something.
- final int left = w.mFrame.left;
- final int top = w.mFrame.top;
- final boolean adjustedForMinimizedDockOrIme = task != null
- && (task.mStack.isAdjustedForMinimizedDockedStack()
- || task.mStack.isAdjustedForIme());
- if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
- && !w.isDragResizing() && !adjustedForMinimizedDockOrIme
- && (task == null || w.getTask().mStack.hasMovementAnimations())
- && !w.mWinAnimator.mLastHidden) {
- winAnimator.setMoveAnimation(left, top);
- }
- //TODO (multidisplay): Accessibility supported only for the default display.
- if (mService.mAccessibilityController != null
- && displayId == Display.DEFAULT_DISPLAY) {
- mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
- }
- try {
- w.mClient.moved(left, top);
- } catch (RemoteException e) {
- }
- w.mMovedByResize = false;
- }
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
- w.mContentChanged = false;
- // Moved from updateWindowsAndWallpaperLocked().
- if (w.mHasSurface) {
- // If we have recently synchronized a previous transaction for this
- // window ensure we don't push through an unsynchronized one now.
- winAnimator.deferToPendingTransaction();
- // Take care of the window being ready to display.
- final boolean committed = winAnimator.commitFinishDrawingLocked();
- if (isDefaultDisplay && committed) {
- if (w.mAttrs.type == TYPE_DREAM) {
- // HACK: When a dream is shown, it may at that
- // point hide the lock screen. So we need to
- // redo the layout to let the phone window manager
- // make this happen.
- displayContent.pendingLayoutChanges |=
- FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) {
- debugLayoutRepeats("dream and commitFinishDrawingLocked true",
- displayContent.pendingLayoutChanges);
- }
- }
- if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
- if (DEBUG_WALLPAPER_LIGHT)
- Slog.v(TAG, "First draw done in potential wallpaper target " + w);
- mWallpaperMayChange = true;
- displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) {
- debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true",
- displayContent.pendingLayoutChanges);
- }
- }
- }
- if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
- // Updates the shown frame before we set up the surface. This is needed
- // because the resizing could change the top-left position (in addition to
- // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
- // position the surface.
- //
- // If an animation is being started, we can't call this method because the
- // animation hasn't processed its initial transformation yet, but in general
- // we do want to update the position if the window is animating.
- winAnimator.computeShownFrameLocked();
- }
- winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
- }
- final AppWindowToken atoken = w.mAppToken;
- if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) {
- Slog.d(TAG, "updateWindows: starting " + w
- + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
- + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
- }
- if (atoken != null && (!atoken.allDrawn || !atoken.allDrawnExcludingSaved
- || atoken.mAppAnimator.freezingScreen)) {
- if (atoken.lastTransactionSequence != mService.mTransactionSequence) {
- atoken.lastTransactionSequence = mService.mTransactionSequence;
- atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
- atoken.numInterestingWindowsExcludingSaved = 0;
- atoken.numDrawnWindowsExclusingSaved = 0;
- atoken.startingDisplayed = false;
- }
- if (!atoken.allDrawn && w.mightAffectAllDrawn(false /* visibleOnly */)) {
- if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
- Slog.v(TAG, "Eval win " + w + ": isDrawn="
- + w.isDrawnLw()
- + ", isAnimationSet=" + winAnimator.isAnimationSet());
- if (!w.isDrawnLw()) {
- Slog.v(TAG, "Not displayed: s="
- + winAnimator.mSurfaceController
- + " pv=" + w.mPolicyVisibility
- + " mDrawState=" + winAnimator.drawStateToString()
- + " ah=" + w.mAttachedHidden
- + " th=" + atoken.hiddenRequested
- + " a=" + winAnimator.mAnimating);
- }
- }
- if (w != atoken.startingWindow) {
- if (w.isInteresting()) {
- atoken.numInterestingWindows++;
- if (w.isDrawnLw()) {
- atoken.numDrawnWindows++;
- if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
- Slog.v(TAG, "tokenMayBeDrawn: " + atoken
- + " w=" + w + " numInteresting="
- + atoken.numInterestingWindows
- + " freezingScreen="
- + atoken.mAppAnimator.freezingScreen
- + " mAppFreezing=" + w.mAppFreezing);
- updateAllDrawn = true;
- }
- }
- } else if (w.isDrawnLw()) {
- mService.mH.sendEmptyMessage(NOTIFY_STARTING_WINDOW_DRAWN);
- atoken.startingDisplayed = true;
- }
- }
- if (!atoken.allDrawnExcludingSaved
- && w.mightAffectAllDrawn(true /* visibleOnly */)) {
- if (w != atoken.startingWindow && w.isInteresting()) {
- atoken.numInterestingWindowsExcludingSaved++;
- if (w.isDrawnLw() && !w.isAnimatingWithSavedSurface()) {
- atoken.numDrawnWindowsExclusingSaved++;
- if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
- Slog.v(TAG, "tokenMayBeDrawnExcludingSaved: " + atoken
- + " w=" + w + " numInteresting="
- + atoken.numInterestingWindowsExcludingSaved
- + " freezingScreen="
- + atoken.mAppAnimator.freezingScreen
- + " mAppFreezing=" + w.mAppFreezing);
- updateAllDrawn = true;
- }
- }
- }
- }
- if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
- && w.isDisplayedLw()) {
- focusDisplayed = true;
- }
- mService.updateResizingWindows(w);
- }
- mService.mDisplayManagerInternal.setDisplayProperties(displayId,
- mDisplayHasContent,
- mPreferredRefreshRate,
- mPreferredModeId,
- true /* inTraversal, must call performTraversalInTrans... below */);
- mService.getDisplayContentLocked(displayId).stopDimmingIfNeeded();
- if (updateAllDrawn) {
- updateAllDrawnLocked(displayContent);
- }
- }
- if (focusDisplayed) {
- mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
- }
- // Give the display manager a chance to adjust properties
- // like display rotation if it needs to.
- mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
- }
- boolean isInLayout() {
- return mInLayout;
- }
- final void performLayoutLockedInner(final DisplayContent displayContent,
- boolean initial, boolean updateInputWindows) {
- if (!displayContent.layoutNeeded) {
- return;
- }
- displayContent.layoutNeeded = false;
- WindowList windows = displayContent.getWindowList();
- boolean isDefaultDisplay = displayContent.isDefaultDisplay;
- DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final int dw = displayInfo.logicalWidth;
- final int dh = displayInfo.logicalHeight;
- if (mService.mInputConsumer != null) {
- mService.mInputConsumer.layout(dw, dh);
- }
- if (mService.mWallpaperInputConsumer != null) {
- mService.mWallpaperInputConsumer.layout(dw, dh);
- }
- final int N = windows.size();
- int i;
- if (DEBUG_LAYOUT) {
- Slog.v(TAG, "-------------------------------------");
- Slog.v(TAG, "performLayout: needed="
- + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
- }
- mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation,
- mService.mCurConfiguration.uiMode);
- if (isDefaultDisplay) {
- // Not needed on non-default displays.
- mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
- mService.mScreenRect.set(0, 0, dw, dh);
- }
- mService.mPolicy.getContentRectLw(mTmpContentRect);
- displayContent.resize(mTmpContentRect);
- int seq = mService.mLayoutSeq+1;
- if (seq < 0) seq = 0;
- mService.mLayoutSeq = seq;
- boolean behindDream = false;
- // First perform layout of any root windows (not attached
- // to another window).
- int topAttached = -1;
- for (i = N-1; i >= 0; i--) {
- final WindowState win = windows.get(i);
- // Don't do layout of a window if it is not visible, or
- // soon won't be visible, to avoid wasting time and funky
- // changes while a window is animating away.
- final boolean gone = (behindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs))
- || win.isGoneForLayoutLw();
- if (DEBUG_LAYOUT && !win.mLayoutAttached) {
- Slog.v(TAG, "1ST PASS " + win
- + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
- + " mLayoutAttached=" + win.mLayoutAttached
- + " screen changed=" + win.isConfigChanged());
- final AppWindowToken atoken = win.mAppToken;
- if (gone) Slog.v(TAG, " GONE: mViewVisibility="
- + win.mViewVisibility + " mRelayoutCalled="
- + win.mRelayoutCalled + " hidden="
- + win.mRootToken.hidden + " hiddenRequested="
- + (atoken != null && atoken.hiddenRequested)
- + " mAttachedHidden=" + win.mAttachedHidden);
- else Slog.v(TAG, " VIS: mViewVisibility="
- + win.mViewVisibility + " mRelayoutCalled="
- + win.mRelayoutCalled + " hidden="
- + win.mRootToken.hidden + " hiddenRequested="
- + (atoken != null && atoken.hiddenRequested)
- + " mAttachedHidden=" + win.mAttachedHidden);
- }
- // If this view is GONE, then skip it -- keep the current
- // frame, and let the caller know so they can ignore it
- // if they want. (We do the normal layout for INVISIBLE
- // windows, since that means "perform layout as normal,
- // just don't display").
- if (!gone || !win.mHaveFrame || win.mLayoutNeeded
- || ((win.isConfigChanged() || win.setReportResizeHints())
- && !win.isGoneForLayoutLw() &&
- ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
- (win.mHasSurface && win.mAppToken != null &&
- win.mAppToken.layoutConfigChanges)))) {
- if (!win.mLayoutAttached) {
- if (initial) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
- win.mContentChanged = false;
- }
- if (win.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it
- // does stuff like hide the status bar we won't get a
- // bad transition when it goes away.
- behindDream = true;
- }
- win.mLayoutNeeded = false;
- win.prelayout();
- mService.mPolicy.layoutWindowLw(win, null);
- win.mLayoutSeq = seq;
- // Window frames may have changed. Update dim layer with the new bounds.
- final Task task = win.getTask();
- if (task != null) {
- displayContent.mDimLayerController.updateDimLayer(task);
- }
- if (DEBUG_LAYOUT) Slog.v(TAG,
- " LAYOUT: mFrame="
- + win.mFrame + " mContainingFrame="
- + win.mContainingFrame + " mDisplayFrame="
- + win.mDisplayFrame);
- } else {
- if (topAttached < 0) topAttached = i;
- }
- }
- }
- boolean attachedBehindDream = false;
- // Now perform layout of attached windows, which usually
- // depend on the position of the window they are attached to.
- // XXX does not deal with windows that are attached to windows
- // that are themselves attached.
- for (i = topAttached; i >= 0; i--) {
- final WindowState win = windows.get(i);
- if (win.mLayoutAttached) {
- if (DEBUG_LAYOUT) Slog.v(TAG,
- "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame + " mViewVisibility="
- + win.mViewVisibility + " mRelayoutCalled=" + win.mRelayoutCalled);
- // If this view is GONE, then skip it -- keep the current
- // frame, and let the caller know so they can ignore it
- // if they want. (We do the normal layout for INVISIBLE
- // windows, since that means "perform layout as normal,
- // just don't display").
- if (attachedBehindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs)) {
- continue;
- }
- if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
- || !win.mHaveFrame || win.mLayoutNeeded) {
- if (initial) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
- win.mContentChanged = false;
- }
- win.mLayoutNeeded = false;
- win.prelayout();
- mService.mPolicy.layoutWindowLw(win, win.mAttachedWindow);
- win.mLayoutSeq = seq;
- if (DEBUG_LAYOUT) Slog.v(TAG,
-