diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-10-19 16:41:04 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-10-19 16:41:04 +0000 |
commit | f397fa74389f886fe72ca0617fddd09d311b9888 (patch) | |
tree | e34e6d3658be9b70990c32d783e8e4bfcb2082ae | |
parent | 8455185d1c18aa873c718910f89ecac3aa199920 (diff) | |
parent | 6ff113e567dc96790735e6c081549b4bb489b9cb (diff) | |
download | native-f397fa74389f886fe72ca0617fddd09d311b9888.tar.gz |
Merge cherrypicks of [16740114, 16740115, 16740116, 15829070, 18029505] into sc-platform-release.android-platform-12.0.0_r17android-platform-12.0.0_r16android-platform-12.0.0_r15android-platform-12.0.0_r14
Change-Id: I118d84e5ea5eebf0d2f8a8c2201a780ad66737fc
-rw-r--r-- | include/input/InputWindow.h | 1 | ||||
-rw-r--r-- | libs/gui/Android.bp | 10 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 10 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 15 | ||||
-rw-r--r-- | libs/gui/android/gui/DropInputMode.aidl | 40 | ||||
-rw-r--r-- | libs/gui/include/gui/LayerState.h | 5 | ||||
-rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 2 | ||||
-rw-r--r-- | libs/gui/tests/EndToEndNativeInputTest.cpp | 140 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 30 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.h | 3 | ||||
-rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 40 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 48 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 9 |
14 files changed, 319 insertions, 40 deletions
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 121be6d963..cea57ec10d 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -128,6 +128,7 @@ struct InputWindowInfo : public Parcelable { DISABLE_TOUCH_PAD_GESTURES = 0x00000001, NO_INPUT_CHANNEL = 0x00000002, DISABLE_USER_ACTIVITY = 0x00000004, + DROP_INPUT = 0x00000008, }; /* These values are filled in by the WM and passed through SurfaceFlinger diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 64203f78a8..b1c6e3a5d6 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -39,13 +39,20 @@ 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_headers { name: "libgui_aidl_headers", vendor_available: true, static_libs: [ "libgui_aidl_static", ], - export_static_lib_headers: [ "libgui_aidl_static", ], @@ -102,6 +109,7 @@ cc_library_shared { ], srcs: [ + ":guiconstants_aidl", ":framework_native_aidl", ":inputconstants_aidl", ":libgui_bufferqueue_sources", diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index bd496ba01e..115579d85b 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -65,6 +65,7 @@ layer_state_t::layer_state_t() frameNumber(0), autoRefresh(false), isTrustedOverlay(false), + dropInputMode(gui::DropInputMode::NONE), bufferCrop(Rect::INVALID_RECT), destinationFrame(Rect::INVALID_RECT), releaseBufferListener(nullptr) { @@ -172,7 +173,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.write, bufferCrop); SAFE_PARCEL(output.write, destinationFrame); SAFE_PARCEL(output.writeBool, isTrustedOverlay); - + output.writeUint32(static_cast<uint32_t>(dropInputMode)); return NO_ERROR; } @@ -304,6 +305,9 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, destinationFrame); SAFE_PARCEL(input.readBool, &isTrustedOverlay); + uint32_t mode; + mode = input.readUint32(); + dropInputMode = static_cast<gui::DropInputMode>(mode); return NO_ERROR; } @@ -598,6 +602,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eTrustedOverlayChanged; isTrustedOverlay = other.isTrustedOverlay; } + if (other.what & eDropInputModeChanged) { + what |= eDropInputModeChanged; + dropInputMode = other.dropInputMode; + } if (other.what & eReleaseBufferListenerChanged) { if (releaseBufferListener) { ALOGW("Overriding releaseBufferListener"); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 37914c18fb..3f1277ed57 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1675,6 +1675,21 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrust 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; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApplyToken( const sp<IBinder>& applyToken) { mApplyToken = applyToken; diff --git a/libs/gui/android/gui/DropInputMode.aidl b/libs/gui/android/gui/DropInputMode.aidl new file mode 100644 index 0000000000..294943667c --- /dev/null +++ b/libs/gui/android/gui/DropInputMode.aidl @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2021, 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 4ffd324cd0..9460319f4b 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -26,6 +26,7 @@ #include <gui/ITransactionCompletedListener.h> #include <math/mat4.h> +#include <android/gui/DropInputMode.h> #ifndef NO_INPUT #include <android/FocusRequest.h> #include <input/InputWindow.h> @@ -122,6 +123,7 @@ struct layer_state_t { eFixedTransformHintChanged = 0x200'00000000, eFrameNumberChanged = 0x400'00000000, eBlurRegionsChanged = 0x800'00000000, + eDropInputModeChanged = 0x8000'00000000, eAutoRefreshChanged = 0x1000'00000000, eStretchChanged = 0x2000'00000000, eTrustedOverlayChanged = 0x4000'00000000, @@ -240,6 +242,9 @@ struct layer_state_t { // Stretch effect to be applied to this layer StretchEffect stretchEffect; + // Force inputflinger to drop all input events for the layer and its children. + gui::DropInputMode dropInputMode; + Rect bufferCrop; Rect destinationFrame; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 271ab86d24..4b2075082c 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -540,6 +540,8 @@ public: // 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); + // Queues up transactions using this token in SurfaceFlinger. By default, all transactions // from a client are placed on the same queue. This can be used to prevent multiple // transactions from blocking each other. diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 49c44a78d1..53e4af4454 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> @@ -68,16 +69,39 @@ static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s; 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; mInputFlinger = getInputFlinger(); - mClientChannel = std::make_shared<InputChannel>(); - mInputFlinger->createInputChannel("testchannels", mClientChannel.get()); + if (noInputChannel) { + mInputInfo.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL; + } else { + mClientChannel = std::make_shared<InputChannel>(); + mInputFlinger->createInputChannel("testchannels", mClientChannel.get()); + mInputInfo.token = mClientChannel->getConnectionToken(); + mInputConsumer = new InputConsumer(mClientChannel); + } - populateInputInfo(width, height); + mInputInfo.name = "Test info"; + mInputInfo.dispatchingTimeout = 5s; + mInputInfo.globalScaleFactor = 1.0; + mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; + mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; + mInputInfo.focusable = true; + mInputInfo.hasWallpaper = false; + mInputInfo.paused = false; + // TODO: Fill in from SF? + mInputInfo.ownerPid = 11111; + mInputInfo.ownerUid = 11111; + mInputInfo.displayId = 0; + mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); - mInputConsumer = new InputConsumer(mClientChannel); + InputApplicationInfo aInfo; + aInfo.token = new BBinder(); + aInfo.name = "Test app info"; + aInfo.dispatchingTimeoutMillis = + std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count(); + mInputInfo.applicationInfo = aInfo; } static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient> &scc, @@ -106,6 +130,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 = @@ -115,8 +149,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; @@ -155,6 +189,24 @@ 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); + } + void expectTapWithFlag(int x, int y, int32_t flags) { InputEvent *ev = consumeEvent(); ASSERT_NE(ev, nullptr); @@ -174,7 +226,9 @@ public: } virtual ~InputSurface() { - mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); + if (mClientChannel) { + mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); + } } virtual void doTransaction( @@ -210,40 +264,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 = mClientChannel->getConnectionToken(); - mInputInfo.name = "Test info"; - mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; - mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; - mInputInfo.dispatchingTimeout = 5s; - mInputInfo.globalScaleFactor = 1.0; - mInputInfo.focusable = 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.displayId = 0; - - InputApplicationInfo aInfo; - aInfo.token = new BBinder(); - aInfo.name = "Test app info"; - aInfo.dispatchingTimeoutMillis = - std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count(); - - mInputInfo.applicationInfo = aInfo; - } public: sp<SurfaceControl> mSurfaceControl; std::shared_ptr<InputChannel> mClientChannel; @@ -358,6 +386,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); @@ -603,6 +639,21 @@ TEST_F(InputSurfacesTest, input_ignores_cursor_layer) { surface->expectTap(1, 1); } +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->requestFocus(); + surface->assertFocusChange(true); + + injectTap(101, 101); + EXPECT_EQ(surface->consumeEvent(100), nullptr); + + injectKey(AKEYCODE_V); + EXPECT_EQ(surface->consumeEvent(100), nullptr); +} + TEST_F(InputSurfacesTest, can_be_focused) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); @@ -776,4 +827,21 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) { 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); + 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); }); + injectTap(101, 101); + + EXPECT_EQ(parent->consumeEvent(100), nullptr); +} + } // namespace android::test diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index ce1f266cfb..7ed0d4eaef 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -1815,6 +1815,11 @@ InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked( return InputEventInjectionResult::FAILED; } + // Drop key events if requested by input feature + if (focusedWindowHandle != nullptr && shouldDropInput(entry, focusedWindowHandle)) { + return InputEventInjectionResult::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 @@ -2040,6 +2045,11 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } } + // Drop touch events if requested by input feature + if (newTouchedWindowHandle != nullptr && shouldDropInput(entry, newTouchedWindowHandle)) { + newTouchedWindowHandle = nullptr; + } + // Drop events that can't be trusted due to occlusion if (newTouchedWindowHandle != nullptr && mBlockUntrustedTouchesMode != BlockUntrustedTouchesMode::DISABLED) { @@ -2126,6 +2136,13 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( sp<InputWindowHandle> oldTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle(); 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) { @@ -6128,6 +6145,19 @@ 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.test(InputWindowInfo::Feature::DROP_INPUT)) { + ALOGW("Dropping %s event targeting %s as requested by inputFeatures={%s} on display " + "%" PRId32 ".", + entry.getDescription().c_str(), windowHandle->getName().c_str(), + windowHandle->getInfo()->inputFeatures.string().c_str(), + windowHandle->getInfo()->displayId); + return true; + } + return false; +} + /** * Sets focus to the window identified by the token. This must be called * after updating any input window handles. diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 30652c65ee..053e82144e 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -530,6 +530,9 @@ private: std::string getApplicationWindowLabel(const 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 50b65cad5d..c973698b20 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -5331,4 +5331,44 @@ TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) { mSecondWindow->assertNoEvents(); } +class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; + +TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { + std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>(); + + sp<FakeWindowHandle> window = + new FakeWindowHandle(app, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT); + window->setInputFeatures(InputWindowInfo::Feature::DROP_INPUT); + mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, app); + window->setFocusable(true); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); + setFocusedWindow(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(static_cast<InputWindowInfo::Feature>(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 6ee13ce508..6b07be40f0 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -133,7 +133,9 @@ Layer::Layer(const LayerCreationArgs& args) mDrawingState.fixedTransformHint = ui::Transform::ROT_INVALID; mDrawingState.frameTimelineInfo = {}; mDrawingState.postTime = -1; + mDrawingState.dropInputMode = gui::DropInputMode::NONE; mDrawingState.destinationFrame.makeInvalid(); + mDrawingState.isTrustedOverlay = false; if (args.flags & ISurfaceComposerClient::eNoColorFill) { // Set an invalid color so there is no color fill. @@ -2131,7 +2133,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet layerInfo->set_owner_uid(mOwnerUid); } - if (traceFlags & SurfaceTracing::TRACE_INPUT) { + if (traceFlags & SurfaceTracing::TRACE_INPUT && needsInputInfo()) { InputWindowInfo info; if (useDrawing) { info = fillInputInfo({nullptr}); @@ -2159,6 +2161,35 @@ ui::Transform Layer::getInputTransform() const { return getTransform(); } +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.test(InputWindowInfo::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::Feature::DROP_INPUT; + ALOGV("Dropping input for %s as requested by policy.", getDebugName()); + return; + } +} + Rect Layer::getInputBounds() const { return getCroppedBufferSize(getDrawingState()); } @@ -2306,6 +2337,7 @@ InputWindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) { info.visible = hasInputInfo() ? canReceiveInput() : isVisible(); info.alpha = getAlpha(); fillTouchOcclusionMode(info); + handleDropInputMode(info); auto cropLayer = mDrawingState.touchableRegionCrop.promote(); if (info.replaceTouchableRegionWithCrop) { @@ -2349,7 +2381,8 @@ sp<Layer> Layer::getClonedRoot() { } bool Layer::hasInputInfo() const { - return mDrawingState.inputInfo.token != nullptr; + return mDrawingState.inputInfo.token != nullptr || + mDrawingState.inputInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL); } bool Layer::canReceiveInput() const { @@ -2514,6 +2547,17 @@ Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t comp } } +bool Layer::setDropInputMode(gui::DropInputMode mode) { + if (mDrawingState.dropInputMode == mode) { + return false; + } + mDrawingState.dropInputMode = mode; + mDrawingState.modified = true; + mFlinger->mInputInfoChanged = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + scheduler::Seamlessness Layer::FrameRate::convertChangeFrameRateStrategy(int8_t strategy) { switch (strategy) { case ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS: diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8905548b64..b67dbbdb44 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -17,6 +17,7 @@ #pragma once +#include <android/gui/DropInputMode.h> #include <compositionengine/LayerFE.h> #include <gui/BufferQueue.h> #include <gui/ISurfaceComposerClient.h> @@ -279,6 +280,7 @@ public: bool isTrustedOverlay; Rect bufferCrop; + gui::DropInputMode dropInputMode; Rect destinationFrame; }; @@ -444,6 +446,8 @@ public: virtual bool setFrameRateSelectionPriority(int32_t priority); virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint); virtual void setAutoRefresh(bool /* autoRefresh */) {} + 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; @@ -1056,6 +1060,8 @@ private: bool setFrameRateForLayerTree(FrameRate); void setZOrderRelativeOf(const wp<Layer>& relativeOf); bool isTrustedOverlay() const; + gui::DropInputMode getDropInputMode() const; + void handleDropInputMode(InputWindowInfo& info) const; // Find the root of the cloned hierarchy, this means the first non cloned parent. // This will return null if first non cloned parent is not found. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index bbf6a2db78..9b49b35ad5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4170,6 +4170,15 @@ uint32_t SurfaceFlinger::setClientStateLocked( 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"); + } + } if (what & layer_state_t::eStretchChanged) { if (layer->setStretchEffect(s.stretchEffect)) { flags |= eTraversalNeeded; |