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

Commit 77bdfb51 authored by Robert Carr's avatar Robert Carr
Browse files

Prepare to replace windows across recreate().

When the activity locally recreates itself, nothing
on the server side is able to prepare preserving windows,
or replacing windows. The activity was trying to defer
removing the old window, but it was just waiting
until the new one was created, not until it was drawn,
thus resulting in a flicker. It's easy to backpack on the
existing replacement infrastructure.

Bug: 28221875
Change-Id: I55fc4ca78e9e11809473fedd8b30b6a6350cf852
parent 63019662
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -4208,7 +4208,7 @@ public final class ActivityThread {
                }
                IBinder wtoken = v.getWindowToken();
                if (r.activity.mWindowAdded) {
                    if (r.onlyLocalRequest || r.mPreserveWindow) {
                    if (r.mPreserveWindow) {
                        // Hold off on removing this until the new activity's
                        // window is being added.
                        r.mPendingRemoveWindow = r.window;
@@ -4443,15 +4443,20 @@ public final class ActivityThread {
        // be replaced and defer requests to destroy or hide them. This way we can achieve
        // visual continuity. It's important that we do this here prior to pause and destroy
        // as that is when we may hide or remove the child views.
        //
        // There is another scenario, if we have decided locally to relaunch the app from a
        // call to recreate, then none of the windows will be prepared for replacement or
        // preserved by the server, so we want to notify it that we are preparing to replace
        // everything
        try {
            if (r.mPreserveWindow) {
                WindowManagerGlobal.getWindowSession().prepareToReplaceChildren(r.token);
            if (r.mPreserveWindow || r.onlyLocalRequest) {
                WindowManagerGlobal.getWindowSession().prepareToReplaceWindows(
                        r.token, !r.onlyLocalRequest);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }


        // Need to ensure state is saved.
        if (!r.paused) {
            performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity");
+4 −2
Original line number Diff line number Diff line
@@ -125,11 +125,13 @@ interface IWindowSession {

    /*
     * Notify the window manager that an application is relaunching and
     * child windows should be prepared for replacement.
     * windows should be prepared for replacement.
     *
     * @param appToken The application
     * @param childrenOnly Whether to only prepare child windows for replacement
     * (for example when main windows are being reused via preservation).
     */
    void prepareToReplaceChildren(IBinder appToken);
    void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly);

    /**
     * If a call to relayout() asked to have the surface destroy deferred,
+2 −2
Original line number Diff line number Diff line
@@ -201,8 +201,8 @@ final class Session extends IWindowSession.Stub
    }

    @Override
    public void prepareToReplaceChildren(IBinder appToken) {
        mService.setReplacingChildren(appToken);
    public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
        mService.setReplacingWindows(appToken, childrenOnly);
    }

    public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
+13 −4
Original line number Diff line number Diff line
@@ -10677,12 +10677,16 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    /**
     * Hint to a token that its children will be replaced across activity relaunch.
     * The children would otherwise be removed  shortly following this as the
     * Hint to a token that its windows will be replaced across activity relaunch.
     * The windows would otherwise be removed  shortly following this as the
     * activity is torn down.
     * @param token Application token for which the activity will be relaunched.
     * @param childrenOnly Whether to mark only child windows for replacement
     *                     (for the case where main windows are being preserved/
     *                     reused rather than replaced).
     *
     */
    public void setReplacingChildren(IBinder token) {
    public void setReplacingWindows(IBinder token, boolean childrenOnly) {
        AppWindowToken appWindowToken = null;
        synchronized (mWindowMap) {
            appWindowToken = findAppWindowToken(token);
@@ -10692,7 +10696,12 @@ public class WindowManagerService extends IWindowManager.Stub
                return;
            }

            if (childrenOnly) {
                appWindowToken.setReplacingChildren();
            } else {
                appWindowToken.setReplacingWindows(false /* animate */);
            }

            scheduleClearReplacingWindowIfNeeded(token, true /* replacing */);
        }
    }
+1 −1
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ public final class BridgeWindowSession implements IWindowSession {
    }

    @Override
    public void prepareToReplaceChildren(IBinder appToken) {
    public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
        // pass for now.
    }