Revert "Use GraphicBuffer instead of GBP for screenshots."
This reverts commit a252d895816b3aa6c3bc2b2083113694ead6963d.
Reason for revert: SystemUI and some other places need to be updated as well. Will resubmit with the other necessary changes
Change-Id: I2dfb7b439c866f31ffa584e450d3208c75afecaa
Bug: 69898957
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4acd448..d81178c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4339,10 +4339,44 @@
const int mApi;
};
-status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform,
+static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth,
+ uint32_t requestedHeight, bool hasWideColorDisplay,
+ bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) {
+ const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+
+ int err = 0;
+ err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight);
+ err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
+ err |= native_window_set_usage(window, usage);
+
+ if (hasWideColorDisplay) {
+ err |= native_window_set_buffers_data_space(window,
+ renderEngineUsesWideColor
+ ? HAL_DATASPACE_DISPLAY_P3
+ : HAL_DATASPACE_V0_SRGB);
+ }
+
+ if (err != NO_ERROR) {
+ return BAD_VALUE;
+ }
+
+ /* TODO: Once we have the sync framework everywhere this can use
+ * server-side waits on the fence that dequeueBuffer returns.
+ */
+ err = native_window_dequeue_buffer_and_wait(window, outBuffer);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ return NO_ERROR;
+}
+
+status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer, Rect sourceCrop,
+ uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ,
+ int32_t maxLayerZ, bool useIdentityTransform,
ISurfaceComposer::Rotation rotation) {
ATRACE_CALL();
@@ -4353,18 +4387,18 @@
auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
device, minLayerZ, maxLayerZ, std::placeholders::_1);
- return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform);
+ return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform);
}
status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
- sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
- float frameScale) {
+ const sp<IGraphicBufferProducer>& producer,
+ const Rect& sourceCrop, float frameScale) {
ATRACE_CALL();
class LayerRenderArea : public RenderArea {
public:
LayerRenderArea(const sp<Layer>& layer, const Rect crop, int32_t reqWidth,
- int32_t reqHeight)
+ 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
@@ -4427,21 +4461,51 @@
visitor(layer);
});
};
- return captureScreenCommon(renderArea, traverseLayers, outBuffer, false);
+ return captureScreenCommon(renderArea, traverseLayers, producer, false);
}
status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
- sp<GraphicBuffer>* outBuffer,
+ const sp<IGraphicBufferProducer>& producer,
bool useIdentityTransform) {
ATRACE_CALL();
+ if (CC_UNLIKELY(producer == 0))
+ return BAD_VALUE;
+
renderArea.updateDimensions();
- const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
- *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(),
- HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot");
+ // if we have secure windows on this display, never allow the screen capture
+ // unless the producer interface is local (i.e.: we can take a screenshot for
+ // ourselves).
+ bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder();
+
+ // create a surface (because we're a producer, and we need to
+ // dequeue/queue a buffer)
+ sp<Surface> surface = new Surface(producer, false);
+
+ // Put the screenshot Surface into async mode so that
+ // Layer::headFenceHasSignaled will always return true and we'll latch the
+ // first buffer regardless of whether or not its acquire fence has
+ // signaled. This is needed to avoid a race condition in the rotation
+ // animation. See b/30209608
+ surface->setAsyncMode(true);
+
+ ANativeWindow* window = surface.get();
+
+ status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL);
+
+ ANativeWindowBuffer* buffer = nullptr;
+ result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(),
+ hasWideColorDisplay && !mForceNativeColorMode,
+ getRenderEngine().usesWideColor(), &buffer);
+ if (result != NO_ERROR) {
+ return result;
+ }
// This mutex protects syncFd and captureResult for communication of the return values from the
// main thread back to this Binder thread
@@ -4466,8 +4530,8 @@
int fd = -1;
{
Mutex::Autolock _l(mStateLock);
- result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(),
- useIdentityTransform, &fd);
+ result = captureScreenImplLocked(renderArea, traverseLayers, buffer,
+ useIdentityTransform, isLocalScreenshot, &fd);
}
{
@@ -4478,7 +4542,7 @@
}
});
- status_t result = postMessageAsync(message);
+ result = postMessageAsync(message);
if (result == NO_ERROR) {
captureCondition.wait(captureLock, [&]() { return captureResult; });
while (*captureResult == EAGAIN) {
@@ -4493,10 +4557,9 @@
}
if (result == NO_ERROR) {
- sync_wait(syncFd, -1);
- close(syncFd);
+ // queueBuffer takes ownership of syncFd
+ result = window->queueBuffer(window, buffer, syncFd);
}
-
return result;
}
@@ -4539,8 +4602,7 @@
}
engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode);
- engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE
- : renderArea.getActiveColorMode());
+ engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode());
// make sure to clear all GL error flags
engine.checkErrors();
@@ -4583,7 +4645,7 @@
status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer,
- bool useIdentityTransform,
+ bool useIdentityTransform, bool isLocalScreenshot,
int* outSyncFd) {
ATRACE_CALL();
@@ -4593,7 +4655,7 @@
secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure());
});
- if (secureLayerIsVisible) {
+ if (!isLocalScreenshot && secureLayerIsVisible) {
ALOGW("FB is protected: PERMISSION_DENIED");
return PERMISSION_DENIED;
}
@@ -4742,4 +4804,4 @@
#if defined(__gl2_h_)
#error "don't include gl2/gl2.h in this file"
-#endif
\ No newline at end of file
+#endif