Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9be7d0c3 authored by jeimysantiago's avatar jeimysantiago Committed by Jeimy Santiago Morales
Browse files

Make screenCapture calls to SF async

The captureDisplay and captureLayers aidl calls have been made one-way and the functions void.
A new function called invokeScreenCaptureError has been created that takes the error and listener as input
and passes the captureResult to onScreenCaptureCompleted.

Bug: 287081404
Test: atest layerScreenshot
Change-Id: Iaa07a3525a2ff0ed8409cac27e9f8ac7b01183df
parent cbb25162
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -230,20 +230,20 @@ interface ISurfaceComposer {
     * The subregion can be optionally rotated.  It will also be scaled to
     * match the size of the output buffer.
     */
    void captureDisplay(in DisplayCaptureArgs args, IScreenCaptureListener listener);
    oneway void captureDisplay(in DisplayCaptureArgs args, IScreenCaptureListener listener);

    /**
     * Capture the specified screen. This requires the READ_FRAME_BUFFER
     * permission.
     */
    void captureDisplayById(long displayId, IScreenCaptureListener listener);
    oneway void captureDisplayById(long displayId, IScreenCaptureListener listener);

    /**
     * Capture a subtree of the layer hierarchy, potentially ignoring the root node.
     * This requires READ_FRAME_BUFFER permission. This function will fail if there
     * is a secure window on screen
     */
    void captureLayers(in LayerCaptureArgs args, IScreenCaptureListener listener);
    oneway void captureLayers(in LayerCaptureArgs args, IScreenCaptureListener listener);

    /**
     * Clears the frame statistics for animations.
+69 −47
Original line number Diff line number Diff line
@@ -7311,16 +7311,27 @@ ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace, const DisplayD

} // namespace

status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
static void invokeScreenCaptureError(const status_t status,
                                     const sp<IScreenCaptureListener>& captureListener) {
    ScreenCaptureResults captureResults;
    captureResults.fenceResult = base::unexpected(status);
    captureListener->onScreenCaptureCompleted(captureResults);
}

void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
                                    const sp<IScreenCaptureListener>& captureListener) {
    ATRACE_CALL();

    status_t validate = validateScreenshotPermissions(args);
    if (validate != OK) {
        return validate;
        invokeScreenCaptureError(validate, captureListener);
        return;
    }

    if (!args.displayToken) return BAD_VALUE;
    if (!args.displayToken) {
        invokeScreenCaptureError(BAD_VALUE, captureListener);
        return;
    }

    wp<const DisplayDevice> displayWeak;
    ui::LayerStack layerStack;
@@ -7329,7 +7340,10 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
    {
        Mutex::Autolock lock(mStateLock);
        sp<DisplayDevice> display = getDisplayDeviceLocked(args.displayToken);
        if (!display) return NAME_NOT_FOUND;
        if (!display) {
            invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
            return;
        }
        displayWeak = display;
        layerStack = display->getLayerStack();

@@ -7344,7 +7358,8 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
                excludeLayerIds.emplace(excludeLayer);
            } else {
                ALOGW("Invalid layer handle passed as excludeLayer to captureDisplay");
                return NAME_NOT_FOUND;
                invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
                return;
            }
        }
    }
@@ -7367,13 +7382,11 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
        getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
    }

    auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize,
                                      args.pixelFormat, args.allowProtected, args.grayscale,
                                      captureListener);
    return fenceStatus(future.get());
    captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat,
                        args.allowProtected, args.grayscale, captureListener);
}

status_t SurfaceFlinger::captureDisplay(DisplayId displayId,
void SurfaceFlinger::captureDisplay(DisplayId displayId,
                                    const sp<IScreenCaptureListener>& captureListener) {
    ui::LayerStack layerStack;
    wp<const DisplayDevice> displayWeak;
@@ -7383,7 +7396,8 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId,

        const auto display = getDisplayDeviceLocked(displayId);
        if (!display) {
            return NAME_NOT_FOUND;
            invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
            return;
        }

        displayWeak = display;
@@ -7411,25 +7425,25 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId,

    if (captureListener == nullptr) {
        ALOGE("capture screen must provide a capture listener callback");
        return BAD_VALUE;
        invokeScreenCaptureError(BAD_VALUE, captureListener);
        return;
    }

    constexpr bool kAllowProtected = false;
    constexpr bool kGrayscale = false;

    auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size,
                                      ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale,
                                      captureListener);
    return fenceStatus(future.get());
    captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size,
                        ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale, captureListener);
}

status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
                                   const sp<IScreenCaptureListener>& captureListener) {
    ATRACE_CALL();

    status_t validate = validateScreenshotPermissions(args);
    if (validate != OK) {
        return validate;
        invokeScreenCaptureError(validate, captureListener);
        return;
    }

    ui::Size reqSize;
@@ -7447,13 +7461,15 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
        parent = LayerHandle::getLayer(args.layerHandle);
        if (parent == nullptr) {
            ALOGE("captureLayers called with an invalid or removed parent");
            return NAME_NOT_FOUND;
            invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
            return;
        }

        if (!canCaptureBlackoutContent &&
            parent->getDrawingState().flags & layer_state_t::eLayerSecure) {
            ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
            return PERMISSION_DENIED;
            invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
            return;
        }

        Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState());
@@ -7470,7 +7486,8 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
        if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) {
            // Error out if the layer has no source bounds (i.e. they are boundless) and a source
            // crop was not specified, or an invalid frame scale was provided.
            return BAD_VALUE;
            invokeScreenCaptureError(BAD_VALUE, captureListener);
            return;
        }
        reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY);

@@ -7480,7 +7497,8 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
                excludeLayerIds.emplace(excludeLayer);
            } else {
                ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
                return NAME_NOT_FOUND;
                invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
                return;
            }
        }
    } // mStateLock
@@ -7488,7 +7506,8 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
    // really small crop or frameScale
    if (reqSize.width <= 0 || reqSize.height <= 0) {
        ALOGW("Failed to captureLayes: crop or scale too small");
        return BAD_VALUE;
        invokeScreenCaptureError(BAD_VALUE, captureListener);
        return;
    }

    bool childrenOnly = args.childrenOnly;
@@ -7552,18 +7571,18 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,

    if (captureListener == nullptr) {
        ALOGE("capture screen must provide a capture listener callback");
        return BAD_VALUE;
        invokeScreenCaptureError(BAD_VALUE, captureListener);
        return;
    }

    auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize,
                                      args.pixelFormat, args.allowProtected, args.grayscale,
                                      captureListener);
    return fenceStatus(future.get());
    captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat,
                        args.allowProtected, args.grayscale, captureListener);
}

ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
        RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots,
        ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale,
void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
                                         GetLayerSnapshotsFunction getLayerSnapshots,
                                         ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
                                         bool allowProtected, bool grayscale,
                                         const sp<IScreenCaptureListener>& captureListener) {
    ATRACE_CALL();

@@ -7571,7 +7590,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
        ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32
              ") that exceeds render target size limit.",
              bufferSize.getWidth(), bufferSize.getHeight());
        return ftl::yield<FenceResult>(base::unexpected(BAD_VALUE)).share();
        invokeScreenCaptureError(BAD_VALUE, captureListener);
        return;
    }

    // Loop over all visible layers to see whether there's any protected layer. A protected layer is
@@ -7611,14 +7631,16 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
        // Otherwise an irreponsible process may cause an SF crash by allocating
        // too much.
        ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
        return ftl::yield<FenceResult>(base::unexpected(bufferStatus)).share();
        invokeScreenCaptureError(bufferStatus, captureListener);
        return;
    }
    const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
            renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
                                                 renderengine::impl::ExternalTexture::Usage::
                                                         WRITEABLE);
    return captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture,
    auto fence = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture,
                                     false /* regionSampling */, grayscale, captureListener);
    fence.get();
}

ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
@@ -9055,28 +9077,28 @@ binder::Status SurfaceComposerAIDL::setGameContentType(const sp<IBinder>& displa

binder::Status SurfaceComposerAIDL::captureDisplay(
        const DisplayCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) {
    status_t status = mFlinger->captureDisplay(args, captureListener);
    return binderStatusFromStatusT(status);
    mFlinger->captureDisplay(args, captureListener);
    return binderStatusFromStatusT(NO_ERROR);
}

binder::Status SurfaceComposerAIDL::captureDisplayById(
        int64_t displayId, const sp<IScreenCaptureListener>& captureListener) {
    status_t status;
    // status_t status;
    IPCThreadState* ipc = IPCThreadState::self();
    const int uid = ipc->getCallingUid();
    if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) {
        std::optional<DisplayId> id = DisplayId::fromValue(static_cast<uint64_t>(displayId));
        status = mFlinger->captureDisplay(*id, captureListener);
        mFlinger->captureDisplay(*id, captureListener);
    } else {
        status = PERMISSION_DENIED;
        invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
    }
    return binderStatusFromStatusT(status);
    return binderStatusFromStatusT(NO_ERROR);
}

binder::Status SurfaceComposerAIDL::captureLayers(
        const LayerCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) {
    status_t status = mFlinger->captureLayers(args, captureListener);
    return binderStatusFromStatusT(status);
    mFlinger->captureLayers(args, captureListener);
    return binderStatusFromStatusT(NO_ERROR);
}

binder::Status SurfaceComposerAIDL::overrideHdrTypes(const sp<IBinder>& display,
+6 −7
Original line number Diff line number Diff line
@@ -535,9 +535,9 @@ private:
            EventRegistrationFlags eventRegistration = {},
            const sp<IBinder>& layerHandle = nullptr);

    status_t captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
    status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
    status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&);
    void captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
    void captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
    void captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&);

    status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
    status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*)
@@ -836,9 +836,8 @@ private:
    // Boot animation, on/off animations and screen capture
    void startBootAnim();

    ftl::SharedFuture<FenceResult> captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction,
                                                       ui::Size bufferSize, ui::PixelFormat,
                                                       bool allowProtected, bool grayscale,
    void captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction, ui::Size bufferSize,
                             ui::PixelFormat, bool allowProtected, bool grayscale,
                             const sp<IScreenCaptureListener>&);
    ftl::SharedFuture<FenceResult> captureScreenCommon(
            RenderAreaFuture, GetLayerSnapshotsFunction,