Merge "RECORD_SOUND must be handled by sound recorder app" into marshmallow-cts-dev
diff --git a/hostsidetests/monkey/src/com/android/cts/monkey/PackageTest.java b/hostsidetests/monkey/src/com/android/cts/monkey/PackageTest.java
index 2e675e8..373a512 100644
--- a/hostsidetests/monkey/src/com/android/cts/monkey/PackageTest.java
+++ b/hostsidetests/monkey/src/com/android/cts/monkey/PackageTest.java
@@ -20,6 +20,7 @@
 
 public class PackageTest extends AbstractMonkeyTest {
 
+    private static final int MAX_ERROR_LENGTH = 256;
     private static final Pattern ALLOW_MONKEY =
             Pattern.compile("^.*Allowing.*cmp=com\\.android\\.cts\\.monkey/\\.MonkeyActivity.*$",
                     Pattern.MULTILINE);
@@ -30,18 +31,25 @@
 
     public void testSinglePackage() throws Exception {
         String out = mDevice.executeShellCommand(MONKEY_CMD + " -v -p " + PKGS[0] + " 5000");
-        assertTrue(out, ALLOW_MONKEY.matcher(out).find());
-        assertFalse(out, ALLOW_CHIMP.matcher(out).find());
+        out = truncateError(out);
+        assertTrue("Monkey not found in: " + out, ALLOW_MONKEY.matcher(out).find());
+        assertFalse("Chimp found in: " + out, ALLOW_CHIMP.matcher(out).find());
 
         out = mDevice.executeShellCommand(MONKEY_CMD + " -v -p " + PKGS[1] + " 5000");
-        assertFalse(out, ALLOW_MONKEY.matcher(out).find());
-        assertTrue(out, ALLOW_CHIMP.matcher(out).find());
+        out = truncateError(out);
+        assertFalse("Monkey found in: " + out, ALLOW_MONKEY.matcher(out).find());
+        assertTrue("Chimp not found in: " + out, ALLOW_CHIMP.matcher(out).find());
     }
 
     public void testMultiplePackages() throws Exception {
         String out = mDevice.executeShellCommand(MONKEY_CMD + " -v -p " + PKGS[0]
                 + " -p " + PKGS[1] + " 5000");
-        assertTrue(out, ALLOW_MONKEY.matcher(out).find());
-        assertTrue(out, ALLOW_CHIMP.matcher(out).find());
+        out = truncateError(out);
+        assertTrue("Monkey not found in: " + out, ALLOW_MONKEY.matcher(out).find());
+        assertTrue("Chimp not found in: " + out, ALLOW_CHIMP.matcher(out).find());
+    }
+
+    private static final String truncateError(String input) {
+        return input.substring(0, Math.min(input.length(), MAX_ERROR_LENGTH));
     }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/Bitmap_ConfigTest.java b/tests/tests/graphics/src/android/graphics/cts/Bitmap_ConfigTest.java
index 7fc5917..e097b5a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/Bitmap_ConfigTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/Bitmap_ConfigTest.java
@@ -31,7 +31,7 @@
     public void testValues(){
         Config[] config = Config.values();
 
-        assertEquals(4, config.length);
+        assertTrue(config.length >= 4);
         assertEquals(Config.ALPHA_8, config[0]);
         assertEquals(Config.RGB_565, config[1]);
         assertEquals(Config.ARGB_4444, config[2]);
diff --git a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
index b875719..99f9759 100644
--- a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
@@ -390,6 +390,12 @@
                 return;
             }
             if (VERBOSE) Log.d(TAG, "found codec: " + codec);
+            
+            String codec_decoder = mcl.findDecoderForFormat(format);
+            if (codec_decoder == null) {
+                Log.e(TAG, "Unable to find an appropriate codec for " + format);
+                return;
+            }
 
             // Create a MediaCodec for the desired codec, then configure it as an encoder with
             // our desired properties.
@@ -411,7 +417,7 @@
 
             // Create a MediaCodec for the decoder, just based on the MIME type.  The various
             // format details will be passed through the csd-0 meta-data later on.
-            decoder = MediaCodec.createDecoderByType(mMimeType);
+            decoder = MediaCodec.createByCodecName(codec_decoder);
             if (VERBOSE) Log.d(TAG, "got decoder: " + decoder.getName());
 
             doEncodeDecodeVideoFromBuffer(encoder, colorFormat, decoder, toSurface);
@@ -472,7 +478,12 @@
 
             // Create a MediaCodec for the decoder, just based on the MIME type.  The various
             // format details will be passed through the csd-0 meta-data later on.
-            decoder = MediaCodec.createDecoderByType(mMimeType);
+            String codec_decoder = mcl.findDecoderForFormat(format);
+            if (codec_decoder == null) {
+                Log.e(TAG, "Unable to find an appropriate codec for " + format);
+                return;
+            }
+            decoder = MediaCodec.createByCodecName(codec_decoder);
             if (VERBOSE) Log.d(TAG, "got decoder: " + decoder.getName());
             decoder.configure(format, outputSurface.getSurface(), null, 0);
             decoder.start();
diff --git a/tests/tests/media/src/android/media/cts/RemoteControllerTest.java b/tests/tests/media/src/android/media/cts/RemoteControllerTest.java
new file mode 100644
index 0000000..2511889
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/RemoteControllerTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.content.Context;
+import android.media.RemoteController;
+import android.media.RemoteController.OnClientUpdateListener;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
+import android.view.KeyEvent;
+import android.util.Log;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests for {@link RemoteController}.
+ */
+public class RemoteControllerTest extends InstrumentationTestCase {
+
+    private static final Set<Integer> MEDIA_KEY_EVENT = new HashSet<Integer>();
+    static {
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MEDIA_PLAY);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MEDIA_PAUSE);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MUTE);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_HEADSETHOOK);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MEDIA_STOP);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MEDIA_NEXT);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MEDIA_REWIND);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MEDIA_RECORD);
+        MEDIA_KEY_EVENT.add(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD);
+    }
+
+    static OnClientUpdateListener listener = new OnClientUpdateListener() {
+            @Override
+            public void onClientChange(boolean clearing) {}
+            @Override
+            public void onClientPlaybackStateUpdate(int state) {}
+            @Override
+            public void onClientPlaybackStateUpdate(
+                int state, long stateChangeTimeMs, long currentPosMs, float speed) {}
+            @Override
+            public void onClientTransportControlUpdate(int transportControlFlags) {}
+            @Override
+            public void onClientMetadataUpdate(RemoteController.MetadataEditor metadataEditor) {}
+        };
+
+    private Context mContext;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getTargetContext();
+    }
+
+    private RemoteController createRemoteController() {
+        return new RemoteController(mContext, listener);
+    }
+
+    @UiThreadTest
+    public void testGetEstimatedMediaPosition() {
+        assertTrue(createRemoteController().getEstimatedMediaPosition() < 0);
+    }
+
+    @UiThreadTest
+    public void testSendMediaKeyEvent() {
+        RemoteController remoteController = createRemoteController();
+        for (Integer mediaKeyEvent : MEDIA_KEY_EVENT) {
+            assertFalse(remoteController.sendMediaKeyEvent(
+                  new KeyEvent(KeyEvent.ACTION_DOWN, mediaKeyEvent)));
+        }
+    }
+
+    @UiThreadTest
+    public void testSeekTo_negativeValues() {
+        try {
+            createRemoteController().seekTo(-1);
+            fail("timeMs must be >= 0");
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    @UiThreadTest
+    public void testSeekTo() {
+        assertTrue(createRemoteController().seekTo(0));
+    }
+
+    @UiThreadTest
+    public void testSetArtworkConfiguration() {
+        assertTrue(createRemoteController().setArtworkConfiguration(1, 1));
+    }
+
+    @UiThreadTest
+    public void testClearArtworkConfiguration() {
+        assertTrue(createRemoteController().clearArtworkConfiguration());
+    }
+
+    @UiThreadTest
+    public void testSetSynchronizationMode_unregisteredRemoteController() {
+        RemoteController remoteController = createRemoteController();
+        assertFalse(remoteController.setSynchronizationMode(
+                RemoteController.POSITION_SYNCHRONIZATION_NONE));
+        assertFalse(remoteController.setSynchronizationMode(
+                RemoteController.POSITION_SYNCHRONIZATION_CHECK));
+    }
+
+    @UiThreadTest
+    public void testEditMetadata() {
+        assertNotNull(createRemoteController().editMetadata());
+    }
+
+    @UiThreadTest
+    public void testOnClientUpdateListenerUnchanged() throws Exception {
+        Map<String, List<Method>> methodMap = new HashMap<String, List<Method>>();
+        for (Method method : listener.getClass().getDeclaredMethods()) {
+          if (!methodMap.containsKey(method.getName())) {
+              methodMap.put(method.getName(), new ArrayList<Method>());
+          }
+          methodMap.get(method.getName()).add(method);
+        }
+
+        for (Method method : OnClientUpdateListener.class.getDeclaredMethods()) {
+            assertTrue("Method not found: " + method.getName(),
+                    methodMap.containsKey(method.getName()));
+            List<Method> implementedMethodList = methodMap.get(method.getName());
+            assertTrue("Method signature changed: " + method,
+                    matchMethod(method, implementedMethodList));
+        }
+    }
+
+    private static boolean matchMethod(Method method, List<Method> potentialMatches) {
+        for (Method potentialMatch : potentialMatches) {
+            if (method.getName().equals(potentialMatch.getName()) &&
+                    method.getReturnType().equals(potentialMatch.getReturnType()) &&
+                            Arrays.equals(method.getTypeParameters(),
+                                    potentialMatch.getTypeParameters())) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/tests/tests/security/res/raw/cve_2015_1538_1.mp4 b/tests/tests/security/res/raw/cve_2015_1538_1.mp4
new file mode 100644
index 0000000..9e665ea
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1538_1.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_1538_2.mp4 b/tests/tests/security/res/raw/cve_2015_1538_2.mp4
new file mode 100644
index 0000000..e01cae6
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1538_2.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_1538_3.mp4 b/tests/tests/security/res/raw/cve_2015_1538_3.mp4
new file mode 100644
index 0000000..9838036
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1538_3.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_1538_4.mp4 b/tests/tests/security/res/raw/cve_2015_1538_4.mp4
new file mode 100644
index 0000000..14f88d8
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1538_4.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_1539.mp4 b/tests/tests/security/res/raw/cve_2015_1539.mp4
new file mode 100644
index 0000000..de871b6
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_1539.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3824.mp4 b/tests/tests/security/res/raw/cve_2015_3824.mp4
new file mode 100644
index 0000000..4ff2220
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3824.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3826.mp4 b/tests/tests/security/res/raw/cve_2015_3826.mp4
new file mode 100644
index 0000000..e0d2300
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3826.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3827.mp4 b/tests/tests/security/res/raw/cve_2015_3827.mp4
new file mode 100644
index 0000000..7b58cf9
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3827.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3828.mp4 b/tests/tests/security/res/raw/cve_2015_3828.mp4
new file mode 100644
index 0000000..033902d
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3828.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3829.mp4 b/tests/tests/security/res/raw/cve_2015_3829.mp4
new file mode 100644
index 0000000..71062bc
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3829.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_3864.mp4 b/tests/tests/security/res/raw/cve_2015_3864.mp4
new file mode 100644
index 0000000..fc0af68
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_3864.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2015_6598.mp3 b/tests/tests/security/res/raw/cve_2015_6598.mp3
new file mode 100644
index 0000000..ee709e4
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2015_6598.mp3
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
new file mode 100644
index 0000000..0f79860
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * This code was provided to AOSP by Zimperium Inc and was
+ * written by:
+ *
+ * Simone "evilsocket" Margaritelli
+ * Joshua "jduck" Drake
+ */
+package android.security.cts;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.MediaPlayer;
+import android.os.Looper;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.android.cts.security.R;
+
+
+/**
+ * Verify that the device is not vulnerable to any known Stagefright
+ * vulnerabilities.
+ */
+public class StagefrightTest extends InstrumentationTestCase {
+    static final String TAG = "StagefrightTest";
+
+    public StagefrightTest() {
+    }
+
+    public void testStagefright_cve_2015_1538_1() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1538_1);
+    }
+
+    public void testStagefright_cve_2015_1538_2() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1538_2);
+    }
+
+    public void testStagefright_cve_2015_1538_3() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1538_3);
+    }
+
+    public void testStagefright_cve_2015_1538_4() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1538_4);
+    }
+
+    public void testStagefright_cve_2015_1539() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_1539);
+    }
+
+    public void testStagefright_cve_2015_3824() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3824);
+    }
+
+    public void testStagefright_cve_2015_3826() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3826);
+    }
+
+    public void testStagefright_cve_2015_3827() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3827);
+    }
+
+    public void testStagefright_cve_2015_3828() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3828);
+    }
+
+    public void testStagefright_cve_2015_3829() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3829);
+    }
+
+    public void testStagefright_cve_2015_3864() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_3864);
+    }
+
+    public void testStagefright_cve_2015_6598() throws Exception {
+        doStagefrightTest(R.raw.cve_2015_6598);
+    }
+
+    private void doStagefrightTest(final int rid) throws Exception {
+        class MediaPlayerCrashListener
+                implements MediaPlayer.OnErrorListener,
+                    MediaPlayer.OnPreparedListener,
+                    MediaPlayer.OnCompletionListener {
+            @Override
+            public boolean onError(MediaPlayer mp, int newWhat, int extra) {
+                what = newWhat;
+                lock.lock();
+                condition.signal();
+                lock.unlock();
+
+                return true; // don't call oncompletion
+            }
+
+            @Override
+            public void onPrepared(MediaPlayer mp) {
+                mp.start();
+            }
+
+            @Override
+            public void onCompletion(MediaPlayer mp) {
+                what = 0;
+                lock.lock();
+                condition.signal();
+                lock.unlock();
+            }
+
+            public int waitForError() throws InterruptedException {
+                lock.lock();
+                condition.await();
+                lock.unlock();
+                return what;
+            }
+
+            ReentrantLock lock = new ReentrantLock();
+            Condition condition = lock.newCondition();
+            int what;
+        }
+
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+
+        Thread t = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                Looper.prepare();
+
+                MediaPlayer mp = new MediaPlayer();
+                mp.setOnErrorListener(mpcl);
+                mp.setOnPreparedListener(mpcl);
+                mp.setOnCompletionListener(mpcl);
+                try {
+                    AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
+                        .openRawResourceFd(rid);
+
+                    mp.setDataSource(fd.getFileDescriptor(),
+                                     fd.getStartOffset(),
+                                     fd.getLength());
+
+                    mp.prepareAsync();
+                } catch (Exception e) {
+                }
+
+                Looper.loop();
+                mp.release();
+            }
+        });
+
+        t.start();
+        String name = getInstrumentation().getContext().getResources().getResourceEntryName(rid);
+        String cve = name.replace("_", "-").toUpperCase();
+        assertFalse("Device *IS* vulnerable to " + cve,
+                    mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+        t.interrupt();
+    }
+}
diff --git a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
index 73fd763..061cda3 100644
--- a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
@@ -26,6 +26,7 @@
 import android.text.SpannableString;
 import android.text.method.MovementMethod;
 import android.text.method.ScrollingMovementMethod;
+import android.util.DisplayMetrics;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
@@ -738,7 +739,8 @@
             public void run() {
                 mTextView.setText("short");
                 mTextView.setSingleLine();
-                int width = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
+                DisplayMetrics dm = getActivity().getResources().getDisplayMetrics();
+                int width = (int) (LITTLE_SPACE * dm.scaledDensity);
                 getActivity().setContentView(mTextView,
                         new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
             }