summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-12-06 02:44:27 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2022-12-06 02:44:27 +0000
commitdb54eb4ef04bff58617216e29f29b1325db31a28 (patch)
tree1e4bc6f2aed67665eacce085c3b8fa061f5c06a5
parent9c6d1420770b7c1e39d57f7b021e6d4f1649f888 (diff)
parent9e2e432fa22cda144a388acfcecd790a6cd5d37e (diff)
downloadnative-android12-gsi.tar.gz
Merge "Merge cherrypicks of [16740114, 16740115, 16740116, 15829070, 18029505] into sc-platform-release. am: f397fa7438" into android12-gsiandroid12-gsi
-rw-r--r--include/input/InputWindow.h1
-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.cpp140
-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/Layer.cpp47
-rw-r--r--services/surfaceflinger/Layer.h6
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp9
14 files changed, 318 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 142e64bd4d..8342481233 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1679,6 +1679,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 6eae1f9629..66eec1010a 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -541,6 +541,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 d8cead5e50..6b07be40f0 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();
mDrawingState.isTrustedOverlay = false;
@@ -2132,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});
@@ -2160,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());
}
@@ -2307,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) {
@@ -2350,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 {
@@ -2515,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 fed0663220..d9238672be 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4184,6 +4184,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;