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

Commit 3cdcc400 authored by chaviw's avatar chaviw Committed by android-build-team Robot
Browse files

Fixed a few issues with starting windows

1. startingData was accessed on a different thread without a lock held.
This caused synchronization issues where startingData could be set to
null while the starting window was getting created.

2. In onFirstWindowDrawn, startingData was not being set to null if the
startingWindow didn't exist. That means if the startingWindow hadn't
been created yet, it would get created after the first window was drawn.

Fixes: 129654434
Test: Steps from bug no longer reproducible
Change-Id: Ic5086798082b9f312cbd5069a937eac95cff7a9c
(cherry picked from commit a8f07a7f)
parent 09917874
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -478,7 +478,7 @@ public class AppTransitionController {
                    outReasons.put(windowingMode,  APP_TRANSITION_WINDOWS_DRAWN);
                } else {
                    outReasons.put(windowingMode,
                            wtoken.startingData instanceof SplashScreenStartingData
                            wtoken.mStartingData instanceof SplashScreenStartingData
                                    ? APP_TRANSITION_SPLASH_SCREEN
                                    : APP_TRANSITION_SNAPSHOT);
                }
+34 −30
Original line number Diff line number Diff line
@@ -204,7 +204,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
    boolean removed;

    // Information about an application starting window if displayed.
    StartingData startingData;
    StartingData mStartingData;
    WindowState startingWindow;
    StartingSurface startingSurface;
    boolean startingDisplayed;
@@ -386,8 +386,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
            // it from behind the starting window, so there is no need for it to also be doing its
            // own stuff.
            win.cancelAnimation();
            removeStartingWindow();
        }
        removeStartingWindow();
        updateReportedVisibilityLocked();
    }

@@ -875,7 +875,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
        if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
                + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));

        if (startingData != null) {
        if (mStartingData != null) {
            removeStartingWindow();
        }

@@ -1054,7 +1054,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
            // 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 startingData");
            startingData = null;
            mStartingData = null;
            if (mHiddenSetFromTransferredStartingWindow) {
                // We set the hidden state to false for the token from a transferred starting window.
                // We now reset it back to true since the starting window was the last window in the
@@ -1487,13 +1487,13 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
            final long origId = Binder.clearCallingIdentity();
            try {
                // Transfer the starting window over to the new token.
                startingData = fromToken.startingData;
                mStartingData = fromToken.mStartingData;
                startingSurface = fromToken.startingSurface;
                startingDisplayed = fromToken.startingDisplayed;
                fromToken.startingDisplayed = false;
                startingWindow = tStartingWindow;
                reportedVisible = fromToken.reportedVisible;
                fromToken.startingData = null;
                fromToken.mStartingData = null;
                fromToken.startingSurface = null;
                fromToken.startingWindow = null;
                fromToken.startingMoved = true;
@@ -1539,13 +1539,13 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
                Binder.restoreCallingIdentity(origId);
            }
            return true;
        } else if (fromToken.startingData != null) {
        } else if (fromToken.mStartingData != 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;
            mStartingData = fromToken.mStartingData;
            fromToken.mStartingData = null;
            fromToken.startingMoved = true;
            scheduleAddStartingWindow();
            return true;
@@ -2043,7 +2043,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
            return false;
        }

        if (startingData != null) {
        if (mStartingData != null) {
            return false;
        }

@@ -2124,7 +2124,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
        }

        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
        startingData = new SplashScreenStartingData(mWmService, pkg,
        mStartingData = new SplashScreenStartingData(mWmService, pkg,
                theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
                getMergedOverrideConfiguration());
        scheduleAddStartingWindow();
@@ -2138,7 +2138,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
        }

        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
        startingData = new SnapshotStartingData(mWmService, snapshot);
        mStartingData = new SnapshotStartingData(mWmService, snapshot);
        scheduleAddStartingWindow();
        return true;
    }
@@ -2157,12 +2157,13 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree

        @Override
        public void run() {
            // Can be accessed without holding the global lock
            final StartingData startingData;
            synchronized (mWmService.mGlobalLock) {
                // There can only be one adding request, silly caller!
                mWmService.mAnimationHandler.removeCallbacks(this);
            }

            if (startingData == null) {
                if (mStartingData == null) {
                    // Animation has been canceled... do nothing.
                    if (DEBUG_STARTING_WINDOW) {
                        Slog.v(TAG, "startingData was nulled out before handling"
@@ -2170,6 +2171,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
                    }
                    return;
                }
                startingData = mStartingData;
            }

            if (DEBUG_STARTING_WINDOW) {
                Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
@@ -2186,19 +2189,20 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
                synchronized (mWmService.mGlobalLock) {
                    // If the window was successfully added, then
                    // we need to remove it.
                    if (removed || startingData == null) {
                    if (removed || mStartingData == null) {
                        if (DEBUG_STARTING_WINDOW) {
                            Slog.v(TAG, "Aborted starting " + AppWindowToken.this
                                    + ": removed=" + removed + " startingData=" + startingData);
                                    + ": removed=" + removed + " startingData=" + mStartingData);
                        }
                        startingWindow = null;
                        startingData = null;
                        mStartingData = null;
                        abort = true;
                    } else {
                        startingSurface = surface;
                    }
                    if (DEBUG_STARTING_WINDOW && !abort) {
                        Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
                        Slog.v(TAG,
                                "Added starting " + AppWindowToken.this + ": startingWindow="
                                        + startingWindow + " startingView=" + startingSurface);
                    }
                }
@@ -2246,21 +2250,21 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree

    void removeStartingWindow() {
        if (startingWindow == null) {
            if (startingData != null) {
            if (mStartingData != null) {
                // Starting window has not been added yet, but it is scheduled to be added.
                // Go ahead and cancel the request.
                if (DEBUG_STARTING_WINDOW) {
                    Slog.v(TAG_WM, "Clearing startingData for token=" + this);
                }
                startingData = null;
                mStartingData = null;
            }
            return;
        }

        final WindowManagerPolicy.StartingSurface surface;
        if (startingData != null) {
        if (mStartingData != null) {
            surface = startingSurface;
            startingData = null;
            mStartingData = null;
            startingSurface = null;
            startingWindow = null;
            startingDisplayed = false;
@@ -2995,8 +2999,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
            pw.print(prefix); pw.print("inPendingTransaction=");
                    pw.println(inPendingTransaction);
        }
        if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
            pw.print(prefix); pw.print("startingData="); pw.print(startingData);
        if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
            pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
                    pw.print(" removed="); pw.print(removed);
                    pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
                    pw.print(" mIsExiting="); pw.println(mIsExiting);
+2 −2
Original line number Diff line number Diff line
@@ -504,14 +504,14 @@ public class AppWindowTokenTests extends WindowTestsBase {

    private void assertHasStartingWindow(AppWindowToken atoken) {
        assertNotNull(atoken.startingSurface);
        assertNotNull(atoken.startingData);
        assertNotNull(atoken.mStartingData);
        assertNotNull(atoken.startingWindow);
    }

    private void assertNoStartingWindow(AppWindowToken atoken) {
        assertNull(atoken.startingSurface);
        assertNull(atoken.startingWindow);
        assertNull(atoken.startingData);
        assertNull(atoken.mStartingData);
        atoken.forAllWindows(windowState -> {
            assertFalse(windowState.getBaseType() == TYPE_APPLICATION_STARTING);
        }, true);