update testGetMaxSupportedInstances logic

Thresholds tuned for normal- and low-RAM devices.
Memory exhaustion is considered in the testing and scoring.
Represents a slightly different algorithm than before:
-- limits the "test until failure" proceeds based on memory and declared value
-- hardware instances should match the declared value
-- sw instances get more flexibility based on memory exhaustion.

Bug: 159148909
Bug: 143668757
Bug: 156967969
Bug: 156200974
Bug: 152066313
Test: cts -m CtsMediaTestCases \
Test: -t android.media.cts.MediaCodecCapabilitiesTest#testGetMaxSupportedInstances
Change-Id: I4a72a9c7e0083403a565131d6724eb98434d121b
Merged-In: I4a72a9c7e0083403a565131d6724eb98434d121b
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index d17e702..7e75fb7 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -35,7 +35,6 @@
 import static android.media.MediaFormat.MIMETYPE_VIDEO_VP9;
 import android.media.MediaPlayer;
 import android.os.Build;
-import android.os.SystemProperties;
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 import android.util.Range;
@@ -697,6 +696,7 @@
     private int getActualMax(
             boolean isEncoder, String name, String mime, CodecCapabilities caps, int max) {
         int flag = isEncoder ? MediaCodec.CONFIGURE_FLAG_ENCODE : 0;
+        boolean memory_limited = false;
         MediaFormat format = createMinFormat(mime, caps);
         Log.d(TAG, "Test format " + format);
         Vector<MediaCodec> codecs = new Vector<MediaCodec>();
@@ -716,6 +716,7 @@
                 am.getMemoryInfo(outInfo);
                 if (outInfo.lowMemory) {
                     Log.d(TAG, "System is in low memory condition, stopping. max: " + i);
+                    memory_limited = true;
                     break;
                 }
             } catch (IllegalArgumentException e) {
@@ -745,6 +746,10 @@
             codecs.get(i).release();
         }
         codecs.clear();
+        // encode both actual max and whether we ran out of memory
+        if (memory_limited) {
+            actualMax = -actualMax;
+        }
         return actualMax;
     }
 
@@ -773,13 +778,20 @@
     }
 
     public void testGetMaxSupportedInstances() {
-        final int MAX_INSTANCES = 32;
         StringBuilder xmlOverrides = new StringBuilder();
         MediaCodecList allCodecs = new MediaCodecList(MediaCodecList.ALL_CODECS);
+        final boolean isLowRam = ActivityManager.isLowRamDeviceStatic();
         for (MediaCodecInfo info : allCodecs.getCodecInfos()) {
             Log.d(TAG, "codec: " + info.getName());
             Log.d(TAG, "  isEncoder = " + info.isEncoder());
 
+            // don't bother testing aliases
+            if (info.isAlias()) {
+                Log.d(TAG, "skipping: " + info.getName() + " is an alias for " +
+                                info.getCanonicalName());
+                continue;
+            }
+
             String[] types = info.getSupportedTypes();
             for (int j = 0; j < types.length; ++j) {
                 if (!knownTypes(types[j])) {
@@ -788,14 +800,55 @@
                 }
                 Log.d(TAG, "calling getCapabilitiesForType " + types[j]);
                 CodecCapabilities caps = info.getCapabilitiesForType(types[j]);
-                int max = caps.getMaxSupportedInstances();
-                Log.d(TAG, "getMaxSupportedInstances returns " + max);
-                assertTrue(max > 0);
+                int advertised = caps.getMaxSupportedInstances();
+                Log.d(TAG, "getMaxSupportedInstances returns " + advertised);
+                assertTrue(advertised > 0);
 
+                // see how well the declared max matches against reality
+
+                int tryMax = isLowRam ? 16 : 32;
+                int tryMin = isLowRam ? 4 : 16;
+
+                int trials = Math.min(advertised + 2, tryMax);
                 int actualMax = getActualMax(
-                        info.isEncoder(), info.getName(), types[j], caps, MAX_INSTANCES);
-                Log.d(TAG, "actualMax " + actualMax + " vs reported max " + max);
-                if (actualMax < (int)(max * 0.9) || actualMax > (int) Math.ceil(max * 1.1)) {
+                        info.isEncoder(), info.getName(), types[j], caps, trials);
+                Log.d(TAG, "actualMax " + actualMax + " vs advertised " + advertised
+                                + " tryMin " + tryMin + " tryMax " + tryMax);
+
+                boolean memory_limited = false;
+                if (actualMax < 0) {
+                    memory_limited = true;
+                    actualMax = -actualMax;
+                }
+
+                boolean compliant = true;
+                if (info.isHardwareAccelerated()) {
+                    // very specific bounds for HW codecs
+                    // so the adv+2 above is to see if the HW codec lets us go beyond adv
+                    // (it should not)
+                    if (actualMax != Math.min(advertised, tryMax)) {
+                        Log.d(TAG, "NO: hwcodec " + actualMax + " != min(" + advertised +
+                                            "," + tryMax + ")");
+                        compliant = false;
+                    }
+                } else {
+                    // sw codecs get a little more relaxation due to memory pressure
+                    if (actualMax >= Math.min(advertised, tryMax)) {
+                        // no memory issues, and we allocated them all
+                        Log.d(TAG, "OK: swcodec " + actualMax + " >= min(" + advertised +
+                                        "," + tryMax + ")");
+                    } else if (actualMax >= Math.min(advertised, tryMin) &&
+                                    memory_limited) {
+                        // memory issues, but we hit our floors
+                        Log.d(TAG, "OK: swcodec " + actualMax + " >= min(" + advertised +
+                                        "," + tryMin + ") + memory limited");
+                    } else {
+                        Log.d(TAG, "NO: swcodec didn't meet criteria");
+                        compliant = false;
+                    }
+                }
+
+                if (!compliant) {
                     String codec = "<MediaCodec name=\"" + info.getName() +
                             "\" type=\"" + types[j] + "\" >";
                     String limit = "    <Limit name=\"concurrent-instances\" max=\"" +