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

Commit 81c4b76c authored by Arthur Hung's avatar Arthur Hung
Browse files

Prevent back navigation not working after activity re-created

When recreating the Activity, if the window is preserved, we would set
the actual dispatcher from the preserved window to the new Activiy's
proxy dispatcher, and expect the new callback could be re-registered
in the recreating flow.

This CL clears the old callbacks of the preserved dispatcher before it
attach to the new proxy dispatcher, this could prevent it access the
wrong top callback after other new callbacks have been unregistered.

Also provide dump log for WindowOnBackInvokedDispatcher.

Bug: 259500250
Test: atest BackNavigationTests
Change-Id: Idc9a6a95f5669a009762570d7bc9acc2c538e4cb
parent cfeab53f
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -8692,6 +8692,8 @@ public final class ViewRootImpl implements ViewParent,


        mInsetsController.dump(prefix, writer);
        mInsetsController.dump(prefix, writer);


        mOnBackInvokedDispatcher.dump(prefix, writer);

        writer.println(prefix + "View Hierarchy:");
        writer.println(prefix + "View Hierarchy:");
        dumpViewHierarchy(innerPrefix, writer, mView);
        dumpViewHierarchy(innerPrefix, writer, mView);
    }
    }
+6 −0
Original line number Original line Diff line number Diff line
@@ -211,6 +211,12 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
        IOnBackInvokedCallback getIOnBackInvokedCallback() {
        IOnBackInvokedCallback getIOnBackInvokedCallback() {
            return mIOnBackInvokedCallback;
            return mIOnBackInvokedCallback;
        }
        }

        @Override
        public String toString() {
            return "ImeCallback=ImeOnBackInvokedCallback@" + mId
                    + " Callback=" + mIOnBackInvokedCallback;
        }
    }
    }


    /**
    /**
+1 −10
Original line number Original line Diff line number Diff line
@@ -180,16 +180,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                return;
                return;
            }
            }
            clearCallbacksOnDispatcher();
            clearCallbacksOnDispatcher();
            if (actualDispatcher instanceof ProxyOnBackInvokedDispatcher) {
                // We don't want to nest ProxyDispatchers, so if we are given on, we unwrap its
                // actual dispatcher.
                // This can happen when an Activity is recreated but the Window is preserved (e.g.
                // when going from split-screen back to single screen)
                mActualDispatcher =
                        ((ProxyOnBackInvokedDispatcher) actualDispatcher).mActualDispatcher;
            } else {
            mActualDispatcher = actualDispatcher;
            mActualDispatcher = actualDispatcher;
            }
            transferCallbacksToDispatcher();
            transferCallbacksToDispatcher();
        }
        }
    }
    }
+21 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import android.util.Log;
import android.view.IWindow;
import android.view.IWindow;
import android.view.IWindowSession;
import android.view.IWindowSession;


import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
@@ -232,6 +233,26 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
        return Checker.isOnBackInvokedCallbackEnabled(mChecker.getContext());
        return Checker.isOnBackInvokedCallbackEnabled(mChecker.getContext());
    }
    }


    /**
     * Dump information about this WindowOnBackInvokedDispatcher
     * @param prefix the prefix that will be prepended to each line of the produced output
     * @param writer the writer that will receive the resulting text
     */
    public void dump(String prefix, PrintWriter writer) {
        String innerPrefix = prefix + "    ";
        writer.println(prefix + "WindowOnBackDispatcher:");
        if (mAllCallbacks.isEmpty()) {
            writer.println(prefix + "<None>");
            return;
        }

        writer.println(innerPrefix + "Top Callback: " + getTopCallback());
        writer.println(innerPrefix + "Callbacks: ");
        mAllCallbacks.forEach((callback, priority) -> {
            writer.println(innerPrefix + "  Callback: " + callback + " Priority=" + priority);
        });
    }

    static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
    static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
        private final WeakReference<OnBackInvokedCallback> mCallback;
        private final WeakReference<OnBackInvokedCallback> mCallback;


+6 −2
Original line number Original line Diff line number Diff line
@@ -378,8 +378,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
            // window, as we'll be skipping the addView in handleResumeActivity(), and
            // window, as we'll be skipping the addView in handleResumeActivity(), and
            // the token will not be updated as for a new window.
            // the token will not be updated as for a new window.
            getAttributes().token = preservedWindow.getAttributes().token;
            getAttributes().token = preservedWindow.getAttributes().token;
            mProxyOnBackInvokedDispatcher.setActualDispatcher(
            final ViewRootImpl viewRoot = mDecor.getViewRootImpl();
                    preservedWindow.getOnBackInvokedDispatcher());
            if (viewRoot != null) {
                // Clear the old callbacks and attach to the new window.
                viewRoot.getOnBackInvokedDispatcher().clear();
                onViewRootImplSet(viewRoot);
            }
        }
        }
        // Even though the device doesn't support picture-in-picture mode,
        // Even though the device doesn't support picture-in-picture mode,
        // an user can force using it through developer options.
        // an user can force using it through developer options.