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

Commit b7a11da4 authored by wilsonshih's avatar wilsonshih
Browse files

Pilfer pointers when touch gesture transferred to embedded.

Once the touch gesture transferred to embedded window, the host
activity won't receive motion event, instead the event will dispatch
to embedded process. In that scenario the remote process must not
receive motion event since there is no DecorView to intercept for back
animation callback.
Also disable send motion events if the client app was register normal
OnBackInvokedCallback, since it does not have to handle back progress.

Flag: com.android.window.flags.disallow_app_progress_embedded_window
Bug: 365504126
Test: Test on sample app, once touch gesture transfer to embedded
process, the remote process must not receive motion event when back
gesture start as soon as possible.

Change-Id: I712bab3c2b0de6a0960acac61dfca81341a7f543
parent 77842fdf
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -87,6 +87,13 @@ public final class BackNavigationInfo implements Parcelable {
     */
    public static final String KEY_GESTURE_FINISHED = "GestureFinished";

    /**
     * Touch gestured has transferred to embedded window, Shell should pilfer pointers so the
     * embedded won't receive motion events.
     * @hide
     */
    public static final String KEY_TOUCH_GESTURE_TRANSFERRED = "TouchGestureTransferred";


    /**
     * Defines the type of back destinations a back even can lead to. This is used to define the
@@ -119,7 +126,7 @@ public final class BackNavigationInfo implements Parcelable {
    @NonNull
    private final Rect mTouchableRegion;

    private final boolean mAppProgressGenerationAllowed;
    private boolean mAppProgressGenerationAllowed;
    private final int mFocusedTaskId;

    /**
@@ -252,6 +259,14 @@ public final class BackNavigationInfo implements Parcelable {
        return mFocusedTaskId;
    }

    /**
     * Force disable app to intercept back progress event.
     * @hide
     */
    public void disableAppProgressGenerationAllowed() {
        mAppProgressGenerationAllowed = false;
    }

    /**
     * Callback to be called when the back preview is finished in order to notify the server that
     * it can clean up the resources created for the animation.
+11 −0
Original line number Diff line number Diff line
@@ -348,3 +348,14 @@ flag {
  bug: "372230928"
  is_fixed_read_only: true
}

flag {
  name: "disallow_app_progress_embedded_window"
  namespace: "windowing_frontend"
  description: "Pilfer pointers when app transfer input gesture to embedded window."
  bug: "365504126"
  is_fixed_read_only: true
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}
 No newline at end of file
+10 −0
Original line number Diff line number Diff line
@@ -191,6 +191,16 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                @Override
                public void onResult(@Nullable Bundle result) {
                    mShellExecutor.execute(() -> {
                        if (mBackGestureStarted && result != null && result.getBoolean(
                                BackNavigationInfo.KEY_TOUCH_GESTURE_TRANSFERRED)) {
                            // Host app won't able to process motion event anymore, so pilfer
                            // pointers anyway.
                            if (mBackNavigationInfo != null) {
                                mBackNavigationInfo.disableAppProgressGenerationAllowed();
                            }
                            tryPilferPointers();
                            return;
                        }
                        if (!mBackGestureStarted || mPostCommitAnimationInProgress) {
                            // If an uninterruptible animation is already in progress, we should
                            // ignore this due to it may cause focus lost. (alpha = 0)
+36 −2
Original line number Diff line number Diff line
@@ -107,6 +107,12 @@ class BackNavigationController {
        mNavigationMonitor.onFocusWindowChanged(newFocus);
    }

    void onEmbeddedWindowGestureTransferred(@NonNull WindowState host) {
        if (Flags.disallowAppProgressEmbeddedWindow()) {
            mNavigationMonitor.onEmbeddedWindowGestureTransferred(host);
        }
    }

    /**
     * Set up the necessary leashes and build a {@link BackNavigationInfo} instance for an upcoming
     * back gesture animation.
@@ -178,6 +184,9 @@ class BackNavigationController {
                return null;
            }

            final ArrayList<EmbeddedWindowController.EmbeddedWindow> embeddedWindows = wmService
                    .mEmbeddedWindowController.getByHostWindow(window);

            currentActivity = window.mActivityRecord;
            currentTask = window.getTask();
            if ((currentTask != null && !currentTask.isVisibleRequested())
@@ -199,11 +208,22 @@ class BackNavigationController {
            infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback());
            infoBuilder.setAnimationCallback(callbackInfo.isAnimationCallback());
            infoBuilder.setTouchableRegion(window.getFrame());
            infoBuilder.setAppProgressAllowed((window.getAttrs().privateFlags
                    & PRIVATE_FLAG_APP_PROGRESS_GENERATION_ALLOWED) != 0);
            if (currentTask != null) {
                infoBuilder.setFocusedTaskId(currentTask.mTaskId);
            }
            boolean transferGestureToEmbedded = false;
            if (Flags.disallowAppProgressEmbeddedWindow() && embeddedWindows != null) {
                for (int i = embeddedWindows.size() - 1; i >= 0; --i) {
                    if (embeddedWindows.get(i).mGestureToEmbedded) {
                        transferGestureToEmbedded = true;
                        break;
                    }
                }
            }
            final boolean canInterruptInView = (window.getAttrs().privateFlags
                    & PRIVATE_FLAG_APP_PROGRESS_GENERATION_ALLOWED) != 0;
            infoBuilder.setAppProgressAllowed(canInterruptInView && !transferGestureToEmbedded
                    && callbackInfo.isAnimationCallback());
            mNavigationMonitor.startMonitor(window, navigationObserver);

            ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation currentTask=%s, "
@@ -741,6 +761,20 @@ class BackNavigationController {
            }
        }

        /**
         * Notify focus window has transferred touch gesture to embedded window. Shell should pilfer
         * pointers so embedded process won't receive motion event.
         *
         */
        void onEmbeddedWindowGestureTransferred(@NonNull WindowState host) {
            if (!isMonitorForRemote() || host != mNavigatingWindow) {
                return;
            }
            final Bundle result = new Bundle();
            result.putBoolean(BackNavigationInfo.KEY_TOUCH_GESTURE_TRANSFERRED, true);
            mObserver.sendResult(result);
        }

        /**
         * Notify an unexpected transition has happened during back navigation.
         */
+33 −3
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ import android.window.InputTransferToken;
import com.android.internal.protolog.ProtoLog;
import com.android.server.input.InputManagerService;

import java.util.ArrayList;

/**
 * Keeps track of embedded windows.
 *
@@ -146,6 +148,20 @@ class EmbeddedWindowController {
        return mWindowsByWindowToken.get(windowToken);
    }

    @Nullable ArrayList<EmbeddedWindow> getByHostWindow(WindowState host) {
        ArrayList<EmbeddedWindow> windows = null;
        for (int i = mWindows.size() - 1; i >= 0; i--) {
            final EmbeddedWindow ew = mWindows.valueAt(i);
            if (ew.mHostWindowState == host) {
                if (windows == null) {
                    windows = new ArrayList<>();
                }
                windows.add(ew);
            }
        }
        return windows;
    }

    private boolean isValidTouchGestureParams(WindowState hostWindowState,
            EmbeddedWindow embeddedWindow) {
        if (embeddedWindow == null) {
@@ -191,8 +207,12 @@ class EmbeddedWindowController {
            throw new SecurityException(
                    "Transfer request must originate from owner of transferFromToken");
        }
        return mInputManagerService.transferTouchGesture(ew.getInputChannelToken(),
                transferToHostWindowState.mInputChannelToken);
        final boolean didTransfer = mInputManagerService.transferTouchGesture(
                ew.getInputChannelToken(), transferToHostWindowState.mInputChannelToken);
        if (didTransfer) {
            ew.mGestureToEmbedded = false;
        }
        return didTransfer;
    }

    boolean transferToEmbedded(int callingUid, WindowState hostWindowState,
@@ -205,8 +225,15 @@ class EmbeddedWindowController {
            throw new SecurityException(
                    "Transfer request must originate from owner of transferFromToken");
        }
        return mInputManagerService.transferTouchGesture(hostWindowState.mInputChannelToken,
        final boolean didTransfer = mInputManagerService.transferTouchGesture(
                hostWindowState.mInputChannelToken,
                ew.getInputChannelToken());
        if (didTransfer) {
            ew.mGestureToEmbedded = true;
            mAtmService.mBackNavigationController.onEmbeddedWindowGestureTransferred(
                    hostWindowState);
        }
        return didTransfer;
    }

    static class EmbeddedWindow implements InputTarget {
@@ -235,6 +262,9 @@ class EmbeddedWindowController {
        // the host window.
        private @WindowInsets.Type.InsetsType int mRequestedVisibleTypes = 0;

        /** Whether the gesture is transferred to embedded window. */
        boolean mGestureToEmbedded = false;

        /**
         * @param session  calling session to check ownership of the window
         * @param clientToken client token used to clean up the map if the embedding process dies