Made AppWindowToken.allAppWindows private

Pre-clean-up before switching class to using WindowContainer.

Bug: 30060889
Change-Id: Ic3d47d47b922668eeb70988ce883267b46ca9d72
This commit is contained in:
Wale Ogunwale
2016-08-02 07:23:47 -07:00
parent 89142e9cc9
commit 9f25beee3a
9 changed files with 809 additions and 716 deletions

View File

@@ -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) {

View File

@@ -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<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);

View File

@@ -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<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 @@ class Task implements DimLayer.DimLayerUser {
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 @@ 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<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 @@ class Task implements DimLayer.DimLayerUser {
}
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 @@ 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 + "}";

View File

@@ -477,15 +477,9 @@ public class TaskStack implements DimLayer.DimLayerUser,
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 @@ 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<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) {

View File

@@ -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) {

View File

@@ -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<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 @@ public class WindowManagerService extends IWindowManager.Stub
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 @@ public class WindowManagerService extends IWindowManager.Stub
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 @@ public class WindowManagerService extends IWindowManager.Stub
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 @@ public class WindowManagerService extends IWindowManager.Stub
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 @@ public class WindowManagerService extends IWindowManager.Stub
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 @@ public class WindowManagerService extends IWindowManager.Stub
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 @@ public class WindowManagerService extends IWindowManager.Stub
return null;
}
private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
if (mDisplayFrozen) {
return;
}

View File

@@ -25,6 +25,7 @@ import android.graphics.PixelFormat;
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;
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_WALLPAPER_LIG
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 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS
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 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS
}
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 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS
}
}
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 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS
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 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS
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 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS
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 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS
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;

View File

@@ -453,7 +453,7 @@ class WindowSurfacePlacer {
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 @@ class WindowSurfacePlacer {
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 @@ class WindowSurfacePlacer {
}
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 @@ class WindowSurfacePlacer {
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 @@ class WindowSurfacePlacer {
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 @@ class WindowSurfacePlacer {
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());
}

View File

@@ -148,13 +148,19 @@ class WindowToken {
}
}
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 @@ class WindowToken {
}
final AppWindowToken appToken = win.mAppToken;
if (appToken != null && !appToken.allAppWindows.contains(win)) {
if (appToken != null) {
appToken.addWindow(win);
}
}