media: don't test video decoders & encoders on watch devices

This patch includes additional fixes for CTS tests that are still
run on watch devices.

Bug: 18664566
Change-Id: Ia69b76a781a1eff8e109e07f4176b1860b6454e7
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index cbb0a3d..1f6b3cf 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -22,7 +22,9 @@
 import android.media.MediaCodecInfo.CodecProfileLevel;
 import static android.media.MediaCodecInfo.CodecProfileLevel.*;
 import static android.media.MediaFormat.MIMETYPE_VIDEO_AVC;
+import static android.media.MediaFormat.MIMETYPE_VIDEO_H263;
 import static android.media.MediaFormat.MIMETYPE_VIDEO_HEVC;
+import static android.media.MediaFormat.MIMETYPE_VIDEO_MPEG4;
 import android.media.MediaCodecList;
 import android.media.MediaFormat;
 import android.media.MediaPlayer;
@@ -76,6 +78,39 @@
         }
     }
 
+    // Android device implementations with H.263 encoders, MUST support Level 45.
+    public void testH263EncoderProfileAndLevel() throws Exception {
+        if (!MediaUtils.checkEncoder(MIMETYPE_VIDEO_H263)) {
+            return; // skip
+        }
+
+        assertTrue(
+                "H.263 must support Level 45",
+                hasEncoder(MIMETYPE_VIDEO_H263, MPEG4ProfileSimple, H263Level45));
+    }
+
+    // Android device implementations with H.263 decoders, MUST support Level 30.
+    public void testH263DecoderProfileAndLevel() throws Exception {
+        if (!MediaUtils.checkDecoder(MIMETYPE_VIDEO_H263)) {
+            return; // skip
+        }
+
+        assertTrue(
+                "H.263 must support Level 30",
+                hasDecoder(MIMETYPE_VIDEO_H263, MPEG4ProfileSimple, H263Level30));
+    }
+
+    // Android device implementations with MPEG-4 decoders, MUST support Simple Profile Level 3.
+    public void testMpeg4DecoderProfileAndLevel() throws Exception {
+        if (!MediaUtils.checkDecoder(MIMETYPE_VIDEO_MPEG4)) {
+            return; // skip
+        }
+
+        assertTrue(
+                "MPEG-4 must support Simple Profile Level 3",
+                hasDecoder(MIMETYPE_VIDEO_MPEG4, MPEG4ProfileSimple, MPEG4Level3));
+    }
+
     // Android device implementations, when supporting H.265 codec MUST support the Main Profile
     // Level 3 Main tier.
     // Android Television Devices MUST support the Main Profile Level 4.1 Main tier.
@@ -279,7 +314,18 @@
             try {
                 CodecCapabilities caps = info.getCapabilitiesForType(mime);
                 for (CodecProfileLevel pl : caps.profileLevels) {
-                    if (pl.profile == profile && pl.level >= level) {
+                    if (pl.profile != profile) {
+                        continue;
+                    }
+
+                    // H.263 levels are not completely ordered:
+                    // Level45 support only implies Level10 support
+                    if (mime.equalsIgnoreCase(MIMETYPE_VIDEO_H263)) {
+                        if (pl.level != level && pl.level == H263Level45 && level > H263Level10) {
+                            continue;
+                        }
+                    }
+                    if (pl.level >= level) {
                         return true;
                     }
                 }
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
index 4030636..e04517d 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
@@ -50,9 +50,10 @@
             mAllCodecs.getCodecInfos();
 
     class CodecType {
-        CodecType(String type, boolean isEncoder) {
+        CodecType(String type, boolean isEncoder, MediaFormat sampleFormat) {
             mMimeTypeName = type;
             mIsEncoder = isEncoder;
+            mSampleFormat = sampleFormat;
         }
 
         boolean equals(CodecType codecType) {
@@ -60,10 +61,35 @@
                     mIsEncoder == codecType.mIsEncoder;
         }
 
-        String mMimeTypeName;
-        boolean mIsEncoder;
+        boolean canBeFound() {
+            return codecCanBeFound(mIsEncoder, mSampleFormat);
+        }
+
+        @Override
+        public String toString() {
+            return mMimeTypeName + (mIsEncoder ? " encoder" : " decoder") + " for " + mSampleFormat;
+        }
+
+        private String mMimeTypeName;
+        private boolean mIsEncoder;
+        private MediaFormat mSampleFormat;
     };
 
+    class AudioCodec extends CodecType {
+        AudioCodec(String mime, boolean isEncoder, int sampleRate) {
+            super(mime, isEncoder, MediaFormat.createAudioFormat(
+                    mime, sampleRate, 1 /* channelCount */));
+        }
+    }
+
+    class VideoCodec extends CodecType {
+        VideoCodec(String mime, boolean isEncoder) {
+            // implicit assumption that QVGA video is always valid
+            super(mime, isEncoder, MediaFormat.createVideoFormat(
+                    mime, 176 /* width */, 144 /* height */));
+        }
+    }
+
     public static void testMediaCodecXmlFileExist() {
         File file = new File(MEDIA_CODEC_XML_FILE);
         assertTrue("/etc/media_codecs.xml does not exist", file.exists());
@@ -241,6 +267,9 @@
         List<CodecType> requiredList = getRequiredCodecTypes();
         List<CodecType> supportedList = getSupportedCodecTypes();
         assertTrue(areRequiredCodecTypesSupported(requiredList, supportedList));
+        for (CodecType type : requiredList) {
+            assertTrue("cannot find " + type, type.canBeFound());
+        }
     }
 
     private boolean hasCamera() {
@@ -268,80 +297,8 @@
                 && !pm.hasSystemFeature(pm.FEATURE_TELEVISION);
     }
 
-    // H263 baseline profile must be supported
-    public void testIsH263BaselineProfileSupported() {
-        if (!hasCamera()) {
-            Log.d(TAG, "not required without camera");
-            return;
-        }
-
-        int profile = CodecProfileLevel.H263ProfileBaseline;
-        assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_H263, false, profile));
-        assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_H263, true, profile));
-    }
-
-    // AVC baseline profile must be supported
-    public void testIsAVCBaselineProfileSupported() {
-        int profile = CodecProfileLevel.AVCProfileBaseline;
-        assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_AVC, false, profile));
-        assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_AVC, true, profile));
-    }
-
-    // HEVC main profile must be supported
-    public void testIsHEVCMainProfileSupported() {
-        int profile = CodecProfileLevel.HEVCProfileMain;
-        assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_HEVC, false, profile));
-    }
-
-    // MPEG4 simple profile must be supported
-    public void testIsM4VSimpleProfileSupported() {
-        if (!hasCamera()) {
-            Log.d(TAG, "not required without camera");
-            return;
-        }
-
-        int profile = CodecProfileLevel.MPEG4ProfileSimple;
-        assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_MPEG4, false, profile));
-
-        // FIXME: no support for M4v simple profile video encoder
-        // assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_MPEG4, true, profile));
-    }
-
-    /*
-     * Find whether the given codec is supported
-     */
-    private boolean checkProfileSupported(
-            String mime, boolean isEncoder, int profile) {
-        return profileIsListed(mime, isEncoder, profile) &&
-                codecCanBeFound(mime, isEncoder);
-    }
-
-    private boolean profileIsListed(
-        String mime, boolean isEncoder, int profile) {
-
-        for (MediaCodecInfo info : mRegularInfos) {
-            if (isEncoder != info.isEncoder()) {
-                continue;
-            }
-
-            for (String type : info.getSupportedTypes()) {
-                if (type.equalsIgnoreCase(mime)) {
-                    CodecCapabilities cap = info.getCapabilitiesForType(type);
-                    for (CodecProfileLevel pl : cap.profileLevels) {
-                        if (pl.profile == profile) {
-                            return true;
-                        }
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
     // Find whether the given codec can be found using MediaCodecList.find methods.
-    private boolean codecCanBeFound(String mime, boolean isEncoder) {
-        // implicit assumption that QVGA video is always valid.
-        MediaFormat format = MediaFormat.createVideoFormat(mime, 176, 144);
+    private boolean codecCanBeFound(boolean isEncoder, MediaFormat format) {
         String codecName = isEncoder
                 ? mRegularCodecs.findEncoderForFormat(format)
                 : mRegularCodecs.findDecoderForFormat(format);
@@ -380,7 +337,7 @@
             assertTrue("Unexpected number of supported types", types.length > 0);
             boolean isEncoder = info.isEncoder();
             for (int j = 0; j < types.length; ++j) {
-                supportedList.add(new CodecType(types[j], isEncoder));
+                supportedList.add(new CodecType(types[j], isEncoder, null /* sampleFormat */));
             }
         }
         return supportedList;
@@ -393,39 +350,51 @@
     private List<CodecType> getRequiredCodecTypes() {
         List<CodecType> list = new ArrayList<CodecType>(16);
 
-        // Mandatory audio codecs
+        // Mandatory audio decoders
 
         // flac decoder is not omx-based yet
-        // list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_FLAC, false));  // flac decoder
-        list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_MPEG, false));     // mp3 decoder
-        list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_VORBIS, false));   // vorbis decoder
-        list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AAC, false));      // aac decoder
-        list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_RAW, false));      // raw/pcm decoder
+        // list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_FLAC, false, 8000));
+        // list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_FLAC, false, 48000));
+        list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_MPEG, false, 8000));  // mp3
+        list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_MPEG, false, 48000)); // mp3
+        list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_VORBIS, false, 8000));
+        list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_VORBIS, false, 48000));
+        list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_AAC, false, 8000));
+        list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_AAC, false, 48000));
+        list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_RAW, false, 8000));
+        list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_RAW, false, 44100));
+        list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_OPUS, false, 48000));
+
+        // Mandatory audio encoders (for non-watch devices with camera)
+
         if (hasMicrophone() && !isWatch()) {
-            list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AAC, true));       // aac encoder
+            list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_AAC, true, 16000));
+            list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_AAC, true, 48000));
             // flac encoder is not required
-            // list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_FLAC, true));   // flac encoder
-        }
-        if (isHandheld()) {
-            list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AMR_NB, false));   // amrnb decoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AMR_NB, true));    // amrnb encoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AMR_WB, false));   // amrwb decoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AMR_WB, true));    // amrwb encoder
+            // list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_FLAC, true));  // encoder
         }
 
-        // Mandatory video codecs
+        // Mandatory audio encoders for handheld devices
+        if (isHandheld()) {
+            list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_AMR_NB, false, 8000));  // decoder
+            list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_AMR_NB, true,  8000));  // encoder
+            list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_AMR_WB, false, 16000)); // decoder
+            list.add(new AudioCodec(MediaFormat.MIMETYPE_AUDIO_AMR_WB, true,  16000)); // encoder
+        }
+
+        // Mandatory video codecs (for non-watch devices)
 
         if (!isWatch()) {
-            list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_AVC, false));    // avc decoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_AVC, true));     // avc encoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_VP8, false));    // vp8 decoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_VP8, true));     // vp8 encoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_VP9, false));    // vp9 decoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_HEVC, false));   // hevc decoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_MPEG4, false));  // m4v decoder
-            list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_H263, false));   // h263 decoder
+            list.add(new VideoCodec(MediaFormat.MIMETYPE_VIDEO_AVC, false));   // avc decoder
+            list.add(new VideoCodec(MediaFormat.MIMETYPE_VIDEO_AVC, true));    // avc encoder
+            list.add(new VideoCodec(MediaFormat.MIMETYPE_VIDEO_VP8, false));   // vp8 decoder
+            list.add(new VideoCodec(MediaFormat.MIMETYPE_VIDEO_VP8, true));    // vp8 encoder
+            list.add(new VideoCodec(MediaFormat.MIMETYPE_VIDEO_VP9, false));   // vp9 decoder
+            list.add(new VideoCodec(MediaFormat.MIMETYPE_VIDEO_HEVC, false));  // hevc decoder
+            list.add(new VideoCodec(MediaFormat.MIMETYPE_VIDEO_MPEG4, false)); // m4v decoder
+            list.add(new VideoCodec(MediaFormat.MIMETYPE_VIDEO_H263, false));  // h263 decoder
             if (hasCamera()) {
-                list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_H263, true));    // h263 encoder
+                list.add(new VideoCodec(MediaFormat.MIMETYPE_VIDEO_H263, true)); // h263 encoder
             }
         }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
index a498eac..32fbfb5 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
@@ -109,6 +109,7 @@
         String[] supported = getSupportedVideos();
         if (supported.length == 0) {
             MediaUtils.skipTest("no codec found");
+            return;
         }
 
         Random random = new Random(seed);