Move touch blocking into InputDispatcher

Remove the InputHandle from ActivityRecordInputSink and instead set
NO_INPUT_CHANNEL and let InputDispatcher drop the touches.

When touches are blocked InputDispatcher logs something like:
03-04 11:36:46.974 16299 16431 W InputDispatcher: Not sending touch gesture to f619bcf ActivityRecordInputSink .FocusTouchActivity because it is not responsive
03-04 11:36:47.155 16299 16431 W InputDispatcher: Not sending touch gesture to f619bcf ActivityRecordInputSink .FocusTouchActivity because it is not responsive

Bug: 194480991
Bug: 222292477
Test: Manually tested that blocking still works
Test: atest android.server.wm.WindowUntrustedTouchTest
Test: atest InputSurfacesTest
Change-Id: If7d9503cb573fbd56f6f9e9eb2dee6298ac1f948
This commit is contained in:
Linus Tufvesson
2022-03-04 09:18:36 +00:00
parent 7884c848df
commit 84705ae31f

View File

@@ -18,20 +18,11 @@ package com.android.server.wm;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.os.IBinder;
import android.os.InputConfig;
import android.os.InputConstants;
import android.os.Looper;
import android.os.Process;
import android.util.Slog;
import android.view.InputChannel;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.widget.Toast;
/**
* Creates a InputWindowHandle that catches all touches that would otherwise pass through an
@@ -45,20 +36,12 @@ class ActivityRecordInputSink {
@ChangeId
static final long ENABLE_TOUCH_OPAQUE_ACTIVITIES = 194480991L;
private static final String TAG = "ActivityRecordInputSink";
private static final int NUMBER_OF_TOUCHES_TO_DISABLE = 3;
private static final long TOAST_COOL_DOWN_MILLIS = 3000L;
private final ActivityRecord mActivityRecord;
private final boolean mIsCompatEnabled;
private final String mName;
// Hold on to InputEventReceiver to prevent it from getting GCd.
private InputEventReceiver mInputEventReceiver;
private InputWindowHandleWrapper mInputWindowHandleWrapper;
private SurfaceControl mSurfaceControl;
private int mRapidTouchCount = 0;
private IBinder mToken;
private boolean mDisabled = false;
ActivityRecordInputSink(ActivityRecord activityRecord) {
@@ -66,7 +49,7 @@ class ActivityRecordInputSink {
mIsCompatEnabled = CompatChanges.isChangeEnabled(ENABLE_TOUCH_OPAQUE_ACTIVITIES,
mActivityRecord.getUid());
mName = Integer.toHexString(System.identityHashCode(this)) + " ActivityRecordInputSink "
+ mActivityRecord.mActivityComponent.getShortClassName();
+ mActivityRecord.mActivityComponent.flattenToShortString();
}
public void applyChangesToSurfaceIfChanged(SurfaceControl.Transaction transaction) {
@@ -93,16 +76,13 @@ class ActivityRecordInputSink {
private InputWindowHandleWrapper getInputWindowHandleWrapper() {
if (mInputWindowHandleWrapper == null) {
mInputWindowHandleWrapper = new InputWindowHandleWrapper(createInputWindowHandle());
InputChannel inputChannel =
mActivityRecord.mWmService.mInputManager.createInputChannel(mName);
mToken = inputChannel.getToken();
mInputEventReceiver = createInputEventReceiver(inputChannel);
}
if (mDisabled || !mIsCompatEnabled || mActivityRecord.isInTransition()) {
// TODO(b/208662670): Investigate if we can have feature active during animations.
mInputWindowHandleWrapper.setToken(null);
mInputWindowHandleWrapper.setInputConfigMasked(InputConfig.NOT_TOUCHABLE,
InputConfig.NOT_TOUCHABLE);
} else {
mInputWindowHandleWrapper.setToken(mToken);
mInputWindowHandleWrapper.setInputConfigMasked(0, InputConfig.NOT_TOUCHABLE);
}
return mInputWindowHandleWrapper;
}
@@ -115,58 +95,8 @@ class ActivityRecordInputSink {
inputWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
inputWindowHandle.ownerUid = Process.myUid();
inputWindowHandle.ownerPid = Process.myPid();
inputWindowHandle.dispatchingTimeoutMillis =
InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
inputWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE;
inputWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE | InputConfig.NO_INPUT_CHANNEL;
return inputWindowHandle;
}
private InputEventReceiver createInputEventReceiver(InputChannel inputChannel) {
return new SinkInputEventReceiver(inputChannel,
mActivityRecord.mAtmService.mUiHandler.getLooper());
}
private void showAsToastAndLog(String message) {
Toast.makeText(mActivityRecord.mAtmService.mUiContext, message,
Toast.LENGTH_LONG).show();
Slog.wtf(TAG, message + " " + mActivityRecord.mActivityComponent);
}
private class SinkInputEventReceiver extends InputEventReceiver {
private long mLastToast = 0;
SinkInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
public void onInputEvent(InputEvent event) {
if (!(event instanceof MotionEvent)) {
Slog.wtf(TAG,
"Received InputEvent that was not a MotionEvent");
finishInputEvent(event, true);
return;
}
MotionEvent motionEvent = (MotionEvent) event;
if (motionEvent.getAction() != MotionEvent.ACTION_DOWN) {
finishInputEvent(event, true);
return;
}
if (event.getEventTime() - mLastToast > TOAST_COOL_DOWN_MILLIS) {
String message = "go/activity-touch-opaque - "
+ mActivityRecord.mActivityComponent.getPackageName()
+ " blocked the touch!";
showAsToastAndLog(message);
mLastToast = event.getEventTime();
mRapidTouchCount = 1;
} else if (++mRapidTouchCount >= NUMBER_OF_TOUCHES_TO_DISABLE && !mDisabled) {
// Disable touch blocking until Activity Record is recreated.
String message = "Disabled go/activity-touch-opaque - "
+ mActivityRecord.mActivityComponent.getPackageName();
showAsToastAndLog(message);
mDisabled = true;
}
finishInputEvent(event, true);
}
}
}