Allow recents animation controller to control input consumer lifecycle

- Removing race between the system cleaning up the input consumer and the
  controller who is also managing the input consumer lifecycle (it's
  preferable for the controller to keep the input consumer registered,
  and only to toggle the enabled state).  Instead, we only ensure that we
  clean up if the runner is unexpected destroyed.
- Also ensure that we don't add the input consumer on top of the runner's
  app window

Bug: 117224991
Test: atest FrameworksServicesTests:RecentsAnimationTest
Test: atest FrameworksServicesTests:com.android.server.wm.RecentsAnimationControllerTest

Change-Id: I258f655417220b95112ba784e2ab2f30a9ee2a4a
This commit is contained in:
Winson Chung
2018-10-03 14:25:34 -07:00
parent e5bc538a9f
commit db111ee2ee
3 changed files with 20 additions and 8 deletions

View File

@@ -435,14 +435,14 @@ final class InputMonitor {
final RecentsAnimationController recentsAnimationController =
mService.getRecentsAnimationController();
if (recentsAnimationController != null
&& recentsAnimationController.hasInputConsumerForApp(w.mAppToken)) {
&& recentsAnimationController.shouldApplyInputConsumer(w.mAppToken)) {
if (recentsAnimationController.updateInputConsumerForApp(
recentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
addInputWindowHandle(recentsAnimationInputConsumer.mWindowHandle);
mAddRecentsAnimationInputConsumerHandle = false;
}
// Skip adding the window below regardless of whether there is an input consumer
// to handle it
// If the target app window does not yet exist, then we don't add the input
// consumer window, but also don't add the app window below.
return;
}
}

View File

@@ -458,10 +458,9 @@ public class RecentsAnimationController implements DeathRecipient {
mRunner = null;
mCanceled = true;
// Clear associated input consumers
// Update the input windows after the animation is complete
final InputMonitor inputMonitor =
mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
inputMonitor.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
inputMonitor.updateInputWindowsLw(true /*force*/);
// We have deferred all notifications to the target app as a part of the recents animation,
@@ -494,6 +493,11 @@ public class RecentsAnimationController implements DeathRecipient {
@Override
public void binderDied() {
cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "binderDied");
// Clear associated input consumers on runner death
final InputMonitor inputMonitor =
mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
inputMonitor.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
}
void checkAnimationReady(WallpaperController wallpaperController) {
@@ -516,8 +520,14 @@ public class RecentsAnimationController implements DeathRecipient {
&& isTargetOverWallpaper();
}
boolean hasInputConsumerForApp(AppWindowToken appToken) {
return mInputConsumerEnabled && isAnimatingApp(appToken);
/**
* @return Whether to use the input consumer to override app input to route home/recents.
*/
boolean shouldApplyInputConsumer(AppWindowToken appToken) {
// Only apply the input consumer if it is enabled, it is not the target (home/recents)
// being revealed with the transition, and we are actively animating the app as a part of
// the animation
return mInputConsumerEnabled && mTargetAppToken != appToken && isAnimatingApp(appToken);
}
boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
@@ -675,6 +685,7 @@ public class RecentsAnimationController implements DeathRecipient {
final String innerPrefix = prefix + " ";
pw.print(prefix); pw.println(RecentsAnimationController.class.getSimpleName() + ":");
pw.print(innerPrefix); pw.println("mPendingStart=" + mPendingStart);
pw.print(innerPrefix); pw.println("mPendingAnimations=" + mPendingAnimations.size());
pw.print(innerPrefix); pw.println("mCanceled=" + mCanceled);
pw.print(innerPrefix); pw.println("mInputConsumerEnabled=" + mInputConsumerEnabled);
pw.print(innerPrefix); pw.println("mSplitScreenMinimized=" + mSplitScreenMinimized);

View File

@@ -2685,8 +2685,9 @@ public class WindowManagerService extends IWindowManager.Stub
public void cleanupRecentsAnimation(@RecentsAnimationController.ReorderMode int reorderMode) {
synchronized (mWindowMap) {
if (mRecentsAnimationController != null) {
mRecentsAnimationController.cleanupAnimation(reorderMode);
final RecentsAnimationController controller = mRecentsAnimationController;
mRecentsAnimationController = null;
controller.cleanupAnimation(reorderMode);
mAppTransition.updateBooster();
}
}