diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 3798ba73a4..03a2709075 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -52,6 +52,7 @@ message SurfaceChange { BackgroundBlurRadiusChange background_blur_radius = 20; ShadowRadiusChange shadow_radius = 21; BlurRegionsChange blur_regions = 22; + TrustedOverlayChange trusted_overlay = 23; } } @@ -192,6 +193,10 @@ message ShadowRadiusChange { required float radius = 1; } +message TrustedOverlayChange { + required float is_trusted_overlay = 1; +} + message BlurRegionsChange { repeated BlurRegionChange blur_regions = 1; } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 2d99fc1903..076c90dd23 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -64,6 +64,7 @@ layer_state_t::layer_state_t() fixedTransformHint(ui::Transform::ROT_INVALID), frameNumber(0), autoRefresh(false), + isTrustedOverlay(false), bufferCrop(Rect::INVALID_RECT), destinationFrame(Rect::INVALID_RECT), releaseBufferListener(nullptr) { @@ -170,6 +171,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.write, stretchEffect); SAFE_PARCEL(output.write, bufferCrop); SAFE_PARCEL(output.write, destinationFrame); + SAFE_PARCEL(output.writeBool, isTrustedOverlay); return NO_ERROR; } @@ -300,6 +302,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, stretchEffect); SAFE_PARCEL(input.read, bufferCrop); SAFE_PARCEL(input.read, destinationFrame); + SAFE_PARCEL(input.readBool, &isTrustedOverlay); return NO_ERROR; } @@ -532,6 +535,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eAutoRefreshChanged; autoRefresh = other.autoRefresh; } + if (other.what & eTrustedOverlayChanged) { + what |= eTrustedOverlayChanged; + isTrustedOverlay = other.isTrustedOverlay; + } if (other.what & eReleaseBufferListenerChanged) { if (releaseBufferListener) { ALOGW("Overriding releaseBufferListener"); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6ea070ea2f..96da8efd19 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1656,6 +1656,19 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAutoR return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrustedOverlay( + const sp& sc, bool isTrustedOverlay) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eTrustedOverlayChanged; + s->isTrustedOverlay = isTrustedOverlay; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApplyToken( const sp& applyToken) { mApplyToken = applyToken; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 465e34ca33..3e57ff611e 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -118,6 +118,7 @@ struct layer_state_t { eBlurRegionsChanged = 0x800'00000000, eAutoRefreshChanged = 0x1000'00000000, eStretchChanged = 0x2000'00000000, + eTrustedOverlayChanged = 0x4000'00000000, }; layer_state_t(); @@ -225,6 +226,10 @@ struct layer_state_t { // in shared buffer mode. bool autoRefresh; + // An inherited state that indicates that this surface control and its children + // should be trusted for input occlusion detection purposes + bool isTrustedOverlay; + // Stretch effect to be applied to this layer StretchEffect stretchEffect; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index c2963b58df..baa0567617 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -537,6 +537,9 @@ public: // in shared buffer mode. Transaction& setAutoRefresh(const sp& sc, bool autoRefresh); + // Sets that this surface control and its children are trusted overlays for input + Transaction& setTrustedOverlay(const sp& sc, bool isTrustedOverlay); + // 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/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e2b6a36794..dbd2793276 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -851,6 +851,23 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t relati return true; } +bool Layer::setTrustedOverlay(bool isTrustedOverlay) { + if (mDrawingState.isTrustedOverlay == isTrustedOverlay) return false; + mDrawingState.isTrustedOverlay = isTrustedOverlay; + mDrawingState.modified = true; + mFlinger->mInputInfoChanged = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool Layer::isTrustedOverlay() const { + if (getDrawingState().isTrustedOverlay) { + return true; + } + const auto& p = mDrawingParent.promote(); + return (p != nullptr) && p->isTrustedOverlay(); +} + bool Layer::setSize(uint32_t w, uint32_t h) { if (mDrawingState.requested_legacy.w == w && mDrawingState.requested_legacy.h == h) return false; @@ -2041,6 +2058,7 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, layerInfo->set_corner_radius(getRoundedCornerState().radius); layerInfo->set_background_blur_radius(getBackgroundBlurRadius()); + layerInfo->set_is_trusted_overlay(isTrustedOverlay()); LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform()); LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(), [&]() { return layerInfo->mutable_position(); }); @@ -2327,6 +2345,11 @@ InputWindowInfo Layer::fillInputInfo(const sp& display) { toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds})); } + // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state + // if it was set by WM for a known system overlay + info.trustedOverlay = info.trustedOverlay || isTrustedOverlay(); + + // If the layer is a clone, we need to crop the input region to cloned root to prevent // touches from going outside the cloned area. if (isClone()) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6b56b2d924..c5cb17ffc7 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -275,6 +275,9 @@ public: // Stretch effect to apply to this layer StretchEffect stretchEffect; + // Whether or not this layer is a trusted overlay for input + bool isTrustedOverlay; + Rect bufferCrop; Rect destinationFrame; }; @@ -393,6 +396,7 @@ public: virtual bool setBackgroundBlurRadius(int backgroundBlurRadius); virtual bool setBlurRegions(const std::vector& effectRegions); virtual bool setTransparentRegionHint(const Region& transparent); + virtual bool setTrustedOverlay(bool); virtual bool setFlags(uint32_t flags, uint32_t mask); virtual bool setLayerStack(uint32_t layerStack); virtual uint32_t getLayerStack() const; @@ -1050,6 +1054,7 @@ private: void updateTreeHasFrameRateVote(); void setZOrderRelativeOf(const wp& relativeOf); + bool isTrustedOverlay() 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 2cc810986f..f44ae71896 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4156,6 +4156,15 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eAutoRefreshChanged) { layer->setAutoRefresh(s.autoRefresh); } + if (what & layer_state_t::eTrustedOverlayChanged) { + if (privileged) { + if (layer->setTrustedOverlay(s.isTrustedOverlay)) { + flags |= eTraversalNeeded; + } + } else { + ALOGE("Attempt to set trusted overlay without permission ACCESS_SURFACE_FLINGER"); + } + } if (what & layer_state_t::eStretchChanged) { if (layer->setStretchEffect(s.stretchEffect)) { flags |= eTraversalNeeded; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 8ca241e53d..23ab7c8bab 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -149,6 +149,7 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, getLayerIdFromWeakRef(layer->mDrawingState.zOrderRelativeOf), layer->mDrawingState.z); addShadowRadiusLocked(transaction, layerId, layer->mDrawingState.shadowRadius); + addTrustedOverlayLocked(transaction, layerId, layer->mDrawingState.isTrustedOverlay); } void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment, @@ -397,6 +398,13 @@ void SurfaceInterceptor::addShadowRadiusLocked(Transaction* transaction, int32_t overrideChange->set_radius(shadowRadius); } +void SurfaceInterceptor::addTrustedOverlayLocked(Transaction* transaction, int32_t layerId, + bool isTrustedOverlay) { + SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); + TrustedOverlayChange* overrideChange(change->mutable_trusted_overlay()); + overrideChange->set_is_trusted_overlay(isTrustedOverlay); +} + void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state) { @@ -460,6 +468,9 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eShadowRadiusChanged) { addShadowRadiusLocked(transaction, layerId, state.shadowRadius); } + if (state.what & layer_state_t::eTrustedOverlayChanged) { + addTrustedOverlayLocked(transaction, layerId, state.isTrustedOverlay); + } if (state.what & layer_state_t::eStretchChanged) { ALOGW("SurfaceInterceptor not implemented for eStretchChanged"); } diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 30aca8340e..673f9e789d 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -177,6 +177,7 @@ private: void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId, int z); void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius); + void addTrustedOverlayLocked(Transaction* transaction, int32_t layerId, bool isTrustedOverlay); // Add display transactions to the trace DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t sequenceId); diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index aef670da33..2841f7c2fd 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -105,6 +105,7 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerP layer.queuedFrames = layerProto.queued_frames(); layer.refreshPending = layerProto.refresh_pending(); layer.isProtected = layerProto.is_protected(); + layer.isTrustedOverlay = layerProto.is_trusted_overlay(); layer.cornerRadius = layerProto.corner_radius(); layer.backgroundBlurRadius = layerProto.background_blur_radius(); for (const auto& entry : layerProto.metadata()) { @@ -289,6 +290,7 @@ std::string LayerProtoParser::Layer::to_string() const { StringAppendF(&result, "crop=%s, ", crop.to_string().c_str()); StringAppendF(&result, "cornerRadius=%f, ", cornerRadius); StringAppendF(&result, "isProtected=%1d, ", isProtected); + StringAppendF(&result, "isTrustedOverlay=%1d, ", isTrustedOverlay); StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate); StringAppendF(&result, "dataspace=%s, ", dataspace.c_str()); StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str()); diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index c48354fe95..52503bad3a 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -109,6 +109,7 @@ public: int32_t queuedFrames; bool refreshPending; bool isProtected; + bool isTrustedOverlay; float cornerRadius; int backgroundBlurRadius; LayerMetadata metadata; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 9f25674f1b..dddc677715 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -128,6 +128,8 @@ message LayerProto { // Regions of a layer, where blur should be applied. repeated BlurRegion blur_regions = 54; + + bool is_trusted_overlay = 55; } message PositionProto { diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index ee4e863474..d5890ffa79 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -193,6 +193,7 @@ public: bool reparentUpdateFound(const SurfaceChange& change, bool found); bool relativeParentUpdateFound(const SurfaceChange& change, bool found); bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found); + bool trustedOverlayUpdateFound(const SurfaceChange& change, bool found); bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase); // Find all of the updates in the single trace @@ -228,6 +229,7 @@ public: void reparentUpdate(Transaction&); void relativeParentUpdate(Transaction&); void shadowRadiusUpdate(Transaction&); + void trustedOverlayUpdate(Transaction&); void surfaceCreation(Transaction&); void displayCreation(Transaction&); void displayDeletion(Transaction&); @@ -405,6 +407,10 @@ void SurfaceInterceptorTest::shadowRadiusUpdate(Transaction& t) { t.setShadowRadius(mBGSurfaceControl, SHADOW_RADIUS_UPDATE); } +void SurfaceInterceptorTest::trustedOverlayUpdate(Transaction& t) { + t.setTrustedOverlay(mBGSurfaceControl, true); +} + void SurfaceInterceptorTest::displayCreation(Transaction&) { sp testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false); SurfaceComposerClient::destroyDisplay(testDisplay); @@ -433,6 +439,7 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::reparentUpdate); runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate); runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate); + runInTransaction(&SurfaceInterceptorTest::trustedOverlayUpdate); } void SurfaceInterceptorTest::surfaceCreation(Transaction&) { @@ -644,6 +651,17 @@ bool SurfaceInterceptorTest::shadowRadiusUpdateFound(const SurfaceChange& change return foundShadowRadius; } +bool SurfaceInterceptorTest::trustedOverlayUpdateFound(const SurfaceChange& change, + bool foundTrustedOverlay) { + bool hasTrustedOverlay(change.trusted_overlay().is_trusted_overlay()); + if (hasTrustedOverlay && !foundTrustedOverlay) { + foundTrustedOverlay = true; + } else if (hasTrustedOverlay && foundTrustedOverlay) { + []() { FAIL(); }(); + } + return foundTrustedOverlay; +} + bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase) { bool foundUpdate = false; @@ -704,6 +722,9 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kShadowRadius: foundUpdate = shadowRadiusUpdateFound(change, foundUpdate); break; + case SurfaceChange::SurfaceChangeCase::kTrustedOverlay: + foundUpdate = trustedOverlayUpdateFound(change, foundUpdate); + break; case SurfaceChange::SurfaceChangeCase::SURFACECHANGE_NOT_SET: break; } @@ -897,6 +918,11 @@ TEST_F(SurfaceInterceptorTest, InterceptShadowRadiusUpdateWorks) { SurfaceChange::SurfaceChangeCase::kShadowRadius); } +TEST_F(SurfaceInterceptorTest, InterceptTrustedOverlayUpdateWorks) { + captureTest(&SurfaceInterceptorTest::trustedOverlayUpdate, + SurfaceChange::SurfaceChangeCase::kTrustedOverlay); +} + TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) { captureTest(&SurfaceInterceptorTest::runAllUpdates, &SurfaceInterceptorTest::assertAllUpdatesFound);