diff options
6 files changed, 47 insertions, 76 deletions
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 0b22586bb373..e6129b9b1f32 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -76,7 +76,6 @@ import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; import android.view.InputMonitor; -import android.view.InputWindowHandle; import android.view.KeyEvent; import android.view.PointerIcon; import android.view.Surface; @@ -221,8 +220,7 @@ public class InputManagerService extends IInputManager.Stub int policyFlags); private static native VerifiedInputEvent nativeVerifyInputEvent(long ptr, InputEvent event); private static native void nativeToggleCapsLock(long ptr, int deviceId); - private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles, - int displayId); + private static native void nativeDisplayRemoved(long ptr, int displayId); private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen); private static native void nativeSetSystemUiVisibility(long ptr, int visibility); private static native void nativeSetFocusedApplication(long ptr, @@ -1536,7 +1534,7 @@ public class InputManagerService extends IInputManager.Stub /** Clean up input window handles of the given display. */ public void onDisplayRemoved(int displayId) { - nativeSetInputWindows(mPtr, null /* windowHandles */, displayId); + nativeDisplayRemoved(mPtr, displayId); } @Override diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 88cdd1781aee..18332b9484c0 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -62,7 +62,7 @@ final class InputMonitor { // When true, need to call updateInputWindowsLw(). private boolean mUpdateInputWindowsNeeded = true; private boolean mUpdateInputWindowsPending; - private boolean mApplyImmediately; + private boolean mUpdateInputWindowsImmediately; // Currently focused input window handle. private InputWindowHandle mFocusedInputWindowHandle; @@ -347,14 +347,20 @@ final class InputMonitor { } } - void updateInputWindowsImmediately() { + /** + * Immediately update the input transaction and merge into the passing Transaction that could be + * collected and applied later. + */ + void updateInputWindowsImmediately(SurfaceControl.Transaction t) { mHandler.removeCallbacks(mUpdateInputWindows); - mApplyImmediately = true; + mUpdateInputWindowsImmediately = true; mUpdateInputWindows.run(); - mApplyImmediately = false; + mUpdateInputWindowsImmediately = false; + t.merge(mInputTransaction); } - /* Called when the current input focus changes. + /** + * Called when the current input focus changes. * Layer assignment is assumed to be complete by the time this is called. */ public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) { @@ -465,10 +471,7 @@ final class InputMonitor { if (mAddWallpaperInputConsumerHandle) { mWallpaperInputConsumer.show(mInputTransaction, 0); } - - if (mApplyImmediately) { - mInputTransaction.apply(); - } else { + if (!mUpdateInputWindowsImmediately) { mDisplayContent.getPendingTransaction().merge(mInputTransaction); mDisplayContent.scheduleAnimation(); } diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index f046e8adc478..be0d6f8a0b9f 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -268,8 +268,9 @@ class TaskPositioner implements IBinder.DeathRecipient { mDisplayContent.getDisplayRotation().pause(); // Notify InputMonitor to take mDragWindowHandle. - mDisplayContent.getInputMonitor().updateInputWindowsImmediately(); - new SurfaceControl.Transaction().syncInputWindows().apply(true); + final SurfaceControl.Transaction t = mService.mTransactionFactory.get(); + mDisplayContent.getInputMonitor().updateInputWindowsImmediately(t); + t.syncInputWindows().apply(); final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics(); mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics); diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 0b11dd28e595..92a9e30c2f0a 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -75,6 +75,7 @@ public class WindowAnimator { * vsync-app and then schedule the animation tick at the right time (vsync-sf). */ private boolean mAnimationFrameCallbackScheduled; + boolean mNotifyWhenNoAnimation = false; /** * A list of runnable that need to be run after {@link WindowContainer#prepareSurfaces} is @@ -97,6 +98,9 @@ public class WindowAnimator { synchronized (mService.mGlobalLock) { mAnimationFrameCallbackScheduled = false; animate(frameTimeNs); + if (mNotifyWhenNoAnimation && !mLastRootAnimating) { + mService.mGlobalLock.notifyAll(); + } } }; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b1f22f8623d6..8e457522c4b0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -193,7 +193,6 @@ import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DisplayMetrics; -import android.util.Log; import android.util.MergedConfiguration; import android.util.Slog; import android.util.SparseArray; @@ -7734,19 +7733,30 @@ public class WindowManagerService extends IWindowManager.Stub public void syncInputTransactions() { waitForAnimationsToComplete(); + // Collect all input transactions from all displays to make sure we could sync all input + // windows at same time. + final SurfaceControl.Transaction t = mTransactionFactory.get(); synchronized (mGlobalLock) { mWindowPlacerLocked.performSurfacePlacementIfScheduled(); mRoot.forAllDisplays(displayContent -> - displayContent.getInputMonitor().updateInputWindowsImmediately()); + displayContent.getInputMonitor().updateInputWindowsImmediately(t)); } - mTransactionFactory.get().syncInputWindows().apply(true); + t.syncInputWindows().apply(); } + /** + * Wait until all container animations and surface operations behalf of WindowManagerService + * complete. + */ private void waitForAnimationsToComplete() { synchronized (mGlobalLock) { long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS; - while (mRoot.isAnimating(TRANSITION | CHILDREN) && timeoutRemaining > 0) { + // This could prevent if there is no container animation, we still have to apply the + // pending transaction and exit waiting. + mAnimator.mNotifyWhenNoAnimation = true; + while ((mAnimator.isAnimationScheduled() + || mRoot.isAnimating(TRANSITION | CHILDREN)) && timeoutRemaining > 0) { long startTime = System.currentTimeMillis(); try { mGlobalLock.wait(timeoutRemaining); @@ -7754,9 +7764,11 @@ public class WindowManagerService extends IWindowManager.Stub } timeoutRemaining -= (System.currentTimeMillis() - startTime); } + mAnimator.mNotifyWhenNoAnimation = false; - if (mRoot.isAnimating(TRANSITION | CHILDREN)) { - Log.w(TAG, "Timed out waiting for animations to complete."); + if (mAnimator.isAnimationScheduled() + || mRoot.isAnimating(TRANSITION | CHILDREN)) { + Slog.w(TAG, "Timed out waiting for animations to complete."); } } } diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index e3f9ae8969b3..9bc5d34c11af 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -206,7 +206,7 @@ public: status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel); status_t pilferPointers(const sp<IBinder>& token); - void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId); + void displayRemoved(JNIEnv* env, int32_t displayId); void setFocusedApplication(JNIEnv* env, int32_t displayId, jobject applicationHandleObj); void setFocusedDisplay(JNIEnv* env, int32_t displayId); void setInputDispatchMode(bool enabled, bool frozen); @@ -771,55 +771,10 @@ void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration } } -void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, - int32_t displayId) { - std::vector<sp<InputWindowHandle> > windowHandles; - - if (windowHandleObjArray) { - jsize length = env->GetArrayLength(windowHandleObjArray); - for (jsize i = 0; i < length; i++) { - jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i); - if (! windowHandleObj) { - break; // found null element indicating end of used portion of the array - } - - sp<InputWindowHandle> windowHandle = - android_view_InputWindowHandle_getHandle(env, windowHandleObj); - if (windowHandle != nullptr) { - windowHandles.push_back(windowHandle); - } - env->DeleteLocalRef(windowHandleObj); - } - } - - mInputManager->getDispatcher()->setInputWindows(windowHandles, displayId); - - // Do this after the dispatcher has updated the window handle state. - bool newPointerGesturesEnabled = true; - size_t numWindows = windowHandles.size(); - for (size_t i = 0; i < numWindows; i++) { - const sp<InputWindowHandle>& windowHandle = windowHandles[i]; - const InputWindowInfo* windowInfo = windowHandle->getInfo(); - if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures - & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) { - newPointerGesturesEnabled = false; - } - } - - bool pointerGesturesEnabledChanged = false; - { // acquire lock - AutoMutex _l(mLock); - - if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) { - mLocked.pointerGesturesEnabled = newPointerGesturesEnabled; - pointerGesturesEnabledChanged = true; - } - } // release lock - - if (pointerGesturesEnabledChanged) { - mInputManager->getReader()->requestRefreshConfiguration( - InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT); - } +void NativeInputManager::displayRemoved(JNIEnv* env, int32_t displayId) { + // Set an empty list to remove all handles from the specific display. + std::vector<sp<InputWindowHandle>> windowHandles; + mInputManager->getDispatcher()->setInputWindows({{displayId, windowHandles}}); } void NativeInputManager::setFocusedApplication(JNIEnv* env, int32_t displayId, @@ -1567,11 +1522,10 @@ static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */, im->getInputManager()->getReader()->toggleCapsLockState(deviceId); } -static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */, - jlong ptr, jobjectArray windowHandleObjArray, jint displayId) { +static void nativeDisplayRemoved(JNIEnv* env, jclass /* clazz */, jlong ptr, jint displayId) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); - im->setInputWindows(env, windowHandleObjArray, displayId); + im->displayRemoved(env, displayId); } static void nativeSetFocusedApplication(JNIEnv* env, jclass /* clazz */, @@ -1815,8 +1769,7 @@ static const JNINativeMethod gInputManagerMethods[] = { {"nativeVerifyInputEvent", "(JLandroid/view/InputEvent;)Landroid/view/VerifiedInputEvent;", (void*)nativeVerifyInputEvent}, {"nativeToggleCapsLock", "(JI)V", (void*)nativeToggleCapsLock}, - {"nativeSetInputWindows", "(J[Landroid/view/InputWindowHandle;I)V", - (void*)nativeSetInputWindows}, + {"nativeDisplayRemoved", "(JI)V", (void*)nativeDisplayRemoved}, {"nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V", (void*)nativeSetFocusedApplication}, {"nativeSetFocusedDisplay", "(JI)V", (void*)nativeSetFocusedDisplay}, |