Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1eb439e authored by Robert Carr's avatar Robert Carr
Browse files

Move window replacement tracking to window state.

In preparation for supporting replacement of child windows
we make replacement per window rather than per app.

Bug: 26070641

Change-Id: Ifa332086599c125611e430219c9497bae7e2ce31
parent 712a1c0a
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -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.
+4 −0
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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()));


+57 −15
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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(),
@@ -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);
+1 −1
Original line number Original line Diff line number Diff line
@@ -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.
+0 −4
Original line number Original line Diff line number Diff line
@@ -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