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

Commit 9cb9bec0 authored by Jayant Chowdhary's avatar Jayant Chowdhary Committed by Android (Google) Code Review
Browse files

Merge "Add an llndk api to get a native handle corresponding to ANativeWindow in AImageReader."

parents d734a499 249e1f25
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ cc_library_shared {
    vndk: {
        enabled: true,
    },

    double_loadable: true,
    srcs: [
        "Conversion.cpp",
        "FrameDropper.cpp",
+29 −2
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ cc_library_shared {
    cflags: [
        "-fvisibility=hidden",
        "-DEXPORT=__attribute__((visibility(\"default\")))",

        "-Werror",
        "-Wall",
    ],
@@ -73,6 +72,8 @@ cc_library_shared {
    ],

    shared_libs: [
        "android.hardware.graphics.bufferqueue@1.0",
        "android.hidl.token@1.0-utils",
        "libbinder",
        "libmedia",
        "libmedia_omx",
@@ -81,12 +82,15 @@ cc_library_shared {
        "libmediaextractor",
        "libstagefright",
        "libstagefright_foundation",
        "libstagefright_bufferqueue_helper",
        "liblog",
        "libutils",
        "libcutils",
        "libandroid",
        "libandroid_runtime",
        "libbinder",
        "libhwbinder",
        "libhidlbase",
        "libgui",
        "libui",
        "libmedia2_jni_core",
@@ -105,7 +109,9 @@ cc_library_shared {
llndk_library {
    name: "libmediandk",
    symbol_file: "libmediandk.map.txt",
    export_include_dirs: ["include"],
    export_include_dirs: [
        "include",
    ],
}

cc_library {
@@ -148,3 +154,24 @@ cc_library {
        },
    },
}

cc_test {
    name: "AImageReaderWindowHandleTest",
    srcs: ["tests/AImageReaderWindowHandleTest.cpp"],
    shared_libs: [
        "libbinder",
        "libmediandk",
        "libnativewindow",
        "libgui",
        "libutils",
        "libui",
        "libcutils",
        "android.hardware.graphics.bufferqueue@1.0",
    ],
    cflags: [
        "-D__ANDROID_VNDK__",
    ],
    include_dirs: [
        "frameworks/av/media/ndk/",
    ],
}
+98 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
#include <grallocusage/GrallocUsageConversion.h>
#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>

using namespace android;

@@ -43,6 +44,10 @@ const char* AImageReader::kCallbackFpKey = "Callback";
const char* AImageReader::kContextKey    = "Context";
const char* AImageReader::kGraphicBufferKey = "GraphicBuffer";

static constexpr int kWindowHalTokenSizeMax = 256;

static native_handle_t *convertHalTokenToNativeHandle(const HalToken &halToken);

bool
AImageReader::isSupportedFormatAndUsage(int32_t format, uint64_t usage) {
    // Check whether usage has either CPU_READ_OFTEN or CPU_READ set. Note that check against
@@ -363,6 +368,15 @@ AImageReader::~AImageReader() {
        mBufferItemConsumer->abandon();
        mBufferItemConsumer->setFrameAvailableListener(nullptr);
    }

    if (mWindowHandle != nullptr) {
        int size = mWindowHandle->data[0];
        hidl_vec<uint8_t> halToken;
        halToken.setToExternal(
            reinterpret_cast<uint8_t *>(&mWindowHandle->data[1]), size);
        deleteHalToken(halToken);
        native_handle_delete(mWindowHandle);
    }
}

media_status_t
@@ -522,6 +536,25 @@ AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd) {
    }
}

media_status_t AImageReader::getWindowNativeHandle(native_handle **handle) {
    if (mWindowHandle != nullptr) {
        *handle = mWindowHandle;
        return AMEDIA_OK;
    }
    sp<HGraphicBufferProducer> hgbp =
        new TWGraphicBufferProducer<HGraphicBufferProducer>(mProducer);
    HalToken halToken;
    if (!createHalToken(hgbp, &halToken)) {
        return AMEDIA_ERROR_UNKNOWN;
    }
    mWindowHandle = convertHalTokenToNativeHandle(halToken);
    if (!mWindowHandle) {
        return AMEDIA_ERROR_UNKNOWN;
    }
    *handle = mWindowHandle;
    return AMEDIA_OK;
}

int
AImageReader::getBufferWidth(BufferItem* buffer) {
    if (buffer == NULL) return -1;
@@ -585,6 +618,58 @@ AImageReader::acquireLatestImage(/*out*/AImage** image, /*out*/int* acquireFence
    }
}

static native_handle_t *convertHalTokenToNativeHandle(
        const HalToken &halToken) {
    // We attempt to store halToken in the ints of the native_handle_t after its
    // size. The first int stores the size of the token. We store this in an int
    // to avoid alignment issues where size_t and int do not have the same
    // alignment.
    size_t nhDataByteSize = halToken.size();
    if (nhDataByteSize > kWindowHalTokenSizeMax) {
        // The size of the token isn't reasonable..
        return nullptr;
    }
    size_t numInts = ceil(nhDataByteSize / sizeof(int)) + 1;

    // We don't check for overflow, whether numInts can fit in an int, since we
    // expect kWindowHalTokenSizeMax to be a reasonable limit.
    // create a native_handle_t with 0 numFds and numInts number of ints.
    native_handle_t *nh =
        native_handle_create(0, numInts);
    if (!nh) {
        return nullptr;
    }
    // Store the size of the token in the first int.
    nh->data[0] = nhDataByteSize;
    memcpy(&(nh->data[1]), halToken.data(), nhDataByteSize);
    return nh;
}

static sp<HGraphicBufferProducer> convertNativeHandleToHGBP (
        const native_handle_t *handle) {
    // Read the size of the halToken vec<uint8_t>
    hidl_vec<uint8_t> halToken;
    halToken.setToExternal(
        reinterpret_cast<uint8_t *>(const_cast<int *>(&(handle->data[1]))),
        handle->data[0]);
    sp<HGraphicBufferProducer> hgbp =
        HGraphicBufferProducer::castFrom(retrieveHalInterface(halToken));
    return hgbp;
}

EXPORT
sp<HGraphicBufferProducer> AImageReader_getHGBPFromHandle(
    const native_handle_t *handle) {
    if (handle == nullptr) {
        return nullptr;
    }
    if (handle->numFds != 0  ||
        handle->numInts < ceil(sizeof(size_t) / sizeof(int))) {
        return nullptr;
    }
    return convertNativeHandleToHGBP(handle);
}

EXPORT
media_status_t AImageReader_new(
        int32_t width, int32_t height, int32_t format, int32_t maxImages,
@@ -594,6 +679,19 @@ media_status_t AImageReader_new(
            width, height, format, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, maxImages, reader);
}

extern "C" {

EXPORT
media_status_t AImageReader_getWindowNativeHandle(
        AImageReader *reader, /*out*/native_handle_t **handle) {
    if (reader == nullptr || handle == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }
    return reader->getWindowNativeHandle(handle);
}

} //extern "C"

EXPORT
media_status_t AImageReader_newWithUsage(
        int32_t width, int32_t height, int32_t format, uint64_t usage,
+9 −0
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ struct AImageReader : public RefBase {
    media_status_t acquireNextImage(/*out*/AImage** image, /*out*/int* fenceFd);
    media_status_t acquireLatestImage(/*out*/AImage** image, /*out*/int* fenceFd);

    media_status_t getWindowNativeHandle(/*out*/native_handle_t **handle);

    ANativeWindow* getWindow()    const { return mWindow.get(); };
    int32_t        getWidth()     const { return mWidth; };
    int32_t        getHeight()    const { return mHeight; };
@@ -160,10 +162,17 @@ struct AImageReader : public RefBase {
    sp<Surface>                mSurface;
    sp<BufferItemConsumer>     mBufferItemConsumer;
    sp<ANativeWindow>          mWindow;
    native_handle_t*           mWindowHandle = nullptr;

    List<AImage*>              mAcquiredImages;

    Mutex                      mLock;
};

// Retrieves HGraphicBufferProducer corresponding to the native_handle_t
// provided. This method also deletes the HalToken corresponding to the
// native_handle_t. Thus, if it is used twice in succession, the second call
// returns nullptr;
sp<HGraphicBufferProducer> AImageReader_getHGBPFromHandle(const native_handle_t *handle);

#endif // _NDK_IMAGE_READER_PRIV_H
+20 −0
Original line number Diff line number Diff line
@@ -37,6 +37,9 @@
#define _NDK_IMAGE_READER_H

#include <sys/cdefs.h>
#ifdef __ANDROID_VNDK__
#include <cutils/native_handle.h>
#endif

#include <android/native_window.h>
#include "NdkMediaError.h"
@@ -461,6 +464,23 @@ typedef struct AImageReader_BufferRemovedListener {
media_status_t AImageReader_setBufferRemovedListener(
        AImageReader* reader, AImageReader_BufferRemovedListener* listener) __INTRODUCED_IN(26);

#ifdef __ANDROID_VNDK__
/*
 * Get the native_handle_t corresponding to the ANativeWindow owned by the
 * AImageReader provided.
 *
 * @param reader The image reader of interest.
 * @param handle The output native_handle_t. This native handle is owned by
 *               this image reader.
 *
 * @return AMEDIA_OK if the method call succeeds.
 *         AMEDIA_ERROR_INVALID_PARAMETER if reader or handle are NULL.
 *         AMEDIA_ERROR_UNKNOWN if some other error is encountered.
 */
media_status_t AImageReader_getWindowNativeHandle(
    AImageReader *reader, /* out */native_handle_t **handle);
#endif

#endif /* __ANDROID_API__ >= 26 */

__END_DECLS
Loading