From 84dec9f7c6a5ecf4ebfe7532c89728e2283d135a Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 22 Apr 2019 13:39:46 -0700 Subject: [PATCH] Added direct call to syncInputTransactions Previously, there was only a way to inject input after syncing inputs. However, some tests require a direct call to sync inputs since we need to ensure the info was propagated to InputManager native before continuing with the test. This exposes a method just to syncInputTransactions. Bug: 130695122 Test: ActivityLifecycleTopResumedStateTests Test: MultiDisplayPolicyTests Change-Id: Ie3115741a20d04c743fd854ac421dc3705332488 --- api/test-current.txt | 1 + .../android/app/IUiAutomationConnection.aidl | 1 + core/java/android/app/UiAutomation.java | 19 ++++++++++++++ .../android/app/UiAutomationConnection.java | 25 +++++++++++++------ core/java/android/view/IWindowManager.aidl | 11 +++++++- .../server/wm/WindowManagerService.java | 22 +++++++++------- 6 files changed, 62 insertions(+), 17 deletions(-) diff --git a/api/test-current.txt b/api/test-current.txt index 63c8df047f902..a665c0af8fb34 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -369,6 +369,7 @@ package android.app { method public android.os.ParcelFileDescriptor[] executeShellCommandRw(String); method @Deprecated public boolean grantRuntimePermission(String, String, android.os.UserHandle); method @Deprecated public boolean revokeRuntimePermission(String, String, android.os.UserHandle); + method public void syncInputTransactions(); } public class UiModeManager { diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl index 96da72a1b5176..8c3180b400efb 100644 --- a/core/java/android/app/IUiAutomationConnection.aidl +++ b/core/java/android/app/IUiAutomationConnection.aidl @@ -37,6 +37,7 @@ interface IUiAutomationConnection { void connect(IAccessibilityServiceClient client, int flags); void disconnect(); boolean injectInputEvent(in InputEvent event, boolean sync); + void syncInputTransactions(); boolean setRotation(int rotation); Bitmap takeScreenshot(in Rect crop, int rotation); boolean clearWindowContentFrameStats(int windowId); diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index 494467324581e..3935628b707f7 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -601,6 +601,25 @@ public final class UiAutomation { return false; } + /** + * A request for WindowManagerService to wait until all animations have completed and input + * information has been sent from WindowManager to native InputManager. + * + * @hide + */ + @TestApi + public void syncInputTransactions() { + synchronized (mLock) { + throwIfNotConnectedLocked(); + } + try { + // Calling out without a lock held. + mUiAutomationConnection.syncInputTransactions(); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error while syncing input transactions!", re); + } + } + /** * Sets the device rotation. A client can freeze the rotation in * desired state or freeze the rotation to its current state or diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index 7e074460bff82..dc07df8d7a874 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -128,18 +128,29 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { : InputManager.INJECT_INPUT_EVENT_MODE_ASYNC; final long identity = Binder.clearCallingIdentity(); try { - IWindowManager manager = IWindowManager.Stub.asInterface( - ServiceManager.getService(Context.WINDOW_SERVICE)); - try { - return manager.injectInputAfterTransactionsApplied(event, mode); - } catch (RemoteException e) { - } - return false; + return mWindowManager.injectInputAfterTransactionsApplied(event, mode); + } catch (RemoteException e) { } finally { Binder.restoreCallingIdentity(identity); } + return false; } + @Override + public void syncInputTransactions() { + synchronized (mLock) { + throwIfCalledByNotTrustedUidLocked(); + throwIfShutdownLocked(); + throwIfNotConnectedLocked(); + } + + try { + mWindowManager.syncInputTransactions(); + } catch (RemoteException e) { + } + } + + @Override public boolean setRotation(int rotation) { synchronized (mLock) { diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 6c37319c63033..c730fe2dc114d 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -640,5 +640,14 @@ interface IWindowManager * This is needed for testing since the system add windows and injects input * quick enough that the windows don't have time to get sent to InputManager. */ - boolean injectInputAfterTransactionsApplied(in InputEvent ev, int mode); + boolean injectInputAfterTransactionsApplied(in InputEvent ev, int mode); + + /** + * Waits until all animations have completed and input information has been sent from + * WindowManager to native InputManager. + * + * This is needed for testing since we need to ensure input information has been propagated to + * native InputManager before proceeding with tests. + */ + void syncInputTransactions(); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d46aa7bdcaeb3..dae29b2cf1803 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7550,20 +7550,24 @@ public class WindowManagerService extends IWindowManager.Stub } if (shouldWaitForAnimToComplete) { - waitForAnimationsToComplete(); - - synchronized (mGlobalLock) { - mWindowPlacerLocked.performSurfacePlacementIfScheduled(); - mRoot.forAllDisplays(displayContent -> - displayContent.getInputMonitor().updateInputWindowsImmediately()); - } - - new SurfaceControl.Transaction().syncInputWindows().apply(true); + syncInputTransactions(); } return LocalServices.getService(InputManagerInternal.class).injectInputEvent(ev, mode); } + @Override + public void syncInputTransactions() { + waitForAnimationsToComplete(); + + synchronized (mGlobalLock) { + mWindowPlacerLocked.performSurfacePlacementIfScheduled(); + mRoot.forAllDisplays(displayContent -> + displayContent.getInputMonitor().updateInputWindowsImmediately()); + } + new SurfaceControl.Transaction().syncInputWindows().apply(true); + } + private void waitForAnimationsToComplete() { synchronized (mGlobalLock) { long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS;