Merge "Adjust cancel back navigation conditions." into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
67182c205b
@@ -65,12 +65,12 @@ import android.os.Debug;
|
||||
import android.os.IBinder;
|
||||
import android.os.IProgressListener;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.StrictMode;
|
||||
import android.os.WorkSource;
|
||||
import android.service.voice.IVoiceInteractionSession;
|
||||
import android.view.IRecentsAnimationRunner;
|
||||
import android.view.IRemoteAnimationRunner;
|
||||
import android.view.IWindowFocusObserver;
|
||||
import android.view.RemoteAnimationDefinition;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
import android.window.IWindowOrganizerController;
|
||||
@@ -349,12 +349,13 @@ interface IActivityTaskManager {
|
||||
/**
|
||||
* 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.
|
||||
* @param focusObserver a remote callback to nofify shell when the focused window lost focus.
|
||||
* @param navigationObserver a remote callback to nofify shell when the focused window is gone,
|
||||
or an unexpected transition has happened on the navigation target.
|
||||
* @param adaptor a remote animation to be run for the back navigation plays the animation.
|
||||
* @return Returns the back navigation info.
|
||||
*/
|
||||
android.window.BackNavigationInfo startBackNavigation(
|
||||
in IWindowFocusObserver focusObserver, in BackAnimationAdapter adaptor);
|
||||
in RemoteCallback navigationObserver, in BackAnimationAdapter adaptor);
|
||||
|
||||
/**
|
||||
* registers a callback to be invoked when the screen is captured.
|
||||
|
||||
@@ -29,8 +29,9 @@ import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
@@ -39,7 +40,6 @@ import android.provider.Settings.Global;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.IRemoteAnimationRunner;
|
||||
import android.view.IWindowFocusObserver;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
@@ -121,23 +121,22 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
private IOnBackInvokedCallback mActiveCallback;
|
||||
|
||||
@VisibleForTesting
|
||||
final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() {
|
||||
@Override
|
||||
public void focusGained(IBinder inputToken) { }
|
||||
@Override
|
||||
public void focusLost(IBinder inputToken) {
|
||||
mShellExecutor.execute(() -> {
|
||||
if (!mBackGestureStarted || mPostCommitAnimationInProgress) {
|
||||
// If an uninterruptible animation is already in progress, we should ignore
|
||||
// this due to it may cause focus lost. (alpha = 0)
|
||||
return;
|
||||
final RemoteCallback mNavigationObserver = new RemoteCallback(
|
||||
new RemoteCallback.OnResultListener() {
|
||||
@Override
|
||||
public void onResult(@Nullable Bundle result) {
|
||||
mShellExecutor.execute(() -> {
|
||||
if (!mBackGestureStarted || mPostCommitAnimationInProgress) {
|
||||
// If an uninterruptible animation is already in progress, we should
|
||||
// ignore this due to it may cause focus lost. (alpha = 0)
|
||||
return;
|
||||
}
|
||||
ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Navigation window gone.");
|
||||
setTriggerBack(false);
|
||||
onGestureFinished(false);
|
||||
});
|
||||
}
|
||||
ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Target window lost focus.");
|
||||
setTriggerBack(false);
|
||||
onGestureFinished(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private final BackAnimationBackground mAnimationBackground;
|
||||
|
||||
@@ -351,7 +350,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
|
||||
try {
|
||||
mBackNavigationInfo = mActivityTaskManager.startBackNavigation(
|
||||
mFocusObserver, mEnableAnimations.get() ? mBackAnimationAdapter : null);
|
||||
mNavigationObserver, mEnableAnimations.get() ? mBackAnimationAdapter : null);
|
||||
onBackNavigationInfoReceived(mBackNavigationInfo);
|
||||
} catch (RemoteException remoteException) {
|
||||
Log.e(TAG, "Failed to initAnimation", remoteException);
|
||||
|
||||
@@ -25,7 +25,6 @@ import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -40,7 +39,6 @@ import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
@@ -341,8 +339,7 @@ public class BackAnimationControllerTest extends ShellTestCase {
|
||||
mController.setTriggerBack(true); // Fake trigger back
|
||||
|
||||
// In case the focus has been changed.
|
||||
IBinder token = mock(IBinder.class);
|
||||
mController.mFocusObserver.focusLost(token);
|
||||
mController.mNavigationObserver.sendResult(null);
|
||||
mShellExecutor.flushAll();
|
||||
verify(mAnimatorCallback).onBackCancelled();
|
||||
|
||||
|
||||
@@ -202,6 +202,7 @@ import android.os.Parcel;
|
||||
import android.os.PowerManager;
|
||||
import android.os.PowerManagerInternal;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.StrictMode;
|
||||
@@ -228,7 +229,6 @@ import android.util.SparseArray;
|
||||
import android.util.TimeUtils;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.IRecentsAnimationRunner;
|
||||
import android.view.IWindowFocusObserver;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
import android.view.RemoteAnimationDefinition;
|
||||
import android.view.WindowManager;
|
||||
@@ -1853,11 +1853,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
|
||||
@Override
|
||||
public BackNavigationInfo startBackNavigation(
|
||||
IWindowFocusObserver observer, BackAnimationAdapter adapter) {
|
||||
RemoteCallback navigationObserver, BackAnimationAdapter adapter) {
|
||||
mAmInternal.enforceCallingPermission(START_TASKS_FROM_RECENTS,
|
||||
"startBackNavigation()");
|
||||
|
||||
return mBackNavigationController.startBackNavigation(observer, adapter);
|
||||
return mBackNavigationController.startBackNavigation(navigationObserver, adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -253,7 +253,7 @@ public class AppTransitionController {
|
||||
|
||||
ArraySet<ActivityRecord> tmpOpenApps = mDisplayContent.mOpeningApps;
|
||||
ArraySet<ActivityRecord> tmpCloseApps = mDisplayContent.mClosingApps;
|
||||
if (mDisplayContent.mAtmService.mBackNavigationController.isWaitBackTransition()) {
|
||||
if (mDisplayContent.mAtmService.mBackNavigationController.isMonitoringTransition()) {
|
||||
tmpOpenApps = new ArraySet<>(mDisplayContent.mOpeningApps);
|
||||
tmpCloseApps = new ArraySet<>(mDisplayContent.mClosingApps);
|
||||
if (mDisplayContent.mAtmService.mBackNavigationController
|
||||
|
||||
@@ -41,7 +41,6 @@ import android.os.SystemProperties;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.IWindowFocusObserver;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowInsets;
|
||||
@@ -66,11 +65,11 @@ import java.util.function.Consumer;
|
||||
class BackNavigationController {
|
||||
private static final String TAG = "BackNavigationController";
|
||||
private WindowManagerService mWindowManagerService;
|
||||
private IWindowFocusObserver mFocusObserver;
|
||||
private boolean mBackAnimationInProgress;
|
||||
private @BackNavigationInfo.BackTargetType int mLastBackType;
|
||||
private boolean mShowWallpaper;
|
||||
private Runnable mPendingAnimation;
|
||||
private final NavigationMonitor mNavigationMonitor = new NavigationMonitor();
|
||||
|
||||
private AnimationHandler mAnimationHandler;
|
||||
private final ArrayList<WindowContainer> mTmpOpenApps = new ArrayList<>();
|
||||
@@ -86,6 +85,11 @@ class BackNavigationController {
|
||||
return SystemProperties.getInt("persist.wm.debug.predictive_back_screenshot", 0) != 0;
|
||||
}
|
||||
|
||||
// Notify focus window changed
|
||||
void onFocusChanged(WindowState newFocus) {
|
||||
mNavigationMonitor.onFocusWindowChanged(newFocus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the necessary leashes and build a {@link BackNavigationInfo} instance for an upcoming
|
||||
* back gesture animation.
|
||||
@@ -96,13 +100,12 @@ class BackNavigationController {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@Nullable
|
||||
BackNavigationInfo startBackNavigation(
|
||||
IWindowFocusObserver observer, BackAnimationAdapter adapter) {
|
||||
BackNavigationInfo startBackNavigation(@NonNull RemoteCallback navigationObserver,
|
||||
BackAnimationAdapter adapter) {
|
||||
if (!sPredictBackEnable) {
|
||||
return null;
|
||||
}
|
||||
final WindowManagerService wmService = mWindowManagerService;
|
||||
mFocusObserver = observer;
|
||||
|
||||
int backType = BackNavigationInfo.TYPE_UNDEFINED;
|
||||
|
||||
@@ -202,9 +205,7 @@ class BackNavigationController {
|
||||
backType = BackNavigationInfo.TYPE_CALLBACK;
|
||||
}
|
||||
infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback());
|
||||
if (mFocusObserver != null) {
|
||||
window.registerFocusObserver(mFocusObserver);
|
||||
}
|
||||
mNavigationMonitor.startMonitor(window, navigationObserver);
|
||||
}
|
||||
|
||||
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation currentTask=%s, "
|
||||
@@ -228,10 +229,8 @@ class BackNavigationController {
|
||||
|| currentActivity.isActivityTypeHome()
|
||||
|| currentActivity.mHasSceneTransition) {
|
||||
infoBuilder.setType(BackNavigationInfo.TYPE_CALLBACK);
|
||||
final WindowState finalFocusedWindow = window;
|
||||
infoBuilder.setOnBackNavigationDone(new RemoteCallback(result ->
|
||||
onBackNavigationDone(result, finalFocusedWindow,
|
||||
BackNavigationInfo.TYPE_CALLBACK)));
|
||||
onBackNavigationDone(result, BackNavigationInfo.TYPE_CALLBACK)));
|
||||
mLastBackType = BackNavigationInfo.TYPE_CALLBACK;
|
||||
return infoBuilder.build();
|
||||
}
|
||||
@@ -334,16 +333,19 @@ class BackNavigationController {
|
||||
WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer;
|
||||
if (finalRemovedWindowContainer != null) {
|
||||
final int finalBackType = backType;
|
||||
final WindowState finalFocusedWindow = window;
|
||||
RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone(
|
||||
result, finalFocusedWindow, finalBackType));
|
||||
result, finalBackType));
|
||||
infoBuilder.setOnBackNavigationDone(onBackNavigationDone);
|
||||
}
|
||||
mLastBackType = backType;
|
||||
return infoBuilder.build();
|
||||
}
|
||||
|
||||
boolean isWaitBackTransition() {
|
||||
boolean isMonitoringTransition() {
|
||||
return isWaitBackTransition() || mNavigationMonitor.isMonitoring();
|
||||
}
|
||||
|
||||
private boolean isWaitBackTransition() {
|
||||
return mAnimationHandler.mComposed && mAnimationHandler.mWaitTransition;
|
||||
}
|
||||
|
||||
@@ -363,11 +365,23 @@ class BackNavigationController {
|
||||
*/
|
||||
boolean removeIfContainsBackAnimationTargets(ArraySet<ActivityRecord> openApps,
|
||||
ArraySet<ActivityRecord> closeApps) {
|
||||
if (!isWaitBackTransition()) {
|
||||
if (!isMonitoringTransition()) {
|
||||
return false;
|
||||
}
|
||||
mTmpCloseApps.addAll(closeApps);
|
||||
boolean result = false;
|
||||
final boolean matchAnimationTargets = removeIfWaitForBackTransition(openApps, closeApps);
|
||||
if (!matchAnimationTargets) {
|
||||
mNavigationMonitor.onTransitionReadyWhileNavigate(mTmpOpenApps, mTmpCloseApps);
|
||||
}
|
||||
mTmpCloseApps.clear();
|
||||
return matchAnimationTargets;
|
||||
}
|
||||
|
||||
boolean removeIfWaitForBackTransition(ArraySet<ActivityRecord> openApps,
|
||||
ArraySet<ActivityRecord> closeApps) {
|
||||
if (!isWaitBackTransition()) {
|
||||
return false;
|
||||
}
|
||||
// Note: TmpOpenApps is empty. Unlike shell transition, the open apps will be removed from
|
||||
// mOpeningApps if there is no visibility change.
|
||||
if (mAnimationHandler.containsBackAnimationTargets(mTmpOpenApps, mTmpCloseApps)) {
|
||||
@@ -386,10 +400,76 @@ class BackNavigationController {
|
||||
closeApps.removeAt(i);
|
||||
}
|
||||
}
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class NavigationMonitor {
|
||||
// The window which triggering the back navigation.
|
||||
private WindowState mNavigatingWindow;
|
||||
private RemoteCallback mObserver;
|
||||
|
||||
void startMonitor(@NonNull WindowState window, @NonNull RemoteCallback observer) {
|
||||
mNavigatingWindow = window;
|
||||
mObserver = observer;
|
||||
}
|
||||
|
||||
void stopMonitor() {
|
||||
mNavigatingWindow = null;
|
||||
mObserver = null;
|
||||
}
|
||||
|
||||
boolean isMonitoring() {
|
||||
return mNavigatingWindow != null && mObserver != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify focus window changed during back navigation. This will cancel the gesture for
|
||||
* scenarios like: a system window popup, or when an activity add a new window.
|
||||
*
|
||||
* This method should only be used to check window-level change, otherwise it may cause
|
||||
* misjudgment in multi-window mode. For example: in split-screen, when user is
|
||||
* navigating on the top task, bottom task can start a new task, which will gain focus for
|
||||
* a short time, but we should not cancel the navigation.
|
||||
*/
|
||||
private void onFocusWindowChanged(WindowState newFocus) {
|
||||
if (!isMonitoring() || !atSameDisplay(newFocus)) {
|
||||
return;
|
||||
}
|
||||
// Keep navigating if either new focus == navigating window or null.
|
||||
if (newFocus != null && newFocus != mNavigatingWindow
|
||||
&& (newFocus.mActivityRecord == null
|
||||
|| (newFocus.mActivityRecord == mNavigatingWindow.mActivityRecord))) {
|
||||
EventLogTags.writeWmBackNaviCanceled("focusWindowChanged");
|
||||
mObserver.sendResult(null /* result */);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify an unexpected transition has happened during back navigation.
|
||||
*/
|
||||
private void onTransitionReadyWhileNavigate(ArrayList<WindowContainer> opening,
|
||||
ArrayList<WindowContainer> closing) {
|
||||
if (!isMonitoring()) {
|
||||
return;
|
||||
}
|
||||
final ArrayList<WindowContainer> all = new ArrayList<>(opening);
|
||||
all.addAll(closing);
|
||||
for (WindowContainer app : all) {
|
||||
if (app.hasChild(mNavigatingWindow)) {
|
||||
EventLogTags.writeWmBackNaviCanceled("transitionHappens");
|
||||
mObserver.sendResult(null /* result */);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean atSameDisplay(WindowState newFocus) {
|
||||
final int navigatingDisplayId = mNavigatingWindow.getDisplayId();
|
||||
return newFocus == null || newFocus.getDisplayId() == navigatingDisplayId;
|
||||
}
|
||||
mTmpCloseApps.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
// For shell transition
|
||||
@@ -403,8 +483,7 @@ class BackNavigationController {
|
||||
* animations, and shouldn't join next transition.
|
||||
*/
|
||||
boolean containsBackAnimationTargets(Transition transition) {
|
||||
if (!mAnimationHandler.mComposed
|
||||
|| (transition.mType != TRANSIT_CLOSE && transition.mType != TRANSIT_TO_BACK)) {
|
||||
if (!isMonitoringTransition()) {
|
||||
return false;
|
||||
}
|
||||
final ArraySet<WindowContainer> targets = transition.mParticipants;
|
||||
@@ -420,19 +499,19 @@ class BackNavigationController {
|
||||
mTmpCloseApps.add(wc);
|
||||
}
|
||||
}
|
||||
final boolean result = mAnimationHandler.containsBackAnimationTargets(
|
||||
mTmpOpenApps, mTmpCloseApps);
|
||||
if (result) {
|
||||
mAnimationHandler.mOpenTransitionTargetMatch =
|
||||
mAnimationHandler.containTarget(mTmpOpenApps, true);
|
||||
final boolean matchAnimationTargets = isWaitBackTransition()
|
||||
&& (transition.mType == TRANSIT_CLOSE || transition.mType == TRANSIT_TO_BACK)
|
||||
&& mAnimationHandler.containsBackAnimationTargets(mTmpOpenApps, mTmpCloseApps);
|
||||
if (!matchAnimationTargets) {
|
||||
mNavigationMonitor.onTransitionReadyWhileNavigate(mTmpOpenApps, mTmpCloseApps);
|
||||
}
|
||||
mTmpOpenApps.clear();
|
||||
mTmpCloseApps.clear();
|
||||
return result;
|
||||
return matchAnimationTargets;
|
||||
}
|
||||
|
||||
boolean isMonitorTransitionTarget(WindowContainer wc) {
|
||||
if (!mAnimationHandler.mComposed || !mAnimationHandler.mWaitTransition) {
|
||||
if (!isWaitBackTransition()) {
|
||||
return false;
|
||||
}
|
||||
return mAnimationHandler.isTarget(wc, wc.isVisibleRequested() /* open */);
|
||||
@@ -951,16 +1030,13 @@ class BackNavigationController {
|
||||
}
|
||||
}
|
||||
|
||||
private void onBackNavigationDone(Bundle result, WindowState focusedWindow, int backType) {
|
||||
private void onBackNavigationDone(Bundle result, int backType) {
|
||||
boolean triggerBack = result != null && result.getBoolean(
|
||||
BackNavigationInfo.KEY_TRIGGER_BACK);
|
||||
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, "
|
||||
+ "triggerBack=%b", backType, triggerBack);
|
||||
|
||||
if (mFocusObserver != null) {
|
||||
focusedWindow.unregisterFocusObserver(mFocusObserver);
|
||||
mFocusObserver = null;
|
||||
}
|
||||
mNavigationMonitor.stopMonitor();
|
||||
mBackAnimationInProgress = false;
|
||||
mShowWallpaper = false;
|
||||
}
|
||||
|
||||
@@ -3809,6 +3809,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
}
|
||||
|
||||
getDisplayPolicy().focusChangedLw(oldFocus, newFocus);
|
||||
mAtmService.mBackNavigationController.onFocusChanged(newFocus);
|
||||
|
||||
if (imWindowChanged && oldFocus != mInputMethodWindow) {
|
||||
// Focus of the input method window changed. Perform layout if needed.
|
||||
|
||||
@@ -66,6 +66,8 @@ option java_package com.android.server.wm
|
||||
# bootanim finished:
|
||||
31007 wm_boot_animation_done (time|2|3)
|
||||
|
||||
# Back navigation.
|
||||
31100 wm_back_navi_canceled (Reason|3)
|
||||
|
||||
# IME surface parent is updated.
|
||||
32003 imf_update_ime_parent (surface name|3)
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK;
|
||||
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
||||
import static android.window.BackNavigationInfo.typeToString;
|
||||
|
||||
@@ -42,8 +45,10 @@ import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.ArraySet;
|
||||
import android.view.WindowManager;
|
||||
import android.window.BackAnimationAdapter;
|
||||
import android.window.BackMotionEvent;
|
||||
@@ -320,6 +325,64 @@ public class BackNavigationControllerTests extends WindowTestsBase {
|
||||
assertThat(backNavigationInfo).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransitionHappensCancelNavigation() {
|
||||
// Create a floating task and a fullscreen task, then navigating on fullscreen task.
|
||||
// The navigation should not been cancelled when transition happens on floating task, and
|
||||
// only be cancelled when transition happens on the navigating task.
|
||||
final Task floatingTask = createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW,
|
||||
ACTIVITY_TYPE_STANDARD);
|
||||
final ActivityRecord baseFloatingActivity = createActivityRecord(floatingTask);
|
||||
|
||||
final Task fullscreenTask = createTopTaskWithActivity();
|
||||
withSystemCallback(fullscreenTask);
|
||||
final ActivityRecord baseFullscreenActivity = fullscreenTask.getTopMostActivity();
|
||||
|
||||
final CountDownLatch navigationObserver = new CountDownLatch(1);
|
||||
startBackNavigation(navigationObserver);
|
||||
|
||||
final ArraySet<ActivityRecord> opening = new ArraySet<>();
|
||||
final ArraySet<ActivityRecord> closing = new ArraySet<>();
|
||||
final ActivityRecord secondFloatingActivity = createActivityRecord(floatingTask);
|
||||
opening.add(secondFloatingActivity);
|
||||
closing.add(baseFloatingActivity);
|
||||
mBackNavigationController.removeIfContainsBackAnimationTargets(opening, closing);
|
||||
assertEquals("Transition happen on an irrelevant task, callback should not been called",
|
||||
1, navigationObserver.getCount());
|
||||
|
||||
// Create a new activity above navigation target, the transition should cancel navigation.
|
||||
final ActivityRecord topFullscreenActivity = createActivityRecord(fullscreenTask);
|
||||
opening.clear();
|
||||
closing.clear();
|
||||
opening.add(topFullscreenActivity);
|
||||
closing.add(baseFullscreenActivity);
|
||||
mBackNavigationController.removeIfContainsBackAnimationTargets(opening, closing);
|
||||
assertEquals("Transition happen on navigation task, callback should have been called",
|
||||
0, navigationObserver.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWindowFocusChangeCancelNavigation() {
|
||||
Task task = createTopTaskWithActivity();
|
||||
withSystemCallback(task);
|
||||
WindowState focusWindow = task.getTopVisibleAppMainWindow();
|
||||
final CountDownLatch navigationObserver = new CountDownLatch(1);
|
||||
startBackNavigation(navigationObserver);
|
||||
|
||||
mBackNavigationController.onFocusChanged(null);
|
||||
assertEquals("change focus to null, callback should not have been called",
|
||||
1, navigationObserver.getCount());
|
||||
mBackNavigationController.onFocusChanged(focusWindow);
|
||||
assertEquals("change focus back, callback should not have been called",
|
||||
1, navigationObserver.getCount());
|
||||
|
||||
WindowState newWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlayWindow");
|
||||
addToWindowMap(newWindow, true);
|
||||
mBackNavigationController.onFocusChanged(newWindow);
|
||||
assertEquals("Focus change, callback should have been called",
|
||||
0, navigationObserver.getCount());
|
||||
}
|
||||
|
||||
private IOnBackInvokedCallback withSystemCallback(Task task) {
|
||||
IOnBackInvokedCallback callback = createOnBackInvokedCallback();
|
||||
task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo(
|
||||
@@ -336,7 +399,14 @@ public class BackNavigationControllerTests extends WindowTestsBase {
|
||||
|
||||
@Nullable
|
||||
private BackNavigationInfo startBackNavigation() {
|
||||
return mBackNavigationController.startBackNavigation(null, mBackAnimationAdapter);
|
||||
return mBackNavigationController.startBackNavigation(
|
||||
createNavigationObserver(null), mBackAnimationAdapter);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private BackNavigationInfo startBackNavigation(CountDownLatch navigationObserverLatch) {
|
||||
return mBackNavigationController.startBackNavigation(
|
||||
createNavigationObserver(navigationObserverLatch), mBackAnimationAdapter);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -371,6 +441,14 @@ public class BackNavigationControllerTests extends WindowTestsBase {
|
||||
};
|
||||
}
|
||||
|
||||
private RemoteCallback createNavigationObserver(CountDownLatch latch) {
|
||||
return new RemoteCallback(result -> {
|
||||
if (latch != null) {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Task initHomeActivity() {
|
||||
final Task task = mDisplayContent.getDefaultTaskDisplayArea().getRootHomeTask();
|
||||
task.forAllLeafTasks((t) -> {
|
||||
|
||||
Reference in New Issue
Block a user