Add tests that activity can receive ACTION_CANCEL after onBackStarted

Add tests for
1. Activity not opt-in predictive back
2. Activity opt-in predictive back and
   - with default onBackInvokedCallback
   - register it's own onBackInvokedCallback
The activity should receive ACTION_CANCEL in above conditions once the
back gesture across the threshold.

Flag: com.android.window.flags.intercept_motion_from_move_to_cancel
Bug: 404173501
Test: atest OnBackInvokedCallbackGestureTest
Change-Id: Ia63d4f886e02206c32094791ae5badd0b65e658a
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index dd74b12..ad4e14d 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -628,6 +628,9 @@
         <activity android:name="android.server.wm.backnavigation.BackNavigationActivity"
                   android:enableOnBackInvokedCallback="true"
                   android:exported="true"/>
+        <activity android:name="android.server.wm.backnavigation.OptOutBackNavigationActivity"
+            android:enableOnBackInvokedCallback="false"
+            android:exported="true"/>
         <activity android:name="android.server.wm.other.PinnedStackTests$TestActivity"
                   android:exported="true"/>
         <activity android:name="android.server.wm.taskfragment.TaskFragmentTrustedModeTest$TranslucentActivity"
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/BackNavigationActivity.java b/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/BackNavigationActivity.java
index 97b6e25..444afa3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/BackNavigationActivity.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/BackNavigationActivity.java
@@ -18,17 +18,22 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.view.MotionEvent;
 
 import androidx.annotation.Nullable;
 
+import java.util.concurrent.CountDownLatch;
+
 public class BackNavigationActivity extends Activity {
 
     boolean mOnBackPressedCalled;
     boolean mOnUserInteractionCalled;
+    CountDownLatch mReceiveMotionCancel;
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        mReceiveMotionCancel = new CountDownLatch(1);
     }
 
     @Override
@@ -42,4 +47,12 @@
         mOnUserInteractionCalled = true;
         super.onUserInteraction();
     }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (event.getAction() == MotionEvent.ACTION_CANCEL) {
+            mReceiveMotionCancel.countDown();
+        }
+        return super.onTouchEvent(event);
+    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/OnBackInvokedCallbackGestureTest.java b/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/OnBackInvokedCallbackGestureTest.java
index 3532c7d..45d14b6 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/OnBackInvokedCallbackGestureTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/OnBackInvokedCallbackGestureTest.java
@@ -21,6 +21,7 @@
 import static android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT;
 import static android.window.OnBackInvokedDispatcher.PRIORITY_SYSTEM_NAVIGATION_OBSERVER;
 
+import static com.android.window.flags.Flags.FLAG_INTERCEPT_MOTION_FROM_MOVE_TO_CANCEL;
 import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER;
 import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_SWIPE_EDGE_NONE_API;
 import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_SYSTEM_OVERRIDE_CALLBACK;
@@ -377,6 +378,75 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(FLAG_INTERCEPT_MOTION_FROM_MOVE_TO_CANCEL)
+    public void testReceiveCancelEvent_default_cancel() throws InterruptedException {
+        testReceivedCancelEvent(mActivity, false, false);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_INTERCEPT_MOTION_FROM_MOVE_TO_CANCEL)
+    public void testReceiveCancelEvent_default_finish() throws InterruptedException {
+        testReceivedCancelEvent(mActivity, false, true);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_INTERCEPT_MOTION_FROM_MOVE_TO_CANCEL)
+    public void testReceiveCancelEvent_override_cancel() throws InterruptedException {
+        testReceivedCancelEvent(mActivity, true, false);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_INTERCEPT_MOTION_FROM_MOVE_TO_CANCEL)
+    public void testReceiveCancelEvent_override_finish() throws InterruptedException {
+        testReceivedCancelEvent(mActivity, true, true);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_INTERCEPT_MOTION_FROM_MOVE_TO_CANCEL)
+    public void testOptOutActivityReceiveCancelEvent_cancel() throws InterruptedException {
+        try (TestActivitySession<OptOutBackNavigationActivity> activitySession =
+                createManagedTestActivitySession()) {
+            activitySession.launchTestActivityOnDisplaySync(
+                    OptOutBackNavigationActivity.class, DEFAULT_DISPLAY);
+            mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
+            final OptOutBackNavigationActivity activity = activitySession.getActivity();
+            testReceivedCancelEvent(activity, false, false);
+        }
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_INTERCEPT_MOTION_FROM_MOVE_TO_CANCEL)
+    public void testOptOutActivityReceiveCancelEvent_finish() throws InterruptedException {
+        try (TestActivitySession<OptOutBackNavigationActivity> activitySession =
+                createManagedTestActivitySession()) {
+            activitySession.launchTestActivityOnDisplaySync(
+                    OptOutBackNavigationActivity.class, DEFAULT_DISPLAY);
+            mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
+            final OptOutBackNavigationActivity activity = activitySession.getActivity();
+            testReceivedCancelEvent(activity, false, true);
+        }
+    }
+
+    private void testReceivedCancelEvent(
+            BackNavigationActivity activity, boolean registerCallback, boolean finishGesture)
+            throws InterruptedException {
+        if (registerCallback) {
+            registerBackCallback(activity, mAnimationCallback, PRIORITY_DEFAULT);
+        }
+        int midHeight = mUiDevice.getDisplayHeight() / 2;
+        int midWidth = mUiDevice.getDisplayWidth() / 2;
+
+        mTouchSwipeSession.beginSwipe(0, midHeight);
+        mTouchSwipeSession.continueSwipe(midWidth, midHeight, PROGRESS_SWIPE_STEPS);
+        if (finishGesture) {
+            mTouchSwipeSession.finishSwipe();
+        } else {
+            mTouchSwipeSession.cancelSwipe();
+        }
+        assertInvoked(activity.mReceiveMotionCancel);
+    }
+
+    @Test
     public void ignoresKeyCodeBackDuringDispatch() throws InterruptedException {
         registerBackCallback(mActivity, mAnimationCallback, PRIORITY_DEFAULT);
         int midHeight = mUiDevice.getDisplayHeight() / 2;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/OptOutBackNavigationActivity.java b/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/OptOutBackNavigationActivity.java
new file mode 100644
index 0000000..76e82f1
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/backnavigation/OptOutBackNavigationActivity.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.backnavigation;
+
+public class OptOutBackNavigationActivity extends BackNavigationActivity {}