diff options
| author | 2021-09-17 12:16:08 -0700 | |
|---|---|---|
| committer | 2021-09-17 12:16:08 -0700 | |
| commit | 9cf4a4d4e57d059a4e4119f0a8f2a8be237f28c2 (patch) | |
| tree | d2e108395e328d83a579ed1cff54d803329b0342 | |
| parent | 133b3bc5a2bb7dec195a571ce718410d3b45d800 (diff) | |
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
Change-Id: I443741d5ab51a45d37fb865f11c433c436d96c1e
| -rw-r--r-- | libs/gui/Android.bp | 1 | ||||
| -rw-r--r-- | libs/gui/LayerState.cpp | 12 | ||||
| -rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 15 | ||||
| -rw-r--r-- | libs/gui/android/gui/DropInputMode.aidl | 45 | ||||
| -rw-r--r-- | libs/gui/include/gui/LayerState.h | 5 | ||||
| -rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 1 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 9 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 10 |
9 files changed, 102 insertions, 1 deletions
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 2d1f5a1694..8c359c7756 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -55,6 +55,7 @@ cc_library_headers { filegroup { name: "guiconstants_aidl", srcs: [ + "android/gui/DropInputMode.aidl", "android/**/TouchOcclusionMode.aidl", ], } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 1fd9d13902..a419a63056 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -69,7 +69,8 @@ layer_state_t::layer_state_t() 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; @@ -174,6 +175,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeBool, isTrustedOverlay); SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint); + SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dropInputMode)); return NO_ERROR; } @@ -304,6 +306,10 @@ status_t layer_state_t::read(const Parcel& input) 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; } @@ -558,6 +564,10 @@ void layer_state_t::merge(const layer_state_t& other) { if (other.what & eProducerDisconnect) { what |= eProducerDisconnect; } + 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%" PRIX64 " what=0x%" PRIX64 " unmerged flags=0x%" PRIX64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 1bca6f9167..64361db41e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1739,6 +1739,21 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesti 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 0000000000..2b31744ca2 --- /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 f14127c9de..b27102bcce 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> @@ -118,6 +119,7 @@ struct layer_state_t { eAutoRefreshChanged = 0x1000'00000000, eStretchChanged = 0x2000'00000000, eTrustedOverlayChanged = 0x4000'00000000, + eDropInputModeChanged = 0x8000'00000000, }; layer_state_t(); @@ -248,6 +250,9 @@ struct layer_state_t { // 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 baa6878414..ffd0244275 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -562,6 +562,7 @@ public: 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 ef6f115fdc..d549fe9966 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -135,6 +135,7 @@ Layer::Layer(const LayerCreationArgs& args) 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. @@ -2541,6 +2542,14 @@ wp<Layer> Layer::fromHandle(const sp<IBinder>& handleBinder) { 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 3c3c7d0b88..b70d5d474c 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> @@ -277,6 +278,8 @@ public: Rect destinationFrame; sp<IBinder> releaseBufferEndpoint; + + gui::DropInputMode dropInputMode; }; /* @@ -442,6 +445,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; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5a881a3dfe..5aa0b87e22 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4147,6 +4147,16 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } } + if (what & layer_state_t::eDropInputModeChanged) { + if (privileged) { + if (layer->setDropInputMode(s.dropInputMode)) { + flags |= eTraversalNeeded; + mInputInfoChanged = true; + } + } else { + ALOGE("Attempt to update DropInputMode 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 |