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

Commit aa758f27 authored by Girish's avatar Girish
Browse files

media: add available/required resources test api

Bug: 363282971
Test: build and boot, manual testing
Flag: android.media.codec.codec_availability
Change-Id: I723d0de9fe1c1acc49da0904783fc9a53c4a84d9
parent fc4529bf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ cc_library_shared {
        "libgrallocusage",
        "libmedia_midiiowrapper",
        "android.companion.virtualdevice.flags-aconfig-cc",
        "android.media.codec-aconfig-cc",
        "android.media.playback.flags-aconfig-cc",
    ],

+147 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@
#include <C2Buffer.h>
#include <C2PlatformSupport.h>

#include <android_media_codec.h>

#include <android/hardware/cas/native/1.0/IDescrambler.h>

#include <android_runtime/android_hardware_HardwareBuffer.h>
@@ -189,6 +191,22 @@ static struct {
    jmethodID setId;
} gBufferInfo;

static struct {
    jclass clazz;
    jmethodID ctorId;
    jfieldID resourceId;
    jfieldID capacityId;
    jfieldID availableId;
} gGlobalResourceInfo;

static struct {
    jclass clazz;
    jmethodID ctorId;
    jfieldID resourceId;
    jfieldID staticCountId;
    jfieldID perFrameCountId;
} gInstanceResourceInfo;

struct fields_t {
    jmethodID postEventFromNativeID;
    jmethodID lockAndGetContextID;
@@ -1129,6 +1147,37 @@ status_t JMediaCodec::unsubscribeFromVendorParameters(JNIEnv *env, jobject names
    return mCodec->unsubscribeFromVendorParameters(names);
}

static jobject getJavaResources(
        JNIEnv *env,
        const std::vector<MediaCodec::InstanceResourceInfo>& resources) {
    jobject resourcesObj = env->NewObject(gArrayListInfo.clazz, gArrayListInfo.ctorId);
    for (const MediaCodec::InstanceResourceInfo& res : resources) {
        ScopedLocalRef<jobject> object{env, env->NewObject(
                gInstanceResourceInfo.clazz, gInstanceResourceInfo.ctorId)};
        ScopedLocalRef<jstring> nameStr{env, env->NewStringUTF(res.mName.c_str())};
        env->SetObjectField(object.get(), gInstanceResourceInfo.resourceId, nameStr.get());
        env->SetLongField(object.get(),
                          gInstanceResourceInfo.staticCountId,
                          (jlong)res.mStaticCount);
        env->SetLongField(object.get(),
                          gInstanceResourceInfo.perFrameCountId,
                          (jlong)res.mPerFrameCount);
        (void)env->CallBooleanMethod(resourcesObj, gArrayListInfo.addId, object.get());
    }

    return resourcesObj;
}

status_t JMediaCodec::getRequiredResources(JNIEnv *env, jobject *resourcesObj) {
    std::vector<MediaCodec::InstanceResourceInfo> resources;
    status_t status = mCodec->getRequiredResources(resources);
    if (status != OK) {
        return status;
    }
    *resourcesObj = getJavaResources(env, resources);
    return OK;
}

static jthrowable createCodecException(
        JNIEnv *env, status_t err, int32_t actionCode, const char *msg = NULL) {
    ScopedLocalRef<jclass> clazz(
@@ -1475,6 +1524,10 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) {
            obj = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
            break;
        }
        case MediaCodec::CB_REQUIRED_RESOURCES_CHANGED:
        {
            break;
        }

        default:
            TRESPASS();
@@ -3560,6 +3613,64 @@ static void android_media_MediaCodec_unsubscribeFromVendorParameters(
    return;
}

static jobject getJavaResources(
        JNIEnv *env,
        const std::vector<MediaCodec::GlobalResourceInfo>& resources) {
    jobject resourcesObj = env->NewObject(gArrayListInfo.clazz, gArrayListInfo.ctorId);
    for (const MediaCodec::GlobalResourceInfo& res : resources) {
        ScopedLocalRef<jobject> object{env, env->NewObject(
                gGlobalResourceInfo.clazz, gGlobalResourceInfo.ctorId)};
        ScopedLocalRef<jstring> nameStr{env, env->NewStringUTF(res.mName.c_str())};
        env->SetObjectField(object.get(), gInstanceResourceInfo.resourceId, nameStr.get());
        env->SetLongField(object.get(), gGlobalResourceInfo.capacityId, (jlong)res.mCapacity);
        env->SetLongField(object.get(), gGlobalResourceInfo.availableId, (jlong)res.mAvailable);
        (void)env->CallBooleanMethod(resourcesObj, gArrayListInfo.addId, object.get());
    }

    return resourcesObj;
}

static jobject android_media_MediaCodec_getGloballyAvailableResources(
        JNIEnv *env, jobject thiz) {
    (void)thiz;
    std::vector<MediaCodec::GlobalResourceInfo> resources;
    status_t status = MediaCodec::getGloballyAvailableResources(resources);
    if (status != OK) {
        if (status == ERROR_UNSUPPORTED) {
            jniThrowException(env, "java/lang/UnsupportedOperationException",
                              "Function Not Implemented");
        } else {
            throwExceptionAsNecessary(env, status, nullptr);
        }
        return nullptr;
    }

    return getJavaResources(env, resources);
}

static jobject android_media_MediaCodec_getRequiredResources(
        JNIEnv *env, jobject thiz) {
    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
    if (codec == nullptr || codec->initCheck() != OK) {
        throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
        return nullptr;
    }

    jobject ret = nullptr;
    status_t status = codec->getRequiredResources(env, &ret);
    if (status != OK) {
        if (status == ERROR_UNSUPPORTED) {
            jniThrowException(env, "java/lang/UnsupportedOperationException",
                              "Function Not Implemented");
        } else {
            throwExceptionAsNecessary(env, status, nullptr);
        }
        return nullptr;
    }

    return ret;
}

static void android_media_MediaCodec_native_init(JNIEnv *env, jclass) {
    ScopedLocalRef<jclass> clazz(
            env, env->FindClass("android/media/MediaCodec"));
@@ -3905,6 +4016,36 @@ static void android_media_MediaCodec_native_init(JNIEnv *env, jclass) {
    gFields.bufferInfoOffset = env->GetFieldID(clazz.get(), "offset", "I");
    gFields.bufferInfoPresentationTimeUs =
            env->GetFieldID(clazz.get(), "presentationTimeUs", "J");

    // Since these TestApis are defined under the flag, make sure they are
    // accessed only when the flag is set.
    if (android::media::codec::codec_availability()) {
        clazz.reset(env->FindClass("android/media/MediaCodec$GlobalResourceInfo"));
        CHECK(clazz.get() != NULL);
        gGlobalResourceInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());
        gGlobalResourceInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V");
        CHECK(gGlobalResourceInfo.ctorId != NULL);
        gGlobalResourceInfo.resourceId =
                env->GetFieldID(clazz.get(), "mName", "Ljava/lang/String;");
        CHECK(gGlobalResourceInfo.resourceId != NULL);
        gGlobalResourceInfo.capacityId = env->GetFieldID(clazz.get(), "mCapacity", "J");
        CHECK(gGlobalResourceInfo.capacityId != NULL);
        gGlobalResourceInfo.availableId = env->GetFieldID(clazz.get(), "mAvailable", "J");
        CHECK(gGlobalResourceInfo.availableId != NULL);

        clazz.reset(env->FindClass("android/media/MediaCodec$InstanceResourceInfo"));
        CHECK(clazz.get() != NULL);
        gInstanceResourceInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());
        gInstanceResourceInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V");
        CHECK(gInstanceResourceInfo.ctorId != NULL);
        gInstanceResourceInfo.resourceId =
                env->GetFieldID(clazz.get(), "mName", "Ljava/lang/String;");
        CHECK(gInstanceResourceInfo.resourceId != NULL);
        gInstanceResourceInfo.staticCountId= env->GetFieldID(clazz.get(), "mStaticCount", "J");
        CHECK(gInstanceResourceInfo.staticCountId != NULL);
        gInstanceResourceInfo.perFrameCountId = env->GetFieldID(clazz.get(), "mPerFrameCount", "J");
        CHECK(gInstanceResourceInfo.perFrameCountId != NULL);
    }
}

static void android_media_MediaCodec_native_setup(
@@ -4261,6 +4402,12 @@ static const JNINativeMethod gMethods[] = {

    { "native_finalize", "()V",
      (void *)android_media_MediaCodec_native_finalize },

    { "native_getGloballyAvailableResources", "()Ljava/util/List;",
      (void *)android_media_MediaCodec_getGloballyAvailableResources},

    { "native_getRequiredResources", "()Ljava/util/List;",
      (void *)android_media_MediaCodec_getRequiredResources},
};

static const JNINativeMethod gLinearBlockMethods[] = {
+2 −0
Original line number Diff line number Diff line
@@ -185,6 +185,8 @@ struct JMediaCodec : public AHandler {

    status_t unsubscribeFromVendorParameters(JNIEnv *env, jobject names);

    status_t getRequiredResources(JNIEnv *env, jobject *resourcesObj);

    bool hasCryptoOrDescrambler() { return mHasCryptoOrDescrambler; }

    const sp<ICrypto> &getCrypto() { return mCrypto; }