diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-02-14 22:44:13 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-02-14 22:44:13 +0000 |
commit | 63420a47455b94ed907bf680cd48cadf53dca8ac (patch) | |
tree | c11d0d9408e7904548c83e09987f093891d10119 | |
parent | bd8887371087ff54f02fe5a9f48b3729121b7d64 (diff) | |
parent | 66ccbc938090f6dfc2b24bc672d7ae190d3a1eeb (diff) | |
download | native-63420a47455b94ed907bf680cd48cadf53dca8ac.tar.gz |
Snap for 8183220 from 66ccbc938090f6dfc2b24bc672d7ae190d3a1eeb to mainline-adbd-releaseandroid-mainline-12.0.0_r85android12-mainline-adbd-release
Change-Id: I99e7e68110cbb605ae40bb8c029fd9dd41cdaba6
26 files changed, 339 insertions, 55 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/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp index b03e24cd1a..23162d2e91 100644 --- a/libs/binder/ndk/Android.bp +++ b/libs/binder/ndk/Android.bp @@ -32,17 +32,10 @@ license { ], } +// TODO(b/211908498): remove this cc_defaults { name: "libbinder_ndk_host_user", target: { - host: { - cflags: [ - "-D__INTRODUCED_IN(n)=", - "-D__assert(a,b,c)=", - // We want all the APIs to be available on the host. - "-D__ANDROID_API__=10000", - ], - }, darwin: { enabled: false, }, @@ -52,7 +45,6 @@ cc_defaults { cc_library { name: "libbinder_ndk", - defaults: ["libbinder_ndk_host_user"], host_supported: true, llndk: { diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h index 6f1fdfcd20..76c7aacb7c 100644 --- a/libs/binder/ndk/include_ndk/android/binder_status.h +++ b/libs/binder/ndk/include_ndk/android/binder_status.h @@ -32,11 +32,26 @@ __BEGIN_DECLS +#ifndef __BIONIC__ + +#ifndef __INTRODUCED_IN +#define __INTRODUCED_IN(n) +#endif + +#ifndef __assert +#define __assert(a, b, c) \ + do { \ + syslog(LOG_ERR, a ": " c); \ + abort(); \ + } while (false) +#endif + #ifndef __ANDROID_API__ -#error Android builds must be compiled against a specific API. If this is an \ - android platform host build, you must use libbinder_ndk_host_user. +#define __ANDROID_API__ 10000 #endif +#endif // __BIONIC__ + /** * Low-level status types for use in binder. This is the least preferable way to * return an error for binder services (where binder_exception_t should be used, diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp index 49d3401a4f..416616031b 100644 --- a/libs/binder/rust/Android.bp +++ b/libs/binder/rust/Android.bp @@ -85,14 +85,6 @@ rust_bindgen { // Currently necessary for host builds // TODO(b/31559095): bionic on host should define this target: { - host: { - cflags: [ - "-D__INTRODUCED_IN(n)=", - "-D__assert(a,b,c)=", - // We want all the APIs to be available on the host. - "-D__ANDROID_API__=10000", - ], - }, darwin: { enabled: false, }, diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp index 74b8eb8d93..4b1bd2f591 100644 --- a/libs/binder/tests/parcel_fuzzer/Android.bp +++ b/libs/binder/tests/parcel_fuzzer/Android.bp @@ -9,7 +9,6 @@ package { cc_fuzz { name: "binder_parcel_fuzzer", - defaults: ["libbinder_ndk_host_user"], host_supported: true, fuzz_config: { @@ -51,6 +50,9 @@ cc_fuzz { "libbinder", ], }, + darwin: { + enabled: false, + }, }, // This flag enables verbose output in the fuzz target, and is very useful // for debugging a failure. If you are trying to diagnose how a crash was @@ -64,7 +66,7 @@ cc_library_static { target: { darwin: { enabled: false, - } + }, }, srcs: [ "random_fd.cpp", diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp index 570af71d9a..1fd2c62772 100644 --- a/libs/cputimeinstate/Android.bp +++ b/libs/cputimeinstate/Android.bp @@ -12,7 +12,7 @@ cc_library { srcs: ["cputimeinstate.cpp"], shared_libs: [ "libbase", - "libbpf", + "libbpf_bcc", "libbpf_android", "liblog", "libnetdutils" @@ -31,7 +31,7 @@ cc_test { srcs: ["testtimeinstate.cpp"], shared_libs: [ "libbase", - "libbpf", + "libbpf_bcc", "libbpf_android", "libtimeinstate", "libnetdutils", 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 076c90dd23..2f31fbbb68 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; } @@ -539,6 +543,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 96da8efd19..6ffd25d227 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1669,6 +1669,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 3e57ff611e..feef343748 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> @@ -116,6 +117,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, @@ -233,6 +235,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 baa0567617..6e17212911 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..f60a58f60b 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> @@ -115,8 +116,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 +156,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); @@ -210,12 +229,12 @@ 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) { @@ -358,6 +377,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 +630,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); diff --git a/services/gpuservice/gpumem/Android.bp b/services/gpuservice/gpumem/Android.bp index 830e53d534..24087ac9e6 100644 --- a/services/gpuservice/gpumem/Android.bp +++ b/services/gpuservice/gpumem/Android.bp @@ -28,7 +28,7 @@ cc_library_shared { ], shared_libs: [ "libbase", - "libbpf", + "libbpf_bcc", "libbpf_android", "libcutils", "liblog", diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp index 6d87c45921..5b69f960a2 100644 --- a/services/gpuservice/tests/unittests/Android.bp +++ b/services/gpuservice/tests/unittests/Android.bp @@ -34,7 +34,7 @@ cc_test { ], shared_libs: [ "libbase", - "libbpf", + "libbpf_bcc", "libbpf_android", "libcutils", "libgfxstats", diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 1899c5f29d..b8f16b0d52 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -1802,6 +1802,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 @@ -2027,6 +2032,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) { @@ -2113,6 +2123,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) { @@ -6116,6 +6133,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 9edf41c9c0..7eb74007f0 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -528,6 +528,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 3a9dede89b..6c2b158882 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -5305,4 +5305,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/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6b6d43425d..99e470dfe6 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -515,13 +515,10 @@ void BufferQueueLayer::onFirstRef() { } status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) { - uint32_t const maxSurfaceDims = - std::min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); - // never allow a surface larger than what our underlying GL implementation // can handle. - if ((uint32_t(w) > maxSurfaceDims) || (uint32_t(h) > maxSurfaceDims)) { - ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); + if (mFlinger->exceedsMaxRenderTargetSize(w, h)) { + ALOGE("dimensions too large %" PRIu32 " x %" PRIu32, w, h); return BAD_VALUE; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e4a777f3c7..71e4791fe9 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -133,6 +133,7 @@ Layer::Layer(const LayerCreationArgs& args) mDrawingState.fixedTransformHint = ui::Transform::ROT_INVALID; mDrawingState.frameTimelineInfo = {}; mDrawingState.postTime = -1; + mDrawingState.dropInputMode = gui::DropInputMode::NONE; mDrawingState.destinationFrame.makeInvalid(); if (args.flags & ISurfaceComposerClient::eNoColorFill) { @@ -2178,6 +2179,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()); } @@ -2325,6 +2355,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) { @@ -2533,6 +2564,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 59f5b0dc73..51eacee240 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; }; @@ -439,6 +441,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; @@ -1051,6 +1055,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 230810c936..c7c3e02604 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -792,6 +792,8 @@ void SurfaceFlinger::init() { ? renderengine::RenderEngine::ContextPriority::REALTIME : renderengine::RenderEngine::ContextPriority::MEDIUM) .build())); + mMaxRenderTargetSize = + std::min(getRenderEngine().getMaxTextureSize(), getRenderEngine().getMaxViewportDims()); // Set SF main policy after initializing RenderEngine which has its own policy. if (!SetTaskProfiles(0, {"SFMainPolicy"})) { @@ -879,14 +881,6 @@ void SurfaceFlinger::startBootAnim() { } } -size_t SurfaceFlinger::getMaxTextureSize() const { - return getRenderEngine().getMaxTextureSize(); -} - -size_t SurfaceFlinger::getMaxViewportDims() const { - return getRenderEngine().getMaxViewportDims(); -} - // ---------------------------------------------------------------------------- bool SurfaceFlinger::authenticateSurfaceTexture( @@ -4178,6 +4172,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; @@ -4218,17 +4221,30 @@ uint32_t SurfaceFlinger::setClientStateLocked( } bool bufferChanged = what & layer_state_t::eBufferChanged; bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged; + bool bufferSizeExceedsLimit = false; std::shared_ptr<renderengine::ExternalTexture> buffer; if (bufferChanged && cacheIdChanged && s.buffer != nullptr) { - ClientCache::getInstance().add(s.cachedBuffer, s.buffer); - buffer = ClientCache::getInstance().get(s.cachedBuffer); + bufferSizeExceedsLimit = + exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight()); + if (!bufferSizeExceedsLimit) { + ClientCache::getInstance().add(s.cachedBuffer, s.buffer); + buffer = ClientCache::getInstance().get(s.cachedBuffer); + } } else if (cacheIdChanged) { buffer = ClientCache::getInstance().get(s.cachedBuffer); } else if (bufferChanged && s.buffer != nullptr) { - buffer = std::make_shared< - renderengine::ExternalTexture>(s.buffer, getRenderEngine(), - renderengine::ExternalTexture::Usage::READABLE); - } + bufferSizeExceedsLimit = + exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight()); + if (!bufferSizeExceedsLimit) { + buffer = std::make_shared< + renderengine::ExternalTexture>(s.buffer, getRenderEngine(), + renderengine::ExternalTexture::Usage::READABLE); + } + } + ALOGE_IF(bufferSizeExceedsLimit, + "Attempted to create an ExternalTexture for layer %s that exceeds render target size " + "limit.", + layer->getDebugName()); if (buffer) { const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged; const uint64_t frameNumber = frameNumberChanged @@ -6198,6 +6214,13 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); + if (exceedsMaxRenderTargetSize(bufferSize.getWidth(), bufferSize.getHeight())) { + ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32 + ") that exceeds render target size limit.", + bufferSize.getWidth(), bufferSize.getHeight()); + return BAD_VALUE; + } + // Loop over all visible layers to see whether there's any protected layer. A protected layer is // typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer. // A protected layer has no implication on whether it's secure, which is explicitly set by diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 380f444221..95c251c721 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -931,8 +931,9 @@ private: void readPersistentProperties(); - size_t getMaxTextureSize() const; - size_t getMaxViewportDims() const; + bool exceedsMaxRenderTargetSize(uint32_t width, uint32_t height) const { + return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize; + } int getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const; @@ -1381,6 +1382,9 @@ private: SurfaceFlingerBE mBE; std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine; + // mMaxRenderTargetSize is only set once in init() so it doesn't need to be protected by + // any mutex. + size_t mMaxRenderTargetSize{1}; const std::string mHwcServiceName; diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp index 6912fcf219..ab2064efd0 100644 --- a/services/surfaceflinger/tests/ScreenCapture_test.cpp +++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp @@ -515,7 +515,8 @@ TEST_F(ScreenCaptureTest, CaptureSize) { } TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { - sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); + sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, + ISurfaceComposerClient::eFXSurfaceBufferState); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); @@ -532,6 +533,21 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { ASSERT_EQ(NAME_NOT_FOUND, ScreenCapture::captureLayers(args, captureResults)); } +TEST_F(ScreenCaptureTest, CaptureTooLargeLayer) { + sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + + Transaction().show(redLayer).setLayer(redLayer, INT32_MAX).apply(true); + + LayerCaptureArgs captureArgs; + captureArgs.layerHandle = redLayer->getHandle(); + captureArgs.frameScaleX = INT32_MAX / 60; + captureArgs.frameScaleY = INT32_MAX / 60; + + ScreenCaptureResults captureResults; + ASSERT_EQ(BAD_VALUE, ScreenCapture::captureLayers(captureArgs, captureResults)); +} + TEST_F(ScreenCaptureTest, CaptureSecureLayer) { sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, ISurfaceComposerClient::eFXSurfaceBufferState); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 560f139719..52a36a2719 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -108,6 +108,8 @@ public: mComposer = new Hwc2::mock::Composer(); mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer)); + + mFlinger.mutableMaxRenderTargetSize() = 16384; } ~CompositionTest() { @@ -519,8 +521,6 @@ struct BaseLayerProperties { static void setupLatchedBuffer(CompositionTest* test, sp<BufferQueueLayer> layer) { // TODO: Eliminate the complexity of actually creating a buffer - EXPECT_CALL(*test->mRenderEngine, getMaxTextureSize()).WillOnce(Return(16384)); - EXPECT_CALL(*test->mRenderEngine, getMaxViewportDims()).WillOnce(Return(16384)); status_t err = layer->setDefaultBufferProperties(LayerProperties::WIDTH, LayerProperties::HEIGHT, LayerProperties::FORMAT); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index cf67593174..3802e0d617 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -435,6 +435,7 @@ public: auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; } auto& mutablePowerAdvisor() { return mFlinger->mPowerAdvisor; } auto& mutableDebugDisableHWC() { return mFlinger->mDebugDisableHWC; } + auto& mutableMaxRenderTargetSize() { return mFlinger->mMaxRenderTargetSize; } auto& mutableHwcDisplayData() { return getHwComposer().mDisplayData; } auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; } |