summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java7
-rw-r--r--services/core/java/com/android/server/wm/RemoteAnimationController.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java68
3 files changed, 72 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index e053ff338a25..0915caedd6bc 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -452,6 +452,13 @@ public class AppTransition implements Dump {
void freeze() {
final int transit = mNextAppTransition;
+ // The RemoteAnimationControl didn't register AppTransitionListener and
+ // only initialized the finish and timeout callback when goodToGo().
+ // So cancel the remote animation here to prevent the animation can't do
+ // finish after transition state cleared.
+ if (mRemoteAnimationController != null) {
+ mRemoteAnimationController.cancelAnimation("freeze");
+ }
setAppTransition(TRANSIT_UNSET, 0 /* flags */);
clear();
setReady();
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 5f95691d5307..b4bfedda94c7 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -132,7 +132,7 @@ class RemoteAnimationController implements DeathRecipient {
sendRunningRemoteAnimation(true);
}
- private void cancelAnimation(String reason) {
+ void cancelAnimation(String reason) {
if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason);
synchronized (mService.getWindowManagerLock()) {
if (mCanceled) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 5fc7f44588e1..5a72a584b122 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -18,30 +18,40 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.graphics.Rect;
+import android.os.IBinder;
+import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
-
-import org.junit.Before;
-import org.junit.Test;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.IRemoteAnimationRunner;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationTarget;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
+import org.junit.Before;
+import org.junit.Test;
+
/**
* Test class for {@link AppTransition}.
*
@@ -51,7 +61,6 @@ import androidx.test.filters.SmallTest;
@SmallTest
@Presubmit
public class AppTransitionTests extends WindowTestsBase {
-
private DisplayContent mDc;
@Before
@@ -181,4 +190,55 @@ public class AppTransitionTests extends WindowTestsBase {
getInstrumentation().getTargetContext(), -1));
}
+ @Test
+ public void testCancelRemoteAnimationWhenFreeze() {
+ final DisplayContent dc = createNewDisplay(Display.STATE_ON);
+ final WindowState exitingAppWindow = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
+ dc, "exiting app");
+ final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
+ // Wait until everything in animation handler get executed to prevent the exiting window
+ // from being removed during WindowSurfacePlacer Traversal.
+ waitUntilHandlersIdle();
+
+ // Set a remote animator.
+ final TestRemoteAnimationRunner runner = new TestRemoteAnimationRunner();
+ final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
+ runner, 100, 50, true /* changeNeedsSnapshot */);
+ // RemoteAnimationController will tracking RemoteAnimationAdapter's caller with calling pid.
+ adapter.setCallingPid(123);
+
+ // Simulate activity finish flows to prepare app transition & set visibility,
+ // make sure transition is set as expected.
+ dc.prepareAppTransition(TRANSIT_ACTIVITY_CLOSE,
+ false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
+ assertEquals(TRANSIT_ACTIVITY_CLOSE, dc.mAppTransition.getAppTransition());
+ dc.mAppTransition.overridePendingAppTransitionRemote(adapter);
+ exitingAppToken.setVisibility(false, false);
+ assertTrue(dc.mClosingApps.size() > 0);
+
+ // Make sure window is in animating stage before freeze, and cancel after freeze.
+ assertTrue(dc.isAppAnimating());
+ assertFalse(runner.mCancelled);
+ dc.mAppTransition.freeze();
+ assertFalse(dc.isAppAnimating());
+ assertTrue(runner.mCancelled);
+ }
+
+ private class TestRemoteAnimationRunner implements IRemoteAnimationRunner {
+ boolean mCancelled = false;
+ @Override
+ public void onAnimationStart(RemoteAnimationTarget[] apps,
+ IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
+ }
+
+ @Override
+ public void onAnimationCancelled() {
+ mCancelled = true;
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return null;
+ }
+ }
}