SurfaceControl: Add setDropInputMode api
Introduces an API to drop input events on this SurfaceControl. This
policy will be inherited by its children. The caller must hold the
ACCESS_SURFACE_FLINGER permission.
Options include:
ALL: SurfaceControl and its children will not receive any
input regardless of whether it has a valid input channel.
OBSCURED: SurfaceControl and its children will not
receive any input if the layer is obscured, cropped by its parent or
translucent.
These policies are used to enable features that allow for a less trusted
interaction model between apps. See the bug for more details.
Test: atest libgui_test InputDispatcherDropInputFeatureTest
Bug:197364677
Merged-In: I443741d5ab51a45d37fb865f11c433c436d96c1e
Change-Id: I443741d5ab51a45d37fb865f11c433c436d96c1e
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 326da3a..8c250a4 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -55,6 +55,7 @@
filegroup {
name: "guiconstants_aidl",
srcs: [
+ "android/**/DropInputMode.aidl",
"android/**/TouchOcclusionMode.aidl",
],
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 8a7a871..54735fa 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -70,7 +70,8 @@
isTrustedOverlay(false),
bufferCrop(Rect::INVALID_RECT),
destinationFrame(Rect::INVALID_RECT),
- releaseBufferListener(nullptr) {
+ releaseBufferListener(nullptr),
+ dropInputMode(gui::DropInputMode::NONE) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
hdrMetadata.validTypes = 0;
@@ -175,6 +176,7 @@
SAFE_PARCEL(output.writeBool, isTrustedOverlay);
SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
+ SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dropInputMode));
return NO_ERROR;
}
@@ -305,6 +307,10 @@
SAFE_PARCEL(input.readBool, &isTrustedOverlay);
SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
+
+ uint32_t mode;
+ SAFE_PARCEL(input.readUint32, &mode);
+ dropInputMode = static_cast<gui::DropInputMode>(mode);
return NO_ERROR;
}
@@ -563,6 +569,10 @@
what |= eDestinationFrameChanged;
destinationFrame = other.destinationFrame;
}
+ if (other.what & eDropInputModeChanged) {
+ what |= eDropInputModeChanged;
+ dropInputMode = other.dropInputMode;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIu64 " what=0x%" PRIu64,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index a2037ac..843e2ff 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1739,6 +1739,21 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDropInputMode(
+ const sp<SurfaceControl>& sc, gui::DropInputMode mode) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ s->what |= layer_state_t::eDropInputModeChanged;
+ s->dropInputMode = mode;
+
+ registerSurfaceControlForCallback(sc);
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
diff --git a/libs/gui/android/gui/DropInputMode.aidl b/libs/gui/android/gui/DropInputMode.aidl
new file mode 100644
index 0000000..2b31744
--- /dev/null
+++ b/libs/gui/android/gui/DropInputMode.aidl
@@ -0,0 +1,45 @@
+/**
+ * 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,
+
+ /**
+ * Similar to DROP but input events are only dropped if the window is considered to be
+ * obscured. ref: b/197364677
+ */
+ OBSCURED
+}
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 8dc8b9a..03e4aac 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>
#include <android/gui/FocusRequest.h>
#include <gui/ISurfaceComposer.h>
@@ -117,6 +118,7 @@
eAutoRefreshChanged = 0x1000'00000000,
eStretchChanged = 0x2000'00000000,
eTrustedOverlayChanged = 0x4000'00000000,
+ eDropInputModeChanged = 0x8000'00000000,
};
layer_state_t();
@@ -247,6 +249,9 @@
// releaseCallbackId and release fence to all listeners so we store which listener the setBuffer
// was called with.
sp<IBinder> releaseBufferEndpoint;
+
+ // Force inputflinger to drop all input events for the layer and its children.
+ gui::DropInputMode dropInputMode;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0f8a32b..4ff2aa0 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -562,6 +562,7 @@
Transaction& setBufferCrop(const sp<SurfaceControl>& sc, const Rect& bufferCrop);
Transaction& setDestinationFrame(const sp<SurfaceControl>& sc,
const Rect& destinationFrame);
+ Transaction& setDropInputMode(const sp<SurfaceControl>& sc, gui::DropInputMode mode);
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 638bb9b..e097745 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -135,6 +135,7 @@
mDrawingState.postTime = -1;
mDrawingState.destinationFrame.makeInvalid();
mDrawingState.isTrustedOverlay = false;
+ mDrawingState.dropInputMode = gui::DropInputMode::NONE;
if (args.flags & ISurfaceComposerClient::eNoColorFill) {
// Set an invalid color so there is no color fill.
@@ -2576,6 +2577,14 @@
return handle->owner;
}
+bool Layer::setDropInputMode(gui::DropInputMode mode) {
+ if (mDrawingState.dropInputMode == mode) {
+ return false;
+ }
+ mDrawingState.dropInputMode = mode;
+ return true;
+}
+
// ---------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 470103c..e4276f5 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>
@@ -282,6 +283,8 @@
Rect destinationFrame;
sp<IBinder> releaseBufferEndpoint;
+
+ gui::DropInputMode dropInputMode;
};
/*
@@ -447,6 +450,8 @@
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;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index aab8331..786d2bb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4149,6 +4149,16 @@
flags |= eTraversalNeeded;
}
}
+ if (what & layer_state_t::eDropInputModeChanged) {
+ if (privileged) {
+ if (layer->setDropInputMode(s.dropInputMode)) {
+ flags |= eTraversalNeeded;
+ mInputInfoChanged = true;
+ }
+ } else {
+ ALOGE("Attempt to update InputPolicyFlags without permission ACCESS_SURFACE_FLINGER");
+ }
+ }
// This has to happen after we reparent children because when we reparent to null we remove
// child layers from current state and remove its relative z. If the children are reparented in
// the same transaction, then we have to make sure we reparent the children first so we do not