diff options
author | 2020-08-19 14:43:14 +0100 | |
---|---|---|
committer | 2020-10-05 16:37:03 +0000 | |
commit | ea97d18b244d01edff2098848022d125af350140 (patch) | |
tree | c48327588557a89afb670636aa690c6dd6fe8348 | |
parent | 21b0037dac3486703303c72ba92ff4ac364c6ebb (diff) |
Block untrusted touches in InputDispatcher
With topic CL InputDispatcher now has the effect of each window for
cross-UID touch occlusion rules: ALLOW, USE_OPACITY or BLOCK_UNTRUSTED.
Check topic CL for exact meaning of each. USE_OPACITY is only used by
SAWs for now.
In this CL, InputDispatcher make use of that information for the stack
of windows above the touch-consuming window to block a touch or not.
The summary of the rules are:
* If there is any visible untrusted window from a different UID (than
the touch-consuming window UID) that has state BLOCK_UNTRUSTED, the
touch is blocked.
* Else, if there is any visible untrusted window from a different UID
that has state USE_OPACITY, we compute the composed obscuring opacity
by each stack of USE_OPACITY windows per UID of occluding window.
We take maximum of those and compare with secure setting
"maximum_obscuring_opacity_for_touch", if it's greater than the
setting the touch is blocked. This means the remaining visibility on the
touch-consuming window is not high enough to let the touch happen.
* Else we don't block the touch.
More details on go/cross-uid-touches. This doesn't interfere with
existing flags FLAG_WINDOW_IS_OBSCURED and
FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
To compute the opacity we also propagate the alpha of each window from
SurfaceFlinger to InputDispatcher.
Test: atest WindowUntrustedTouchTest
Test: atest inputflinger_tests inputflinger_benchmarks libinput_tests
Test: go/try-cross-uid-touches for manual testing
Bug: 158002302
Change-Id: I673d7a5f16b19952311e8cb44a48af4349a4bd40
-rw-r--r-- | include/input/InputWindow.h | 9 | ||||
-rw-r--r-- | libs/input/Android.bp | 6 | ||||
-rw-r--r-- | libs/input/InputWindow.cpp | 20 | ||||
-rw-r--r-- | libs/input/android/os/BlockUntrustedTouchesMode.aidl | 35 | ||||
-rw-r--r-- | libs/input/android/os/TouchOcclusionMode.aidl | 47 | ||||
-rw-r--r-- | libs/input/tests/InputWindow_test.cpp | 6 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 110 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.h | 15 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/include/InputDispatcherInterface.h | 18 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 1 |
10 files changed, 262 insertions, 5 deletions
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 7372022078..36097d6d65 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -17,6 +17,7 @@ #ifndef _UI_INPUT_WINDOW_H #define _UI_INPUT_WINDOW_H +#include <android/os/TouchOcclusionMode.h> #include <binder/Parcel.h> #include <binder/Parcelable.h> #include <input/Flags.h> @@ -30,6 +31,8 @@ #include "InputApplication.h" +using android::os::TouchOcclusionMode; + namespace android { /* @@ -158,6 +161,10 @@ struct InputWindowInfo : public Parcelable { // in scaling of the TOUCH_MAJOR/TOUCH_MINOR axis. float globalScaleFactor = 1.0f; + // The opacity of this window, from 0.0 to 1.0 (inclusive). + // An alpha of 1.0 means fully opaque and 0.0 means fully transparent. + float alpha; + // Transform applied to individual windows. ui::Transform transform; @@ -176,8 +183,10 @@ struct InputWindowInfo : public Parcelable { * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */ bool trustedOverlay = false; + TouchOcclusionMode touchOcclusionMode = TouchOcclusionMode::BLOCK_UNTRUSTED; int32_t ownerPid = -1; int32_t ownerUid = -1; + std::string packageName; Flags<Feature> inputFeatures; int32_t displayId = ADISPLAY_ID_NONE; int32_t portalToDisplayId = ADISPLAY_ID_NONE; diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 8f575a8cae..b442700138 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -18,6 +18,8 @@ filegroup { name: "inputconstants_aidl", srcs: [ "android/os/IInputConstants.aidl", + "android/os/TouchOcclusionMode.aidl", + "android/os/BlockUntrustedTouchesMode.aidl", ], } @@ -71,10 +73,14 @@ cc_library { "android/FocusRequest.aidl", "android/InputApplicationInfo.aidl", "android/os/IInputConstants.aidl", + "android/os/TouchOcclusionMode.aidl", + "android/os/BlockUntrustedTouchesMode.aidl", "android/os/IInputFlinger.aidl", "android/os/ISetInputWindowsListener.aidl", ], + export_shared_lib_headers: ["libbinder"], + shared_libs: [ "libutils", "libbinder", diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 885dc9b51e..8546bbbb43 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -59,10 +59,11 @@ bool InputWindowInfo::operator==(const InputWindowInfo& info) const { info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor && info.transform == transform && info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible && info.trustedOverlay == trustedOverlay && - info.focusable == focusable && info.hasWallpaper == hasWallpaper && - info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid && - info.inputFeatures == inputFeatures && info.displayId == displayId && - info.portalToDisplayId == portalToDisplayId && + info.focusable == focusable && info.touchOcclusionMode == touchOcclusionMode && + info.hasWallpaper == hasWallpaper && info.paused == paused && + info.ownerPid == ownerPid && info.ownerUid == ownerUid && + info.packageName == packageName && info.inputFeatures == inputFeatures && + info.displayId == displayId && info.portalToDisplayId == portalToDisplayId && info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && info.applicationInfo == applicationInfo; } @@ -91,6 +92,7 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeInt32(frameBottom) ?: parcel->writeInt32(surfaceInset) ?: parcel->writeFloat(globalScaleFactor) ?: + parcel->writeFloat(alpha) ?: parcel->writeFloat(transform.dsdx()) ?: parcel->writeFloat(transform.dtdx()) ?: parcel->writeFloat(transform.tx()) ?: @@ -102,8 +104,10 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeBool(hasWallpaper) ?: parcel->writeBool(paused) ?: parcel->writeBool(trustedOverlay) ?: + parcel->writeInt32(static_cast<int32_t>(touchOcclusionMode)) ?: parcel->writeInt32(ownerPid) ?: parcel->writeInt32(ownerUid) ?: + parcel->writeUtf8AsUtf16(packageName) ?: parcel->writeInt32(inputFeatures.get()) ?: parcel->writeInt32(displayId) ?: parcel->writeInt32(portalToDisplayId) ?: @@ -134,6 +138,7 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { flags = Flags<Flag>(parcel->readInt32()); type = static_cast<Type>(parcel->readInt32()); float dsdx, dtdx, tx, dtdy, dsdy, ty; + int32_t touchOcclusionModeInt; // clang-format off status = parcel->readInt32(&frameLeft) ?: parcel->readInt32(&frameTop) ?: @@ -141,6 +146,7 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { parcel->readInt32(&frameBottom) ?: parcel->readInt32(&surfaceInset) ?: parcel->readFloat(&globalScaleFactor) ?: + parcel->readFloat(&alpha) ?: parcel->readFloat(&dsdx) ?: parcel->readFloat(&dtdx) ?: parcel->readFloat(&tx) ?: @@ -152,14 +158,18 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { parcel->readBool(&hasWallpaper) ?: parcel->readBool(&paused) ?: parcel->readBool(&trustedOverlay) ?: + parcel->readInt32(&touchOcclusionModeInt) ?: parcel->readInt32(&ownerPid) ?: - parcel->readInt32(&ownerUid); + parcel->readInt32(&ownerUid) ?: + parcel->readUtf8FromUtf16(&packageName); // clang-format on if (status != OK) { return status; } + touchOcclusionMode = static_cast<TouchOcclusionMode>(touchOcclusionModeInt); + inputFeatures = Flags<Feature>(parcel->readInt32()); status = parcel->readInt32(&displayId) ?: parcel->readInt32(&portalToDisplayId) ?: diff --git a/libs/input/android/os/BlockUntrustedTouchesMode.aidl b/libs/input/android/os/BlockUntrustedTouchesMode.aidl new file mode 100644 index 0000000000..9504e993f8 --- /dev/null +++ b/libs/input/android/os/BlockUntrustedTouchesMode.aidl @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2020, 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 android.os; + + +/** + * Block untrusted touches feature mode. + * + * @hide + */ +@Backing(type="int") +enum BlockUntrustedTouchesMode { + /** Feature is off. */ + DISABLED, + + /** Untrusted touches are flagged but not blocked. */ + PERMISSIVE, + + /** Untrusted touches are blocked. */ + BLOCK +} diff --git a/libs/input/android/os/TouchOcclusionMode.aidl b/libs/input/android/os/TouchOcclusionMode.aidl new file mode 100644 index 0000000000..106f159a50 --- /dev/null +++ b/libs/input/android/os/TouchOcclusionMode.aidl @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2020, 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 android.os; + + +/** + * Touch occlusion modes: These modes represent how windows are taken into + * consideration in order to decide whether to block obscured touches or + * not. + * + * @hide + */ +@Backing(type="int") +enum TouchOcclusionMode { + /** + * Touches that pass through this window will be blocked if they are + * consumed by a different UID and this window is not trusted. + */ + BLOCK_UNTRUSTED, + + /** + * The window's opacity will be taken into consideration for touch + * occlusion rules if the touch passes through it and the window is not + * trusted. + */ + USE_OPACITY, + + /** + * The window won't count for touch occlusion rules if the touch passes + * through it. + */ + ALLOW +} diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 65a7761aec..c18a17f1ae 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -53,13 +53,16 @@ TEST(InputWindowInfo, Parcelling) { i.frameBottom = 19; i.surfaceInset = 17; i.globalScaleFactor = 0.3; + i.alpha = 0.7; i.transform.set({0.4, -1, 100, 0.5, 0, 40, 0, 0, 1}); i.visible = false; i.focusable = false; i.hasWallpaper = false; i.paused = false; + i.touchOcclusionMode = TouchOcclusionMode::ALLOW; i.ownerPid = 19; i.ownerUid = 24; + i.packageName = "com.example.package"; i.inputFeatures = InputWindowInfo::Feature::DISABLE_USER_ACTIVITY; i.displayId = 34; i.portalToDisplayId = 2; @@ -86,13 +89,16 @@ TEST(InputWindowInfo, Parcelling) { ASSERT_EQ(i.frameBottom, i2.frameBottom); ASSERT_EQ(i.surfaceInset, i2.surfaceInset); ASSERT_EQ(i.globalScaleFactor, i2.globalScaleFactor); + ASSERT_EQ(i.alpha, i2.alpha); ASSERT_EQ(i.transform, i2.transform); ASSERT_EQ(i.visible, i2.visible); ASSERT_EQ(i.focusable, i2.focusable); ASSERT_EQ(i.hasWallpaper, i2.hasWallpaper); ASSERT_EQ(i.paused, i2.paused); + ASSERT_EQ(i.touchOcclusionMode, i2.touchOcclusionMode); ASSERT_EQ(i.ownerPid, i2.ownerPid); ASSERT_EQ(i.ownerUid, i2.ownerUid); + ASSERT_EQ(i.packageName, i2.packageName); ASSERT_EQ(i.inputFeatures, i2.inputFeatures); ASSERT_EQ(i.displayId, i2.displayId); ASSERT_EQ(i.portalToDisplayId, i2.portalToDisplayId); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 3ccb0c966e..ab0d340363 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -402,6 +402,7 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic // To avoid leaking stack in case that call never comes, and for tests, // initialize it here anyways. mInTouchMode(true), + mMaximumObscuringOpacityForTouch(1.0f), mFocusedDisplayId(ADISPLAY_ID_DEFAULT) { mLooper = new Looper(false); mReporter = createInputReporter(); @@ -1708,6 +1709,22 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } } + // Drop events that can't be trusted due to occlusion + if (newTouchedWindowHandle != nullptr && + mBlockUntrustedTouchesMode != BlockUntrustedTouchesMode::DISABLED) { + TouchOcclusionInfo occlusionInfo = + computeTouchOcclusionInfoLocked(newTouchedWindowHandle, x, y); + // The order of the operands in the 'if' below is important because even if the feature + // is not BLOCK we want isTouchTrustedLocked() to execute in order to log details to + // logcat. + if (!isTouchTrustedLocked(occlusionInfo) && + mBlockUntrustedTouchesMode == BlockUntrustedTouchesMode::BLOCK) { + ALOGW("Dropping untrusted touch event due to %s/%d", + occlusionInfo.obscuringPackage.c_str(), occlusionInfo.obscuringUid); + newTouchedWindowHandle = nullptr; + } + } + // Also don't send the new touch event to unresponsive gesture monitors newGestureMonitors = selectResponsiveMonitorsLocked(newGestureMonitors); @@ -2121,6 +2138,84 @@ static bool canBeObscuredBy(const sp<InputWindowHandle>& windowHandle, return true; } +/** + * Returns touch occlusion information in the form of TouchOcclusionInfo. To check if the touch is + * untrusted, one should check: + * + * 1. If result.hasBlockingOcclusion is true. + * If it's, it means the touch should be blocked due to a window with occlusion mode of + * BLOCK_UNTRUSTED. + * + * 2. If result.obscuringOpacity > mMaximumObscuringOpacityForTouch. + * If it is (and 1 is false), then the touch should be blocked because a stack of windows + * (possibly only one) with occlusion mode of USE_OPACITY from one UID resulted in a composed + * obscuring opacity above the threshold. Note that if there was no window of occlusion mode + * USE_OPACITY, result.obscuringOpacity would've been 0 and since + * mMaximumObscuringOpacityForTouch >= 0, the condition above would never be true. + * + * If neither of those is true, then it means the touch can be allowed. + */ +InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked( + const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const { + int32_t displayId = windowHandle->getInfo()->displayId; + const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); + TouchOcclusionInfo info; + info.hasBlockingOcclusion = false; + info.obscuringOpacity = 0; + info.obscuringUid = -1; + std::map<int32_t, float> opacityByUid; + for (const sp<InputWindowHandle>& otherHandle : windowHandles) { + if (windowHandle == otherHandle) { + break; // All future windows are below us. Exit early. + } + const InputWindowInfo* otherInfo = otherHandle->getInfo(); + if (canBeObscuredBy(windowHandle, otherHandle) && + windowHandle->getInfo()->ownerUid != otherInfo->ownerUid && + otherInfo->frameContainsPoint(x, y)) { + // canBeObscuredBy() has returned true above, which means this window is untrusted, so + // we perform the checks below to see if the touch can be propagated or not based on the + // window's touch occlusion mode + if (otherInfo->touchOcclusionMode == TouchOcclusionMode::BLOCK_UNTRUSTED) { + info.hasBlockingOcclusion = true; + info.obscuringUid = otherInfo->ownerUid; + info.obscuringPackage = otherInfo->packageName; + break; + } + if (otherInfo->touchOcclusionMode == TouchOcclusionMode::USE_OPACITY) { + uint32_t uid = otherInfo->ownerUid; + float opacity = + (opacityByUid.find(uid) == opacityByUid.end()) ? 0 : opacityByUid[uid]; + // Given windows A and B: + // opacity(A, B) = 1 - [1 - opacity(A)] * [1 - opacity(B)] + opacity = 1 - (1 - opacity) * (1 - otherInfo->alpha); + opacityByUid[uid] = opacity; + if (opacity > info.obscuringOpacity) { + info.obscuringOpacity = opacity; + info.obscuringUid = uid; + info.obscuringPackage = otherInfo->packageName; + } + } + } + } + return info; +} + +bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const { + if (occlusionInfo.hasBlockingOcclusion) { + ALOGW("Untrusted touch due to occlusion by %s/%d", occlusionInfo.obscuringPackage.c_str(), + occlusionInfo.obscuringUid); + return false; + } + if (occlusionInfo.obscuringOpacity > mMaximumObscuringOpacityForTouch) { + ALOGW("Untrusted touch due to occlusion by %s/%d (obscuring opacity = " + "%.2f, maximum allowed = %.2f)", + occlusionInfo.obscuringPackage.c_str(), occlusionInfo.obscuringUid, + occlusionInfo.obscuringOpacity, mMaximumObscuringOpacityForTouch); + return false; + } + return true; +} + bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const { int32_t displayId = windowHandle->getInfo()->displayId; @@ -4060,6 +4155,21 @@ void InputDispatcher::setInTouchMode(bool inTouchMode) { mInTouchMode = inTouchMode; } +void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) { + if (opacity < 0 || opacity > 1) { + LOG_ALWAYS_FATAL("Maximum obscuring opacity for touch should be >= 0 and <= 1"); + return; + } + + std::scoped_lock lock(mLock); + mMaximumObscuringOpacityForTouch = opacity; +} + +void InputDispatcher::setBlockUntrustedTouchesMode(BlockUntrustedTouchesMode mode) { + std::scoped_lock lock(mLock); + mBlockUntrustedTouchesMode = mode; +} + bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) { if (fromToken == toToken) { if (DEBUG_FOCUS) { diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 4fcdcc297e..d361b172e1 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -112,6 +112,8 @@ public: virtual void setInputDispatchMode(bool enabled, bool frozen) override; virtual void setInputFilterEnabled(bool enabled) override; virtual void setInTouchMode(bool inTouchMode) override; + virtual void setMaximumObscuringOpacityForTouch(float opacity) override; + virtual void setBlockUntrustedTouchesMode(BlockUntrustedTouchesMode mode) override; virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) override; @@ -296,6 +298,8 @@ private: bool mDispatchFrozen GUARDED_BY(mLock); bool mInputFilterEnabled GUARDED_BY(mLock); bool mInTouchMode GUARDED_BY(mLock); + float mMaximumObscuringOpacityForTouch GUARDED_BY(mLock); + BlockUntrustedTouchesMode mBlockUntrustedTouchesMode GUARDED_BY(mLock); std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay GUARDED_BY(mLock); @@ -446,6 +450,17 @@ private: void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock); bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle, const InjectionState* injectionState); + + struct TouchOcclusionInfo { + bool hasBlockingOcclusion; + float obscuringOpacity; + std::string obscuringPackage; + int32_t obscuringUid; + }; + + TouchOcclusionInfo computeTouchOcclusionInfoLocked(const sp<InputWindowHandle>& windowHandle, + int32_t x, int32_t y) const REQUIRES(mLock); + bool isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const REQUIRES(mLock); bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const REQUIRES(mLock); bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 67d9a06108..65687c4c9b 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -20,12 +20,15 @@ #include <InputListener.h> #include <android-base/result.h> #include <android/FocusRequest.h> +#include <android/os/BlockUntrustedTouchesMode.h> #include <android/os/ISetInputWindowsListener.h> #include <input/InputApplication.h> #include <input/InputTransport.h> #include <input/InputWindow.h> #include <unordered_map> +using android::os::BlockUntrustedTouchesMode; + namespace android { /* @@ -145,6 +148,21 @@ public: */ virtual void setInTouchMode(bool inTouchMode) = 0; + /** + * Sets the maximum allowed obscuring opacity by UID to propagate touches. + * For certain window types (eg. SAWs), the decision of honoring + * FLAG_NOT_TOUCHABLE or not depends on the combined obscuring opacity of + * the windows above the touch-consuming window. + */ + virtual void setMaximumObscuringOpacityForTouch(float opacity) = 0; + + /** + * Sets the mode of the block untrusted touches feature. + * + * TODO(b/169067926): Clean-up feature modes. + */ + virtual void setBlockUntrustedTouchesMode(BlockUntrustedTouchesMode mode) = 0; + /* Transfers touch focus from one window to another window. * * Returns true on success. False if the window did not actually have touch focus. diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 85046a4194..0127b31229 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2485,6 +2485,7 @@ InputWindowInfo Layer::fillInputInfo() { // InputDispatcher, and obviously if they aren't visible they can't occlude // anything. info.visible = hasInputInfo() ? canReceiveInput() : isVisible(); + info.alpha = getAlpha(); auto cropLayer = mDrawingState.touchableRegionCrop.promote(); if (info.replaceTouchableRegionWithCrop) { |