From 9f25beee3a8cd6f452534006ea9068178cbb4ce1 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Tue, 2 Aug 2016 07:23:47 -0700 Subject: [PATCH] Made AppWindowToken.allAppWindows private Pre-clean-up before switching class to using WindowContainer. Bug: 30060889 Change-Id: Ic3d47d47b922668eeb70988ce883267b46ca9d72 --- .../android/server/wm/AppWindowAnimator.java | 26 +- .../com/android/server/wm/AppWindowToken.java | 540 +++++++++++++++++- .../core/java/com/android/server/wm/Task.java | 103 ++-- .../java/com/android/server/wm/TaskStack.java | 55 +- .../com/android/server/wm/WindowAnimator.java | 30 +- .../server/wm/WindowManagerService.java | 529 +---------------- .../com/android/server/wm/WindowState.java | 197 ++++++- .../server/wm/WindowSurfacePlacer.java | 31 +- .../com/android/server/wm/WindowToken.java | 14 +- 9 files changed, 809 insertions(+), 716 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 39a549dbd03e8..950fb20bc4616 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 @@ public class AppWindowAnimator { } // 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 @@ public class AppWindowAnimator { } 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 01be4c8f46420..bbd6fd74351c3 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.annotation.NonNull; 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 @@ class AppWindowToken extends WindowToken { // 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 @@ class AppWindowToken extends WindowToken { } } + 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 @@ class AppWindowToken extends WindowToken { 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 @@ class AppWindowToken extends WindowToken { 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 @@ class AppWindowToken extends WindowToken { } 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 @@ class AppWindowToken extends WindowToken { } } + 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 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 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 7394309c812d3..048d980bd9da0 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.util.Slog; 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 @@ class Task implements DimLayer.DimLayerUser { resizeLocked(bounds, config, false /* force */); for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) { - final ArrayList 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 @@ class Task implements DimLayer.DimLayerUser { void resetDragResizingChangeReported() { for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) { - final ArrayList 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 @@ class Task implements DimLayer.DimLayerUser { * 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 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 @@ class Task implements DimLayer.DimLayerUser { } void resizeWindows() { - final ArrayList 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 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 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 @@ class Task implements DimLayer.DimLayerUser { 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 @@ class Task implements DimLayer.DimLayerUser { 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 b1378409861b0..d2ec792610988 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 @@ public class TaskStack implements DimLayer.DimLayerUser, boolean isAnimating() { for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { - final ArrayList activities = mTasks.get(taskNdx).mAppTokens; - for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { - final ArrayList 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 @@ public class TaskStack implements DimLayer.DimLayerUser, } 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 @@ public class TaskStack implements DimLayer.DimLayerUser, 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 @@ public class TaskStack implements DimLayer.DimLayerUser, 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 @@ public class TaskStack implements DimLayer.DimLayerUser, return true; } - void forceWindowsScaleable(Task task, boolean force) { - SurfaceControl.openTransaction(); - try { - final ArrayList activities = task.mAppTokens; - for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { - final ArrayList 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 a7a7a396adac2..6e7313cb1f416 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 @@ public class WindowAnimator { // 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 @@ public class WindowAnimator { } 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 @@ public class WindowAnimator { } } - 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 aceff332737ed..6b46ddde301b3 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.WindowManager.LayoutParams.TYPE_WALLPAPER; 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } } - 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 @@ public class WindowManagerService extends IWindowManager.Stub } 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } } - 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } } - if (transferStartingWindow(transferFrom, wtoken)) { + if (wtoken != null && wtoken.transferStartingWindow(transferFrom)) { return true; } @@ -3700,108 +3532,6 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } } - 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 @@ public class WindowManagerService extends IWindowManager.Stub } 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