Merge "[bug fix] Handle the case when rfFieldOnTime is not set in OemLog." into main
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 79c4fb6..59327c8 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2044,6 +2044,29 @@
method public boolean isAidlHal();
}
+ public final class MediaCodec {
+ method @FlaggedApi("android.media.codec.codec_availability") @NonNull public static java.util.List<android.media.MediaCodec.GlobalResourceInfo> getGloballyAvailableResources();
+ method @FlaggedApi("android.media.codec.codec_availability") @NonNull public java.util.List<android.media.MediaCodec.InstanceResourceInfo> getRequiredResources();
+ }
+
+ public abstract static class MediaCodec.Callback {
+ method @FlaggedApi("android.media.codec.codec_availability") public void onRequiredResourcesChanged(@NonNull android.media.MediaCodec);
+ }
+
+ @FlaggedApi("android.media.codec.codec_availability") public static final class MediaCodec.GlobalResourceInfo {
+ ctor public MediaCodec.GlobalResourceInfo();
+ method public long getAvailable();
+ method public long getCapacity();
+ method @NonNull public String getName();
+ }
+
+ @FlaggedApi("android.media.codec.codec_availability") public static final class MediaCodec.InstanceResourceInfo {
+ ctor public MediaCodec.InstanceResourceInfo();
+ method @NonNull public String getName();
+ method public long getPerFrameCount();
+ method public long getStaticCount();
+ }
+
public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int, int, @NonNull android.util.Size);
ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint, @NonNull android.util.Size);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 2ae89d3..82e9503 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -16,6 +16,7 @@
package android.media;
+import static android.media.codec.Flags.FLAG_CODEC_AVAILABILITY;
import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE;
import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST;
import static android.media.codec.Flags.FLAG_SUBSESSION_METRICS;
@@ -29,6 +30,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.ImageFormat;
import android.graphics.Rect;
@@ -1843,6 +1845,12 @@
*/
private static final int CB_METRICS_FLUSHED = 8;
+ /**
+ * Callback ID to notify the change in resource requirement
+ * for the codec component.
+ */
+ private static final int CB_REQUIRED_RESOURCES_CHANGE = 9;
+
private class EventHandler extends Handler {
private MediaCodec mCodec;
@@ -2017,13 +2025,19 @@
case CB_METRICS_FLUSHED:
{
-
if (GetFlag(() -> android.media.codec.Flags.subsessionMetrics())) {
mCallback.onMetricsFlushed(mCodec, (PersistableBundle)msg.obj);
}
break;
}
+ case CB_REQUIRED_RESOURCES_CHANGE: {
+ if (android.media.codec.Flags.codecAvailability()) {
+ mCallback.onRequiredResourcesChanged(mCodec);
+ }
+ break;
+ }
+
default:
{
break;
@@ -2302,6 +2316,70 @@
}
/**
+ * @hide
+ * Abstraction for the Global Codec resources.
+ * This encapsulates all the available codec resources on the device.
+ *
+ * To be able to enforce and test the implementation of codec availability hal APIs,
+ * globally available codec resources are exposed only as TestApi.
+ * This will be tracked and verified through cts.
+ */
+ @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+ @TestApi
+ public static final class GlobalResourceInfo {
+ /**
+ * Identifier for the Resource type.
+ */
+ String mName;
+ /**
+ * Total count/capacity of resources of this type.
+ */
+ long mCapacity;
+ /**
+ * Available count of this resource type.
+ */
+ long mAvailable;
+
+ @NonNull
+ public String getName() {
+ return mName;
+ }
+
+ public long getCapacity() {
+ return mCapacity;
+ }
+
+ public long getAvailable() {
+ return mAvailable;
+ }
+ };
+
+ /**
+ * @hide
+ * Get a list of globally available codec resources.
+ *
+ * To be able to enforce and test the implementation of codec availability hal APIs,
+ * it is exposed only as TestApi.
+ * This will be tracked and verified through cts.
+ *
+ * This returns a {@link java.util.List} list of codec resources.
+ * For every {@link GlobalResourceInfo} in the list, it encapsulates the
+ * information about each resources available globaly on device.
+ *
+ * @return A list of available device codec resources; an empty list if no
+ * device codec resources are available.
+ * @throws UnsupportedOperationException if not implemented.
+ */
+ @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+ @TestApi
+ public static @NonNull List<GlobalResourceInfo> getGloballyAvailableResources() {
+ return native_getGloballyAvailableResources();
+ }
+
+ @NonNull
+ private static native List<GlobalResourceInfo> native_getGloballyAvailableResources();
+
+ /**
* Configures a component.
*
* @param format The format of the input data (decoder) or the desired
@@ -2443,6 +2521,73 @@
}
/**
+ * @hide
+ * Abstraction for the resources associated with a codec instance.
+ * This encapsulates the required codec resources for a configured codec instance.
+ *
+ * To be able to enforce and test the implementation of codec availability hal APIs,
+ * required codec resources are exposed only as TestApi.
+ * This will be tracked and verified through cts.
+ */
+ @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+ @TestApi
+ public static final class InstanceResourceInfo {
+ /**
+ * Identifier for the Resource type.
+ */
+ String mName;
+ /**
+ * Required resource count of this type.
+ */
+ long mStaticCount;
+ /**
+ * Per frame resource requirement of this resource type.
+ */
+ long mPerFrameCount;
+
+ @NonNull
+ public String getName() {
+ return mName;
+ }
+
+ public long getStaticCount() {
+ return mStaticCount;
+ }
+
+ public long getPerFrameCount() {
+ return mPerFrameCount;
+ }
+ };
+
+ /**
+ * @hide
+ * Get a list of required codec resources for this configuration.
+ *
+ * To be able to enforce and test the implementation of codec availability hal APIs,
+ * it is exposed only as TestApi.
+ * This will be tracked and verified through cts.
+ *
+ * This returns a {@link java.util.List} list of codec resources.
+ * For every {@link GlobalResourceInfo} in the list, it encapsulates the
+ * information about each resources required for the current configuration.
+ *
+ * NOTE: This may only be called after {@link #configure}.
+ *
+ * @return A list of required device codec resources; an empty list if no
+ * device codec resources are required.
+ * @throws IllegalStateException if the codec wasn't configured yet.
+ * @throws UnsupportedOperationException if not implemented.
+ */
+ @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+ @TestApi
+ public @NonNull List<InstanceResourceInfo> getRequiredResources() {
+ return native_getRequiredResources();
+ }
+
+ @NonNull
+ private native List<InstanceResourceInfo> native_getRequiredResources();
+
+ /**
* Dynamically sets the output surface of a codec.
* <p>
* This can only be used if the codec was configured with an output surface. The
@@ -5740,6 +5885,25 @@
@NonNull MediaCodec codec, @NonNull PersistableBundle metrics) {
// default implementation ignores this callback.
}
+
+ /**
+ * @hide
+ * Called when there is a change in the required resources for the codec.
+ * <p>
+ * Upon receiving this notification, the updated resource requirement
+ * can be queried through {@link #getRequiredResources}.
+ *
+ * @param codec The MediaCodec object.
+ */
+ @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+ @TestApi
+ public void onRequiredResourcesChanged(@NonNull MediaCodec codec) {
+ /*
+ * A default implementation for backward compatibility.
+ * Since this is a TestApi, we are not enforcing the callback to be
+ * overridden.
+ */
+ }
}
private void postEventFromNative(
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; }