Loading core/java/android/view/WindowManager.java +10 −0 Original line number Original line Diff line number Diff line Loading @@ -1171,6 +1171,16 @@ public interface WindowManager extends ViewManager { */ */ public static final int PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY = 0x00004000; public static final int PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY = 0x00004000; /** * Flag to indicate that this window is not expected to be replaced across * configuration change triggered activity relaunches. In general the WindowManager * expects Windows to be replaced after relaunch, and thus it will preserve their surfaces * until the replacement is ready to show in order to prevent visual glitch. However * some windows, such as PopupWindows expect to be cleared across configuration change, * and thus should hint to the WindowManager that it should not wait for a replacement. * @hide */ public static final int PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH = 0x00008000; /** /** * Control flags that are private to the platform. * Control flags that are private to the platform. Loading core/java/android/widget/PopupWindow.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.widget; package android.widget; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; import com.android.internal.R; import com.android.internal.R; import android.annotation.NonNull; import android.annotation.NonNull; Loading Loading @@ -1311,6 +1313,8 @@ public class PopupWindow { p.width = mLastWidth = mWidth; p.width = mLastWidth = mWidth; } } p.privateFlags = PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; // Used for debugging. // Used for debugging. p.setTitle("PopupWindow:" + Integer.toHexString(hashCode())); p.setTitle("PopupWindow:" + Integer.toHexString(hashCode())); Loading services/core/java/com/android/server/wm/AppWindowToken.java +57 −15 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 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_APP_TRANSITIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 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.DEBUG_WINDOW_MOVEMENT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; Loading Loading @@ -122,21 +123,6 @@ class AppWindowToken extends WindowToken { // True if the windows associated with this token should be cropped to their stack bounds. // True if the windows associated with this token should be cropped to their stack bounds. boolean mCropWindowsToStack; boolean mCropWindowsToStack; // This application will have its window replaced due to relaunch. This allows window manager // to differentiate between simple removal of a window and replacement. In the latter case it // will preserve the old window until the new one is drawn. boolean mWillReplaceWindow; // If true, the replaced window was already requested to be removed. boolean mReplacingRemoveRequested; // Whether the replacement of the window should trigger app transition animation. boolean mAnimateReplacingWindow; // If not null, the window that will be used to replace the old one. This is being set when // the window is added and unset when this window reports its first draw. WindowState mReplacingWindow; // Whether the new window has replaced the old one, so the old one can be removed without // blinking. boolean mHasReplacedWindow; AppWindowToken(WindowManagerService _service, IApplicationToken _token, AppWindowToken(WindowManagerService _service, IApplicationToken _token, boolean _voiceInteraction) { boolean _voiceInteraction) { super(_service, _token.asBinder(), super(_service, _token.asBinder(), Loading Loading @@ -392,6 +378,62 @@ class AppWindowToken extends WindowToken { } } } } void setReplacingWindows(boolean animate) { if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken + " with replacing windows."); for (int i = allAppWindows.size() - 1; i >= 0; i--) { final WindowState w = allAppWindows.get(i); w.setReplacing(animate); } if (animate) { // Set-up dummy animation so we can start treating windows associated with this // token like they are in transition before the new app window is ready for us to // run the real transition animation. if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setReplacingWindow() Setting dummy animation on: " + this); mAppAnimator.setDummyAnimation(); } } void addWindow(WindowState w) { for (int i = allAppWindows.size() - 1; i >= 0; i--) { WindowState candidate = allAppWindows.get(i); if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null && candidate.getWindowTag().equals(w.getWindowTag().toString())) { candidate.mReplacingWindow = w; } } allAppWindows.add(w); } boolean waitingForReplacement() { for (int i = allAppWindows.size() -1; i >= 0; i--) { WindowState candidate = allAppWindows.get(i); if (candidate.mWillReplaceWindow) { return true; } } return false; } void clearTimedoutReplaceesLocked() { for (int i = allAppWindows.size() - 1; i >= 0; // removeWindowLocked at bottom of loop may remove multiple entries from // allAppWindows if the window to be removed has child windows. It also may // not remove any windows from allAppWindows at all if win is exiting and // currently animating away. This ensures that winNdx is monotonically decreasing // and never beyond allAppWindows bounds. i = Math.min(i - 1, allAppWindows.size() - 1)) { WindowState candidate = allAppWindows.get(i); if (candidate.mWillReplaceWindow == false) { continue; } candidate.mWillReplaceWindow = false; service.removeWindowLocked(candidate); } } @Override @Override void dump(PrintWriter pw, String prefix) { void dump(PrintWriter pw, String prefix) { super.dump(pw, prefix); super.dump(pw, prefix); Loading services/core/java/com/android/server/wm/WallpaperController.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -506,7 +506,7 @@ class WallpaperController { inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID; inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID; } } replacing = replacing || (w.mAppToken != null && w.mAppToken.mWillReplaceWindow); replacing = replacing || w.mWillReplaceWindow; // If the app is executing an animation because the keyguard is going away, // If the app is executing an animation because the keyguard is going away, // keep the wallpaper during the animation so it doesn't flicker out. // keep the wallpaper during the animation so it doesn't flicker out. Loading services/core/java/com/android/server/wm/WindowAnimator.java +0 −4 Original line number Original line Diff line number Diff line Loading @@ -918,10 +918,6 @@ public class WindowAnimator { } } void requestRemovalOfReplacedWindows(WindowState win) { void requestRemovalOfReplacedWindows(WindowState win) { final AppWindowToken token = win.mAppToken; if (token != null && token.mWillReplaceWindow && token.mReplacingWindow == win) { token.mHasReplacedWindow = true; } mRemoveReplacedWindows = true; mRemoveReplacedWindows = true; } } Loading Loading
core/java/android/view/WindowManager.java +10 −0 Original line number Original line Diff line number Diff line Loading @@ -1171,6 +1171,16 @@ public interface WindowManager extends ViewManager { */ */ public static final int PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY = 0x00004000; public static final int PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY = 0x00004000; /** * Flag to indicate that this window is not expected to be replaced across * configuration change triggered activity relaunches. In general the WindowManager * expects Windows to be replaced after relaunch, and thus it will preserve their surfaces * until the replacement is ready to show in order to prevent visual glitch. However * some windows, such as PopupWindows expect to be cleared across configuration change, * and thus should hint to the WindowManager that it should not wait for a replacement. * @hide */ public static final int PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH = 0x00008000; /** /** * Control flags that are private to the platform. * Control flags that are private to the platform. Loading
core/java/android/widget/PopupWindow.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.widget; package android.widget; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; import com.android.internal.R; import com.android.internal.R; import android.annotation.NonNull; import android.annotation.NonNull; Loading Loading @@ -1311,6 +1313,8 @@ public class PopupWindow { p.width = mLastWidth = mWidth; p.width = mLastWidth = mWidth; } } p.privateFlags = PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; // Used for debugging. // Used for debugging. p.setTitle("PopupWindow:" + Integer.toHexString(hashCode())); p.setTitle("PopupWindow:" + Integer.toHexString(hashCode())); Loading
services/core/java/com/android/server/wm/AppWindowToken.java +57 −15 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 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_APP_TRANSITIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 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.DEBUG_WINDOW_MOVEMENT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; Loading Loading @@ -122,21 +123,6 @@ class AppWindowToken extends WindowToken { // True if the windows associated with this token should be cropped to their stack bounds. // True if the windows associated with this token should be cropped to their stack bounds. boolean mCropWindowsToStack; boolean mCropWindowsToStack; // This application will have its window replaced due to relaunch. This allows window manager // to differentiate between simple removal of a window and replacement. In the latter case it // will preserve the old window until the new one is drawn. boolean mWillReplaceWindow; // If true, the replaced window was already requested to be removed. boolean mReplacingRemoveRequested; // Whether the replacement of the window should trigger app transition animation. boolean mAnimateReplacingWindow; // If not null, the window that will be used to replace the old one. This is being set when // the window is added and unset when this window reports its first draw. WindowState mReplacingWindow; // Whether the new window has replaced the old one, so the old one can be removed without // blinking. boolean mHasReplacedWindow; AppWindowToken(WindowManagerService _service, IApplicationToken _token, AppWindowToken(WindowManagerService _service, IApplicationToken _token, boolean _voiceInteraction) { boolean _voiceInteraction) { super(_service, _token.asBinder(), super(_service, _token.asBinder(), Loading Loading @@ -392,6 +378,62 @@ class AppWindowToken extends WindowToken { } } } } void setReplacingWindows(boolean animate) { if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken + " with replacing windows."); for (int i = allAppWindows.size() - 1; i >= 0; i--) { final WindowState w = allAppWindows.get(i); w.setReplacing(animate); } if (animate) { // Set-up dummy animation so we can start treating windows associated with this // token like they are in transition before the new app window is ready for us to // run the real transition animation. if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setReplacingWindow() Setting dummy animation on: " + this); mAppAnimator.setDummyAnimation(); } } void addWindow(WindowState w) { for (int i = allAppWindows.size() - 1; i >= 0; i--) { WindowState candidate = allAppWindows.get(i); if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null && candidate.getWindowTag().equals(w.getWindowTag().toString())) { candidate.mReplacingWindow = w; } } allAppWindows.add(w); } boolean waitingForReplacement() { for (int i = allAppWindows.size() -1; i >= 0; i--) { WindowState candidate = allAppWindows.get(i); if (candidate.mWillReplaceWindow) { return true; } } return false; } void clearTimedoutReplaceesLocked() { for (int i = allAppWindows.size() - 1; i >= 0; // removeWindowLocked at bottom of loop may remove multiple entries from // allAppWindows if the window to be removed has child windows. It also may // not remove any windows from allAppWindows at all if win is exiting and // currently animating away. This ensures that winNdx is monotonically decreasing // and never beyond allAppWindows bounds. i = Math.min(i - 1, allAppWindows.size() - 1)) { WindowState candidate = allAppWindows.get(i); if (candidate.mWillReplaceWindow == false) { continue; } candidate.mWillReplaceWindow = false; service.removeWindowLocked(candidate); } } @Override @Override void dump(PrintWriter pw, String prefix) { void dump(PrintWriter pw, String prefix) { super.dump(pw, prefix); super.dump(pw, prefix); Loading
services/core/java/com/android/server/wm/WallpaperController.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -506,7 +506,7 @@ class WallpaperController { inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID; inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID; } } replacing = replacing || (w.mAppToken != null && w.mAppToken.mWillReplaceWindow); replacing = replacing || w.mWillReplaceWindow; // If the app is executing an animation because the keyguard is going away, // If the app is executing an animation because the keyguard is going away, // keep the wallpaper during the animation so it doesn't flicker out. // keep the wallpaper during the animation so it doesn't flicker out. Loading
services/core/java/com/android/server/wm/WindowAnimator.java +0 −4 Original line number Original line Diff line number Diff line Loading @@ -918,10 +918,6 @@ public class WindowAnimator { } } void requestRemovalOfReplacedWindows(WindowState win) { void requestRemovalOfReplacedWindows(WindowState win) { final AppWindowToken token = win.mAppToken; if (token != null && token.mWillReplaceWindow && token.mReplacingWindow == win) { token.mHasReplacedWindow = true; } mRemoveReplacedWindows = true; mRemoveReplacedWindows = true; } } Loading