diff options
author | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-12-06 02:39:56 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-12-06 02:39:56 +0000 |
commit | 0652bec39b63ae07a96bb3f8ae8a4309ccf2d66f (patch) | |
tree | 2b25d3dde8be8b4b5126ec7e3adf3938acc5c032 | |
parent | 7b91109f8da100e8b8ba7a3b56267d50af412b91 (diff) | |
parent | 0999fe2ab4d1063b4b788457b6356a390da06d61 (diff) | |
download | native-android11-gsi.tar.gz |
Merge "Merge cherrypicks of [15975347, 15975348, 15975349, 16508592, 16508593, 16508594, 18029504] into rvc-platform-release. am: 95af48052c" into android11-gsiandroid11-gsi
22 files changed, 444 insertions, 63 deletions
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index b57409867f..372cecd63c 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -53,6 +53,7 @@ message SurfaceChange { ReparentChildrenChange reparent_children = 20; BackgroundBlurRadiusChange background_blur_radius = 21; ShadowRadiusChange shadow_radius = 22; + TrustedOverlayChange trusted_overlay = 23; } } @@ -208,4 +209,8 @@ message DetachChildrenChange { message ShadowRadiusChange { required float radius = 1; +} + +message TrustedOverlayChange { + required float is_trusted_overlay = 1; }
\ No newline at end of file diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 2dac5b62a7..bbf793e62b 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -108,7 +108,6 @@ struct InputWindowInfo { TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32, TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34, TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40, - TYPE_TRUSTED_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 42, LAST_SYSTEM_WINDOW = 2999, }; @@ -116,6 +115,7 @@ struct InputWindowInfo { INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001, INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002, INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004, + INPUT_FEATURE_DROP_INPUT = 0x00000008, }; /* These values are filled in by the WM and passed through SurfaceFlinger @@ -163,6 +163,12 @@ struct InputWindowInfo { bool hasFocus = false; bool hasWallpaper = false; bool paused = false; + /* This flag is set when the window is of a trusted type that is allowed to silently + * overlay other windows for the purpose of implementing the secure views feature. + * Trusted overlays, such as IME windows, can partly obscure other windows without causing + * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. + */ + bool trustedOverlay = false; int32_t ownerPid = -1; int32_t ownerUid = -1; int32_t inputFeatures = 0; @@ -175,20 +181,15 @@ struct InputWindowInfo { void addTouchableRegion(const Rect& region); bool touchableRegionContainsPoint(int32_t x, int32_t y) const; - bool frameContainsPoint(int32_t x, int32_t y) const; - /* Returns true if the window is of a trusted type that is allowed to silently - * overlay other windows for the purpose of implementing the secure views feature. - * Trusted overlays, such as IME windows, can partly obscure other windows without causing - * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. - */ - bool isTrustedOverlay() const; + bool frameContainsPoint(int32_t x, int32_t y) const; bool supportsSplitTouch() const; bool overlaps(const InputWindowInfo* other) const; status_t write(Parcel& output) const; + static InputWindowInfo read(const Parcel& from); }; diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 4a4510e047..6ec1f471c3 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -30,6 +30,14 @@ cc_library_headers { min_sdk_version: "29", } +// AIDL files that should be exposed to java +filegroup { + name: "guiconstants_aidl", + srcs: [ + "android/gui/DropInputMode.aidl", + ], +} + cc_library_shared { name: "libgui", vendor_available: false, @@ -41,6 +49,7 @@ cc_library_shared { defaults: ["libgui_bufferqueue-defaults"], srcs: [ + ":guiconstants_aidl", ":framework_native_aidl", ":libgui_bufferqueue_sources", diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e43446ac8c..dfcef8fe7a 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -117,6 +117,8 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(frameRate); output.writeByte(frameRateCompatibility); output.writeUint32(fixedTransformHint); + output.writeBool(isTrustedOverlay); + output.writeUint32(static_cast<uint32_t>(dropInputMode)); return NO_ERROR; } @@ -200,6 +202,11 @@ status_t layer_state_t::read(const Parcel& input) frameRate = input.readFloat(); frameRateCompatibility = input.readByte(); fixedTransformHint = static_cast<ui::Transform::RotationFlags>(input.readUint32()); + isTrustedOverlay = input.readBool(); + + uint32_t mode; + mode = input.readUint32(); + dropInputMode = static_cast<gui::DropInputMode>(mode); return NO_ERROR; } @@ -439,6 +446,14 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFixedTransformHintChanged; fixedTransformHint = other.fixedTransformHint; } + if (other.what & eTrustedOverlayChanged) { + what |= eTrustedOverlayChanged; + isTrustedOverlay = other.isTrustedOverlay; + } + if (other.what & eDropInputModeChanged) { + what |= eDropInputModeChanged; + dropInputMode = other.dropInputMode; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 83bc06997a..d2c96218f4 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1484,6 +1484,34 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixed return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrustedOverlay( + const sp<SurfaceControl>& sc, bool isTrustedOverlay) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eTrustedOverlayChanged; + s->isTrustedOverlay = isTrustedOverlay; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDropInputMode( + const sp<SurfaceControl>& sc, gui::DropInputMode mode) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eDropInputModeChanged; + s->dropInputMode = mode; + + registerSurfaceControlForCallback(sc); + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) { diff --git a/libs/gui/android/gui/DropInputMode.aidl b/libs/gui/android/gui/DropInputMode.aidl new file mode 100644 index 0000000000..248a0318b7 --- /dev/null +++ b/libs/gui/android/gui/DropInputMode.aidl @@ -0,0 +1,40 @@ +/** + * 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 android.gui; + + +/** + * Input event drop modes: Input event drop options for windows and its children. + * + * @hide + */ +@Backing(type="int") +enum DropInputMode { + /** + * Default mode, input events are sent to the target as usual. + */ + NONE, + + /** + * Window and its children will not receive any input even if it has a valid input channel. + * Touches and keys will be dropped. If a window is focused, it will remain focused but will + * not receive any keys. If the window has a touchable region and is the target of an input + * event, the event will be dropped and will not go to the window behind. ref: b/197296414 + */ + ALL, +} + diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index e60f6777ae..39dbe9e035 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -25,6 +25,7 @@ #include <gui/ITransactionCompletedListener.h> #include <math/mat4.h> +#include <android/gui/DropInputMode.h> #ifndef NO_INPUT #include <input/InputWindow.h> #endif @@ -105,6 +106,8 @@ struct layer_state_t { eBackgroundBlurRadiusChanged = 0x80'00000000, eProducerDisconnect = 0x100'00000000, eFixedTransformHintChanged = 0x200'00000000, + eTrustedOverlayChanged = 0x400'00000000, + eDropInputModeChanged = 0x8000'00000000, }; layer_state_t() @@ -139,7 +142,9 @@ struct layer_state_t { frameRateSelectionPriority(-1), frameRate(0.0f), frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), - fixedTransformHint(ui::Transform::ROT_INVALID) { + fixedTransformHint(ui::Transform::ROT_INVALID), + isTrustedOverlay(false), + dropInputMode(gui::DropInputMode::NONE) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -237,6 +242,13 @@ struct layer_state_t { // a buffer of a different size. -1 means the transform hint is not set, // otherwise the value will be a valid ui::Rotation. ui::Transform::RotationFlags fixedTransformHint; + + // An inherited state that indicates that this surface control and its children + // should be trusted for input occlusion detection purposes + bool isTrustedOverlay; + + // Force inputflinger to drop all input events for the layer and its children. + gui::DropInputMode dropInputMode; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index adcb8982a0..2e189e5d89 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -529,6 +529,10 @@ public: // a buffer of a different size. Transaction& setFixedTransformHint(const sp<SurfaceControl>& sc, int32_t transformHint); + // Sets that this surface control and its children are trusted overlays for input + Transaction& setTrustedOverlay(const sp<SurfaceControl>& sc, bool isTrustedOverlay); + + Transaction& setDropInputMode(const sp<SurfaceControl>& sc, gui::DropInputMode mode); status_t setDisplaySurface(const sp<IBinder>& token, const sp<IGraphicBufferProducer>& bufferProducer); diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index b1d3ecbf36..e3f4798019 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -24,6 +24,7 @@ #include <memory> +#include <android/keycodes.h> #include <android/native_window.h> #include <binder/Binder.h> @@ -65,17 +66,40 @@ static const int LAYER_BASE = INT32_MAX - 10; class InputSurface { public: - InputSurface(const sp<SurfaceControl> &sc, int width, int height) { + InputSurface(const sp<SurfaceControl> &sc, int width, int height, bool noInputChannel = false) { mSurfaceControl = sc; - InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); - mInputFlinger = getInputFlinger(); - mInputFlinger->registerInputChannel(mServerChannel); + if (noInputChannel) { + mInputInfo.inputFeatures = InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL; + } else { + InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); + mInputFlinger->registerInputChannel(mServerChannel); + mInputInfo.token = mServerChannel->getConnectionToken(); + mInputConsumer = new InputConsumer(mClientChannel); + } - populateInputInfo(width, height); + mInputInfo.name = "Test info"; + mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL; + mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION; + mInputInfo.dispatchingTimeout = seconds_to_nanoseconds(5); + mInputInfo.globalScaleFactor = 1.0; + mInputInfo.canReceiveKeys = true; + mInputInfo.hasFocus = true; + mInputInfo.hasWallpaper = false; + mInputInfo.paused = false; + mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); + // TODO: Fill in from SF? + mInputInfo.ownerPid = 11111; + mInputInfo.ownerUid = 11111; + mInputInfo.inputFeatures = 0; + mInputInfo.displayId = 0; - mInputConsumer = new InputConsumer(mClientChannel); + InputApplicationInfo aInfo; + aInfo.token = new BBinder(); + aInfo.name = "Test app info"; + aInfo.dispatchingTimeout = seconds_to_nanoseconds(5); + mInputInfo.applicationInfo = aInfo; } static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient> &scc, @@ -104,6 +128,16 @@ public: return std::make_unique<InputSurface>(surfaceControl, width, height); } + static std::unique_ptr<InputSurface> makeContainerInputSurfaceNoInputChannel( + const sp<SurfaceComposerClient> &scc, int width, int height) { + sp<SurfaceControl> surfaceControl = + scc->createSurface(String8("Test Container Surface"), 0 /* bufHeight */, + 0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceContainer); + return std::make_unique<InputSurface>(surfaceControl, width, height, + true /* noInputChannel */); + } + static std::unique_ptr<InputSurface> makeCursorInputSurface( const sp<SurfaceComposerClient> &scc, int width, int height) { sp<SurfaceControl> surfaceControl = @@ -113,8 +147,8 @@ public: return std::make_unique<InputSurface>(surfaceControl, width, height); } - InputEvent* consumeEvent() { - waitForEventAvailable(); + InputEvent *consumeEvent(int timeoutMs = 3000) { + waitForEventAvailable(timeoutMs); InputEvent *ev; uint32_t seqId; @@ -153,8 +187,28 @@ public: EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); } + void expectKey(uint32_t keycode) { + InputEvent *ev = consumeEvent(); + ASSERT_NE(ev, nullptr); + ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType()); + KeyEvent *keyEvent = static_cast<KeyEvent *>(ev); + EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, keyEvent->getAction()); + EXPECT_EQ(keycode, keyEvent->getKeyCode()); + EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS); + + ev = consumeEvent(); + ASSERT_NE(ev, nullptr); + ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType()); + keyEvent = static_cast<KeyEvent *>(ev); + EXPECT_EQ(AMOTION_EVENT_ACTION_UP, keyEvent->getAction()); + EXPECT_EQ(keycode, keyEvent->getKeyCode()); + EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS); + } + ~InputSurface() { - mInputFlinger->unregisterInputChannel(mServerChannel); + if (mInputInfo.token) { + mInputFlinger->unregisterInputChannel(mServerChannel); + } } void doTransaction(std::function<void(SurfaceComposerClient::Transaction&, @@ -176,41 +230,14 @@ public: } private: - void waitForEventAvailable() { + void waitForEventAvailable(int timeoutMs) { struct pollfd fd; fd.fd = mClientChannel->getFd(); fd.events = POLLIN; - poll(&fd, 1, 3000); + poll(&fd, 1, timeoutMs); } - void populateInputInfo(int width, int height) { - mInputInfo.token = mServerChannel->getConnectionToken(); - mInputInfo.name = "Test info"; - mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL; - mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION; - mInputInfo.dispatchingTimeout = seconds_to_nanoseconds(5); - mInputInfo.globalScaleFactor = 1.0; - mInputInfo.canReceiveKeys = true; - mInputInfo.hasFocus = true; - mInputInfo.hasWallpaper = false; - mInputInfo.paused = false; - - mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); - - // TODO: Fill in from SF? - mInputInfo.ownerPid = 11111; - mInputInfo.ownerUid = 11111; - mInputInfo.inputFeatures = 0; - mInputInfo.displayId = 0; - - InputApplicationInfo aInfo; - aInfo.token = new BBinder(); - aInfo.name = "Test app info"; - aInfo.dispatchingTimeout = seconds_to_nanoseconds(5); - - mInputInfo.applicationInfo = aInfo; - } public: sp<SurfaceControl> mSurfaceControl; sp<InputChannel> mServerChannel, mClientChannel; @@ -277,6 +304,14 @@ void injectTap(int x, int y) { } } +void injectKey(uint32_t keycode) { + char *buf1; + asprintf(&buf1, "%d", keycode); + if (fork() == 0) { + execlp("input", "input", "keyevent", buf1, NULL); + } +} + TEST_F(InputSurfacesTest, can_receive_input) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); @@ -561,5 +596,36 @@ TEST_F(InputSurfacesTest, input_ignores_cursor_layer) { injectTap(11, 11); surface->expectTap(1, 1); } + +TEST_F(InputSurfacesTest, child_container_with_no_input_channel_blocks_parent) { + std::unique_ptr<InputSurface> parent = makeSurface(100, 100); + parent->showAt(100, 100); + parent->assertFocusChange(true); + injectTap(101, 101); + parent->expectTap(1, 1); + + std::unique_ptr<InputSurface> childContainerSurface = + InputSurface::makeContainerInputSurfaceNoInputChannel(mComposerClient, 100, 100); + childContainerSurface->showAt(0, 0); + childContainerSurface->doTransaction( + [&](auto &t, auto &sc) { t.reparent(sc, parent->mSurfaceControl->getHandle()); }); + injectTap(101, 101); + + EXPECT_EQ(parent->consumeEvent(100), nullptr); +} + +TEST_F(InputSurfacesTest, drop_input_policy) { + std::unique_ptr<InputSurface> surface = makeSurface(100, 100); + surface->doTransaction( + [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::ALL); }); + surface->showAt(100, 100); + surface->assertFocusChange(true); + + injectTap(101, 101); + EXPECT_EQ(surface->consumeEvent(100), nullptr); + + injectKey(AKEYCODE_V); + EXPECT_EQ(surface->consumeEvent(100), nullptr); } } +} // namespace android
\ No newline at end of file diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 85a2015e43..301c3f56f2 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -42,20 +42,6 @@ bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const { && y >= frameTop && y < frameBottom; } -// TODO(b/155781676): Remove and replace call points with trustedOverlay when that is ready. -bool InputWindowInfo::isTrustedOverlay() const { - return layoutParamsType == TYPE_INPUT_METHOD || layoutParamsType == TYPE_INPUT_METHOD_DIALOG || - layoutParamsType == TYPE_MAGNIFICATION_OVERLAY || layoutParamsType == TYPE_STATUS_BAR || - layoutParamsType == TYPE_NOTIFICATION_SHADE || - layoutParamsType == TYPE_NAVIGATION_BAR || - layoutParamsType == TYPE_NAVIGATION_BAR_PANEL || - layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY || - layoutParamsType == TYPE_DOCK_DIVIDER || - layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY || - layoutParamsType == TYPE_INPUT_CONSUMER || - layoutParamsType == TYPE_TRUSTED_APPLICATION_OVERLAY; -} - bool InputWindowInfo::supportsSplitTouch() const { return layoutParamsFlags & FLAG_SPLIT_TOUCH; } @@ -92,6 +78,7 @@ status_t InputWindowInfo::write(Parcel& output) const { output.writeBool(hasFocus); output.writeBool(hasWallpaper); output.writeBool(paused); + output.writeBool(trustedOverlay); output.writeInt32(ownerPid); output.writeInt32(ownerUid); output.writeInt32(inputFeatures); @@ -130,6 +117,7 @@ InputWindowInfo InputWindowInfo::read(const Parcel& from) { ret.hasFocus = from.readBool(); ret.hasWallpaper = from.readBool(); ret.paused = from.readBool(); + ret.trustedOverlay = from.readBool(); ret.ownerPid = from.readInt32(); ret.ownerUid = from.readInt32(); ret.inputFeatures = from.readInt32(); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 8907b3576d..e3ab522d6d 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -1465,6 +1465,11 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime, return INPUT_EVENT_INJECTION_FAILED; } + // Drop key events if requested by input feature + if (focusedWindowHandle != nullptr && shouldDropInput(entry, focusedWindowHandle)) { + return INPUT_EVENT_INJECTION_FAILED; + } + // Compatibility behavior: raise ANR if there is a focused application, but no focused window. // Only start counting when we have a focused event to dispatch. The ANR is canceled if we // start interacting with another application via touch (app switch). This code can be removed @@ -1694,6 +1699,11 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } } + // Drop touch events if requested by input feature + if (newTouchedWindowHandle != nullptr && shouldDropInput(entry, newTouchedWindowHandle)) { + newTouchedWindowHandle = nullptr; + } + // Also don't send the new touch event to unresponsive gesture monitors newGestureMonitors = selectResponsiveMonitorsLocked(newGestureMonitors); @@ -1758,6 +1768,13 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, tempTouchState.getFirstForegroundWindowHandle(); sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState); + + // Drop touch events if requested by input feature + if (newTouchedWindowHandle != nullptr && + shouldDropInput(entry, newTouchedWindowHandle)) { + newTouchedWindowHandle = nullptr; + } + if (oldTouchedWindowHandle != newTouchedWindowHandle && oldTouchedWindowHandle != nullptr && newTouchedWindowHandle != nullptr) { if (DEBUG_FOCUS) { @@ -2094,7 +2111,7 @@ static bool canBeObscuredBy(const sp<InputWindowHandle>& windowHandle, // If ownerPid is the same we don't generate occlusion events as there // is no in-process security boundary. return false; - } else if (otherInfo->isTrustedOverlay()) { + } else if (otherInfo->trustedOverlay) { return false; } else if (otherInfo->displayId != info->displayId) { return false; @@ -5099,4 +5116,16 @@ bool InputDispatcher::waitForIdle() { return result == std::cv_status::no_timeout; } +bool InputDispatcher::shouldDropInput(const EventEntry& entry, + const sp<InputWindowHandle>& windowHandle) const { + if (windowHandle->getInfo()->inputFeatures & InputWindowInfo::INPUT_FEATURE_DROP_INPUT) { + ALOGW("Dropping %s event targeting %s as requested by inputFeatures=0x%08x on display " + "%" PRId32 ".", + EventEntry::typeToString(entry.type), windowHandle->getName().c_str(), + windowHandle->getInfo()->inputFeatures, windowHandle->getInfo()->displayId); + return true; + } + return false; +} + } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index e679c6b06f..b078662870 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -420,6 +420,9 @@ private: std::string getApplicationWindowLabel(const sp<InputApplicationHandle>& applicationHandle, const sp<InputWindowHandle>& windowHandle); + bool shouldDropInput(const EventEntry& entry, const sp<InputWindowHandle>& windowHandle) const + REQUIRES(mLock); + // Manage the dispatch cycle for a single connection. // These methods are deliberately not Interruptible because doing all of the work // with the mutex held makes it easier to ensure that connection invariants are maintained. diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 86c0503662..6842e6cd33 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -785,6 +785,8 @@ public: void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; } + void setInputFeatures(int32_t inputFeatures) { mInfo.inputFeatures = inputFeatures; } + void setDispatchingTimeout(std::chrono::nanoseconds timeout) { mInfo.dispatchingTimeout = timeout.count(); } @@ -903,6 +905,8 @@ public: mInfo.ownerUid = ownerUid; } + void setFlags(int32_t layoutParamsFlags) { mInfo.layoutParamsFlags = layoutParamsFlags; } + private: const std::string mName; std::unique_ptr<FakeInputReceiver> mInputReceiver; @@ -3112,4 +3116,42 @@ TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) { mFocusedWindow->assertNoEvents(); } +class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; + +TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { + sp<FakeApplicationHandle> application = new FakeApplicationHandle(); + sp<FakeWindowHandle> window = + new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT); + window->setInputFeatures(InputWindowInfo::INPUT_FEATURE_DROP_INPUT); + mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); + window->setFocus(true); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); + window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/); + + // With the flag set, window should not get any input + NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); + mDispatcher->notifyKey(&keyArgs); + window->assertNoEvents(); + + NotifyMotionArgs motionArgs = + generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT); + mDispatcher->notifyMotion(&motionArgs); + window->assertNoEvents(); + + // With the flag cleared, the window should get input + window->setInputFeatures(0); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); + + keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT); + mDispatcher->notifyKey(&keyArgs); + window->consumeKeyUp(ADISPLAY_ID_DEFAULT); + + motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT); + mDispatcher->notifyMotion(&motionArgs); + window->consumeMotionDown(ADISPLAY_ID_DEFAULT); + window->assertNoEvents(); +} + } // namespace android::inputdispatcher diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e9965d4717..6215d5cecc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -118,6 +118,8 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.shadowRadius = 0.f; mCurrentState.treeHasFrameRateVote = false; mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID; + mCurrentState.isTrustedOverlay = false; + mCurrentState.dropInputMode = gui::DropInputMode::NONE; if (args.flags & ISurfaceComposerClient::eNoColorFill) { // Set an invalid color so there is no color fill. @@ -1142,6 +1144,23 @@ bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relati return true; } +bool Layer::setTrustedOverlay(bool isTrustedOverlay) { + if (mCurrentState.isTrustedOverlay == isTrustedOverlay) return false; + mCurrentState.isTrustedOverlay = isTrustedOverlay; + mCurrentState.modified = true; + mCurrentState.inputInfoChanged = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool Layer::isTrustedOverlay() const { + if (getDrawingState().isTrustedOverlay) { + return true; + } + const auto& p = mDrawingParent.promote(); + return (p != nullptr) && p->isTrustedOverlay(); +} + bool Layer::setSize(uint32_t w, uint32_t h) { if (mCurrentState.requested_legacy.w == w && mCurrentState.requested_legacy.h == h) return false; @@ -2252,6 +2271,7 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, layerInfo->set_effective_scaling_mode(getEffectiveScalingMode()); layerInfo->set_corner_radius(getRoundedCornerState().radius); + layerInfo->set_is_trusted_overlay(isTrustedOverlay()); LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform()); LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(), [&]() { return layerInfo->mutable_position(); }); @@ -2365,6 +2385,36 @@ bool Layer::isRemovedFromCurrentState() const { return mRemovedFromCurrentState; } +gui::DropInputMode Layer::getDropInputMode() const { + gui::DropInputMode mode = mDrawingState.dropInputMode; + if (mode == gui::DropInputMode::ALL) { + return mode; + } + sp<Layer> parent = mDrawingParent.promote(); + if (parent) { + gui::DropInputMode parentMode = parent->getDropInputMode(); + if (parentMode != gui::DropInputMode::NONE) { + return parentMode; + } + } + return mode; +} + +void Layer::handleDropInputMode(InputWindowInfo& info) const { + if ((mDrawingState.inputInfo.inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL) == + InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL) { + return; + } + + // Check if we need to drop input unconditionally + gui::DropInputMode dropInputMode = getDropInputMode(); + if (dropInputMode == gui::DropInputMode::ALL) { + info.inputFeatures |= InputWindowInfo::INPUT_FEATURE_DROP_INPUT; + ALOGV("Dropping input for %s as requested by policy.", getDebugName()); + return; + } +} + InputWindowInfo Layer::fillInputInfo() { if (!hasInputInfo()) { mDrawingState.inputInfo.name = getName(); @@ -2438,6 +2488,7 @@ InputWindowInfo Layer::fillInputInfo() { // InputDispatcher, and obviously if they aren't visible they can't occlude // anything. info.visible = hasInputInfo() ? canReceiveInput() : isVisible(); + handleDropInputMode(info); auto cropLayer = mDrawingState.touchableRegionCrop.promote(); if (info.replaceTouchableRegionWithCrop) { @@ -2450,6 +2501,10 @@ InputWindowInfo Layer::fillInputInfo() { info.touchableRegion = info.touchableRegion.intersect(Rect{cropLayer->mScreenBounds}); } + // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state + // if it was set by WM for a known system overlay + info.trustedOverlay = info.trustedOverlay || isTrustedOverlay(); + // If the layer is a clone, we need to crop the input region to cloned root to prevent // touches from going outside the cloned area. if (isClone()) { @@ -2474,7 +2529,8 @@ sp<Layer> Layer::getClonedRoot() { } bool Layer::hasInputInfo() const { - return mDrawingState.inputInfo.token != nullptr; + return mDrawingState.inputInfo.token != nullptr || + mDrawingState.inputInfo.inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL; } bool Layer::canReceiveInput() const { @@ -2637,6 +2693,16 @@ Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t comp } } +bool Layer::setDropInputMode(gui::DropInputMode mode) { + if (mCurrentState.dropInputMode == mode) { + return false; + } + mCurrentState.dropInputMode = mode; + mCurrentState.modified = true; + mCurrentState.inputInfoChanged = true; + setTransactionFlags(eTransactionNeeded); + return true; +} // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 2c90c92f6c..6c5d114f86 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -16,6 +16,7 @@ #pragma once +#include <android/gui/DropInputMode.h> #include <compositionengine/LayerFE.h> #include <gui/BufferQueue.h> #include <gui/ISurfaceComposerClient.h> @@ -279,6 +280,11 @@ public: // a buffer of a different size. ui::Transform::ROT_INVALID means the // a fixed transform hint is not set. ui::Transform::RotationFlags fixedTransformHint; + + // Whether or not this layer is a trusted overlay for input + bool isTrustedOverlay; + + gui::DropInputMode dropInputMode; }; explicit Layer(const LayerCreationArgs& args); @@ -356,6 +362,7 @@ public: // is specified in pixels. virtual bool setBackgroundBlurRadius(int backgroundBlurRadius); virtual bool setTransparentRegionHint(const Region& transparent); + virtual bool setTrustedOverlay(bool); virtual bool setFlags(uint8_t flags, uint8_t mask); virtual bool setLayerStack(uint32_t layerStack); virtual uint32_t getLayerStack() const; @@ -406,6 +413,8 @@ public: bool setShadowRadius(float shadowRadius); virtual bool setFrameRateSelectionPriority(int32_t priority); virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint); + bool setDropInputMode(gui::DropInputMode); + // If the variable is not set on the layer, it traverses up the tree to inherit the frame // rate priority from its parent. virtual int32_t getFrameRateSelectionPriority() const; @@ -1064,6 +1073,9 @@ private: const std::vector<Layer*>& layersInTree); void updateTreeHasFrameRateVote(); + bool isTrustedOverlay() const; + gui::DropInputMode getDropInputMode() const; + void handleDropInputMode(InputWindowInfo& info) const; // Cached properties computed from drawing state // Effective transform taking into account parent transforms and any parent scaling. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 79f99cc5d5..0d95819497 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3859,6 +3859,24 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded | eTransformHintUpdateNeeded; } } + if (what & layer_state_t::eTrustedOverlayChanged) { + if (privileged) { + if (layer->setTrustedOverlay(s.isTrustedOverlay)) { + flags |= eTraversalNeeded; + } + } else { + ALOGE("Attempt to set trusted overlay without permission ACCESS_SURFACE_FLINGER"); + } + } + if (what & layer_state_t::eDropInputModeChanged) { + if (privileged) { + if (layer->setDropInputMode(s.dropInputMode)) { + flags |= eTraversalNeeded; + } + } else { + ALOGE("Attempt to update InputPolicyFlags without permission ACCESS_SURFACE_FLINGER"); + } + } // This has to happen after we reparent children because when we reparent to null we remove // child layers from current state and remove its relative z. If the children are reparented in // the same transaction, then we have to make sure we reparent the children first so we do not diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 80102bdbb6..0555acff43 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -130,6 +130,7 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf), layer->mCurrentState.z); addShadowRadiusLocked(transaction, layerId, layer->mCurrentState.shadowRadius); + addTrustedOverlayLocked(transaction, layerId, layer->mDrawingState.isTrustedOverlay); } void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment, @@ -388,6 +389,13 @@ void SurfaceInterceptor::addShadowRadiusLocked(Transaction* transaction, int32_t overrideChange->set_radius(shadowRadius); } +void SurfaceInterceptor::addTrustedOverlayLocked(Transaction* transaction, int32_t layerId, + bool isTrustedOverlay) { + SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); + TrustedOverlayChange* overrideChange(change->mutable_trusted_overlay()); + overrideChange->set_is_trusted_overlay(isTrustedOverlay); +} + void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state) { @@ -467,6 +475,9 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eShadowRadiusChanged) { addShadowRadiusLocked(transaction, layerId, state.shadowRadius); } + if (state.what & layer_state_t::eTrustedOverlayChanged) { + addTrustedOverlayLocked(transaction, layerId, state.isTrustedOverlay); + } } void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction, diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 896bdcc259..6b98b44420 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -168,6 +168,7 @@ private: void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId, int z); void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius); + void addTrustedOverlayLocked(Transaction* transaction, int32_t layerId, bool isTrustedOverlay); // Add display transactions to the trace DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t sequenceId); diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index 8fce0c9bf3..2eceba848d 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -105,6 +105,7 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerP layer.queuedFrames = layerProto.queued_frames(); layer.refreshPending = layerProto.refresh_pending(); layer.isProtected = layerProto.is_protected(); + layer.isTrustedOverlay = layerProto.is_trusted_overlay(); layer.cornerRadius = layerProto.corner_radius(); layer.backgroundBlurRadius = layerProto.background_blur_radius(); for (const auto& entry : layerProto.metadata()) { @@ -288,6 +289,7 @@ std::string LayerProtoParser::Layer::to_string() const { StringAppendF(&result, "crop=%s, ", crop.to_string().c_str()); StringAppendF(&result, "cornerRadius=%f, ", cornerRadius); StringAppendF(&result, "isProtected=%1d, ", isProtected); + StringAppendF(&result, "isTrustedOverlay=%1d, ", isTrustedOverlay); StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate); StringAppendF(&result, "dataspace=%s, ", dataspace.c_str()); StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str()); diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 52b916555f..67bbd76934 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -109,6 +109,7 @@ public: int32_t queuedFrames; bool refreshPending; bool isProtected; + bool isTrustedOverlay; float cornerRadius; int backgroundBlurRadius; LayerMetadata metadata; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 7f1f542e4b..780b066000 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -123,6 +123,8 @@ message LayerProto { bool is_relative_of = 51; // Layer's background blur radius in pixels. int32 background_blur_radius = 52; + + bool is_trusted_overlay = 53; } message PositionProto { diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 8d97f275ba..5bafbd8975 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -195,6 +195,7 @@ public: bool detachChildrenUpdateFound(const SurfaceChange& change, bool found); bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found); bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found); + bool trustedOverlayUpdateFound(const SurfaceChange& change, bool found); bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase); // Find all of the updates in the single trace @@ -233,6 +234,7 @@ public: void detachChildrenUpdate(Transaction&); void reparentChildrenUpdate(Transaction&); void shadowRadiusUpdate(Transaction&); + void trustedOverlayUpdate(Transaction&); void surfaceCreation(Transaction&); void displayCreation(Transaction&); void displayDeletion(Transaction&); @@ -421,6 +423,10 @@ void SurfaceInterceptorTest::shadowRadiusUpdate(Transaction& t) { t.setShadowRadius(mBGSurfaceControl, SHADOW_RADIUS_UPDATE); } +void SurfaceInterceptorTest::trustedOverlayUpdate(Transaction& t) { + t.setTrustedOverlay(mBGSurfaceControl, true); +} + void SurfaceInterceptorTest::displayCreation(Transaction&) { sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true); SurfaceComposerClient::destroyDisplay(testDisplay); @@ -452,6 +458,7 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate); runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate); runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate); + runInTransaction(&SurfaceInterceptorTest::trustedOverlayUpdate); } void SurfaceInterceptorTest::surfaceCreation(Transaction&) { @@ -695,6 +702,17 @@ bool SurfaceInterceptorTest::shadowRadiusUpdateFound(const SurfaceChange& change return foundShadowRadius; } +bool SurfaceInterceptorTest::trustedOverlayUpdateFound(const SurfaceChange& change, + bool foundTrustedOverlay) { + bool hasTrustedOverlay(change.trusted_overlay().is_trusted_overlay()); + if (hasTrustedOverlay && !foundTrustedOverlay) { + foundTrustedOverlay = true; + } else if (hasTrustedOverlay && foundTrustedOverlay) { + []() { FAIL(); }(); + } + return foundTrustedOverlay; +} + bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase) { bool foundUpdate = false; @@ -764,6 +782,9 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kShadowRadius: foundUpdate = shadowRadiusUpdateFound(change, foundUpdate); break; + case SurfaceChange::SurfaceChangeCase::kTrustedOverlay: + foundUpdate = trustedOverlayUpdateFound(change, foundUpdate); + break; case SurfaceChange::SurfaceChangeCase::SURFACECHANGE_NOT_SET: break; } @@ -976,6 +997,11 @@ TEST_F(SurfaceInterceptorTest, InterceptShadowRadiusUpdateWorks) { SurfaceChange::SurfaceChangeCase::kShadowRadius); } +TEST_F(SurfaceInterceptorTest, InterceptTrustedOverlayUpdateWorks) { + captureTest(&SurfaceInterceptorTest::trustedOverlayUpdate, + SurfaceChange::SurfaceChangeCase::kTrustedOverlay); +} + TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) { captureTest(&SurfaceInterceptorTest::runAllUpdates, &SurfaceInterceptorTest::assertAllUpdatesFound); |