Use binder tokens to remove its gesture monitors if a process dies

Bug: 162194035
Test: manual: "adb shell am crash com.android.systemui" and observe its
gesture monitors are removed through dumpsys input

Change-Id: I02a480dd8e4b98a9911d976de2684d283c9e7d8b
This commit is contained in:
Prabir Pradhan
2021-11-23 10:26:38 -08:00
parent 88f9f15233
commit c809658285
5 changed files with 37 additions and 16 deletions

View File

@@ -112,7 +112,7 @@ interface IInputManager {
oneway void requestPointerCapture(IBinder inputChannelToken, boolean enabled);
/** Create an input monitor for gestures. */
InputMonitor monitorGestureInput(String name, int displayId);
InputMonitor monitorGestureInput(IBinder token, String name, int displayId);
// Add a runtime association between the input port and the display port. This overrides any
// static associations.

View File

@@ -35,6 +35,7 @@ import android.hardware.lights.Light;
import android.hardware.lights.LightState;
import android.hardware.lights.LightsManager;
import android.hardware.lights.LightsRequest;
import android.os.Binder;
import android.os.BlockUntrustedTouchesMode;
import android.os.Build;
import android.os.CombinedVibration;
@@ -1211,7 +1212,7 @@ public final class InputManager {
*/
public InputMonitor monitorGestureInput(String name, int displayId) {
try {
return mIm.monitorGestureInput(name, displayId);
return mIm.monitorGestureInput(new Binder(), name, displayId);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}

View File

@@ -79,13 +79,17 @@ public final class InputMonitor implements Parcelable {
// Code below generated by codegen v1.0.7.
// Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
//
// To regenerate run:
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/InputMonitor.java
//
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
// Settings > Editor > Code Style > Formatter Control
//@formatter:off
@DataClass.Generated.Member
@@ -126,7 +130,7 @@ public final class InputMonitor implements Parcelable {
@Override
@DataClass.Generated.Member
public void writeToParcel(Parcel dest, int flags) {
public void writeToParcel(@NonNull Parcel dest, int flags) {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
@@ -141,7 +145,7 @@ public final class InputMonitor implements Parcelable {
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
/* package-private */ InputMonitor(Parcel in) {
/* package-private */ InputMonitor(@NonNull Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
@@ -167,17 +171,21 @@ public final class InputMonitor implements Parcelable {
}
@Override
public InputMonitor createFromParcel(Parcel in) {
public InputMonitor createFromParcel(@NonNull Parcel in) {
return new InputMonitor(in);
}
};
@DataClass.Generated(
time = 1571177265149L,
codegenVersion = "1.0.7",
time = 1637697281750L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/view/InputMonitor.java",
inputSignatures = "private static final java.lang.String TAG\nprivate static final boolean DEBUG\nprivate final @android.annotation.NonNull android.view.InputChannel mInputChannel\nprivate final @android.annotation.NonNull android.view.IInputMonitorHost mHost\npublic void pilferPointers()\npublic void dispose()\nclass InputMonitor extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true)")
@Deprecated
private void __metadata() {}
//@formatter:on
// End of generated code
}

View File

@@ -18,6 +18,7 @@ package com.android.server.input;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import android.os.IBinder;
import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputMonitor;
@@ -37,12 +38,14 @@ class GestureMonitorSpyWindow {
final InputApplicationHandle mApplicationHandle;
final InputWindowHandle mWindowHandle;
// The InputChannel and SurfaceControl are owned by this object.
// The token, InputChannel, and SurfaceControl are owned by this object.
final IBinder mMonitorToken;
final InputChannel mClientChannel;
final SurfaceControl mInputSurface;
GestureMonitorSpyWindow(String name, int displayId, int pid, int uid, SurfaceControl sc,
InputChannel inputChannel) {
GestureMonitorSpyWindow(IBinder token, String name, int displayId, int pid, int uid,
SurfaceControl sc, InputChannel inputChannel) {
mMonitorToken = token;
mClientChannel = inputChannel;
mInputSurface = sc;

View File

@@ -725,8 +725,8 @@ public class InputManagerService extends IInputManager.Stub
}
@NonNull
private InputChannel createSpyWindowGestureMonitor(String name, int displayId, int pid,
int uid) {
private InputChannel createSpyWindowGestureMonitor(IBinder monitorToken, String name,
int displayId, int pid, int uid) {
final SurfaceControl sc = mWindowManagerCallbacks.createSurfaceForGestureMonitor(name,
displayId);
if (sc == null) {
@@ -735,9 +735,16 @@ public class InputManagerService extends IInputManager.Stub
}
final InputChannel channel = createInputChannel(name);
try {
monitorToken.linkToDeath(() -> removeSpyWindowGestureMonitor(channel.getToken()), 0);
} catch (RemoteException e) {
Slog.i(TAG, "Client died before '" + name + "' could be created.");
return null;
}
synchronized (mInputMonitors) {
mInputMonitors.put(channel.getToken(),
new GestureMonitorSpyWindow(name, displayId, pid, uid, sc, channel));
new GestureMonitorSpyWindow(monitorToken, name, displayId, pid, uid, sc,
channel));
}
final InputChannel outInputChannel = new InputChannel();
@@ -764,12 +771,14 @@ public class InputManagerService extends IInputManager.Stub
* @return The input channel.
*/
@Override // Binder call
public InputMonitor monitorGestureInput(@NonNull String requestedName, int displayId) {
public InputMonitor monitorGestureInput(IBinder monitorToken, @NonNull String requestedName,
int displayId) {
if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT,
"monitorGestureInput()")) {
throw new SecurityException("Requires MONITOR_INPUT permission");
}
Objects.requireNonNull(requestedName, "name must not be null.");
Objects.requireNonNull(monitorToken, "token must not be null.");
if (displayId < Display.DEFAULT_DISPLAY) {
throw new IllegalArgumentException("displayId must >= 0.");
@@ -782,7 +791,7 @@ public class InputManagerService extends IInputManager.Stub
try {
final InputChannel inputChannel =
USE_SPY_WINDOW_GESTURE_MONITORS
? createSpyWindowGestureMonitor(name, displayId, pid, uid)
? createSpyWindowGestureMonitor(monitorToken, name, displayId, pid, uid)
: nativeCreateInputMonitor(mPtr, displayId, true /*isGestureMonitor*/,
requestedName, pid);
return new InputMonitor(inputChannel, new InputMonitorHost(inputChannel.getToken()));