diff options
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 125 |
1 files changed, 87 insertions, 38 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5469ae7ba9..2c559775d3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3201,20 +3201,34 @@ void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& displayDevice, engine.fillRegionWithColor(region, height, 0, 0, 0, 0); } -status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, - const sp<IBinder>& handle, - const sp<IGraphicBufferProducer>& gbc, - const sp<Layer>& lbc, - const sp<Layer>& parent) -{ +status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, + const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc, + const sp<IBinder>& parentHandle, + const sp<Layer>& parentLayer) { // add this layer to the current state list { Mutex::Autolock _l(mStateLock); + sp<Layer> parent; + + if (parentHandle != nullptr) { + parent = fromHandle(parentHandle); + if (parent == nullptr) { + return NAME_NOT_FOUND; + } + } else { + parent = parentLayer; + } + if (mNumLayers >= MAX_LAYERS) { ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers, MAX_LAYERS); return NO_MEMORY; } + + auto [itr, inserted] = mLayersByLocalBinderToken.emplace(handle->localBinder(), lbc); + if (!inserted) { + ALOGE("-----------ERROR REGISTERING HANDLE, layer pair: handle is already a key"); + } if (parent == nullptr) { mCurrentState.layersSortedByZ.add(lbc); } else { @@ -3248,6 +3262,24 @@ status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) return removeLayerLocked(mStateLock, layer, topLevelOnly); } +status_t SurfaceFlinger::removeLayerFromMap(Layer* layer) { + auto it = mLayersByLocalBinderToken.begin(); + while (it != mLayersByLocalBinderToken.end()) { + auto strongRef = it->second.promote(); + if (strongRef != nullptr && strongRef.get() == layer) { + it = mLayersByLocalBinderToken.erase(it); + break; + } else { + it++; + } + } + if (it == mLayersByLocalBinderToken.end()) { + ALOGE("Failed to remove layer from mapping - could not find matching layer"); + return BAD_VALUE; + } + return NO_ERROR; +} + status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly) { if (layer->isPendingRemoval()) { @@ -3684,13 +3716,12 @@ void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { } } -status_t SurfaceFlinger::createLayer( - const String8& name, - const sp<Client>& client, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - int32_t windowType, int32_t ownerUid, sp<IBinder>* handle, - sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent) -{ +status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w, + uint32_t h, PixelFormat format, uint32_t flags, + int32_t windowType, int32_t ownerUid, sp<IBinder>* handle, + sp<IGraphicBufferProducer>* gbp, + const sp<IBinder>& parentHandle, + const sp<Layer>& parentLayer) { if (int32_t(w|h) < 0) { ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", int(w), int(h)); @@ -3733,7 +3764,7 @@ status_t SurfaceFlinger::createLayer( layer->setInfo(windowType, ownerUid); - result = addClientLayer(client, *handle, *gbp, layer, *parent); + result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer); if (result != NO_ERROR) { return result; } @@ -5017,34 +5048,40 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, const bool mChildrenOnly; }; - auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get()); - auto parent = layerHandle->owner.promote(); + int reqWidth = 0; + int reqHeight = 0; + sp<Layer> parent; + Rect crop(sourceCrop); - if (parent == nullptr || parent->isPendingRemoval()) { - ALOGE("captureLayers called with a removed parent"); - return NAME_NOT_FOUND; - } + { + Mutex::Autolock _l(mStateLock); - const int uid = IPCThreadState::self()->getCallingUid(); - const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM; - if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) { - ALOGW("Attempting to capture secure layer: PERMISSION_DENIED"); - return PERMISSION_DENIED; - } + parent = fromHandle(layerHandleBinder); + if (parent == nullptr || parent->isPendingRemoval()) { + ALOGE("captureLayers called with an invalid or removed parent"); + return NAME_NOT_FOUND; + } - Rect crop(sourceCrop); - if (sourceCrop.width() <= 0) { - crop.left = 0; - crop.right = parent->getCurrentState().active.w; - } + const int uid = IPCThreadState::self()->getCallingUid(); + const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM; + if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) { + ALOGW("Attempting to capture secure layer: PERMISSION_DENIED"); + return PERMISSION_DENIED; + } - if (sourceCrop.height() <= 0) { - crop.top = 0; - crop.bottom = parent->getCurrentState().active.h; - } + if (sourceCrop.width() <= 0) { + crop.left = 0; + crop.right = parent->getCurrentState().active.w; + } + + if (sourceCrop.height() <= 0) { + crop.top = 0; + crop.bottom = parent->getCurrentState().active.h; + } - int32_t reqWidth = crop.width() * frameScale; - int32_t reqHeight = crop.height() * frameScale; + reqWidth = crop.width() * frameScale; + reqHeight = crop.height() * frameScale; + } // mStateLock // really small crop or frameScale if (reqWidth <= 0) { @@ -5297,8 +5334,20 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& hw, } } -}; // namespace android +sp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) { + BBinder *b = handle->localBinder(); + if (b == nullptr) { + return nullptr; + } + auto it = mLayersByLocalBinderToken.find(b); + if (it != mLayersByLocalBinderToken.end()) { + auto ret = it->second.promote(); + return ret; + } + return nullptr; +} +} // namespace android #if defined(__gl_h_) #error "don't include gl/gl.h in this file" |
