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

Commit 2fe6f173 authored by Wei Sheng Shih's avatar Wei Sheng Shih Committed by Android (Google) Code Review
Browse files

Merge "Ensure register/unregister OnBackInvokedCallback thread safed." into main

parents d1514239 713eaa58
Loading
Loading
Loading
Loading
+124 −97
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ import android.view.ImeBackAnimationController;
import androidx.annotation.VisibleForTesting;


import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -75,14 +77,17 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
    @Nullable
    private ImeBackAnimationController mImeBackAnimationController;

    @GuardedBy("mLock")
    /** Convenience hashmap to quickly decide if a callback has been added. */
    private final HashMap<OnBackInvokedCallback, Integer> mAllCallbacks = new HashMap<>();
    /** Holds all callbacks by priorities. */

    @VisibleForTesting
    @GuardedBy("mLock")
    public final TreeMap<Integer, ArrayList<OnBackInvokedCallback>>
            mOnBackInvokedCallbacks = new TreeMap<>();
    private Checker mChecker;
    private final Object mLock = new Object();

    public WindowOnBackInvokedDispatcher(@NonNull Context context) {
        mChecker = new Checker(context);
@@ -94,6 +99,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
     */
    public void attachToWindow(@NonNull IWindowSession windowSession, @NonNull IWindow window,
            @Nullable ImeBackAnimationController imeBackAnimationController) {
        synchronized (mLock) {
            mWindowSession = windowSession;
            mWindow = window;
            mImeBackAnimationController = imeBackAnimationController;
@@ -101,14 +107,17 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                setTopOnBackInvokedCallback(getTopCallback());
            }
        }
    }

    /** Detaches the dispatcher instance from its window. */
    public void detachFromWindow() {
        synchronized (mLock) {
            clear();
            mWindow = null;
            mWindowSession = null;
            mImeBackAnimationController = null;
        }
    }

    // TODO: Take an Executor for the callback to run on.
    @Override
@@ -125,6 +134,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
     */
    public void registerOnBackInvokedCallbackUnchecked(
            @NonNull OnBackInvokedCallback callback, @Priority int priority) {
        synchronized (mLock) {
            if (mImeDispatcher != null) {
                mImeDispatcher.registerOnBackInvokedCallback(priority, callback);
                return;
@@ -155,9 +165,11 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                setTopOnBackInvokedCallback(callback);
            }
        }
    }

    @Override
    public void unregisterOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) {
        synchronized (mLock) {
            if (mImeDispatcher != null) {
                mImeDispatcher.unregisterOnBackInvokedCallback(callback);
                return;
@@ -179,28 +191,37 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                mOnBackInvokedCallbacks.remove(priority);
            }
            mAllCallbacks.remove(callback);
        // Re-populate the top callback to WM if the removed callback was previously the top one.
            // Re-populate the top callback to WM if the removed callback was previously the top
            // one.
            if (previousTopCallback == callback) {
            // We should call onBackCancelled() when an active callback is removed from dispatcher.
                // We should call onBackCancelled() when an active callback is removed from
                // dispatcher.
                sendCancelledIfInProgress(callback);
                setTopOnBackInvokedCallback(getTopCallback());
            }
        }
    }

    /**
     * Indicates if the dispatcher is actively dispatching to a callback.
     */
    public boolean isDispatching() {
        synchronized (mLock) {
            return mIsDispatching;
        }
    }

    private void onStartDispatching() {
        synchronized (mLock) {
            mIsDispatching = true;
        }
    }

    private void onStopDispatching() {
        synchronized (mLock) {
            mIsDispatching = false;
        }
    }

    private void sendCancelledIfInProgress(@NonNull OnBackInvokedCallback callback) {
        boolean isInProgress = mProgressAnimator.isBackAnimationInProgress();
@@ -223,6 +244,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {

    /** Clears all registered callbacks on the instance. */
    public void clear() {
        synchronized (mLock) {
            if (mImeDispatcher != null) {
                mImeDispatcher.clear();
                mImeDispatcher = null;
@@ -245,6 +267,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
            mAllCallbacks.clear();
            mOnBackInvokedCallbacks.clear();
        }
    }

    private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) {
        if (mWindowSession == null || mWindow == null) {
@@ -275,6 +298,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
    }

    public OnBackInvokedCallback getTopCallback() {
        synchronized (mLock) {
            if (mAllCallbacks.isEmpty()) {
                return null;
            }
@@ -284,6 +308,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                    return callbacks.get(callbacks.size() - 1);
                }
            }
        }
        return null;
    }

@@ -315,6 +340,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
    public void dump(String prefix, PrintWriter writer) {
        String innerPrefix = prefix + "    ";
        writer.println(prefix + "WindowOnBackDispatcher:");
        synchronized (mLock) {
            if (mAllCallbacks.isEmpty()) {
                writer.println(prefix + "<None>");
                return;
@@ -326,6 +352,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                writer.println(innerPrefix + "  Callback: " + callback + " Priority=" + priority);
            });
        }
    }

    static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
        static class CallbackRef {