Only update native InputApplicationHandle once This makes sure the write operation (NativeInputApplicationHandle ::updateInfo) is always called from window manager side once when calling SurfaceControl.Transaction#setInputWindowInfo or InputManagerService#setFocusedApplication. If the info of input application handle is changed, a new instance will be created. That avoids the race condition of reading the fields of the same InputApplicationInfo instance from input dispatcher. Bug: 171857140 Bug: 161334769 Bug: 174768985 Test: WindowInputTests Merged-In: Ief84bbe6e6fa4da5309912059904932ccf775b75 Merged-In: I70de9835c7699fe6f56fc3655b0fee5c317ecc3a Change-Id: I70de9835c7699fe6f56fc3655b0fee5c317ecc3a (cherry picked from commit a68473ce978f3e3ad73bd127cdcfcf663d9fd4d9)
diff --git a/core/java/android/view/InputApplicationHandle.java b/core/java/android/view/InputApplicationHandle.java index 3d05e2a..9b96f7f 100644 --- a/core/java/android/view/InputApplicationHandle.java +++ b/core/java/android/view/InputApplicationHandle.java
@@ -16,6 +16,7 @@ package android.view; +import android.annotation.NonNull; import android.os.IBinder; /** @@ -31,17 +32,20 @@ private long ptr; // Application name. - public String name; + public final @NonNull String name; // Dispatching timeout. - public long dispatchingTimeoutNanos; + public final long dispatchingTimeoutNanos; public final IBinder token; private native void nativeDispose(); - public InputApplicationHandle(IBinder token) { + public InputApplicationHandle(@NonNull IBinder token, @NonNull String name, + long dispatchingTimeoutNanos) { this.token = token; + this.name = name; + this.dispatchingTimeoutNanos = dispatchingTimeoutNanos; } public InputApplicationHandle(InputApplicationHandle handle) {
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java index 5f74b2a..71d26b8 100644 --- a/core/java/android/view/InputWindowHandle.java +++ b/core/java/android/view/InputWindowHandle.java
@@ -36,7 +36,7 @@ private long ptr; // The input application handle. - public final InputApplicationHandle inputApplicationHandle; + public InputApplicationHandle inputApplicationHandle; // The token associates input data with a window and its input channel. The client input // channel and the server input channel will both contain this token.
diff --git a/core/jni/android_hardware_input_InputApplicationHandle.cpp b/core/jni/android_hardware_input_InputApplicationHandle.cpp index 71edfd5..c1ecae8 100644 --- a/core/jni/android_hardware_input_InputApplicationHandle.cpp +++ b/core/jni/android_hardware_input_InputApplicationHandle.cpp
@@ -58,6 +58,11 @@ if (!obj) { return false; } + if (mInfo.token.get() != nullptr) { + // The java fields are immutable, so it doesn't need to update again. + env->DeleteLocalRef(obj); + return true; + } mInfo.name = getStringField(env, obj, gInputApplicationHandleClassInfo.name, "<null>");
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 1a13d0f..dc4caf8 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -416,7 +416,7 @@ // mOccludesParent field. final boolean hasWallpaper; // Input application handle used by the input dispatcher. - final InputApplicationHandle mInputApplicationHandle; + private InputApplicationHandle mInputApplicationHandle; final int launchedFromPid; // always the pid who started the activity. final int launchedFromUid; // always the uid who started the activity. @@ -1501,7 +1501,6 @@ info = aInfo; mUserId = UserHandle.getUserId(info.applicationInfo.uid); packageName = info.applicationInfo.packageName; - mInputApplicationHandle = new InputApplicationHandle(appToken); intent = _intent; // If the class name in the intent doesn't match that of the target, this is probably an @@ -1686,6 +1685,21 @@ return lockTaskLaunchMode; } + @NonNull InputApplicationHandle getInputApplicationHandle(boolean update) { + if (mInputApplicationHandle == null) { + mInputApplicationHandle = new InputApplicationHandle(appToken, toString(), + mInputDispatchingTimeoutNanos); + } else if (update) { + final String name = toString(); + if (mInputDispatchingTimeoutNanos != mInputApplicationHandle.dispatchingTimeoutNanos + || !name.equals(mInputApplicationHandle.name)) { + mInputApplicationHandle = new InputApplicationHandle(appToken, name, + mInputDispatchingTimeoutNanos); + } + } + return mInputApplicationHandle; + } + @Override ActivityRecord asActivityRecord() { // I am an activity record!
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index f840d92..7b562a9 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java
@@ -269,10 +269,8 @@ mInputEventReceiver = new DragInputEventReceiver(mClientChannel, mService.mH.getLooper(), mDragDropController); - mDragApplicationHandle = new InputApplicationHandle(new Binder()); - mDragApplicationHandle.name = "drag"; - mDragApplicationHandle.dispatchingTimeoutNanos = - WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + mDragApplicationHandle = new InputApplicationHandle(new Binder(), "drag", + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS); mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, display.getDisplayId());
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java index 3b39b6b..1918573 100644 --- a/services/core/java/com/android/server/wm/InputConsumerImpl.java +++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -67,10 +67,8 @@ } mService.mInputManager.registerInputChannel(mServerChannel); - mApplicationHandle = new InputApplicationHandle(new Binder()); - mApplicationHandle.name = name; - mApplicationHandle.dispatchingTimeoutNanos = - WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + mApplicationHandle = new InputApplicationHandle(new Binder(), name, + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS); mWindowHandle = new InputWindowHandle(mApplicationHandle, displayId); mWindowHandle.name = name;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 3663ee1..8366fde 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -43,7 +43,6 @@ import android.os.UserHandle; import android.util.ArrayMap; import android.util.Slog; -import android.view.InputApplicationHandle; import android.view.InputChannel; import android.view.InputEventReceiver; import android.view.InputWindowHandle; @@ -268,6 +267,8 @@ final boolean hasFocus, final boolean hasWallpaper) { // Add a window to our list of input windows. inputWindowHandle.name = child.toString(); + inputWindowHandle.inputApplicationHandle = child.mActivityRecord != null + ? child.mActivityRecord.getInputApplicationHandle(false /* update */) : null; flags = child.getSurfaceTouchableRegion(inputWindowHandle, flags); inputWindowHandle.layoutParamsFlags = flags; inputWindowHandle.layoutParamsType = type; @@ -386,15 +387,8 @@ public void setFocusedAppLw(ActivityRecord newApp) { // Focused app has changed. - if (newApp == null) { - mService.mInputManager.setFocusedApplication(mDisplayId, null); - } else { - final InputApplicationHandle handle = newApp.mInputApplicationHandle; - handle.name = newApp.toString(); - handle.dispatchingTimeoutNanos = newApp.mInputDispatchingTimeoutNanos; - - mService.mInputManager.setFocusedApplication(mDisplayId, handle); - } + mService.mInputManager.setFocusedApplication(mDisplayId, + newApp != null ? newApp.getInputApplicationHandle(true /* update */) : null); } public void pauseDispatchingLw(WindowToken window) {
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index c68b660..44f4a58 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -228,10 +228,8 @@ mClientChannel, mService.mAnimationHandler.getLooper(), mService.mAnimator.getChoreographer()); - mDragApplicationHandle = new InputApplicationHandle(new Binder()); - mDragApplicationHandle.name = TAG; - mDragApplicationHandle.dispatchingTimeoutNanos = - WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + mDragApplicationHandle = new InputApplicationHandle(new Binder(), TAG, + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS); mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, displayContent.getDisplayId());
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index bab83dc..faa483a 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -943,7 +943,8 @@ mLastRequestedHeight = 0; mLayer = 0; mInputWindowHandle = new InputWindowHandle( - mActivityRecord != null ? mActivityRecord.mInputApplicationHandle : null, + mActivityRecord != null + ? mActivityRecord.getInputApplicationHandle(false /* update */) : null, getDisplayId()); // Make sure we initial all fields before adding to parentWindow, to prevent exception