From b9d9d7adeb5b6bdf1b95d9d3e27af38f5ae2757b Mon Sep 17 00:00:00 2001 From: Linus Tufvesson Date: Fri, 6 May 2022 16:28:26 +0200 Subject: [PATCH] Allow some cross activity touches Resolve app compatibility issues caused by ActivityRecordInputSink agressivly blocking all touches. This change makes ActivityRecordInputSink more conservable and it now only blocks touches if the touches would otherwise: 1. Cross a task boundry 2. Go to an activity with a different uid AND that activity hasn't explicilty launched an activity with the same uid as this activity Bug: 231701903 Bug: 194480991 Test: atest CtsWindowManagerDeviceTestCases:ActivityRecordInputSinkTests Test: atest CtsWindowManagerDeviceTestCases:CrossAppDragAndDropTests Test: atest CtsWindowManagerDeviceTestCases:PinnedStackTests Test: atest CtsWindowManagerDeviceTestCases:WindowUntrustedTouchTest Change-Id: Icd1668f465ba01b330c056d9ea95aed6104fc6a9 Merged-In: Icd1668f465ba01b330c056d9ea95aed6104fc6a9 --- .../com/android/server/wm/ActivityRecord.java | 7 ++++++- .../server/wm/ActivityRecordInputSink.java | 17 +++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index abbcd28575cdb..2ab1a5fd3e94f 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -926,6 +926,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private final ActivityRecordInputSink mActivityRecordInputSink; + // Activities with this uid are allowed to not create an input sink while being in the same + // task and directly above this ActivityRecord. This field is updated whenever a new activity + // is launched from this ActivityRecord. Touches are always allowed within the same uid. + int mAllowedTouchUid; + private final Runnable mPauseTimeoutRunnable = new Runnable() { @Override public void run() { @@ -2099,7 +2104,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } mAtmService.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, packageName); - mActivityRecordInputSink = new ActivityRecordInputSink(this); + mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord); updateEnterpriseThumbnailDrawable(mAtmService.mUiContext); } diff --git a/services/core/java/com/android/server/wm/ActivityRecordInputSink.java b/services/core/java/com/android/server/wm/ActivityRecordInputSink.java index 23a832496cc9c..fc22e2decbef0 100644 --- a/services/core/java/com/android/server/wm/ActivityRecordInputSink.java +++ b/services/core/java/com/android/server/wm/ActivityRecordInputSink.java @@ -42,14 +42,16 @@ class ActivityRecordInputSink { private InputWindowHandleWrapper mInputWindowHandleWrapper; private SurfaceControl mSurfaceControl; - private boolean mDisabled = false; - ActivityRecordInputSink(ActivityRecord activityRecord) { + ActivityRecordInputSink(ActivityRecord activityRecord, ActivityRecord sourceRecord) { mActivityRecord = activityRecord; mIsCompatEnabled = CompatChanges.isChangeEnabled(ENABLE_TOUCH_OPAQUE_ACTIVITIES, mActivityRecord.getUid()); mName = Integer.toHexString(System.identityHashCode(this)) + " ActivityRecordInputSink " + mActivityRecord.mActivityComponent.flattenToShortString(); + if (sourceRecord != null) { + sourceRecord.mAllowedTouchUid = mActivityRecord.getUid(); + } } public void applyChangesToSurfaceIfChanged(SurfaceControl.Transaction transaction) { @@ -77,8 +79,15 @@ class ActivityRecordInputSink { if (mInputWindowHandleWrapper == null) { mInputWindowHandleWrapper = new InputWindowHandleWrapper(createInputWindowHandle()); } - if (mDisabled || !mIsCompatEnabled || mActivityRecord.isInTransition()) { - // TODO(b/208662670): Investigate if we can have feature active during animations. + // Don't block touches from passing through to an activity below us in the same task, if + // that activity is either from the same uid or if that activity has launched an activity + // in our uid. + final ActivityRecord activityBelowInTask = + mActivityRecord.getTask().getActivityBelow(mActivityRecord); + final boolean allowPassthrough = activityBelowInTask != null && ( + activityBelowInTask.mAllowedTouchUid == mActivityRecord.getUid() + || activityBelowInTask.isUid(mActivityRecord.getUid())); + if (allowPassthrough || !mIsCompatEnabled || mActivityRecord.isInTransition()) { mInputWindowHandleWrapper.setInputConfigMasked(InputConfig.NOT_TOUCHABLE, InputConfig.NOT_TOUCHABLE); } else {