Merge "media: add CodecCapabilities.getMaxSupportedInstances."
diff --git a/api/current.txt b/api/current.txt
index 87cd2d6..dc83f6e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15186,6 +15186,7 @@
     method public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
     method public android.media.MediaFormat getDefaultFormat();
     method public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
+    method public int getMaxSupportedInstances();
     method public java.lang.String getMimeType();
     method public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities();
     method public final boolean isFeatureRequired(java.lang.String);
diff --git a/api/system-current.txt b/api/system-current.txt
index 9e635bf..ac80474 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -16398,6 +16398,7 @@
     method public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
     method public android.media.MediaFormat getDefaultFormat();
     method public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
+    method public int getMaxSupportedInstances();
     method public java.lang.String getMimeType();
     method public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities();
     method public final boolean isFeatureRequired(java.lang.String);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index ebf73da..ce06e65 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -124,6 +124,8 @@
     private static final Range<Integer> SIZE_RANGE = Range.create(1, 32768);
     private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960);
     private static final Range<Integer> BITRATE_RANGE = Range.create(0, 500000000);
+    private static final int DEFAULT_MAX_SUPPORTED_INSTANCES = 32;
+    private static final int MAX_SUPPORTED_INSTANCES_LIMIT = 256;
 
     // found stuff that is not supported by framework (=> this should not happen)
     private static final int ERROR_UNRECOGNIZED   = (1 << 0);
@@ -147,6 +149,7 @@
 
         // CLASSIFICATION
         private String mMime;
+        private int mMaxSupportedInstances;
 
         // LEGACY FIELDS
 
@@ -366,6 +369,18 @@
             return mMime;
         }
 
+        /**
+         * Returns the max number of the supported concurrent codec instances.
+         * <p>
+         * This is a hint for an upper bound. Applications should not expect to successfully
+         * operate more instances than the returned value, but the actual number of
+         * concurrently operable instances may be less as it depends on the available
+         * resources at time of use.
+         */
+        public int getMaxSupportedInstances() {
+            return mMaxSupportedInstances;
+        }
+
         private boolean isAudio() {
             return mAudioCaps != null;
         }
@@ -467,6 +482,15 @@
                 mEncoderCaps.setDefaultFormat(mDefaultFormat);
             }
 
+            final Map<String, Object> global = MediaCodecList.getGlobalSettings();
+            mMaxSupportedInstances = Utils.parseIntSafely(
+                    global.get("max-supported-instances"), DEFAULT_MAX_SUPPORTED_INSTANCES);
+
+            int maxInstances = Utils.parseIntSafely(
+                    map.get("max-supported-instances"), mMaxSupportedInstances);
+            mMaxSupportedInstances =
+                    Range.create(1, MAX_SUPPORTED_INSTANCES_LIMIT).clamp(maxInstances);
+
             for (Feature feat: getValidFeatures()) {
                 String key = MediaFormat.KEY_FEATURE_ + feat.mName;
                 Integer yesNo = (Integer)map.get(key);
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index 7fd0186..f44e048 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -21,6 +21,7 @@
 import android.media.MediaCodecInfo;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Map;
 
 /**
  * Allows you to enumerate available codecs, each specified as a {@link MediaCodecInfo} object,
@@ -61,13 +62,19 @@
         return sRegularCodecInfos[index];
     }
 
+    /* package private */ static final Map<String, Object> getGlobalSettings() {
+        return sGlobalSettings;
+    }
+
     private static Object sInitLock = new Object();
     private static MediaCodecInfo[] sAllCodecInfos;
     private static MediaCodecInfo[] sRegularCodecInfos;
+    private static Map<String, Object> sGlobalSettings;
 
     private static final void initCodecList() {
         synchronized (sInitLock) {
             if (sRegularCodecInfos == null) {
+                sGlobalSettings = native_getGlobalSettings();
                 int count = native_getCodecCount();
                 ArrayList<MediaCodecInfo> regulars = new ArrayList<MediaCodecInfo>();
                 ArrayList<MediaCodecInfo> all = new ArrayList<MediaCodecInfo>();
@@ -112,6 +119,8 @@
     /* package private */ static native final MediaCodecInfo.CodecCapabilities
         getCodecCapabilities(int index, String type);
 
+    /* package private */ static native final Map<String, Object> native_getGlobalSettings();
+
     /* package private */ static native final int findCodecByName(String codec);
 
     /** @hide */
diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp
index f8c349b..82dd48d 100644
--- a/media/jni/android_media_MediaCodecList.cpp
+++ b/media/jni/android_media_MediaCodecList.cpp
@@ -262,6 +262,27 @@
     return caps;
 }
 
+static jobject android_media_MediaCodecList_getGlobalSettings(JNIEnv *env, jobject /* thiz */) {
+    sp<IMediaCodecList> mcl = getCodecList(env);
+    if (mcl == NULL) {
+        // Runtime exception already pending.
+        return NULL;
+    }
+
+    const sp<AMessage> settings = mcl->getGlobalSettings();
+    if (settings == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "cannot get global settings");
+        return NULL;
+    }
+
+    jobject settingsObj = NULL;
+    if (ConvertMessageToMap(env, settings, &settingsObj)) {
+        return NULL;
+    }
+
+    return settingsObj;
+}
+
 static void android_media_MediaCodecList_native_init(JNIEnv* /* env */) {
 }
 
@@ -277,6 +298,10 @@
       "(ILjava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;",
       (void *)android_media_MediaCodecList_getCodecCapabilities },
 
+    { "native_getGlobalSettings",
+      "()Ljava/util/Map;",
+      (void *)android_media_MediaCodecList_getGlobalSettings },
+
     { "findCodecByName", "(Ljava/lang/String;)I",
       (void *)android_media_MediaCodecList_findCodecByName },