diff options
| author | 2019-05-07 19:49:31 +0800 | |
|---|---|---|
| committer | 2019-05-10 11:11:07 +0000 | |
| commit | 442aff2d0b82790a08b792990d625c10a63f9570 (patch) | |
| tree | bb1240b12bfb952ec6936f1e989b87d09aab60ba | |
| parent | 906e4169864f38488a661552ad45bd890a992f26 (diff) | |
Fix window didn't disappear if enable/disable ime at same time
When starting to freeze display, AppTransition also clear all status and
data, but if the RemoteAnimation didn't start. The window can't recevice the
finish animation callback, that would make the state is always EXITING.
Bug: 130618911
Test: atest DocumentsTest
Test: atest WmTests:RemoteAnimationControllerTest
Test: atest WmTests:AppTransitionTests
Change-Id: I5695a291f26323eb78cced435722b459b963a9f1
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; + } + } } |