Made AppWindowToken.allAppWindows private
Pre-clean-up before switching class to using WindowContainer.
Bug: 30060889
Change-Id: Ic3d47d47b922668eeb70988ce883267b46ca9d72
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 39a549d..950fb20 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -157,11 +157,9 @@
}
// Since we are finally starting our animation, we don't need the logic anymore to prevent
- // the app from showing again if we just moved between stacks. See
- // {@link WindowState#notifyMovedInStack}.
- for (int i = mAppToken.allAppWindows.size() - 1; i >= 0; i--) {
- mAppToken.allAppWindows.get(i).resetJustMovedInStack();
- }
+ // the app from showing again if we just moved between stacks.
+ // See {@link WindowState#notifyMovedInStack}.
+ mAppToken.resetJustMovedInStack();
}
public void setDummyAnimation() {
@@ -234,23 +232,7 @@
}
void updateLayers() {
- final int windowCount = mAppToken.allAppWindows.size();
- final int adj = animLayerAdjustment;
- thumbnailLayer = -1;
- final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
- for (int i = 0; i < windowCount; i++) {
- final WindowState w = mAppToken.allAppWindows.get(i);
- final WindowStateAnimator winAnimator = w.mWinAnimator;
- winAnimator.mAnimLayer = w.mLayer + adj;
- if (winAnimator.mAnimLayer > thumbnailLayer) {
- thumbnailLayer = winAnimator.mAnimLayer;
- }
- if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " + winAnimator.mAnimLayer);
- if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
- mService.mLayersController.setInputMethodAnimLayerAdjustment(adj);
- }
- wallpaperController.setAnimLayerAdjustment(w, adj);
- }
+ thumbnailLayer = mAppToken.adjustAnimLayer(animLayerAdjustment);
}
private void stepThumbnailAnimation(long currentTime) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 01be4c8..bbd6fd7 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -17,18 +17,27 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManagerPolicy.TRANSIT_ENTER;
+import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
+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_RESIZE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
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.NOTIFY_ACTIVITY_DRAWN;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.logWithStack;
import com.android.server.input.InputApplicationHandle;
import com.android.server.wm.WindowManagerService.H;
@@ -37,8 +46,11 @@
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Binder;
+import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.Slog;
import android.view.IApplicationToken;
import android.view.View;
@@ -63,7 +75,7 @@
// All of the windows and child windows that are included in this
// application token. Note this list is NOT sorted!
- final WindowList allAppWindows = new WindowList();
+ private final WindowList allAppWindows = new WindowList();
@NonNull final AppWindowAnimator mAppAnimator;
final boolean voiceInteraction;
@@ -280,6 +292,149 @@
}
}
+ boolean setVisibility(WindowManager.LayoutParams lp,
+ boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
+
+ boolean delayed = false;
+ inPendingTransaction = false;
+
+ if (clientHidden == visible) {
+ clientHidden = !visible;
+ sendAppVisibilityToClients();
+ }
+
+ // Allow for state changes and animation to be applied if:
+ // * token is transitioning visibility state
+ // * or the token was marked as hidden and is exiting before we had a chance to play the
+ // transition animation
+ // * or this is an opening app and windows are being replaced.
+ boolean visibilityChanged = false;
+ if (hidden == visible || (hidden && mIsExiting) || (visible && waitingForReplacement())) {
+ final AccessibilityController accessibilityController = service.mAccessibilityController;
+ boolean changed = false;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
+ "Changing app " + this + " hidden=" + hidden + " performLayout=" + performLayout);
+
+ boolean runningAppAnimation = false;
+
+ if (transit != AppTransition.TRANSIT_UNSET) {
+ if (mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
+ mAppAnimator.setNullAnimation();
+ }
+ if (service.applyAnimationLocked(this, lp, transit, visible, isVoiceInteraction)) {
+ delayed = runningAppAnimation = true;
+ }
+ final WindowState window = findMainWindow();
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (window != null && accessibilityController != null
+ && window.getDisplayId() == DEFAULT_DISPLAY) {
+ accessibilityController.onAppWindowTransitionLocked(window, transit);
+ }
+ changed = true;
+ }
+
+ final int windowsCount = allAppWindows.size();
+ for (int i = 0; i < windowsCount; i++) {
+ final WindowState win = allAppWindows.get(i);
+ if (win == startingWindow) {
+ // Starting window that's exiting will be removed when the animation finishes.
+ // Mark all relevant flags for that onExitAnimationDone will proceed all the way
+ // to actually remove it.
+ if (!visible && win.isVisibleNow() && mAppAnimator.isAnimating()) {
+ win.mAnimatingExit = true;
+ win.mRemoveOnExit = true;
+ win.mWindowRemovalAllowed = true;
+ }
+ continue;
+ }
+
+ //Slog.i(TAG_WM, "Window " + win + ": vis=" + win.isVisible());
+ //win.dump(" ");
+ if (visible) {
+ if (!win.isVisibleNow()) {
+ if (!runningAppAnimation) {
+ win.mWinAnimator.applyAnimationLocked(TRANSIT_ENTER, true);
+ //TODO (multidisplay): Magnification is supported only for the default
+ if (accessibilityController != null
+ && win.getDisplayId() == DEFAULT_DISPLAY) {
+ accessibilityController.onWindowTransitionLocked(win, TRANSIT_ENTER);
+ }
+ }
+ changed = true;
+ win.setDisplayLayoutNeeded();
+ }
+ } else if (win.isVisibleNow()) {
+ if (!runningAppAnimation) {
+ win.mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
+ //TODO (multidisplay): Magnification is supported only for the default
+ if (accessibilityController != null
+ && win.getDisplayId() == DEFAULT_DISPLAY) {
+ accessibilityController.onWindowTransitionLocked(win,TRANSIT_EXIT);
+ }
+ }
+ changed = true;
+ win.setDisplayLayoutNeeded();
+ }
+ }
+
+ hidden = hiddenRequested = !visible;
+ visibilityChanged = true;
+ if (!visible) {
+ stopFreezingScreen(true, true);
+ } else {
+ // If we are being set visible, and the starting window is
+ // not yet displayed, then make sure it doesn't get displayed.
+ WindowState swin = startingWindow;
+ if (swin != null && !swin.isDrawnLw()) {
+ swin.mPolicyVisibility = false;
+ swin.mPolicyVisibilityAfterAnim = false;
+ }
+ }
+
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setVisibility: " + this
+ + ": hidden=" + hidden + " hiddenRequested=" + hiddenRequested);
+
+ if (changed) {
+ service.mInputMonitor.setUpdateInputWindowsNeededLw();
+ if (performLayout) {
+ service.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/);
+ service.mWindowPlacerLocked.performSurfacePlacement();
+ }
+ service.mInputMonitor.updateInputWindowsLw(false /*force*/);
+ }
+ }
+
+ if (mAppAnimator.animation != null) {
+ delayed = true;
+ }
+
+ for (int i = allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
+ if (allAppWindows.get(i).mWinAnimator.isWindowAnimationSet()) {
+ delayed = true;
+ }
+ }
+
+ if (visibilityChanged) {
+ if (visible && !delayed) {
+ // The token was made immediately visible, there will be no entrance animation.
+ // We need to inform the client the enter animation was finished.
+ mEnteringAnimation = true;
+ service.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(token);
+ }
+
+ if (!service.mClosingApps.contains(this) && !service.mOpeningApps.contains(this)) {
+ // The token is not closing nor opening, so even if there is an animation set, that
+ // doesn't mean that it goes through the normal app transition cycle so we have
+ // to inform the docked controller about visibility change.
+ service.getDefaultDisplayContentLocked().getDockedDividerController()
+ .notifyAppVisibilityChanged();
+ }
+ }
+
+ return delayed;
+ }
+
WindowState findMainWindow() {
WindowState candidate = null;
int j = allAppWindows.size();
@@ -323,6 +478,16 @@
return false;
}
+ boolean isVisibleForUser() {
+ for (int j = allAppWindows.size() - 1; j >= 0; j--) {
+ final WindowState w = allAppWindows.get(j);
+ if (!w.isHiddenFromUserLocked()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void removeAppFromTaskLocked() {
mIsExiting = false;
removeAllWindows();
@@ -585,6 +750,27 @@
windows.clear();
}
+ @Override
+ void removeWindow(WindowState win) {
+ super.removeWindow(win);
+
+ allAppWindows.remove(win);
+
+ if (startingWindow == win) {
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
+ service.scheduleRemoveStartingWindowLocked(this);
+ } else if (allAppWindows.size() == 0 && startingData != null) {
+ // If this is the last window and we had requested a starting transition window,
+ // well there is no point now.
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow");
+ startingData = null;
+ } else if (allAppWindows.size() == 1 && startingView != null) {
+ // If this is the last window except for a starting transition window,
+ // we need to get rid of the starting transition.
+ service.scheduleRemoveStartingWindowLocked(this);
+ }
+ }
+
void removeAllDeadWindows() {
for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
// removeWindowLocked at bottom of loop may remove multiple entries from
@@ -691,6 +877,10 @@
}
void addWindow(WindowState w) {
+ if (allAppWindows.contains(w)) {
+ return;
+ }
+
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
WindowState candidate = allAppWindows.get(i);
if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null &&
@@ -819,6 +1009,350 @@
}
}
+ void resetJustMovedInStack() {
+ for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+ allAppWindows.get(i).resetJustMovedInStack();
+ }
+ }
+
+ @Override
+ int adjustAnimLayer(int adj) {
+ int highestAnimLayer = super.adjustAnimLayer(adj);
+
+ final int windowCount = allAppWindows.size();
+
+ for (int i = 0; i < windowCount; i++) {
+ final WindowState w = allAppWindows.get(i);
+ w.adjustAnimLayer(adj);
+
+ final int animLayer = w.mWinAnimator.mAnimLayer;
+ if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " + animLayer);
+ if (animLayer > highestAnimLayer) {
+ highestAnimLayer = animLayer;
+ }
+ if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
+ service.mLayersController.setInputMethodAnimLayerAdjustment(adj);
+ }
+ }
+
+ return highestAnimLayer;
+ }
+
+ @Override
+ int getHighestAnimLayer() {
+ int layer = super.getHighestAnimLayer();
+ for (int j = 0; j < allAppWindows.size(); j++) {
+ final WindowState win = allAppWindows.get(j);
+ if (win.mWinAnimator.mAnimLayer > layer) {
+ layer = win.mWinAnimator.mAnimLayer;
+ }
+ }
+ return layer;
+ }
+
+ void setWaitingForDrawnIfResizingChanged() {
+ for (int i = allAppWindows.size() - 1; i >= 0; --i) {
+ final WindowState win = allAppWindows.get(i);
+ if (win.isDragResizeChanged()) {
+ service.mWaitingForDrawn.add(win);
+ }
+ }
+ }
+
+ void resizeWindows() {
+ final ArrayList<WindowState> resizingWindows = service.mResizingWindows;
+ // Some windows won't go through the resizing process, if they don't have a surface, so
+ // destroy all saved surfaces here.
+ destroySavedSurfaces();
+
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowState win = allAppWindows.get(winNdx);
+ if (win.mHasSurface && !resizingWindows.contains(win)) {
+ if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + win);
+ resizingWindows.add(win);
+
+ // If we are not drag resizing, force recreating of a new surface so updating
+ // the content and positioning that surface will be in sync.
+ //
+ // As we use this flag as a hint to freeze surface boundary updates,
+ // we'd like to only apply this to TYPE_BASE_APPLICATION,
+ // windows of TYPE_APPLICATION like dialogs, could appear
+ // to not be drag resizing while they resize, but we'd
+ // still like to manipulate their frame to update crop, etc...
+ //
+ // Anyway we don't need to synchronize position and content updates for these
+ // windows since they aren't at the base layer and could be moved around anyway.
+ if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION &&
+ !mTask.mStack.getBoundsAnimating() && !win.isGoneForLayoutLw() &&
+ !mTask.inPinnedWorkspace()) {
+ win.setResizedWhileNotDragResizing(true);
+ }
+ }
+ if (win.isGoneForLayoutLw()) {
+ win.mResizedWhileGone = true;
+ }
+ }
+ }
+
+ void moveWindows() {
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowState win = allAppWindows.get(winNdx);
+ if (DEBUG_RESIZE) Slog.d(TAG, "moveWindows: Moving " + win);
+ win.mMovedByResize = true;
+ }
+ }
+
+ void notifyMovedInStack() {
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowState win = allAppWindows.get(winNdx);
+ win.notifyMovedInStack();
+ }
+ }
+
+ void resetDragResizingChangeReported() {
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowState win = allAppWindows.get(winNdx);
+ win.resetDragResizingChangeReported();
+ }
+ }
+
+ void detachDisplay() {
+ boolean doAnotherLayoutPass = false;
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; --winNdx) {
+ // We are in the middle of changing the state of displays/stacks/tasks. We need
+ // to finish that, before we let layout interfere with it.
+ service.removeWindowLocked(allAppWindows.get(winNdx));
+ doAnotherLayoutPass = true;
+ }
+ if (doAnotherLayoutPass) {
+ service.mWindowPlacerLocked.requestTraversal();
+ }
+ }
+
+ void forceWindowsScaleableInTransaction(boolean force) {
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowStateAnimator winAnimator = allAppWindows.get(winNdx).mWinAnimator;
+ if (winAnimator == null || !winAnimator.hasSurface()) {
+ continue;
+ }
+ winAnimator.mSurfaceController.forceScaleableInTransaction(force);
+ }
+ }
+
+ boolean isAnimating() {
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowStateAnimator winAnimator = allAppWindows.get(winNdx).mWinAnimator;
+ if (winAnimator.isAnimationSet() || winAnimator.mWin.mAnimatingExit) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void setAppLayoutChanges(int changes, String reason, int displayId) {
+ final WindowAnimator windowAnimator = mAppAnimator.mAnimator;
+ for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+ if (displayId == allAppWindows.get(i).getDisplayId()) {
+ windowAnimator.setPendingLayoutChanges(displayId, changes);
+ if (DEBUG_LAYOUT_REPEATS) {
+ service.mWindowPlacerLocked.debugLayoutRepeats(
+ reason, windowAnimator.getPendingLayoutChanges(displayId));
+ }
+ break;
+ }
+ }
+ }
+
+ void removeReplacedWindowIfNeeded(WindowState replacement) {
+ for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+ final WindowState win = allAppWindows.get(i);
+ if (win.mWillReplaceWindow && win.mReplacingWindow == replacement
+ && replacement.hasDrawnLw()) {
+ replacement.mSkipEnterAnimationForSeamlessReplacement = false;
+ win.removeReplacedWindow();
+ }
+ }
+ }
+
+ void startFreezingScreen() {
+ if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
+ + hidden + " freezing=" + mAppAnimator.freezingScreen);
+ if (!hiddenRequested) {
+ if (!mAppAnimator.freezingScreen) {
+ mAppAnimator.freezingScreen = true;
+ mAppAnimator.lastFreezeDuration = 0;
+ service.mAppsFreezingScreen++;
+ if (service.mAppsFreezingScreen == 1) {
+ service.startFreezingDisplayLocked(false, 0, 0);
+ service.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
+ service.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
+ }
+ }
+ final int count = allAppWindows.size();
+ for (int i = 0; i < count; i++) {
+ final WindowState w = allAppWindows.get(i);
+ w.mAppFreezing = true;
+ }
+ }
+ }
+
+ void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
+ if (!mAppAnimator.freezingScreen) {
+ return;
+ }
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
+ final int count = allAppWindows.size();
+ boolean unfrozeWindows = false;
+ for (int i = 0; i < count; i++) {
+ final WindowState w = allAppWindows.get(i);
+ if (w.mAppFreezing) {
+ w.mAppFreezing = false;
+ if (w.mHasSurface && !w.mOrientationChanging
+ && service.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + w);
+ w.mOrientationChanging = true;
+ service.mWindowPlacerLocked.mOrientationChangeComplete = false;
+ }
+ w.mLastFreezeDuration = 0;
+ unfrozeWindows = true;
+ w.setDisplayLayoutNeeded();
+ }
+ }
+ if (force || unfrozeWindows) {
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
+ mAppAnimator.freezingScreen = false;
+ mAppAnimator.lastFreezeDuration =
+ (int)(SystemClock.elapsedRealtime() - service.mDisplayFreezeTime);
+ service.mAppsFreezingScreen--;
+ service.mLastFinishedFreezeSource = this;
+ }
+ if (unfreezeSurfaceNow) {
+ if (unfrozeWindows) {
+ service.mWindowPlacerLocked.performSurfacePlacement();
+ }
+ service.stopFreezingDisplayLocked();
+ }
+ }
+
+ boolean transferStartingWindow(IBinder transferFrom) {
+ final AppWindowToken fromToken = service.findAppWindowToken(transferFrom);
+ if (fromToken == null) {
+ return false;
+ }
+
+ final WindowState tStartingWindow = fromToken.startingWindow;
+ if (tStartingWindow != null && fromToken.startingView != null) {
+ // In this case, the starting icon has already been displayed, so start
+ // letting windows get shown immediately without any more transitions.
+ service.mSkipAppTransitionAnimation = true;
+
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
+ + " from " + fromToken + " to " + this);
+
+ final long origId = Binder.clearCallingIdentity();
+
+ // Transfer the starting window over to the new token.
+ startingData = fromToken.startingData;
+ startingView = fromToken.startingView;
+ startingDisplayed = fromToken.startingDisplayed;
+ fromToken.startingDisplayed = false;
+ startingWindow = tStartingWindow;
+ reportedVisible = fromToken.reportedVisible;
+ fromToken.startingData = null;
+ fromToken.startingView = null;
+ fromToken.startingWindow = null;
+ fromToken.startingMoved = true;
+ tStartingWindow.mToken = this;
+ tStartingWindow.mRootToken = this;
+ tStartingWindow.mAppToken = this;
+
+ if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
+ "Removing starting window: " + tStartingWindow);
+ tStartingWindow.getWindowList().remove(tStartingWindow);
+ service.mWindowsChanged = true;
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+ "Removing starting " + tStartingWindow + " from " + fromToken);
+ fromToken.removeWindow(tStartingWindow);
+ fromToken.allAppWindows.remove(tStartingWindow);
+ addWindowToList(tStartingWindow);
+
+ // Propagate other interesting state between the tokens. If the old token is displayed,
+ // we should immediately force the new one to be displayed. If it is animating, we need
+ // to move that animation to the new one.
+ if (fromToken.allDrawn) {
+ allDrawn = true;
+ deferClearAllDrawn = fromToken.deferClearAllDrawn;
+ }
+ if (fromToken.firstWindowDrawn) {
+ firstWindowDrawn = true;
+ }
+ if (!fromToken.hidden) {
+ hidden = false;
+ hiddenRequested = false;
+ }
+ if (clientHidden != fromToken.clientHidden) {
+ clientHidden = fromToken.clientHidden;
+ sendAppVisibilityToClients();
+ }
+ fromToken.mAppAnimator.transferCurrentAnimation(
+ mAppAnimator, tStartingWindow.mWinAnimator);
+
+ service.updateFocusedWindowLocked(
+ UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
+ service.getDefaultDisplayContentLocked().layoutNeeded = true;
+ service.mWindowPlacerLocked.performSurfacePlacement();
+ Binder.restoreCallingIdentity(origId);
+ return true;
+ } else if (fromToken.startingData != null) {
+ // The previous app was getting ready to show a
+ // starting window, but hasn't yet done so. Steal it!
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
+ "Moving pending starting from " + fromToken + " to " + this);
+ startingData = fromToken.startingData;
+ fromToken.startingData = null;
+ fromToken.startingMoved = true;
+ final Message m = service.mH.obtainMessage(H.ADD_STARTING, this);
+ // Note: we really want to do sendMessageAtFrontOfQueue() because we want to process the
+ // message ASAP, before any other queued messages.
+ service.mH.sendMessageAtFrontOfQueue(m);
+ return true;
+ }
+
+ final AppWindowAnimator tAppAnimator = fromToken.mAppAnimator;
+ final AppWindowAnimator wAppAnimator = mAppAnimator;
+ if (tAppAnimator.thumbnail != null) {
+ // The old token is animating with a thumbnail, transfer that to the new token.
+ if (wAppAnimator.thumbnail != null) {
+ wAppAnimator.thumbnail.destroy();
+ }
+ wAppAnimator.thumbnail = tAppAnimator.thumbnail;
+ wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
+ wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
+ tAppAnimator.thumbnail = null;
+ }
+ return false;
+ }
+
+ int getWindowsCount() {
+ return allAppWindows.size();
+ }
+
+ void setAllAppWinAnimators() {
+ final ArrayList<WindowStateAnimator> allAppWinAnimators = mAppAnimator.mAllAppWinAnimators;
+ allAppWinAnimators.clear();
+
+ final int windowsCount = allAppWindows.size();
+ for (int j = 0; j < windowsCount; j++) {
+ allAppWinAnimators.add(allAppWindows.get(j).mWinAnimator);
+ }
+ }
+
+ /** Returns true if the app token windows list is empty. */
+ @Override
+ boolean isEmpty() {
+ return allAppWindows.isEmpty();
+ }
+
@Override
void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7394309..048d980 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -39,6 +39,7 @@
import android.view.DisplayInfo;
import android.view.Surface;
+import android.view.SurfaceControl;
import com.android.server.EventLogTags;
import java.io.PrintWriter;
@@ -178,11 +179,7 @@
resizeLocked(bounds, config, false /* force */);
for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
- final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
- win.notifyMovedInStack();
- }
+ mAppTokens.get(activityNdx).notifyMovedInStack();
}
}
@@ -478,11 +475,7 @@
void resetDragResizingChangeReported() {
for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
- final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
- win.resetDragResizingChangeReported();
- }
+ mAppTokens.get(activityNdx).resetDragResizingChangeReported();
}
}
@@ -498,15 +491,15 @@
* Adds all of the tasks windows to {@link WindowManagerService#mWaitingForDrawn} if drag
* resizing state of the window has been changed.
*/
- void addWindowsWaitingForDrawnIfResizingChanged() {
- for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
- final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
- if (win.isDragResizeChanged()) {
- mService.mWaitingForDrawn.add(win);
- }
- }
+ void setWaitingForDrawnIfResizingChanged() {
+ for (int i = mAppTokens.size() - 1; i >= 0; --i) {
+ mAppTokens.get(i).setWaitingForDrawnIfResizingChanged();
+ }
+ }
+
+ void detachDisplay() {
+ for (int i = mAppTokens.size() - 1; i >= 0; --i) {
+ mAppTokens.get(i).detachDisplay();
}
}
@@ -546,52 +539,14 @@
}
void resizeWindows() {
- final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
- final AppWindowToken atoken = mAppTokens.get(activityNdx);
-
- // Some windows won't go through the resizing process, if they don't have a surface, so
- // destroy all saved surfaces here.
- atoken.destroySavedSurfaces();
- final ArrayList<WindowState> windows = atoken.allAppWindows;
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
- if (win.mHasSurface && !resizingWindows.contains(win)) {
- if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + win);
- resizingWindows.add(win);
-
- // If we are not drag resizing, force recreating of a new surface so updating
- // the content and positioning that surface will be in sync.
- //
- // As we use this flag as a hint to freeze surface boundary updates,
- // we'd like to only apply this to TYPE_BASE_APPLICATION,
- // windows of TYPE_APPLICATION like dialogs, could appear
- // to not be drag resizing while they resize, but we'd
- // still like to manipulate their frame to update crop, etc...
- //
- // Anyway we don't need to synchronize position and content updates for these
- // windows since they aren't at the base layer and could be moved around anyway.
- if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION &&
- !mStack.getBoundsAnimating() && !win.isGoneForLayoutLw() &&
- !inPinnedWorkspace()) {
- win.setResizedWhileNotDragResizing(true);
- }
- }
- if (win.isGoneForLayoutLw()) {
- win.mResizedWhileGone = true;
- }
- }
+ mAppTokens.get(activityNdx).resizeWindows();
}
}
void moveWindows() {
- for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
- final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
- if (DEBUG_RESIZE) Slog.d(TAG, "moveWindows: Moving " + win);
- win.mMovedByResize = true;
- }
+ for (int i = mAppTokens.size() - 1; i >= 0; --i) {
+ mAppTokens.get(i).moveWindows();
}
}
@@ -621,11 +576,8 @@
boolean isVisibleForUser() {
for (int i = mAppTokens.size() - 1; i >= 0; i--) {
final AppWindowToken appToken = mAppTokens.get(i);
- for (int j = appToken.allAppWindows.size() - 1; j >= 0; j--) {
- WindowState window = appToken.allAppWindows.get(j);
- if (!window.isHiddenFromUserLocked()) {
- return true;
- }
+ if (appToken.isVisibleForUser()) {
+ return true;
}
}
return false;
@@ -697,6 +649,27 @@
return mStack.getDisplayContent().getDisplayInfo();
}
+ void forceWindowsScaleable(boolean force) {
+ SurfaceControl.openTransaction();
+ try {
+ for (int i = mAppTokens.size() - 1; i >= 0; i--) {
+ mAppTokens.get(i).forceWindowsScaleableInTransaction(force);
+ }
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+
+ boolean isAnimating() {
+ for (int i = mAppTokens.size() - 1; i >= 0; i--) {
+ final AppWindowToken aToken = mAppTokens.get(i);
+ if (aToken.isAnimating()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public String toString() {
return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b137840..d2ec792 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -477,15 +477,9 @@
boolean isAnimating() {
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
- for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
- if (winAnimator.isAnimationSet() || winAnimator.mWin.mAnimatingExit) {
- return true;
- }
- }
+ final Task task = mTasks.get(taskNdx);
+ if (task.isAnimating()) {
+ return true;
}
}
return false;
@@ -532,12 +526,11 @@
}
if (StackId.windowsAreScaleable(mStackId)) {
- // We force windows out of SCALING_MODE_FREEZE
- // so that we can continue to animate them
+ // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
// while a resize is pending.
- forceWindowsScaleable(task, true);
+ task.forceWindowsScaleable(true);
} else {
- forceWindowsScaleable(task, false);
+ task.forceWindowsScaleable(false);
}
EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.mTaskId, toTop ? 1 : 0, position);
}
@@ -773,21 +766,8 @@
void detachDisplay() {
EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
- boolean doAnotherLayoutPass = false;
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- final AppTokenList appWindowTokens = mTasks.get(taskNdx).mAppTokens;
- for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
- final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
- for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
- // We are in the middle of changing the state of displays/stacks/tasks. We need
- // to finish that, before we let layout interfere with it.
- mService.removeWindowLocked(appWindows.get(winNdx));
- doAnotherLayoutPass = true;
- }
- }
- }
- if (doAnotherLayoutPass) {
- mService.mWindowPlacerLocked.requestTraversal();
+ mTasks.get(taskNdx).detachDisplay();
}
close();
@@ -922,7 +902,7 @@
final Task task = mTasks.get(j);
if (task.isVisibleForUser()) {
task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
- task.addWindowsWaitingForDrawnIfResizingChanged();
+ task.setWaitingForDrawnIfResizingChanged();
}
}
}
@@ -1290,25 +1270,6 @@
return true;
}
- void forceWindowsScaleable(Task task, boolean force) {
- SurfaceControl.openTransaction();
- try {
- final ArrayList<AppWindowToken> activities = task.mAppTokens;
- for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
- if (winAnimator == null || !winAnimator.hasSurface()) {
- continue;
- }
- winAnimator.mSurfaceController.forceScaleableInTransaction(force);
- }
- }
- } finally {
- SurfaceControl.closeTransaction();
- }
- }
-
@Override // AnimatesBounds
public void onAnimationStart() {
synchronized (mService.mWindowMap) {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index a7a7a39..6e7313c 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -624,7 +624,7 @@
// windows shown... what to do, what to do?
if (appAnimator.freezingScreen) {
appAnimator.showAllWindowsLocked();
- mService.unsetAppFreezingScreenLocked(wtoken, false, true);
+ wtoken.stopFreezingScreen(false, true);
if (DEBUG_ORIENTATION) Slog.i(TAG,
"Setting mOrientationChangeComplete=true because wtoken "
+ wtoken + " numInteresting=" + wtoken.numInterestingWindows
@@ -800,21 +800,23 @@
}
private void removeReplacedWindowsLocked() {
- if (SHOW_TRANSACTIONS) Slog.i(
- TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
SurfaceControl.openTransaction();
try {
for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
DisplayContent display = mService.mDisplayContents.valueAt(i);
final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
for (int j = windows.size() - 1; j >= 0; j--) {
- windows.get(j).maybeRemoveReplacedWindow();
+ final WindowState win = windows.get(j);
+ final AppWindowToken aToken = win.mAppToken;
+ if (aToken != null) {
+ aToken.removeReplacedWindowIfNeeded(win);
+ }
}
}
} finally {
SurfaceControl.closeTransaction();
- if (SHOW_TRANSACTIONS) Slog.i(
- TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
}
mRemoveReplacedWindows = false;
}
@@ -903,19 +905,9 @@
}
}
- void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason,
- final int displayId) {
- WindowList windows = appAnimator.mAppToken.allAppWindows;
- for (int i = windows.size() - 1; i >= 0; i--) {
- if (displayId == windows.get(i).getDisplayId()) {
- setPendingLayoutChanges(displayId, changes);
- if (DEBUG_LAYOUT_REPEATS) {
- mWindowPlacerLocked.debugLayoutRepeats(reason,
- getPendingLayoutChanges(displayId));
- }
- break;
- }
- }
+ void setAppLayoutChanges(
+ AppWindowAnimator appAnimator, int changes, String reason, int displayId) {
+ appAnimator.mAppToken.setAppLayoutChanges(changes, reason, displayId);
}
private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index aceff33..6b46ddd 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -204,8 +204,7 @@
import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
-import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
+import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
@@ -886,7 +885,7 @@
private final DisplayContentList mReconfigureOnConfigurationChanged = new DisplayContentList();
/** Listener to notify activity manager about app transitions. */
- private final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
+ final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
= new WindowManagerInternal.AppTransitionListener() {
@Override
@@ -1872,19 +1871,6 @@
}
}
- private void setupWindowForRemoveOnExit(WindowState win) {
- win.mRemoveOnExit = true;
- win.setDisplayLayoutNeeded();
- // Request a focus update as this window's input channel is already gone. Otherwise
- // we could have no focused window in input manager.
- final boolean focusChanged = updateFocusedWindowLocked(
- UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
- mWindowPlacerLocked.performSurfacePlacement();
- if (focusChanged) {
- mInputMonitor.updateInputWindowsLw(false /*force*/);
- }
- }
-
public void removeWindow(Session session, IWindow client) {
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
@@ -1896,145 +1882,7 @@
}
void removeWindowLocked(WindowState win) {
- removeWindowLocked(win, false);
- }
-
- void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) {
- win.mWindowRemovalAllowed = true;
- if (DEBUG_ADD_REMOVE) Slog.v(TAG,
- "removeWindowLocked: " + win + " callers=" + Debug.getCallers(4));
-
- final boolean startingWindow = win.mAttrs.type == TYPE_APPLICATION_STARTING;
- if (startingWindow) {
- if (DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, "Starting window removed " + win);
- }
-
- if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win == mCurrentFocus) Slog.v(
- TAG_WM, "Remove " + win + " client="
- + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
- + ", surfaceController=" + win.mWinAnimator.mSurfaceController + " Callers="
- + Debug.getCallers(4));
-
- final long origId = Binder.clearCallingIdentity();
-
- win.disposeInputChannel();
-
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
- "Remove " + win + ": mSurfaceController=" + win.mWinAnimator.mSurfaceController
- + " mAnimatingExit=" + win.mAnimatingExit
- + " mRemoveOnExit=" + win.mRemoveOnExit
- + " mHasSurface=" + win.mHasSurface
- + " surfaceShowing=" + win.mWinAnimator.getShown()
- + " isAnimationSet=" + win.mWinAnimator.isAnimationSet()
- + " app-animation="
- + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
- + " mWillReplaceWindow=" + win.mWillReplaceWindow
- + " inPendingTransaction="
- + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
- + " mDisplayFrozen=" + mDisplayFrozen
- + " callers=" + Debug.getCallers(6));
- // Visibility of the removed window. Will be used later to update orientation later on.
- boolean wasVisible = false;
- // First, see if we need to run an animation. If we do, we have to hold off on removing the
- // window until the animation is done. If the display is frozen, just remove immediately,
- // since the animation wouldn't be seen.
- if (win.mHasSurface && okToDisplay()) {
- final AppWindowToken appToken = win.mAppToken;
- if (win.mWillReplaceWindow) {
- // This window is going to be replaced. We need to keep it around until the new one
- // gets added, then we will get rid of this one.
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is "
- + "added");
- // TODO: We are overloading mAnimatingExit flag to prevent the window state from
- // been removed. We probably need another flag to indicate that window removal
- // should be deffered vs. overloading the flag that says we are playing an exit
- // animation.
- win.mAnimatingExit = true;
- win.mReplacingRemoveRequested = true;
- Binder.restoreCallingIdentity(origId);
- return;
- }
-
- if (win.isAnimatingWithSavedSurface() && !appToken.allDrawnExcludingSaved) {
- // We started enter animation early with a saved surface, now the app asks to remove
- // this window. If we remove it now and the app is not yet drawn, we'll show a
- // flicker. Delay the removal now until it's really drawn.
- if (DEBUG_ADD_REMOVE) {
- Slog.d(TAG_WM, "removeWindowLocked: delay removal of " + win
- + " due to early animation");
- }
- // Do not set mAnimatingExit to true here, it will cause the surface to be hidden
- // immediately after the enter animation is done. If the app is not yet drawn then
- // it will show up as a flicker.
- setupWindowForRemoveOnExit(win);
- Binder.restoreCallingIdentity(origId);
- return;
- }
- // If we are not currently running the exit animation, we need to see about starting one
- wasVisible = win.isWinVisibleLw();
-
- if (keepVisibleDeadWindow) {
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Not removing " + win + " because app died while it's visible");
-
- win.mAppDied = true;
- win.setDisplayLayoutNeeded();
- mWindowPlacerLocked.performSurfacePlacement();
-
- // Set up a replacement input channel since the app is now dead.
- // We need to catch tapping on the dead window to restart the app.
- win.openInputChannel(null);
- mInputMonitor.updateInputWindowsLw(true /*force*/);
-
- Binder.restoreCallingIdentity(origId);
- return;
- }
-
- final WindowStateAnimator winAnimator = win.mWinAnimator;
- if (wasVisible) {
- final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
-
- // Try starting an animation.
- if (winAnimator.applyAnimationLocked(transit, false)) {
- win.mAnimatingExit = true;
- }
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (mAccessibilityController != null
- && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
- mAccessibilityController.onWindowTransitionLocked(win, transit);
- }
- }
- final boolean isAnimating =
- winAnimator.isAnimationSet() && !winAnimator.isDummyAnimation();
- final boolean lastWindowIsStartingWindow = startingWindow && appToken != null
- && appToken.allAppWindows.size() == 1;
- // We delay the removal of a window if it has a showing surface that can be used to run
- // exit animation and it is marked as exiting.
- // Also, If isn't the an animating starting window that is the last window in the app.
- // We allow the removal of the non-animating starting window now as there is no
- // additional window or animation that will trigger its removal.
- if (winAnimator.getShown() && win.mAnimatingExit
- && (!lastWindowIsStartingWindow || isAnimating)) {
- // The exit animation is running or should run... wait for it!
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Not removing " + win + " due to exit animation ");
- setupWindowForRemoveOnExit(win);
- if (appToken != null) {
- appToken.updateReportedVisibilityLocked();
- }
- Binder.restoreCallingIdentity(origId);
- return;
- }
- }
-
- win.remove();
- // Removing a visible window will effect the computed orientation
- // So just update orientation if needed.
- if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
- mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
- }
- updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
- Binder.restoreCallingIdentity(origId);
+ win.removeIfPossible(false /*keepVisibleDeadWindow*/);
}
/**
@@ -2063,42 +1911,26 @@
final AppWindowToken atoken = win.mAppToken;
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token);
token.removeWindow(win);
- if (atoken != null) {
- atoken.allAppWindows.remove(win);
- }
if (token.isEmpty()) {
if (!token.explicit) {
mTokenMap.remove(token.token);
} else if (atoken != null) {
+ // TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
+ // re-factor.
atoken.firstWindowDrawn = false;
atoken.clearAllDrawn();
}
}
if (atoken != null) {
- if (atoken.startingWindow == win) {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
- scheduleRemoveStartingWindowLocked(atoken);
- } else
- if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
- // If this is the last window and we had requested a starting
- // transition window, well there is no point now.
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow");
- atoken.startingData = null;
- } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
- // If this is the last window except for a starting transition
- // window, we need to get rid of the starting transition.
- scheduleRemoveStartingWindowLocked(atoken);
- }
+ atoken.removeWindow(win);
}
if (win.mAttrs.type == TYPE_WALLPAPER) {
mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
- getDefaultDisplayContentLocked().pendingLayoutChanges |=
- WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
- getDefaultDisplayContentLocked().pendingLayoutChanges |=
- WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ getDefaultDisplayContentLocked().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ } else if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+ getDefaultDisplayContentLocked().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
final WindowList windows = win.getWindowList();
@@ -2735,7 +2567,7 @@
}
}
- private boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp,
+ boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp,
int transit, boolean enter, boolean isVoiceInteraction) {
// Only apply an animation if the display isn't frozen. If it is
// frozen, there is no reason to animate and it can cause strange
@@ -3231,9 +3063,9 @@
if (updateOrientationFromAppTokensLocked(false)) {
if (freezeThisOneIfNeeded != null) {
- AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
+ final AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
if (atoken != null) {
- startAppFreezingScreenLocked(atoken);
+ atoken.startFreezingScreen();
}
}
config = computeNewConfigurationLocked();
@@ -3677,7 +3509,7 @@
}
}
- if (transferStartingWindow(transferFrom, wtoken)) {
+ if (wtoken != null && wtoken.transferStartingWindow(transferFrom)) {
return true;
}
@@ -3700,108 +3532,6 @@
return true;
}
- private boolean transferStartingWindow(IBinder transferFrom, AppWindowToken wtoken) {
- if (transferFrom == null) {
- return false;
- }
- AppWindowToken ttoken = findAppWindowToken(transferFrom);
- if (ttoken == null) {
- return false;
- }
- WindowState startingWindow = ttoken.startingWindow;
- if (startingWindow != null && ttoken.startingView != null) {
- // In this case, the starting icon has already been displayed, so start
- // letting windows get shown immediately without any more transitions.
- mSkipAppTransitionAnimation = true;
-
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
- "Moving existing starting " + startingWindow + " from " + ttoken
- + " to " + wtoken);
- final long origId = Binder.clearCallingIdentity();
-
- // Transfer the starting window over to the new token.
- wtoken.startingData = ttoken.startingData;
- wtoken.startingView = ttoken.startingView;
- wtoken.startingDisplayed = ttoken.startingDisplayed;
- ttoken.startingDisplayed = false;
- wtoken.startingWindow = startingWindow;
- wtoken.reportedVisible = ttoken.reportedVisible;
- ttoken.startingData = null;
- ttoken.startingView = null;
- ttoken.startingWindow = null;
- ttoken.startingMoved = true;
- startingWindow.mToken = wtoken;
- startingWindow.mRootToken = wtoken;
- startingWindow.mAppToken = wtoken;
-
- if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
- Slog.v(TAG_WM, "Removing starting window: " + startingWindow);
- }
- startingWindow.getWindowList().remove(startingWindow);
- mWindowsChanged = true;
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Removing starting " + startingWindow + " from " + ttoken);
- ttoken.removeWindow(startingWindow);
- ttoken.allAppWindows.remove(startingWindow);
- wtoken.addWindowToList(startingWindow);
-
- // Propagate other interesting state between the tokens. If the old token is displayed,
- // we should immediately force the new one to be displayed. If it is animating, we need
- // to move that animation to the new one.
- if (ttoken.allDrawn) {
- wtoken.allDrawn = true;
- wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
- }
- if (ttoken.firstWindowDrawn) {
- wtoken.firstWindowDrawn = true;
- }
- if (!ttoken.hidden) {
- wtoken.hidden = false;
- wtoken.hiddenRequested = false;
- }
- if (wtoken.clientHidden != ttoken.clientHidden) {
- wtoken.clientHidden = ttoken.clientHidden;
- wtoken.sendAppVisibilityToClients();
- }
- ttoken.mAppAnimator.transferCurrentAnimation(
- wtoken.mAppAnimator, startingWindow.mWinAnimator);
-
- updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
- true /*updateInputWindows*/);
- getDefaultDisplayContentLocked().layoutNeeded = true;
- mWindowPlacerLocked.performSurfacePlacement();
- Binder.restoreCallingIdentity(origId);
- return true;
- } else if (ttoken.startingData != null) {
- // The previous app was getting ready to show a
- // starting window, but hasn't yet done so. Steal it!
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving pending starting from " + ttoken
- + " to " + wtoken);
- wtoken.startingData = ttoken.startingData;
- ttoken.startingData = null;
- ttoken.startingMoved = true;
- Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
- // Note: we really want to do sendMessageAtFrontOfQueue() because we
- // want to process the message ASAP, before any other queued
- // messages.
- mH.sendMessageAtFrontOfQueue(m);
- return true;
- }
- final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
- final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
- if (tAppAnimator.thumbnail != null) {
- // The old token is animating with a thumbnail, transfer that to the new token.
- if (wAppAnimator.thumbnail != null) {
- wAppAnimator.thumbnail.destroy();
- }
- wAppAnimator.thumbnail = tAppAnimator.thumbnail;
- wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
- wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
- tAppAnimator.thumbnail = null;
- }
- return false;
- }
-
public void removeAppStartingWindow(IBinder token) {
synchronized (mWindowMap) {
final AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
@@ -3836,155 +3566,8 @@
}
}
- boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
- boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
- boolean delayed = false;
-
- if (wtoken.clientHidden == visible) {
- wtoken.clientHidden = !visible;
- wtoken.sendAppVisibilityToClients();
- }
-
- // Allow for state changes and animation to be applied if:
- // * token is transitioning visibility state
- // * or the token was marked as hidden and is exiting before we had a chance to play the
- // transition animation
- // * or this is an opening app and windows are being replaced.
- boolean visibilityChanged = false;
- if (wtoken.hidden == visible || (wtoken.hidden && wtoken.mIsExiting) ||
- (visible && wtoken.waitingForReplacement())) {
- boolean changed = false;
- if (DEBUG_APP_TRANSITIONS) Slog.v(
- TAG_WM, "Changing app " + wtoken + " hidden=" + wtoken.hidden
- + " performLayout=" + performLayout);
-
- boolean runningAppAnimation = false;
-
- if (transit != AppTransition.TRANSIT_UNSET) {
- if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
- wtoken.mAppAnimator.setNullAnimation();
- }
- if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) {
- delayed = runningAppAnimation = true;
- }
- WindowState window = wtoken.findMainWindow();
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (window != null && mAccessibilityController != null
- && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
- mAccessibilityController.onAppWindowTransitionLocked(window, transit);
- }
- changed = true;
- }
-
- final int windowsCount = wtoken.allAppWindows.size();
- for (int i = 0; i < windowsCount; i++) {
- WindowState win = wtoken.allAppWindows.get(i);
- if (win == wtoken.startingWindow) {
- // Starting window that's exiting will be removed when the animation
- // finishes. Mark all relevant flags for that onExitAnimationDone will proceed
- // all the way to actually remove it.
- if (!visible && win.isVisibleNow() && wtoken.mAppAnimator.isAnimating()) {
- win.mAnimatingExit = true;
- win.mRemoveOnExit = true;
- win.mWindowRemovalAllowed = true;
- }
- continue;
- }
-
- //Slog.i(TAG_WM, "Window " + win + ": vis=" + win.isVisible());
- //win.dump(" ");
- if (visible) {
- if (!win.isVisibleNow()) {
- if (!runningAppAnimation) {
- win.mWinAnimator.applyAnimationLocked(
- WindowManagerPolicy.TRANSIT_ENTER, true);
- //TODO (multidisplay): Magnification is supported only for the default
- if (mAccessibilityController != null
- && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
- mAccessibilityController.onWindowTransitionLocked(win,
- WindowManagerPolicy.TRANSIT_ENTER);
- }
- }
- changed = true;
- win.setDisplayLayoutNeeded();
- }
- } else if (win.isVisibleNow()) {
- if (!runningAppAnimation) {
- win.mWinAnimator.applyAnimationLocked(
- WindowManagerPolicy.TRANSIT_EXIT, false);
- //TODO (multidisplay): Magnification is supported only for the default
- if (mAccessibilityController != null
- && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
- mAccessibilityController.onWindowTransitionLocked(win,
- WindowManagerPolicy.TRANSIT_EXIT);
- }
- }
- changed = true;
- win.setDisplayLayoutNeeded();
- }
- }
-
- wtoken.hidden = wtoken.hiddenRequested = !visible;
- visibilityChanged = true;
- if (!visible) {
- unsetAppFreezingScreenLocked(wtoken, true, true);
- } else {
- // If we are being set visible, and the starting window is
- // not yet displayed, then make sure it doesn't get displayed.
- WindowState swin = wtoken.startingWindow;
- if (swin != null && !swin.isDrawnLw()) {
- swin.mPolicyVisibility = false;
- swin.mPolicyVisibilityAfterAnim = false;
- }
- }
-
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setTokenVisibilityLocked: " + wtoken
- + ": hidden=" + wtoken.hidden + " hiddenRequested="
- + wtoken.hiddenRequested);
-
- if (changed) {
- mInputMonitor.setUpdateInputWindowsNeededLw();
- if (performLayout) {
- updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
- false /*updateInputWindows*/);
- mWindowPlacerLocked.performSurfacePlacement();
- }
- mInputMonitor.updateInputWindowsLw(false /*force*/);
- }
- }
-
- if (wtoken.mAppAnimator.animation != null) {
- delayed = true;
- }
-
- for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
- if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimationSet()) {
- delayed = true;
- }
- }
-
- if (visibilityChanged) {
- if (visible && !delayed) {
- // The token was made immediately visible, there will be no entrance animation.
- // We need to inform the client the enter animation was finished.
- wtoken.mEnteringAnimation = true;
- mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(wtoken.token);
- }
-
- if (!mClosingApps.contains(wtoken) && !mOpeningApps.contains(wtoken)) {
- // The token is not closing nor opening, so even if there is an animation set, that
- // doesn't mean that it goes through the normal app transition cycle so we have
- // to inform the docked controller about visibility change.
- getDefaultDisplayContentLocked().getDockedDividerController()
- .notifyAppVisibilityChanged();
- }
- }
-
- return delayed;
- }
-
void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
- if (transit != AppTransition.TRANSIT_UNSET) {
+ if (transit != TRANSIT_UNSET) {
if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
wtoken.mAppAnimator.setNullAnimation();
}
@@ -4141,75 +3724,12 @@
}
final long origId = Binder.clearCallingIdentity();
- wtoken.inPendingTransaction = false;
- setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
- true, wtoken.voiceInteraction);
+ wtoken.setVisibility(null, visible, TRANSIT_UNSET, true, wtoken.voiceInteraction);
wtoken.updateReportedVisibilityLocked();
Binder.restoreCallingIdentity(origId);
}
}
- void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
- boolean unfreezeSurfaceNow, boolean force) {
- if (wtoken.mAppAnimator.freezingScreen) {
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + wtoken
- + " force=" + force);
- final int N = wtoken.allAppWindows.size();
- boolean unfrozeWindows = false;
- for (int i=0; i<N; i++) {
- WindowState w = wtoken.allAppWindows.get(i);
- if (w.mAppFreezing) {
- w.mAppFreezing = false;
- if (w.mHasSurface && !w.mOrientationChanging
- && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + w);
- w.mOrientationChanging = true;
- mWindowPlacerLocked.mOrientationChangeComplete = false;
- }
- w.mLastFreezeDuration = 0;
- unfrozeWindows = true;
- w.setDisplayLayoutNeeded();
- }
- }
- if (force || unfrozeWindows) {
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + wtoken);
- wtoken.mAppAnimator.freezingScreen = false;
- wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- - mDisplayFreezeTime);
- mAppsFreezingScreen--;
- mLastFinishedFreezeSource = wtoken;
- }
- if (unfreezeSurfaceNow) {
- if (unfrozeWindows) {
- mWindowPlacerLocked.performSurfacePlacement();
- }
- stopFreezingDisplayLocked();
- }
- }
- }
-
- private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
- if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + wtoken.appToken + ": hidden="
- + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
- if (!wtoken.hiddenRequested) {
- if (!wtoken.mAppAnimator.freezingScreen) {
- wtoken.mAppAnimator.freezingScreen = true;
- wtoken.mAppAnimator.lastFreezeDuration = 0;
- mAppsFreezingScreen++;
- if (mAppsFreezingScreen == 1) {
- startFreezingDisplayLocked(false, 0, 0);
- mH.removeMessages(H.APP_FREEZE_TIMEOUT);
- mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
- }
- }
- final int N = wtoken.allAppWindows.size();
- for (int i=0; i<N; i++) {
- WindowState w = wtoken.allAppWindows.get(i);
- w.mAppFreezing = true;
- }
- }
- }
-
@Override
public void startAppFreezingScreen(IBinder token, int configChanges) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@@ -4223,13 +3743,13 @@
return;
}
- AppWindowToken wtoken = findAppWindowToken(token);
+ final AppWindowToken wtoken = findAppWindowToken(token);
if (wtoken == null || wtoken.appToken == null) {
Slog.w(TAG_WM, "Attempted to freeze screen with non-existing app token: " + wtoken);
return;
}
final long origId = Binder.clearCallingIdentity();
- startAppFreezingScreenLocked(wtoken);
+ wtoken.startFreezingScreen();
Binder.restoreCallingIdentity(origId);
}
}
@@ -4249,7 +3769,7 @@
final long origId = Binder.clearCallingIdentity();
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + token
+ ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
- unsetAppFreezingScreenLocked(wtoken, true, force);
+ wtoken.stopFreezingScreen(true, force);
Binder.restoreCallingIdentity(origId);
}
}
@@ -4270,9 +3790,8 @@
WindowToken basewtoken = mTokenMap.remove(token);
if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + wtoken);
- delayed = setTokenVisibilityLocked(wtoken, null, false,
- AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction);
- wtoken.inPendingTransaction = false;
+ delayed = wtoken.setVisibility(null, false,
+ TRANSIT_UNSET, true, wtoken.voiceInteraction);
mOpeningApps.remove(wtoken);
wtoken.waitingToShow = false;
if (mClosingApps.contains(wtoken)) {
@@ -4288,7 +3807,7 @@
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
+ wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
final TaskStack stack = wtoken.mTask.mStack;
- if (delayed && !wtoken.allAppWindows.isEmpty()) {
+ if (delayed && !wtoken.isEmpty()) {
// set the token aside because it has an active animation to be finished
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
"removeAppToken make exiting: " + wtoken);
@@ -4307,7 +3826,7 @@
if (wtoken.startingData != null) {
startingToken = wtoken;
}
- unsetAppFreezingScreenLocked(wtoken, true, true);
+ wtoken.stopFreezingScreen(true, true);
if (mFocusedApp == wtoken) {
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + wtoken);
mFocusedApp = null;
@@ -7909,7 +7428,7 @@
AppWindowToken tok = tokens.get(tokenNdx);
if (tok.mAppAnimator.freezingScreen) {
Slog.w(TAG_WM, "Force clearing freeze: " + tok);
- unsetAppFreezingScreenLocked(tok, true, true);
+ tok.stopFreezingScreen(true, true);
}
}
}
@@ -9292,7 +8811,7 @@
return null;
}
- private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
+ void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
if (mDisplayFrozen) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 0c4ee7e..845f112 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -25,6 +25,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
+import android.os.Binder;
import android.os.Debug;
import android.os.IBinder;
import android.os.PowerManager;
@@ -97,6 +98,8 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
+import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
@@ -117,8 +120,12 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
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.SEND_NEW_CONFIGURATION;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.localLOGV;
import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
@@ -570,7 +577,7 @@
DeathRecipient deathRecipient = new DeathRecipient();
mSeq = seq;
mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
- if (WindowManagerService.localLOGV) Slog.v(
+ if (localLOGV) Slog.v(
TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
try {
@@ -658,7 +665,7 @@
}
void attach() {
- if (WindowManagerService.localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
+ if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
mSession.windowAddedLocked();
}
@@ -943,7 +950,7 @@
}
}
- if (DEBUG_LAYOUT || WindowManagerService.localLOGV) Slog.v(TAG,
+ if (DEBUG_LAYOUT || localLOGV) Slog.v(TAG,
"Resolving (mRequestedWidth="
+ mRequestedWidth + ", mRequestedheight="
+ mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
@@ -1489,6 +1496,154 @@
mService.postWindowRemoveCleanupLocked(this);
}
+ void removeIfPossible(boolean keepVisibleDeadWindow) {
+ mWindowRemovalAllowed = true;
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG,
+ "removeIfPossible: " + this + " callers=" + Debug.getCallers(5));
+
+ final boolean startingWindow = mAttrs.type == TYPE_APPLICATION_STARTING;
+ if (startingWindow && DEBUG_STARTING_WINDOW) Slog.d(TAG_WM,
+ "Starting window removed " + this);
+
+ if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && this == mService.mCurrentFocus)
+ Slog.v(TAG_WM, "Remove " + this + " client="
+ + Integer.toHexString(System.identityHashCode(mClient.asBinder()))
+ + ", surfaceController=" + mWinAnimator.mSurfaceController + " Callers="
+ + Debug.getCallers(5));
+
+ final long origId = Binder.clearCallingIdentity();
+
+ disposeInputChannel();
+
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Remove " + this
+ + ": mSurfaceController=" + mWinAnimator.mSurfaceController
+ + " mAnimatingExit=" + mAnimatingExit
+ + " mRemoveOnExit=" + mRemoveOnExit
+ + " mHasSurface=" + mHasSurface
+ + " surfaceShowing=" + mWinAnimator.getShown()
+ + " isAnimationSet=" + mWinAnimator.isAnimationSet()
+ + " app-animation="
+ + (mAppToken != null ? mAppToken.mAppAnimator.animation : null)
+ + " mWillReplaceWindow=" + mWillReplaceWindow
+ + " inPendingTransaction="
+ + (mAppToken != null ? mAppToken.inPendingTransaction : false)
+ + " mDisplayFrozen=" + mService.mDisplayFrozen
+ + " callers=" + Debug.getCallers(6));
+
+ // Visibility of the removed window. Will be used later to update orientation later on.
+ boolean wasVisible = false;
+
+ // First, see if we need to run an animation. If we do, we have to hold off on removing the
+ // window until the animation is done. If the display is frozen, just remove immediately,
+ // since the animation wouldn't be seen.
+ if (mHasSurface && mService.okToDisplay()) {
+ if (mWillReplaceWindow) {
+ // This window is going to be replaced. We need to keep it around until the new one
+ // gets added, then we will get rid of this one.
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+ "Preserving " + this + " until the new one is " + "added");
+ // TODO: We are overloading mAnimatingExit flag to prevent the window state from
+ // been removed. We probably need another flag to indicate that window removal
+ // should be deffered vs. overloading the flag that says we are playing an exit
+ // animation.
+ mAnimatingExit = true;
+ mReplacingRemoveRequested = true;
+ Binder.restoreCallingIdentity(origId);
+ return;
+ }
+
+ if (isAnimatingWithSavedSurface() && !mAppToken.allDrawnExcludingSaved) {
+ // We started enter animation early with a saved surface, now the app asks to remove
+ // this window. If we remove it now and the app is not yet drawn, we'll show a
+ // flicker. Delay the removal now until it's really drawn.
+ if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
+ "removeWindowLocked: delay removal of " + this + " due to early animation");
+ // Do not set mAnimatingExit to true here, it will cause the surface to be hidden
+ // immediately after the enter animation is done. If the app is not yet drawn then
+ // it will show up as a flicker.
+ setupWindowForRemoveOnExit();
+ Binder.restoreCallingIdentity(origId);
+ return;
+ }
+ // If we are not currently running the exit animation, we need to see about starting one
+ wasVisible = isWinVisibleLw();
+
+ if (keepVisibleDeadWindow) {
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+ "Not removing " + this + " because app died while it's visible");
+
+ mAppDied = true;
+ setDisplayLayoutNeeded();
+ mService.mWindowPlacerLocked.performSurfacePlacement();
+
+ // Set up a replacement input channel since the app is now dead.
+ // We need to catch tapping on the dead window to restart the app.
+ openInputChannel(null);
+ mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+ Binder.restoreCallingIdentity(origId);
+ return;
+ }
+
+ if (wasVisible) {
+ final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
+
+ // Try starting an animation.
+ if (mWinAnimator.applyAnimationLocked(transit, false)) {
+ mAnimatingExit = true;
+ }
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (mService.mAccessibilityController != null
+ && getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mService.mAccessibilityController.onWindowTransitionLocked(this, transit);
+ }
+ }
+ final boolean isAnimating =
+ mWinAnimator.isAnimationSet() && !mWinAnimator.isDummyAnimation();
+ final boolean lastWindowIsStartingWindow = startingWindow && mAppToken != null
+ && mAppToken.getWindowsCount() == 1;
+ // We delay the removal of a window if it has a showing surface that can be used to run
+ // exit animation and it is marked as exiting.
+ // Also, If isn't the an animating starting window that is the last window in the app.
+ // We allow the removal of the non-animating starting window now as there is no
+ // additional window or animation that will trigger its removal.
+ if (mWinAnimator.getShown() && mAnimatingExit
+ && (!lastWindowIsStartingWindow || isAnimating)) {
+ // The exit animation is running or should run... wait for it!
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+ "Not removing " + this + " due to exit animation ");
+ setupWindowForRemoveOnExit();
+ if (mAppToken != null) {
+ mAppToken.updateReportedVisibilityLocked();
+ }
+ Binder.restoreCallingIdentity(origId);
+ return;
+ }
+ }
+
+ remove();
+ // Removing a visible window will effect the computed orientation
+ // So just update orientation if needed.
+ if (wasVisible && mService.updateOrientationFromAppTokensLocked(false)) {
+ mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+ }
+ mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
+ Binder.restoreCallingIdentity(origId);
+ }
+
+ private void setupWindowForRemoveOnExit() {
+ mRemoveOnExit = true;
+ setDisplayLayoutNeeded();
+ // Request a focus update as this window's input channel is already gone. Otherwise
+ // we could have no focused window in input manager.
+ final boolean focusChanged = mService.updateFocusedWindowLocked(
+ UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
+ mService.mWindowPlacerLocked.performSurfacePlacement();
+ if (focusChanged) {
+ mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+ }
+ }
+
void setHasSurface(boolean hasSurface) {
mHasSurface = hasSurface;
}
@@ -1637,27 +1792,17 @@
return getStack();
}
- void maybeRemoveReplacedWindow() {
- if (mAppToken == null) {
- return;
+ void removeReplacedWindow() {
+ if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this);
+ if (isDimming()) {
+ transferDimToReplacement();
}
- for (int i = mAppToken.allAppWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mAppToken.allAppWindows.get(i);
- if (win.mWillReplaceWindow && win.mReplacingWindow == this && hasDrawnLw()) {
- if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + win);
- if (win.isDimming()) {
- win.transferDimToReplacement();
- }
- win.mWillReplaceWindow = false;
- final boolean animateReplacingWindow = win.mAnimateReplacingWindow;
- win.mAnimateReplacingWindow = false;
- win.mReplacingRemoveRequested = false;
- win.mReplacingWindow = null;
- mSkipEnterAnimationForSeamlessReplacement = false;
- if (win.mAnimatingExit || !animateReplacingWindow) {
- win.remove();
- }
- }
+ mWillReplaceWindow = false;
+ mAnimateReplacingWindow = false;
+ mReplacingRemoveRequested = false;
+ mReplacingWindow = null;
+ if (mAnimatingExit || !mAnimateReplacingWindow) {
+ remove();
}
}
@@ -1797,10 +1942,10 @@
public void binderDied() {
try {
synchronized(mService.mWindowMap) {
- WindowState win = mService.windowForClientLocked(mSession, mClient, false);
+ final WindowState win = mService.windowForClientLocked(mSession, mClient, false);
Slog.i(TAG, "WIN DEATH: " + win);
if (win != null) {
- mService.removeWindowLocked(win, shouldKeepVisibleDeadAppWindow());
+ win.removeIfPossible(shouldKeepVisibleDeadAppWindow());
if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
// The owner of the docked divider died :( We reset the docked stack,
// just in case they have the divider at an unstable position. Better
@@ -3178,7 +3323,7 @@
return;
}
- if (WindowManagerService.localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG,
+ if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG,
"Exit animation finished in " + this + ": remove=" + mRemoveOnExit);
mDestroying = true;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 677b4af..25709c5 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -453,7 +453,7 @@
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())) {
+ (!token.mIsExiting || token.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
@@ -1248,10 +1248,8 @@
appAnimator.clearThumbnail();
appAnimator.setNullAnimation();
}
- wtoken.inPendingTransaction = false;
- if (!mService.setTokenVisibilityLocked(
- wtoken, animLp, true, transit, false, voiceInteraction)){
+ if (!wtoken.setVisibility(animLp, true, transit, false, voiceInteraction)){
// This token isn't going to be animating. Add it to the list of tokens to
// be notified of app transition complete since the notification will not be
// sent be the app window animator.
@@ -1259,12 +1257,8 @@
}
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
+ wtoken.setAllAppWinAnimators();
- appAnimator.mAllAppWinAnimators.clear();
- final int windowsCount = wtoken.allAppWindows.size();
- for (int j = 0; j < windowsCount; j++) {
- appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
- }
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
">>> OPEN TRANSACTION handleAppTransitionReadyLocked()");
SurfaceControl.openTransaction();
@@ -1279,13 +1273,7 @@
int topOpeningLayer = 0;
if (animLp != null) {
- int layer = -1;
- for (int j = 0; j < wtoken.allAppWindows.size(); j++) {
- final WindowState win = wtoken.allAppWindows.get(j);
- if (win.mWinAnimator.mAnimLayer > layer) {
- layer = win.mWinAnimator.mAnimLayer;
- }
- }
+ final int layer = wtoken.getHighestAnimLayer();
if (topOpeningApp == null || layer > topOpeningLayer) {
topOpeningApp = wtoken;
topOpeningLayer = layer;
@@ -1316,9 +1304,7 @@
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
appAnimator.clearThumbnail();
appAnimator.setNullAnimation();
- wtoken.inPendingTransaction = false;
- mService.setTokenVisibilityLocked(wtoken, animLp, false, transit, false,
- voiceInteraction);
+ wtoken.setVisibility(animLp, false, transit, false, voiceInteraction);
wtoken.updateReportedVisibilityLocked();
// Force the allDrawn flag, because we want to start
// this guy's animations regardless of whether it's
@@ -1604,12 +1590,7 @@
appAnimator.setNullAnimation();
mService.updateTokenInPlaceLocked(wtoken, transit);
wtoken.updateReportedVisibilityLocked();
-
- appAnimator.mAllAppWinAnimators.clear();
- final int N = wtoken.allAppWindows.size();
- for (int j = 0; j < N; j++) {
- appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
- }
+ wtoken.setAllAppWinAnimators();
mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
mService.mAnimator.orAnimating(appAnimator.showAllWindowsLocked());
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 53ea981..c421cea 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -148,13 +148,19 @@
}
}
- void adjustAnimLayer(int adj) {
+ int adjustAnimLayer(int adj) {
+ int highestAnimLayer = -1;
for (int j = windows.size() - 1; j >= 0; j--) {
final WindowState w = windows.get(j);
w.adjustAnimLayer(adj);
- if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "adjustAnimLayer win "
- + w + " anim layer: " + w.mWinAnimator.mAnimLayer);
+ final int animLayer = w.mWinAnimator.mAnimLayer;
+ if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
+ "adjustAnimLayer win " + w + " anim layer: " + animLayer);
+ if (animLayer > highestAnimLayer) {
+ highestAnimLayer = animLayer;
+ }
}
+ return highestAnimLayer;
}
private WindowState getTopWindow() {
@@ -274,7 +280,7 @@
}
final AppWindowToken appToken = win.mAppToken;
- if (appToken != null && !appToken.allAppWindows.contains(win)) {
+ if (appToken != null) {
appToken.addWindow(win);
}
}