Loading services/core/java/com/android/server/wm/ActivityRecord.java +13 −0 Original line number Diff line number Diff line Loading @@ -775,6 +775,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) { Loading Loading @@ -1720,6 +1727,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A createTime = _createTime; } mAtmService.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, packageName); mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord); } /** Loading Loading @@ -3556,6 +3565,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A destroyImmediately("removeImmediately"); } onRemovedFromDisplay(); mActivityRecordInputSink.releaseSurfaceControl(); super.removeImmediately(); } Loading Loading @@ -6690,6 +6700,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); Loading services/core/java/com/android/server/wm/ActivityRecordInputSink.java 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * 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; } } } Loading
services/core/java/com/android/server/wm/ActivityRecord.java +13 −0 Original line number Diff line number Diff line Loading @@ -775,6 +775,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) { Loading Loading @@ -1720,6 +1727,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A createTime = _createTime; } mAtmService.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, packageName); mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord); } /** Loading Loading @@ -3556,6 +3565,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A destroyImmediately("removeImmediately"); } onRemovedFromDisplay(); mActivityRecordInputSink.releaseSurfaceControl(); super.removeImmediately(); } Loading Loading @@ -6690,6 +6700,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); Loading
services/core/java/com/android/server/wm/ActivityRecordInputSink.java 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * 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; } } }