media: add available/required resources test api
Bug: 363282971
Test: build and boot, manual testing
Flag: android.media.codec.codec_availability
Change-Id: I723d0de9fe1c1acc49da0904783fc9a53c4a84d9
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 7f487e5..13dc748 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -104,6 +104,7 @@
"libgrallocusage",
"libmedia_midiiowrapper",
"android.companion.virtualdevice.flags-aconfig-cc",
+ "android.media.codec-aconfig-cc",
"android.media.playback.flags-aconfig-cc",
],
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 001653b..fc184fe 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -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 @@
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 @@
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 @@
obj = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
break;
}
+ case MediaCodec::CB_REQUIRED_RESOURCES_CHANGED:
+ {
+ break;
+ }
default:
TRESPASS();
@@ -3560,6 +3613,64 @@
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 @@
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 @@
{ "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[] = {
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index c9b6b7f6..930dbbe 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -185,6 +185,8 @@
status_t unsubscribeFromVendorParameters(JNIEnv *env, jobject names);
+ status_t getRequiredResources(JNIEnv *env, jobject *resourcesObj);
+
bool hasCryptoOrDescrambler() { return mHasCryptoOrDescrambler; }
const sp<ICrypto> &getCrypto() { return mCrypto; }