Merge changes from topic "capture-child-layers" into pi-dev
am: 17511b0527
Change-Id: Ib2ae98549c92f13db5c010533ec6e243d72a230c
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 5de84ec..beda778 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -132,12 +132,13 @@
virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
- float frameScale) {
+ float frameScale, bool childrenOnly) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(layerHandleBinder);
data.write(sourceCrop);
data.writeFloat(frameScale);
+ data.writeBool(childrenOnly);
status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
if (err != NO_ERROR) {
@@ -629,8 +630,10 @@
Rect sourceCrop(Rect::EMPTY_RECT);
data.read(sourceCrop);
float frameScale = data.readFloat();
+ bool childrenOnly = data.readBool();
- status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale);
+ status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale,
+ childrenOnly);
reply->writeInt32(res);
if (res == NO_ERROR) {
reply->write(*outBuffer);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 92a24ad..0d7ffc3 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -751,7 +751,17 @@
float frameScale, sp<GraphicBuffer>* outBuffer) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == NULL) return NO_INIT;
- status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale);
+ status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale,
+ false /* childrenOnly */);
+ return ret;
+}
+
+status_t ScreenshotClient::captureChildLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
+ float frameScale, sp<GraphicBuffer>* outBuffer) {
+ sp<ISurfaceComposer> s(ComposerService::getComposerService());
+ if (s == NULL) return NO_INIT;
+ status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale,
+ true /* childrenOnly */);
return ret;
}
// ----------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e26e332..5ab6445 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -173,9 +173,12 @@
int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
Rotation rotation = eRotateNone) = 0;
+ /**
+ * Capture a subtree of the layer hierarchy, potentially ignoring the root node.
+ */
virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
- float frameScale = 1.0) = 0;
+ float frameScale = 1.0, bool childrenOnly = false) = 0;
/* Clears the frame statistics for animations.
*
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 3fe6635..fe46146 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -297,8 +297,10 @@
uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
bool useIdentityTransform, uint32_t rotation,
sp<GraphicBuffer>* outBuffer);
- static status_t captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop, float fameScale,
+ static status_t captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop, float frameScale,
sp<GraphicBuffer>* outBuffer);
+ static status_t captureChildLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
+ float frameScale, sp<GraphicBuffer>* outBuffer);
};
// ---------------------------------------------------------------------------
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 8060b6e..4fb51e1 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -593,8 +593,8 @@
bool /*useIdentityTransform*/,
Rotation /*rotation*/) override { return NO_ERROR; }
virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/,
- sp<GraphicBuffer>* /*outBuffer*/,
- const Rect& /*sourceCrop*/, float /*frameScale*/) override {
+ sp<GraphicBuffer>* /*outBuffer*/, const Rect& /*sourceCrop*/,
+ float /*frameScale*/, bool /*childrenOnly*/) override {
return NO_ERROR;
}
status_t clearAnimationFrameStats() override { return NO_ERROR; }
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 0c0fedc..ba28eb5 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -87,6 +87,7 @@
"BufferLayerConsumer.cpp",
"Client.cpp",
"ColorLayer.cpp",
+ "ContainerLayer.cpp",
"DisplayDevice.cpp",
"DisplayHardware/ComposerHal.cpp",
"DisplayHardware/FramebufferSurface.cpp",
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 4022b31..0cde398 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -13,16 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#pragma once
-#ifndef ANDROID_COLOR_LAYER_H
-#define ANDROID_COLOR_LAYER_H
-
-#include <stdint.h>
#include <sys/types.h>
-#include "Layer.h"
+#include <cstdint>
-// ---------------------------------------------------------------------------
+#include "Layer.h"
namespace android {
@@ -36,36 +33,8 @@
virtual void onDraw(const RenderArea& renderArea, const Region& clip,
bool useIdentityTransform) const;
bool isVisible() const override;
- virtual bool isOpaque(const Layer::State&) const { return false; }
- virtual bool isFixedSize() const { return true; }
- void notifyAvailableFrames() override {}
- PixelFormat getPixelFormat() const override { return PIXEL_FORMAT_NONE; }
- uint32_t getEffectiveScalingMode() const override { return 0; }
- void releasePendingBuffer(nsecs_t) override {}
- Region latchBuffer(bool&, nsecs_t) override { return Region(); }
- void useSurfaceDamage() override {}
- void useEmptyDamage() override {}
- bool isBufferLatched() const override { return false; }
- bool onPreComposition(nsecs_t) override { return true; }
- void abandon() override {}
void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
- void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) override {}
- bool shouldPresentNow(const DispSync& /*dispSync*/) const override { return false; }
- bool onPostComposition(const std::shared_ptr<FenceTime>& /*glDoneFence*/,
- const std::shared_ptr<FenceTime>& /*presentFence*/,
- const CompositorTiming& /*compositorTiming*/) override {
- return false;
- }
- void setTransformHint(uint32_t /*orientation*/) const override {}
- std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool /*forceFlush*/) override {
- return {};
- }
- bool getTransformToDisplayInverse() const override { return false; }
};
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_COLOR_LAYER_H
+} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
new file mode 100644
index 0000000..f259d93
--- /dev/null
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+// #define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "ContainerLayer"
+
+#include "ContainerLayer.h"
+
+namespace android {
+
+ContainerLayer::ContainerLayer(SurfaceFlinger* flinger, const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags)
+ : Layer(flinger, client, name, w, h, flags) {
+ mDrawingState = mCurrentState;
+}
+
+void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {}
+
+bool ContainerLayer::isVisible() const {
+ return !isHiddenByPolicy();
+}
+
+void ContainerLayer::setPerFrameData(const sp<const DisplayDevice>&) {}
+
+} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
new file mode 100644
index 0000000..543f60a
--- /dev/null
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+#pragma once
+
+#include <sys/types.h>
+
+#include <cstdint>
+
+#include "Layer.h"
+
+namespace android {
+
+class ContainerLayer : public Layer {
+public:
+ ContainerLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags);
+ virtual ~ContainerLayer() = default;
+
+ const char* getTypeId() const override { return "ContainerLayer"; }
+ void onDraw(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform) const override;
+ bool isVisible() const override;
+
+ void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 78dd40b..44e60ed 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1594,6 +1594,12 @@
return true;
}
+void Layer::reparentChildrenForDrawing(const sp<Layer>& newParent) {
+ for (const sp<Layer>& child : mDrawingChildren) {
+ child->mDrawingParent = newParent;
+ }
+}
+
bool Layer::reparent(const sp<IBinder>& newParentHandle) {
if (newParentHandle == nullptr) {
return false;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3671a2b..996d686 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -17,7 +17,6 @@
#ifndef ANDROID_LAYER_H
#define ANDROID_LAYER_H
-#include <stdint.h>
#include <sys/types.h>
#include <utils/RefBase.h>
@@ -35,6 +34,7 @@
#include <gui/BufferQueue.h>
#include <list>
+#include <cstdint>
#include "Client.h"
#include "FrameTracker.h"
@@ -287,14 +287,15 @@
bool setOverrideScalingMode(int32_t overrideScalingMode);
void setInfo(uint32_t type, uint32_t appId);
bool reparentChildren(const sp<IBinder>& layer);
+ void reparentChildrenForDrawing(const sp<Layer>& layer);
bool reparent(const sp<IBinder>& newParentHandle);
bool detachChildren();
// If we have received a new buffer this frame, we will pass its surface
// damage down to hardware composer. Otherwise, we must send a region with
// one empty rect.
- virtual void useSurfaceDamage() = 0;
- virtual void useEmptyDamage() = 0;
+ virtual void useSurfaceDamage() {}
+ virtual void useEmptyDamage() {}
uint32_t getTransactionFlags(uint32_t flags);
uint32_t setTransactionFlags(uint32_t flags);
@@ -320,7 +321,7 @@
* pixel format includes an alpha channel) and the "opaque" flag set
* on the layer. It does not examine the current plane alpha value.
*/
- virtual bool isOpaque(const Layer::State& s) const = 0;
+ virtual bool isOpaque(const Layer::State&) const { return false; }
/*
* isSecure - true if this surface is secure, that is if it prevents
@@ -344,7 +345,8 @@
/*
* isFixedSize - true if content has a fixed size
*/
- virtual bool isFixedSize() const = 0;
+ virtual bool isFixedSize() const { return true; }
+
bool isPendingRemoval() const { return mPendingRemoval; }
@@ -359,7 +361,7 @@
bool useIdentityTransform) const = 0;
public:
- virtual void setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
+ virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z);
void forceClientComposition(int32_t hwcId);
@@ -379,27 +381,30 @@
*/
virtual void onLayerDisplayed(const sp<Fence>& releaseFence);
- virtual void abandon() = 0;
+ virtual void abandon() {}
- virtual bool shouldPresentNow(const DispSync& dispSync) const = 0;
- virtual void setTransformHint(uint32_t orientation) const = 0;
+ virtual bool shouldPresentNow(const DispSync& /*dispSync*/) const { return false; }
+ virtual void setTransformHint(uint32_t /*orientation*/) const { }
/*
* called before composition.
* returns true if the layer has pending updates.
*/
- virtual bool onPreComposition(nsecs_t refreshStartTime) = 0;
+ virtual bool onPreComposition(nsecs_t /*refreshStartTime*/) { return true; }
/*
* called after composition.
* returns true if the layer latched a new buffer this frame.
*/
- virtual bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
- const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming) = 0;
+ virtual bool onPostComposition(const std::shared_ptr<FenceTime>& /*glDoneFence*/,
+ const std::shared_ptr<FenceTime>& /*presentFence*/,
+ const CompositorTiming& /*compositorTiming*/) {
+ return false;
+ }
// If a buffer was replaced this frame, release the former buffer
- virtual void releasePendingBuffer(nsecs_t dequeueReadyTime) = 0;
+ virtual void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { }
+
/*
* draw - performs some global clipping optimizations
@@ -445,8 +450,11 @@
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
- virtual Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
- virtual bool isBufferLatched() const = 0;
+ virtual Region latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) {
+ return {};
+ }
+
+ virtual bool isBufferLatched() const { return false; }
bool isPotentialCursor() const { return mPotentialCursor; }
/*
@@ -519,13 +527,15 @@
void logFrameStats();
void getFrameStats(FrameStats* outStats) const;
- virtual std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) = 0;
+ virtual std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool /*forceFlush*/) {
+ return {};
+ }
void onDisconnect();
void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry,
FrameEventHistoryDelta* outDelta);
- virtual bool getTransformToDisplayInverse() const = 0;
+ virtual bool getTransformToDisplayInverse() const { return false; }
Transform getTransform() const;
@@ -649,7 +659,7 @@
// Returns mCurrentScaling mode (originating from the
// Client) or mOverrideScalingMode mode (originating from
// the Surface Controller) if set.
- virtual uint32_t getEffectiveScalingMode() const = 0;
+ virtual uint32_t getEffectiveScalingMode() const { return 0; }
public:
/*
@@ -670,8 +680,8 @@
sp<IBinder> getHandle();
const String8& getName() const;
- virtual void notifyAvailableFrames() = 0;
- virtual PixelFormat getPixelFormat() const = 0;
+ virtual void notifyAvailableFrames() {}
+ virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; }
bool getPremultipledAlpha() const;
protected:
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index fa4df83..940a34c 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -2,6 +2,8 @@
#include "Transform.h"
+#include <functional>
+
namespace android {
class RenderArea {
@@ -22,6 +24,8 @@
virtual bool needsFiltering() const = 0;
virtual Rect getSourceCrop() const = 0;
+ virtual void render(std::function<void()> drawLayers) { drawLayers(); }
+
int getReqHeight() const { return mReqHeight; };
int getReqWidth() const { return mReqWidth; };
Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cb410a1..38b93b1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -61,20 +61,21 @@
#include <private/android_filesystem_config.h>
#include <private/gui/SyncFeatures.h>
+#include "BufferLayer.h"
#include "Client.h"
-#include "clz.h"
+#include "ColorLayer.h"
#include "Colorizer.h"
+#include "ContainerLayer.h"
#include "DdmConnection.h"
-#include "DisplayDevice.h"
#include "DispSync.h"
+#include "DisplayDevice.h"
#include "EventControlThread.h"
#include "EventThread.h"
#include "Layer.h"
-#include "BufferLayer.h"
#include "LayerVector.h"
-#include "ColorLayer.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
+#include "clz.h"
#include "DisplayHardware/ComposerHal.h"
#include "DisplayHardware/FramebufferSurface.h"
@@ -4418,19 +4419,18 @@
status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
- float frameScale) {
+ float frameScale, bool childrenOnly) {
ATRACE_CALL();
class LayerRenderArea : public RenderArea {
public:
- LayerRenderArea(const sp<Layer>& layer, const Rect crop, int32_t reqWidth,
- int32_t reqHeight)
- : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {}
- const Transform& getTransform() const override {
- // Make the top level transform the inverse the transform and it's parent so it sets
- // the whole capture back to 0,0
- return *new Transform(mLayer->getTransform().inverse());
- }
+ LayerRenderArea(SurfaceFlinger* flinger, const sp<Layer>& layer, const Rect crop,
+ int32_t reqWidth, int32_t reqHeight, bool childrenOnly)
+ : RenderArea(reqHeight, reqWidth),
+ mLayer(layer),
+ mCrop(crop),
+ mFlinger(flinger),
+ mChildrenOnly(childrenOnly) {}
Rect getBounds() const override {
const Layer::State& layerState(mLayer->getDrawingState());
return Rect(layerState.active.w, layerState.active.h);
@@ -4439,6 +4439,34 @@
int getWidth() const override { return mLayer->getDrawingState().active.w; }
bool isSecure() const override { return false; }
bool needsFiltering() const override { return false; }
+ const Transform& getTransform() const { return mTransform; }
+
+ class ReparentForDrawing {
+ public:
+ const sp<Layer>& oldParent;
+ const sp<Layer>& newParent;
+
+ ReparentForDrawing(const sp<Layer>& oldParent, const sp<Layer>& newParent)
+ : oldParent(oldParent), newParent(newParent) {
+ oldParent->reparentChildrenForDrawing(newParent);
+ }
+ ~ReparentForDrawing() { newParent->reparentChildrenForDrawing(oldParent); }
+ };
+
+ void render(std::function<void()> drawLayers) override {
+ if (!mChildrenOnly) {
+ mTransform = mLayer->getTransform().inverse();
+ drawLayers();
+ } else {
+ Rect bounds = getBounds();
+ screenshotParentLayer =
+ new ContainerLayer(mFlinger, nullptr, String8("Screenshot Parent"),
+ bounds.getWidth(), bounds.getHeight(), 0);
+
+ ReparentForDrawing reparent(mLayer, screenshotParentLayer);
+ drawLayers();
+ }
+ }
Rect getSourceCrop() const override {
if (mCrop.isEmpty()) {
@@ -4453,6 +4481,14 @@
private:
const sp<Layer> mLayer;
const Rect mCrop;
+
+ // In the "childrenOnly" case we reparent the children to a screenshot
+ // layer which has no properties set and which does not draw.
+ sp<ContainerLayer> screenshotParentLayer;
+ Transform mTransform;
+
+ SurfaceFlinger* mFlinger;
+ const bool mChildrenOnly;
};
auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
@@ -4463,6 +4499,13 @@
return NAME_NOT_FOUND;
}
+ 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;
+ }
+
Rect crop(sourceCrop);
if (sourceCrop.width() <= 0) {
crop.left = 0;
@@ -4477,12 +4520,14 @@
int32_t reqWidth = crop.width() * frameScale;
int32_t reqHeight = crop.height() * frameScale;
- LayerRenderArea renderArea(parent, crop, reqWidth, reqHeight);
+ LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, childrenOnly);
- auto traverseLayers = [parent](const LayerVector::Visitor& visitor) {
+ auto traverseLayers = [parent, childrenOnly](const LayerVector::Visitor& visitor) {
parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
if (!layer->isVisible()) {
return;
+ } else if (childrenOnly && layer == parent.get()) {
+ return;
}
visitor(layer);
});
@@ -4529,8 +4574,10 @@
int fd = -1;
{
Mutex::Autolock _l(mStateLock);
- result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(),
- useIdentityTransform, forSystem, &fd);
+ renderArea.render([&]() {
+ result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(),
+ useIdentityTransform, forSystem, &fd);
+ });
}
{
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 392acaa..33786e8 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -387,7 +387,7 @@
int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
ISurfaceComposer::Rotation rotation);
virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
- const Rect& sourceCrop, float frameScale);
+ const Rect& sourceCrop, float frameScale, bool childrenOnly);
virtual status_t getDisplayStats(const sp<IBinder>& display,
DisplayStatInfo* stats);
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 92c26af..fd21991 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -192,6 +192,16 @@
*sc = std::make_unique<ScreenCapture>(outBuffer);
}
+ static void captureChildLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
+ Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) {
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ SurfaceComposerClient::Transaction().apply(true);
+
+ sp<GraphicBuffer> outBuffer;
+ ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale, true));
+ *sc = std::make_unique<ScreenCapture>(outBuffer);
+ }
+
void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
@@ -2306,6 +2316,74 @@
mCapture->expectChildColor(0, 0);
}
+TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child =
+ mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mFGSurfaceControl.get());
+ fillSurfaceRGBA8(child, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ // Captures mFGSurfaceControl's child
+ ScreenCapture::captureChildLayers(&mCapture, fgHandle);
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->expectChildColor(0, 0);
+}
+
+
+// In the following tests we verify successful skipping of a parent layer,
+// so we use the same verification logic and only change how we mutate
+// the parent layer to verify that various properties are ignored.
+class ScreenCaptureChildOnlyTest : public LayerUpdateTest {
+public:
+ void SetUp() override {
+ LayerUpdateTest::SetUp();
+
+ mChild =
+ mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mFGSurfaceControl.get());
+ fillSurfaceRGBA8(mChild, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(mChild).apply(true);
+ }
+
+ void verify() {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+ ScreenCapture::captureChildLayers(&mCapture, fgHandle);
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->expectChildColor(0, 0);
+ }
+
+ std::unique_ptr<ScreenCapture> mCapture;
+ sp<SurfaceControl> mChild;
+};
+
+TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) {
+
+ SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true);
+
+ // Even though the parent is hidden we should still capture the child.
+ verify();
+}
+
+TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) {
+
+ SurfaceComposerClient::Transaction().setCrop(mFGSurfaceControl, Rect(0, 0, 1, 1)).apply(true);
+
+ // Even though the parent is cropped out we should still capture the child.
+ verify();
+}
+
+TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) {
+
+ SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2);
+
+ // We should not inherit the parent scaling.
+ verify();
+}
+
TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
auto fgHandle = mFGSurfaceControl->getHandle();