Make Activites touch opaque - DO NOT MERGE am: 74ce78dfb4
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18029146 Change-Id: I6731998b36385769ff7322c75d7c931d2221647d Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3173,6 +3182,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
@Override
|
||||
void removeImmediately() {
|
||||
onRemovedFromDisplay();
|
||||
mActivityRecordInputSink.releaseSurfaceControl();
|
||||
super.removeImmediately();
|
||||
}
|
||||
|
||||
@@ -6048,6 +6058,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);
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user