RESTRICT AUTOMERGE 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 Test: WindowInputTests Change-Id: I70de9835c7699fe6f56fc3655b0fee5c317ecc3a
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package android.view;
|
package android.view;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,17 +32,20 @@ public final class InputApplicationHandle {
|
|||||||
private long ptr;
|
private long ptr;
|
||||||
|
|
||||||
// Application name.
|
// Application name.
|
||||||
public String name;
|
public final @NonNull String name;
|
||||||
|
|
||||||
// Dispatching timeout.
|
// Dispatching timeout.
|
||||||
public long dispatchingTimeoutNanos;
|
public final long dispatchingTimeoutNanos;
|
||||||
|
|
||||||
public final IBinder token;
|
public final IBinder token;
|
||||||
|
|
||||||
private native void nativeDispose();
|
private native void nativeDispose();
|
||||||
|
|
||||||
public InputApplicationHandle(IBinder token) {
|
public InputApplicationHandle(@NonNull IBinder token, @NonNull String name,
|
||||||
|
long dispatchingTimeoutNanos) {
|
||||||
this.token = token;
|
this.token = token;
|
||||||
|
this.name = name;
|
||||||
|
this.dispatchingTimeoutNanos = dispatchingTimeoutNanos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputApplicationHandle(InputApplicationHandle handle) {
|
public InputApplicationHandle(InputApplicationHandle handle) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public final class InputWindowHandle {
|
|||||||
private long ptr;
|
private long ptr;
|
||||||
|
|
||||||
// The input application handle.
|
// 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
|
// 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.
|
// channel and the server input channel will both contain this token.
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ bool NativeInputApplicationHandle::updateInfo() {
|
|||||||
if (!obj) {
|
if (!obj) {
|
||||||
return false;
|
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>");
|
mInfo.name = getStringField(env, obj, gInputApplicationHandleClassInfo.name, "<null>");
|
||||||
|
|
||||||
|
|||||||
@@ -416,7 +416,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
// mOccludesParent field.
|
// mOccludesParent field.
|
||||||
final boolean hasWallpaper;
|
final boolean hasWallpaper;
|
||||||
// Input application handle used by the input dispatcher.
|
// 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 launchedFromPid; // always the pid who started the activity.
|
||||||
final int launchedFromUid; // always the uid who started the activity.
|
final int launchedFromUid; // always the uid who started the activity.
|
||||||
@@ -1501,7 +1501,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
info = aInfo;
|
info = aInfo;
|
||||||
mUserId = UserHandle.getUserId(info.applicationInfo.uid);
|
mUserId = UserHandle.getUserId(info.applicationInfo.uid);
|
||||||
packageName = info.applicationInfo.packageName;
|
packageName = info.applicationInfo.packageName;
|
||||||
mInputApplicationHandle = new InputApplicationHandle(appToken);
|
|
||||||
intent = _intent;
|
intent = _intent;
|
||||||
|
|
||||||
// If the class name in the intent doesn't match that of the target, this is probably an
|
// If the class name in the intent doesn't match that of the target, this is probably an
|
||||||
@@ -1685,6 +1684,21 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
return lockTaskLaunchMode;
|
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
|
@Override
|
||||||
ActivityRecord asActivityRecord() {
|
ActivityRecord asActivityRecord() {
|
||||||
// I am an activity record!
|
// I am an activity record!
|
||||||
|
|||||||
@@ -269,10 +269,8 @@ class DragState {
|
|||||||
mInputEventReceiver = new DragInputEventReceiver(mClientChannel,
|
mInputEventReceiver = new DragInputEventReceiver(mClientChannel,
|
||||||
mService.mH.getLooper(), mDragDropController);
|
mService.mH.getLooper(), mDragDropController);
|
||||||
|
|
||||||
mDragApplicationHandle = new InputApplicationHandle(new Binder());
|
mDragApplicationHandle = new InputApplicationHandle(new Binder(), "drag",
|
||||||
mDragApplicationHandle.name = "drag";
|
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS);
|
||||||
mDragApplicationHandle.dispatchingTimeoutNanos =
|
|
||||||
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
|
|
||||||
|
|
||||||
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle,
|
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle,
|
||||||
display.getDisplayId());
|
display.getDisplayId());
|
||||||
|
|||||||
@@ -67,10 +67,8 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
|
|||||||
}
|
}
|
||||||
mService.mInputManager.registerInputChannel(mServerChannel);
|
mService.mInputManager.registerInputChannel(mServerChannel);
|
||||||
|
|
||||||
mApplicationHandle = new InputApplicationHandle(new Binder());
|
mApplicationHandle = new InputApplicationHandle(new Binder(), name,
|
||||||
mApplicationHandle.name = name;
|
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS);
|
||||||
mApplicationHandle.dispatchingTimeoutNanos =
|
|
||||||
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
|
|
||||||
|
|
||||||
mWindowHandle = new InputWindowHandle(mApplicationHandle, displayId);
|
mWindowHandle = new InputWindowHandle(mApplicationHandle, displayId);
|
||||||
mWindowHandle.name = name;
|
mWindowHandle.name = name;
|
||||||
|
|||||||
@@ -258,6 +258,8 @@ final class InputMonitor {
|
|||||||
final boolean hasFocus, final boolean hasWallpaper) {
|
final boolean hasFocus, final boolean hasWallpaper) {
|
||||||
// Add a window to our list of input windows.
|
// Add a window to our list of input windows.
|
||||||
inputWindowHandle.name = child.toString();
|
inputWindowHandle.name = child.toString();
|
||||||
|
inputWindowHandle.inputApplicationHandle = child.mActivityRecord != null
|
||||||
|
? child.mActivityRecord.getInputApplicationHandle(false /* update */) : null;
|
||||||
flags = child.getSurfaceTouchableRegion(inputWindowHandle, flags);
|
flags = child.getSurfaceTouchableRegion(inputWindowHandle, flags);
|
||||||
inputWindowHandle.layoutParamsFlags = flags;
|
inputWindowHandle.layoutParamsFlags = flags;
|
||||||
inputWindowHandle.layoutParamsType = type;
|
inputWindowHandle.layoutParamsType = type;
|
||||||
@@ -376,15 +378,8 @@ final class InputMonitor {
|
|||||||
|
|
||||||
public void setFocusedAppLw(ActivityRecord newApp) {
|
public void setFocusedAppLw(ActivityRecord newApp) {
|
||||||
// Focused app has changed.
|
// Focused app has changed.
|
||||||
if (newApp == null) {
|
mService.mInputManager.setFocusedApplication(mDisplayId,
|
||||||
mService.mInputManager.setFocusedApplication(mDisplayId, null);
|
newApp != null ? newApp.getInputApplicationHandle(true /* update */) : null);
|
||||||
} else {
|
|
||||||
final InputApplicationHandle handle = newApp.mInputApplicationHandle;
|
|
||||||
handle.name = newApp.toString();
|
|
||||||
handle.dispatchingTimeoutNanos = newApp.mInputDispatchingTimeoutNanos;
|
|
||||||
|
|
||||||
mService.mInputManager.setFocusedApplication(mDisplayId, handle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pauseDispatchingLw(WindowToken window) {
|
public void pauseDispatchingLw(WindowToken window) {
|
||||||
|
|||||||
@@ -228,10 +228,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
|||||||
mClientChannel, mService.mAnimationHandler.getLooper(),
|
mClientChannel, mService.mAnimationHandler.getLooper(),
|
||||||
mService.mAnimator.getChoreographer());
|
mService.mAnimator.getChoreographer());
|
||||||
|
|
||||||
mDragApplicationHandle = new InputApplicationHandle(new Binder());
|
mDragApplicationHandle = new InputApplicationHandle(new Binder(), TAG,
|
||||||
mDragApplicationHandle.name = TAG;
|
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS);
|
||||||
mDragApplicationHandle.dispatchingTimeoutNanos =
|
|
||||||
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
|
|
||||||
|
|
||||||
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle,
|
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle,
|
||||||
displayContent.getDisplayId());
|
displayContent.getDisplayId());
|
||||||
|
|||||||
@@ -942,7 +942,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
|||||||
mLastRequestedHeight = 0;
|
mLastRequestedHeight = 0;
|
||||||
mLayer = 0;
|
mLayer = 0;
|
||||||
mInputWindowHandle = new InputWindowHandle(
|
mInputWindowHandle = new InputWindowHandle(
|
||||||
mActivityRecord != null ? mActivityRecord.mInputApplicationHandle : null,
|
mActivityRecord != null ?
|
||||||
|
mActivityRecord.getInputApplicationHandle(false /* update */) : null,
|
||||||
getDisplayId());
|
getDisplayId());
|
||||||
|
|
||||||
// Make sure we initial all fields before adding to parentWindow, to prevent exception
|
// Make sure we initial all fields before adding to parentWindow, to prevent exception
|
||||||
|
|||||||
Reference in New Issue
Block a user