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

Commit 10d3ca60 authored by Jeimy Santiago Morales's avatar Jeimy Santiago Morales Committed by Android (Google) Code Review
Browse files

Merge "Make screenCapture calls to SF async" into main

parents e6c479a9 9be7d0c3
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -230,20 +230,20 @@ interface ISurfaceComposer {
     * The subregion can be optionally rotated.  It will also be scaled to
     * The subregion can be optionally rotated.  It will also be scaled to
     * match the size of the output buffer.
     * 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
     * Capture the specified screen. This requires the READ_FRAME_BUFFER
     * permission.
     * 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.
     * Capture a subtree of the layer hierarchy, potentially ignoring the root node.
     * This requires READ_FRAME_BUFFER permission. This function will fail if there
     * This requires READ_FRAME_BUFFER permission. This function will fail if there
     * is a secure window on screen
     * 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.
     * Clears the frame statistics for animations.
+69 −47
Original line number Original line Diff line number Diff line
@@ -7332,16 +7332,27 @@ ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace, const DisplayD


} // namespace
} // 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) {
                                    const sp<IScreenCaptureListener>& captureListener) {
    ATRACE_CALL();
    ATRACE_CALL();


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


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


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


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


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


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


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


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


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


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


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


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


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


        Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState());
        Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState());
@@ -7491,7 +7507,8 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
        if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) {
        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
            // 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.
            // 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);
        reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY);


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


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


    if (captureListener == nullptr) {
    if (captureListener == nullptr) {
        ALOGE("capture screen must provide a capture listener callback");
        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,
    captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat,
                                      args.pixelFormat, args.allowProtected, args.grayscale,
                        args.allowProtected, args.grayscale, captureListener);
                                      captureListener);
    return fenceStatus(future.get());
}
}


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


@@ -7592,7 +7611,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
        ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32
        ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32
              ") that exceeds render target size limit.",
              ") that exceeds render target size limit.",
              bufferSize.getWidth(), bufferSize.getHeight());
              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
    // Loop over all visible layers to see whether there's any protected layer. A protected layer is
@@ -7632,14 +7652,16 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
        // Otherwise an irreponsible process may cause an SF crash by allocating
        // Otherwise an irreponsible process may cause an SF crash by allocating
        // too much.
        // too much.
        ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
        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<
    const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
            renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
            renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
                                                 renderengine::impl::ExternalTexture::Usage::
                                                 renderengine::impl::ExternalTexture::Usage::
                                                         WRITEABLE);
                                                         WRITEABLE);
    return captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture,
    auto fence = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture,
                                     false /* regionSampling */, grayscale, captureListener);
                                     false /* regionSampling */, grayscale, captureListener);
    fence.get();
}
}


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


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


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


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


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


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


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


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