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

Commit e3476afe authored by Arthur Hung's avatar Arthur Hung
Browse files

Cancel back invoke when window focus has lost

This reverts commit 0099ca8f and provide
new mechanism.

The back invoke target could lost focus during back navigation gesture.
To prevent the non-focused window could still trigger back action cause
some unexpected behavior, this CL will listen the focus change of
current focused window and cancel back gesture when its focus has lost.

Bug: 238050065
Bug: 239792909
Test: atest BackNavigationControllerTests
Test: atest BackNavigationLegacyGestureTest BackNavigationLegacyTest
Test: atest BackNavigationTests
Test: atest WindowOnBackInvokedDispatcherTest BackNavigationTest
Test: atset BackAnimationControllerTest

Change-Id: I65eb19371020ce39977eeb2a2a80c7f08600aaec
parent 8be2f810
Loading
Loading
Loading
Loading
+4 −1
Original line number Original line Diff line number Diff line
@@ -69,6 +69,7 @@ import android.os.WorkSource;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.IVoiceInteractionSession;
import android.view.IRecentsAnimationRunner;
import android.view.IRecentsAnimationRunner;
import android.view.IRemoteAnimationRunner;
import android.view.IRemoteAnimationRunner;
import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationAdapter;
import android.window.IWindowOrganizerController;
import android.window.IWindowOrganizerController;
@@ -352,6 +353,8 @@ interface IActivityTaskManager {
     * Prepare the back navigation in the server. This setups the leashed for sysui to animate
     * Prepare the back navigation in the server. This setups the leashed for sysui to animate
     * the back gesture and returns the data needed for the animation.
     * the back gesture and returns the data needed for the animation.
     * @param requestAnimation true if the caller wishes to animate the back navigation
     * @param requestAnimation true if the caller wishes to animate the back navigation
     * @param focusObserver a remote callback to nofify shell when the focused window lost focus.
     */
     */
    android.window.BackNavigationInfo startBackNavigation(in boolean requestAnimation);
    android.window.BackNavigationInfo startBackNavigation(in boolean requestAnimation,
            in IWindowFocusObserver focusObserver);
}
}
+0 −1
Original line number Original line Diff line number Diff line
@@ -3759,7 +3759,6 @@ public final class ViewRootImpl implements ViewParent,
            }
            }
        }
        }
        mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
        mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
        mOnBackInvokedDispatcher.onWindowFocusChanged(hasWindowFocus);


        // NOTE: there's no view visibility (appeared / disapparead) events when the windows focus
        // NOTE: there's no view visibility (appeared / disapparead) events when the windows focus
        // is lost, so we don't need to to force a flush - there might be other events such as
        // is lost, so we don't need to to force a flush - there might be other events such as
+1 −1
Original line number Original line Diff line number Diff line
@@ -118,7 +118,7 @@ public final class BackNavigationInfo implements Parcelable {
     *                                back preview.
     *                                back preview.
     * @param onBackInvokedCallback   The back callback registered by the current top level window.
     * @param onBackInvokedCallback   The back callback registered by the current top level window.
     */
     */
    public BackNavigationInfo(@BackTargetType int type,
    private BackNavigationInfo(@BackTargetType int type,
            @Nullable RemoteAnimationTarget departingAnimationTarget,
            @Nullable RemoteAnimationTarget departingAnimationTarget,
            @Nullable SurfaceControl screenshotSurface,
            @Nullable SurfaceControl screenshotSurface,
            @Nullable HardwareBuffer screenshotBuffer,
            @Nullable HardwareBuffer screenshotBuffer,
+1 −2
Original line number Original line Diff line number Diff line
@@ -83,8 +83,7 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
        final Bundle bundle = new Bundle();
        final Bundle bundle = new Bundle();
        // Always invoke back for ime without checking the window focus.
        // Always invoke back for ime without checking the window focus.
        final IOnBackInvokedCallback iCallback =
        final IOnBackInvokedCallback iCallback =
                new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(callback,
                new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(callback);
                        () -> true);
        bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder());
        bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder());
        bundle.putInt(RESULT_KEY_PRIORITY, priority);
        bundle.putInt(RESULT_KEY_PRIORITY, priority);
        bundle.putInt(RESULT_KEY_ID, callback.hashCode());
        bundle.putInt(RESULT_KEY_ID, callback.hashCode());
+2 −22
Original line number Original line Diff line number Diff line
@@ -32,7 +32,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.Objects;
import java.util.Objects;
import java.util.TreeMap;
import java.util.TreeMap;
import java.util.function.Supplier;


/**
/**
 * Provides window based implementation of {@link OnBackInvokedDispatcher}.
 * Provides window based implementation of {@link OnBackInvokedDispatcher}.
@@ -65,7 +64,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
    private final TreeMap<Integer, ArrayList<OnBackInvokedCallback>>
    private final TreeMap<Integer, ArrayList<OnBackInvokedCallback>>
            mOnBackInvokedCallbacks = new TreeMap<>();
            mOnBackInvokedCallbacks = new TreeMap<>();
    private final Checker mChecker;
    private final Checker mChecker;
    private boolean mHasFocus;


    public WindowOnBackInvokedDispatcher(boolean applicationCallBackEnabled) {
    public WindowOnBackInvokedDispatcher(boolean applicationCallBackEnabled) {
        mChecker = new Checker(applicationCallBackEnabled);
        mChecker = new Checker(applicationCallBackEnabled);
@@ -191,7 +189,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                                    .ImeOnBackInvokedCallback
                                    .ImeOnBackInvokedCallback
                                ? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
                                ? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
                                        callback).getIOnBackInvokedCallback()
                                        callback).getIOnBackInvokedCallback()
                                : new OnBackInvokedCallbackWrapper(callback, this::hasFocus);
                                : new OnBackInvokedCallbackWrapper(callback);
                callbackInfo = new OnBackInvokedCallbackInfo(iCallback, priority);
                callbackInfo = new OnBackInvokedCallbackInfo(iCallback, priority);
            }
            }
            mWindowSession.setOnBackInvokedCallbackInfo(mWindow, callbackInfo);
            mWindowSession.setOnBackInvokedCallbackInfo(mWindow, callbackInfo);
@@ -200,17 +198,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
        }
        }
    }
    }


    /**
     * Called when window focus changed.
     */
    public void onWindowFocusChanged(boolean hasFocus) {
        mHasFocus = hasFocus;
    }

    private boolean hasFocus() {
        return mHasFocus;
    }

    public OnBackInvokedCallback getTopCallback() {
    public OnBackInvokedCallback getTopCallback() {
        if (mAllCallbacks.isEmpty()) {
        if (mAllCallbacks.isEmpty()) {
            return null;
            return null;
@@ -234,11 +221,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {


    static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
    static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
        private final WeakReference<OnBackInvokedCallback> mCallback;
        private final WeakReference<OnBackInvokedCallback> mCallback;
        private final Supplier<Boolean> mHasFocus;
        OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback) {
        OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback,
                @NonNull Supplier<Boolean> hasFocus) {
            mCallback = new WeakReference<>(callback);
            mCallback = new WeakReference<>(callback);
            mHasFocus = hasFocus;
        }
        }


        @Override
        @Override
@@ -278,10 +262,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                if (callback == null) {
                if (callback == null) {
                    return;
                    return;
                }
                }
                if (!mHasFocus.get()) {
                    Log.w(TAG, "Skip back invoke due to current focus has lost.");
                    return;
                }
                callback.onBackInvoked();
                callback.onBackInvoked();
            });
            });
        }
        }
Loading