summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-15 19:03:05 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-15 19:03:05 +0000
commitd02117fe6bda19e221b51d6a1c3c9f7d90565198 (patch)
treec11d0d9408e7904548c83e09987f093891d10119
parent56ec6fcdbfb40447d2b67ba72b73ffa316b3e29a (diff)
parent6ddd4bf1fa937a0a048fa3da796969f194dbf54e (diff)
downloadnative-android12-mainline-sdkext-release.tar.gz
Snap for 8303596 from 6ddd4bf1fa937a0a048fa3da796969f194dbf54e to mainline-sdkext-releaseandroid-mainline-12.0.0_r109aml_sdk_311710000android12-mainline-sdkext-release
Change-Id: I23d0aa093b2306b32ff31027850cc246c430bfe1
-rw-r--r--include/input/InputWindow.h1
-rw-r--r--libs/binder/ndk/Android.bp10
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_status.h19
-rw-r--r--libs/binder/rust/Android.bp8
-rw-r--r--libs/binder/tests/parcel_fuzzer/Android.bp6
-rw-r--r--libs/gui/Android.bp10
-rw-r--r--libs/gui/LayerState.cpp10
-rw-r--r--libs/gui/SurfaceComposerClient.cpp15
-rw-r--r--libs/gui/android/gui/DropInputMode.aidl40
-rw-r--r--libs/gui/include/gui/LayerState.h5
-rw-r--r--libs/gui/include/gui/SurfaceComposerClient.h2
-rw-r--r--libs/gui/tests/EndToEndNativeInputTest.cpp50
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp30
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.h3
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp40
-rw-r--r--services/surfaceflinger/BufferQueueLayer.cpp7
-rw-r--r--services/surfaceflinger/Layer.cpp42
-rw-r--r--services/surfaceflinger/Layer.h6
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp51
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h8
-rw-r--r--services/surfaceflinger/tests/ScreenCapture_test.cpp18
-rw-r--r--services/surfaceflinger/tests/unittests/CompositionTest.cpp4
-rw-r--r--services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h1
23 files changed, 335 insertions, 51 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/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/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; }