From dd4ee68792b9f8683637f57af10544a22c8f5c27 Mon Sep 17 00:00:00 2001 From: Justin Dunlap Date: Wed, 1 Mar 2023 00:08:22 +0000 Subject: Revert "Make Activites touch opaque - DO NOT MERGE" This reverts commit 74ce78dfb4179cb317d6e2fc3cabe5f60af5d02d. Reason for revert: re-release due to functional regression Change-Id: I71e2e889d1f2d026f708bdb617b73a5c7c10467d --- .../java/com/android/server/wm/ActivityRecord.java | 13 --- .../android/server/wm/ActivityRecordInputSink.java | 113 --------------------- 2 files changed, 126 deletions(-) delete mode 100644 services/core/java/com/android/server/wm/ActivityRecordInputSink.java diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 1a2eedceda88..af921e201861 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -673,13 +673,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private AppSaturationInfo mLastAppSaturationInfo; - 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 ColorDisplayService.ColorTransformController mColorTransformController = (matrix, translation) -> mWmService.mH.post(() -> { synchronized (mWmService.mGlobalLock) { @@ -1657,8 +1650,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ? (TaskDisplayArea) WindowContainer.fromBinder(daToken.asBinder()) : null; mHandoverLaunchDisplayId = options.getLaunchDisplayId(); } - - mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord); } /** @@ -3179,7 +3170,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override void removeImmediately() { onRemovedFromDisplay(); - mActivityRecordInputSink.releaseSurfaceControl(); super.removeImmediately(); } @@ -6046,9 +6036,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } else if (!show && mLastSurfaceShowing) { getSyncTransaction().hide(mSurfaceControl); } - if (show) { - mActivityRecordInputSink.applyChangesToSurfaceIfChanged(getSyncTransaction()); - } } if (mThumbnail != null) { mThumbnail.setShowing(getPendingTransaction(), show); diff --git a/services/core/java/com/android/server/wm/ActivityRecordInputSink.java b/services/core/java/com/android/server/wm/ActivityRecordInputSink.java deleted file mode 100644 index 95b5cec9a144..000000000000 --- a/services/core/java/com/android/server/wm/ActivityRecordInputSink.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import android.os.Process; -import android.view.InputWindowHandle; -import android.view.SurfaceControl; -import android.view.WindowManager; - -/** - * Creates a InputWindowHandle that catches all touches that would otherwise pass through an - * Activity. - */ -class ActivityRecordInputSink { - - private final ActivityRecord mActivityRecord; - private final String mName; - - private InputWindowHandle mInputWindowHandle; - private SurfaceControl mSurfaceControl; - - ActivityRecordInputSink(ActivityRecord activityRecord, ActivityRecord sourceRecord) { - mActivityRecord = activityRecord; - mName = Integer.toHexString(System.identityHashCode(this)) + " ActivityRecordInputSink " - + mActivityRecord.mActivityComponent.flattenToShortString(); - if (sourceRecord != null) { - sourceRecord.mAllowedTouchUid = mActivityRecord.getUid(); - } - } - - public void applyChangesToSurfaceIfChanged(SurfaceControl.Transaction transaction) { - boolean windowHandleChanged = updateInputWindowHandle(); - if (mSurfaceControl == null) { - mSurfaceControl = createSurface(transaction); - } - if (windowHandleChanged) { - transaction.setInputWindowInfo(mSurfaceControl, mInputWindowHandle); - } - } - - private SurfaceControl createSurface(SurfaceControl.Transaction t) { - SurfaceControl surfaceControl = mActivityRecord.makeChildSurface(null) - .setName(mName) - .setHidden(false) - .setCallsite("ActivityRecordInputSink.createSurface") - .build(); - // Put layer below all siblings (and the parent surface too) - t.setLayer(surfaceControl, Integer.MIN_VALUE); - return surfaceControl; - } - - private boolean updateInputWindowHandle() { - boolean changed = false; - if (mInputWindowHandle == null) { - mInputWindowHandle = createInputWindowHandle(); - changed = true; - } - // 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())); - boolean notTouchable = (mInputWindowHandle.layoutParamsFlags - & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0; - if (allowPassthrough || mActivityRecord.isAppTransitioning()) { - mInputWindowHandle.layoutParamsFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; - changed |= !notTouchable; - } else { - mInputWindowHandle.layoutParamsFlags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; - changed |= notTouchable; - } - return changed; - } - - private InputWindowHandle createInputWindowHandle() { - InputWindowHandle inputWindowHandle = new InputWindowHandle(null, - mActivityRecord.getDisplayId()); - inputWindowHandle.replaceTouchableRegionWithCrop = true; - inputWindowHandle.name = mName; - inputWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; - inputWindowHandle.ownerUid = Process.myUid(); - inputWindowHandle.ownerPid = Process.myPid(); - inputWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; - inputWindowHandle.inputFeatures = - WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; - return inputWindowHandle; - } - - void releaseSurfaceControl() { - if (mSurfaceControl != null) { - mSurfaceControl.release(); - mSurfaceControl = null; - } - } - -} -- cgit v1.2.3-59-g8ed1b From 73ee4cb9c4f108c2edf68443c339bc64a9240322 Mon Sep 17 00:00:00 2001 From: Linus Tufvesson Date: Wed, 1 Mar 2023 11:20:16 +0100 Subject: Make Activites touch opaque - DO NOT MERGE Block touches from passing through activities by adding a dedicated surface that consumes all touches that would otherwise pass through the bounds availble to the Activity. + Keep displayId in sync for ActivityRecord Bug: 194480991 Test: atest CtsWindowManagerDeviceTestCases:ActivityRecordInputSinkTests Test: atest CtsWindowManagerDeviceTestCases:CrossAppDragAndDropTests Test: atest CtsWindowManagerDeviceTestCases:PinnedStackTests Test: Used "System > Developer Options > Simulate secondary display" to test that moving activites between displays work as intended. Change-Id: Idace4104c2708ce99309fa54fd44dd000e7f8894 --- .../java/com/android/server/wm/ActivityRecord.java | 13 +++ .../android/server/wm/ActivityRecordInputSink.java | 117 +++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 services/core/java/com/android/server/wm/ActivityRecordInputSink.java diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index af921e201861..1a2eedceda88 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -673,6 +673,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private AppSaturationInfo mLastAppSaturationInfo; + 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 ColorDisplayService.ColorTransformController mColorTransformController = (matrix, translation) -> mWmService.mH.post(() -> { synchronized (mWmService.mGlobalLock) { @@ -1650,6 +1657,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ? (TaskDisplayArea) WindowContainer.fromBinder(daToken.asBinder()) : null; mHandoverLaunchDisplayId = options.getLaunchDisplayId(); } + + mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord); } /** @@ -3170,6 +3179,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override void removeImmediately() { onRemovedFromDisplay(); + mActivityRecordInputSink.releaseSurfaceControl(); super.removeImmediately(); } @@ -6036,6 +6046,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } else if (!show && mLastSurfaceShowing) { getSyncTransaction().hide(mSurfaceControl); } + if (show) { + mActivityRecordInputSink.applyChangesToSurfaceIfChanged(getSyncTransaction()); + } } if (mThumbnail != null) { mThumbnail.setShowing(getPendingTransaction(), show); diff --git a/services/core/java/com/android/server/wm/ActivityRecordInputSink.java b/services/core/java/com/android/server/wm/ActivityRecordInputSink.java new file mode 100644 index 000000000000..95a6e8b8b88f --- /dev/null +++ b/services/core/java/com/android/server/wm/ActivityRecordInputSink.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import android.os.Process; +import android.view.InputWindowHandle; +import android.view.SurfaceControl; +import android.view.WindowManager; + +/** + * Creates a InputWindowHandle that catches all touches that would otherwise pass through an + * Activity. + */ +class ActivityRecordInputSink { + + private final ActivityRecord mActivityRecord; + private final String mName; + + private InputWindowHandle mInputWindowHandle; + private SurfaceControl mSurfaceControl; + + ActivityRecordInputSink(ActivityRecord activityRecord, ActivityRecord sourceRecord) { + mActivityRecord = activityRecord; + mName = Integer.toHexString(System.identityHashCode(this)) + " ActivityRecordInputSink " + + mActivityRecord.mActivityComponent.flattenToShortString(); + if (sourceRecord != null) { + sourceRecord.mAllowedTouchUid = mActivityRecord.getUid(); + } + } + + public void applyChangesToSurfaceIfChanged(SurfaceControl.Transaction transaction) { + boolean windowHandleChanged = updateInputWindowHandle(); + if (mSurfaceControl == null) { + mSurfaceControl = createSurface(transaction); + } + if (windowHandleChanged) { + transaction.setInputWindowInfo(mSurfaceControl, mInputWindowHandle); + } + } + + private SurfaceControl createSurface(SurfaceControl.Transaction t) { + SurfaceControl surfaceControl = mActivityRecord.makeChildSurface(null) + .setName(mName) + .setHidden(false) + .setCallsite("ActivityRecordInputSink.createSurface") + .build(); + // Put layer below all siblings (and the parent surface too) + t.setLayer(surfaceControl, Integer.MIN_VALUE); + return surfaceControl; + } + + private boolean updateInputWindowHandle() { + boolean changed = false; + if (mInputWindowHandle == null) { + mInputWindowHandle = createInputWindowHandle(); + changed = true; + } + // 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())); + boolean notTouchable = (mInputWindowHandle.layoutParamsFlags + & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0; + if (allowPassthrough || mActivityRecord.isAppTransitioning()) { + mInputWindowHandle.layoutParamsFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + changed |= !notTouchable; + } else { + mInputWindowHandle.layoutParamsFlags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + changed |= notTouchable; + } + if (mInputWindowHandle.displayId != mActivityRecord.getDisplayId()) { + mInputWindowHandle.displayId = mActivityRecord.getDisplayId(); + changed = true; + } + return changed; + } + + private InputWindowHandle createInputWindowHandle() { + InputWindowHandle inputWindowHandle = new InputWindowHandle(null, + mActivityRecord.getDisplayId()); + inputWindowHandle.replaceTouchableRegionWithCrop = true; + inputWindowHandle.name = mName; + inputWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; + inputWindowHandle.ownerUid = Process.myUid(); + inputWindowHandle.ownerPid = Process.myPid(); + inputWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + inputWindowHandle.inputFeatures = + WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; + return inputWindowHandle; + } + + void releaseSurfaceControl() { + if (mSurfaceControl != null) { + mSurfaceControl.release(); + mSurfaceControl = null; + } + } + +} -- cgit v1.2.3-59-g8ed1b