Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  *
     17  * This code was provided to AOSP by Zimperium Inc and was
     18  * written by:
     19  *
     20  * Simone "evilsocket" Margaritelli
     21  * Joshua "jduck" Drake
     22  */
     23 package android.security.cts;
     24 
     25 import android.test.AndroidTestCase;
     26 import android.util.Log;
     27 import android.content.Context;
     28 import android.content.res.AssetFileDescriptor;
     29 import android.content.res.Resources;
     30 import android.graphics.Bitmap;
     31 import android.graphics.BitmapFactory;
     32 import android.graphics.SurfaceTexture;
     33 import android.media.MediaCodec;
     34 import android.media.MediaCodecInfo;
     35 import android.media.MediaCodecList;
     36 import android.media.MediaDrm;
     37 import android.media.MediaDrm.MediaDrmStateException;
     38 import android.media.MediaExtractor;
     39 import android.media.MediaFormat;
     40 import android.media.MediaMetadataRetriever;
     41 import android.media.MediaPlayer;
     42 import android.opengl.GLES20;
     43 import android.opengl.GLES11Ext;
     44 import android.os.Looper;
     45 import android.os.SystemClock;
     46 import android.platform.test.annotations.SecurityTest;
     47 import android.test.InstrumentationTestCase;
     48 import android.util.Log;
     49 import android.view.Surface;
     50 import android.webkit.cts.CtsTestServer;
     51 
     52 import java.io.BufferedInputStream;
     53 import java.io.FileInputStream;
     54 import java.io.IOException;
     55 import java.io.InputStream;
     56 import java.net.URL;
     57 import java.nio.ByteBuffer;
     58 import java.io.FileOutputStream;
     59 import java.io.File;
     60 import java.util.ArrayList;
     61 import java.util.HashMap;
     62 import java.util.UUID;
     63 import java.util.concurrent.locks.Condition;
     64 import java.util.concurrent.locks.ReentrantLock;
     65 
     66 import android.security.cts.R;
     67 
     68 
     69 /**
     70  * Verify that the device is not vulnerable to any known Stagefright
     71  * vulnerabilities.
     72  */
     73 @SecurityTest
     74 public class StagefrightTest extends InstrumentationTestCase {
     75     static final String TAG = "StagefrightTest";
     76 
     77     private final long TIMEOUT_NS = 10000000000L;  // 10 seconds.
     78 
     79     public StagefrightTest() {
     80     }
     81 
     82     /***********************************************************
     83      to prevent merge conflicts, add K tests below this comment,
     84      before any existing test methods
     85      ***********************************************************/
     86 
     87     @SecurityTest
     88     public void testStagefright_bug_36725407() throws Exception {
     89         doStagefrightTest(R.raw.bug_36725407);
     90     }
     91 
     92     @SecurityTest
     93     public void testStagefright_cve_2016_3829() throws Exception {
     94         doStagefrightTest(R.raw.cve_2016_3829);
     95     }
     96 
     97     @SecurityTest
     98     public void testStagefright_cve_2016_3828() throws Exception {
     99         doStagefrightTest(R.raw.cve_2016_3828);
    100     }
    101 
    102     @SecurityTest
    103     public void testStagefright_bug_64710074() throws Exception {
    104         doStagefrightTest(R.raw.bug_64710074);
    105     }
    106 
    107     @SecurityTest
    108     public void testStagefright_cve_2017_0643() throws Exception {
    109         doStagefrightTest(R.raw.cve_2017_0643);
    110     }
    111 
    112     @SecurityTest
    113     public void testStagefright_cve_2017_0728() throws Exception {
    114         doStagefrightTest(R.raw.cve_2017_0728);
    115     }
    116 
    117     @SecurityTest
    118     public void testStagefright_bug_62187433() throws Exception {
    119         doStagefrightTest(R.raw.bug_62187433);
    120     }
    121 
    122     @SecurityTest
    123     public void testStagefrightANR_bug_62673844() throws Exception {
    124         doStagefrightTestANR(R.raw.bug_62673844);
    125     }
    126 
    127     @SecurityTest
    128     public void testStagefright_bug_37079296() throws Exception {
    129         doStagefrightTest(R.raw.bug_37079296);
    130     }
    131 
    132     @SecurityTest
    133     public void testStagefright_bug_38342499() throws Exception {
    134         doStagefrightTest(R.raw.bug_38342499);
    135     }
    136 
    137     @SecurityTest
    138     public void testStagefright_bug_22771132() throws Exception {
    139         doStagefrightTest(R.raw.bug_22771132);
    140     }
    141 
    142     public void testStagefright_bug_21443020() throws Exception {
    143         doStagefrightTest(R.raw.bug_21443020_webm);
    144     }
    145 
    146     public void testStagefright_bug_34360591() throws Exception {
    147         doStagefrightTest(R.raw.bug_34360591);
    148     }
    149 
    150     public void testStagefright_bug_35763994() throws Exception {
    151         doStagefrightTest(R.raw.bug_35763994);
    152     }
    153 
    154     @SecurityTest
    155     public void testStagefright_bug_33137046() throws Exception {
    156         doStagefrightTest(R.raw.bug_33137046);
    157     }
    158 
    159     @SecurityTest
    160     public void testStagefright_cve_2016_2507() throws Exception {
    161         doStagefrightTest(R.raw.cve_2016_2507);
    162     }
    163 
    164     @SecurityTest
    165     public void testStagefright_bug_31647370() throws Exception {
    166         doStagefrightTest(R.raw.bug_31647370);
    167     }
    168 
    169     @SecurityTest
    170     public void testStagefright_bug_32577290() throws Exception {
    171         doStagefrightTest(R.raw.bug_32577290);
    172     }
    173 
    174     @SecurityTest
    175     public void testStagefright_cve_2015_1538_1() throws Exception {
    176         doStagefrightTest(R.raw.cve_2015_1538_1);
    177     }
    178 
    179     @SecurityTest
    180     public void testStagefright_cve_2015_1538_2() throws Exception {
    181         doStagefrightTest(R.raw.cve_2015_1538_2);
    182     }
    183 
    184     @SecurityTest
    185     public void testStagefright_cve_2015_1538_3() throws Exception {
    186         doStagefrightTest(R.raw.cve_2015_1538_3);
    187     }
    188 
    189     @SecurityTest
    190     public void testStagefright_cve_2015_1538_4() throws Exception {
    191         doStagefrightTest(R.raw.cve_2015_1538_4);
    192     }
    193 
    194     @SecurityTest
    195     public void testStagefright_cve_2015_1539() throws Exception {
    196         doStagefrightTest(R.raw.cve_2015_1539);
    197     }
    198 
    199     @SecurityTest
    200     public void testStagefright_cve_2015_3824() throws Exception {
    201         doStagefrightTest(R.raw.cve_2015_3824);
    202     }
    203 
    204     @SecurityTest
    205     public void testStagefright_cve_2015_3826() throws Exception {
    206         doStagefrightTest(R.raw.cve_2015_3826);
    207     }
    208 
    209     @SecurityTest
    210     public void testStagefright_cve_2015_3827() throws Exception {
    211         doStagefrightTest(R.raw.cve_2015_3827);
    212     }
    213 
    214     @SecurityTest
    215     public void testStagefright_cve_2015_3828() throws Exception {
    216         doStagefrightTest(R.raw.cve_2015_3828);
    217     }
    218 
    219     @SecurityTest
    220     public void testStagefright_cve_2015_3829() throws Exception {
    221         doStagefrightTest(R.raw.cve_2015_3829);
    222     }
    223 
    224     @SecurityTest
    225     public void testStagefright_cve_2015_3836() throws Exception {
    226         doStagefrightTest(R.raw.cve_2015_3836);
    227     }
    228 
    229     @SecurityTest
    230     public void testStagefright_cve_2015_3864() throws Exception {
    231         doStagefrightTest(R.raw.cve_2015_3864);
    232     }
    233 
    234     @SecurityTest
    235     public void testStagefright_cve_2015_3864_b23034759() throws Exception {
    236         doStagefrightTest(R.raw.cve_2015_3864_b23034759);
    237     }
    238 
    239     @SecurityTest
    240     public void testStagefright_cve_2015_6598() throws Exception {
    241         doStagefrightTest(R.raw.cve_2015_6598);
    242     }
    243 
    244     @SecurityTest
    245     public void testStagefright_cve_2016_6766() throws Exception {
    246         doStagefrightTest(R.raw.cve_2016_6766);
    247     }
    248 
    249     @SecurityTest
    250     public void testStagefright_bug_26366256() throws Exception {
    251         doStagefrightTest(R.raw.bug_26366256);
    252     }
    253 
    254     @SecurityTest
    255     public void testStagefright_cve_2016_2429_b_27211885() throws Exception {
    256         doStagefrightTest(R.raw.cve_2016_2429_b_27211885);
    257     }
    258 
    259     @SecurityTest
    260     public void testStagefright_bug_34031018() throws Exception {
    261         doStagefrightTest(R.raw.bug_34031018_32bit);
    262         doStagefrightTest(R.raw.bug_34031018_64bit);
    263     }
    264 
    265     /***********************************************************
    266      to prevent merge conflicts, add L tests below this comment,
    267      before any existing test methods
    268      ***********************************************************/
    269 
    270     @SecurityTest
    271     public void testStagefright_bug_65123471() throws Exception {
    272         doStagefrightTest(R.raw.bug_65123471);
    273     }
    274 
    275     @SecurityTest
    276     public void testStagefright_bug_72165027() throws Exception {
    277         doStagefrightTest(R.raw.bug_72165027);
    278     }
    279 
    280     @SecurityTest
    281     public void testStagefright_bug_65483665() throws Exception {
    282         doStagefrightTest(R.raw.bug_65483665);
    283     }
    284 
    285     @SecurityTest
    286     public void testStagefright_cve_2017_0852_b_62815506() throws Exception {
    287         doStagefrightTest(R.raw.cve_2017_0852_b_62815506);
    288     }
    289 
    290     @SecurityTest
    291     public void testStagefright_cve_2017_13229() throws Exception {
    292         doStagefrightTest(R.raw.cve_2017_13229);
    293     }
    294 
    295     @SecurityTest
    296     public void testStagefright_cve_2017_0763() throws Exception {
    297         doStagefrightTest(R.raw.cve_2017_0763);
    298     }
    299 
    300     /***********************************************************
    301      to prevent merge conflicts, add M tests below this comment,
    302      before any existing test methods
    303      ***********************************************************/
    304 
    305     @SecurityTest
    306     public void testStagefright_bug_68953854() throws Exception {
    307         doStagefrightTest(R.raw.bug_68953854, 1 * 60 * 1000);
    308     }
    309 
    310     @SecurityTest
    311     public void testStagefright_bug_38448381() throws Exception {
    312         doStagefrightTest(R.raw.bug_38448381);
    313     }
    314 
    315     @SecurityTest
    316     public void testStagefright_cve_2016_3821() throws Exception {
    317         doStagefrightTest(R.raw.cve_2016_3821);
    318     }
    319 
    320     @SecurityTest
    321     public void testStagefright_bug_70897454() throws Exception {
    322         doStagefrightTestRawBlob(R.raw.b70897454_avc, "video/avc", 320, 420);
    323     }
    324 
    325     @SecurityTest
    326     public void testStagefright_bug_38115076() throws Exception {
    327         doStagefrightTest(R.raw.bug_38115076);
    328     }
    329 
    330     @SecurityTest
    331     public void testStagefright_bug_34618607() throws Exception {
    332         doStagefrightTest(R.raw.bug_34618607);
    333     }
    334 
    335     @SecurityTest
    336     public void testStagefright_bug_69478425() throws Exception {
    337         doStagefrightTest(R.raw.bug_69478425);
    338     }
    339 
    340     @SecurityTest
    341     public void testStagefright_bug_65735716() throws Exception {
    342         doStagefrightTestRawBlob(R.raw.bug_65735716_avc, "video/avc", 320, 240);
    343     }
    344 
    345     @SecurityTest
    346     public void testStagefright_bug_65717533() throws Exception {
    347         doStagefrightTest(R.raw.bug_65717533_header_corrupt);
    348     }
    349 
    350     @SecurityTest
    351     public void testStagefright_bug_38239864() throws Exception {
    352         doStagefrightTest(R.raw.bug_38239864, (4 * 60 * 1000));
    353     }
    354 
    355     @SecurityTest
    356     public void testStagefright_cve_2017_0600() throws Exception {
    357         doStagefrightTest(R.raw.cve_2017_0600);
    358     }
    359 
    360     @SecurityTest
    361     public void testBug_38014992() throws Exception {
    362         int[] frameSizes = getFrameSizes(R.raw.bug_38014992_framelen);
    363         doStagefrightTestRawBlob(R.raw.bug_38014992_avc, "video/avc", 640, 480, frameSizes);
    364     }
    365 
    366     @SecurityTest
    367     public void testBug_35584425() throws Exception {
    368         int[] frameSizes = getFrameSizes(R.raw.bug_35584425_framelen);
    369         doStagefrightTestRawBlob(R.raw.bug_35584425_avc, "video/avc", 352, 288, frameSizes);
    370     }
    371 
    372     @SecurityTest
    373     public void testBug_31092462() throws Exception {
    374         int[] frameSizes = getFrameSizes(R.raw.bug_31092462_framelen);
    375         doStagefrightTestRawBlob(R.raw.bug_31092462_avc, "video/avc", 1280, 1024, frameSizes);
    376     }
    377 
    378     @SecurityTest
    379     public void testBug_34097866() throws Exception {
    380         int[] frameSizes = getFrameSizes(R.raw.bug_34097866_frame_len);
    381         doStagefrightTestRawBlob(R.raw.bug_34097866_avc, "video/avc", 352, 288, frameSizes);
    382     }
    383 
    384     @SecurityTest
    385     public void testBug_33862021() throws Exception {
    386         int[] frameSizes = getFrameSizes(R.raw.bug_33862021_frame_len);
    387         doStagefrightTestRawBlob(R.raw.bug_33862021_hevc, "video/hevc", 160, 96, frameSizes);
    388     }
    389 
    390     @SecurityTest
    391     public void testBug_33387820() throws Exception {
    392         int[] frameSizes = {45, 3202, 430, 2526};
    393         doStagefrightTestRawBlob(R.raw.bug_33387820_avc, "video/avc", 320, 240, frameSizes);
    394     }
    395 
    396     @SecurityTest
    397     public void testBug_37008096() throws Exception {
    398         int[] frameSizes = {245, 12, 33, 140, 164};
    399         doStagefrightTestRawBlob(R.raw.bug_37008096_avc, "video/avc", 320, 240, frameSizes);
    400     }
    401 
    402     @SecurityTest
    403     public void testStagefright_bug_34231163() throws Exception {
    404         int[] frameSizes = {22, 357, 217, 293, 175};
    405         doStagefrightTestRawBlob(R.raw.bug_34231163_mpeg2, "video/mpeg2", 320, 240, frameSizes);
    406     }
    407 
    408     @SecurityTest
    409     public void testStagefright_bug_33933140() throws Exception {
    410         int[] frameSizes = getFrameSizes(R.raw.bug_33933140_framelen);
    411         doStagefrightTestRawBlob(R.raw.bug_33933140_avc, "video/avc", 320, 240, frameSizes);
    412     }
    413 
    414     @SecurityTest
    415     public void testStagefright_bug_34097915() throws Exception {
    416         int[] frameSizes = {4140, 593, 0, 15495};
    417         doStagefrightTestRawBlob(R.raw.bug_34097915_avc, "video/avc", 320, 240, frameSizes);
    418     }
    419 
    420     @SecurityTest
    421     public void testStagefright_bug_34097213() throws Exception {
    422         int[] frameSizes = {2571, 210, 33858};
    423         doStagefrightTestRawBlob(R.raw.bug_34097213_avc, "video/avc", 320, 240, frameSizes);
    424     }
    425 
    426     @SecurityTest
    427     public void testBug_28816956() throws Exception {
    428         int[] frameSizes = getFrameSizes(R.raw.bug_28816956_framelen);
    429         doStagefrightTestRawBlob(R.raw.bug_28816956_hevc, "video/hevc", 352, 288, frameSizes);
    430     }
    431 
    432     @SecurityTest
    433     public void testBug_33818500() throws Exception {
    434         int[] frameSizes = getFrameSizes(R.raw.bug_33818500_framelen);
    435         doStagefrightTestRawBlob(R.raw.bug_33818500_avc, "video/avc", 64, 32, frameSizes);
    436     }
    437 
    438     @SecurityTest
    439     public void testBug_64784973() throws Exception {
    440         int[] frameSizes = getFrameSizes(R.raw.bug_64784973_framelen);
    441         doStagefrightTestRawBlob(R.raw.bug_64784973_hevc, "video/hevc", 1280, 720, frameSizes);
    442     }
    443 
    444     @SecurityTest
    445     public void testBug_34231231() throws Exception {
    446         int[] frameSizes = getFrameSizes(R.raw.bug_34231231_framelen);
    447         doStagefrightTestRawBlob(R.raw.bug_34231231_mpeg2, "video/mpeg2", 352, 288, frameSizes);
    448     }
    449 
    450     @SecurityTest
    451     public void testBug_63045918() throws Exception {
    452         int[] frameSizes = getFrameSizes(R.raw.bug_63045918_framelen);
    453         doStagefrightTestRawBlob(R.raw.bug_63045918_hevc, "video/hevc", 352, 288, frameSizes);
    454     }
    455 
    456     @SecurityTest
    457     public void testBug_33298089() throws Exception {
    458         int[] frameSizes = {3247, 430, 221, 2305};
    459         doStagefrightTestRawBlob(R.raw.bug_33298089_avc, "video/avc", 32, 64, frameSizes);
    460     }
    461 
    462     @SecurityTest
    463     public void testStagefright_cve_2017_0599() throws Exception {
    464         doStagefrightTest(R.raw.cve_2017_0599);
    465     }
    466 
    467     @SecurityTest
    468     public void testStagefright_bug_36492741() throws Exception {
    469         doStagefrightTest(R.raw.bug_36492741);
    470     }
    471 
    472     @SecurityTest
    473     public void testStagefright_bug_38487564() throws Exception {
    474         doStagefrightTest(R.raw.bug_38487564, (4 * 60 * 1000));
    475     }
    476 
    477     @SecurityTest
    478     public void testStagefright_bug_37237396() throws Exception {
    479         doStagefrightTest(R.raw.bug_37237396);
    480     }
    481 
    482     @SecurityTest
    483     public void testStagefright_cve_2016_0842() throws Exception {
    484         doStagefrightTest(R.raw.cve_2016_0842);
    485     }
    486 
    487     @SecurityTest
    488     public void testStagefright_bug_63121644() throws Exception {
    489         doStagefrightTest(R.raw.bug_63121644);
    490     }
    491 
    492     @SecurityTest
    493     public void testStagefright_cve_2016_6712() throws Exception {
    494         doStagefrightTest(R.raw.cve_2016_6712);
    495     }
    496 
    497     @SecurityTest
    498     public void testStagefright_bug_34097231() throws Exception {
    499         doStagefrightTestRawBlob(R.raw.bug_34097231_avc, "video/avc", 320, 240);
    500     }
    501 
    502     @SecurityTest
    503     public void testStagefright_bug_34097672() throws Exception {
    504         doStagefrightTest(R.raw.bug_34097672);
    505     }
    506 
    507 
    508     @SecurityTest
    509     public void testStagefright_bug_33751193() throws Exception {
    510         doStagefrightTestRawBlob(R.raw.bug_33751193_avc, "video/avc", 320, 240);
    511     }
    512 
    513     @SecurityTest
    514     public void testBug_36993291() throws Exception {
    515         doStagefrightTestRawBlob(R.raw.bug_36993291_avc, "video/avc", 320, 240);
    516     }
    517 
    518     @SecurityTest
    519     public void testStagefright_bug_33818508() throws Exception {
    520         doStagefrightTest(R.raw.bug_33818508);
    521     }
    522 
    523     @SecurityTest
    524     public void testStagefright_bug_32873375() throws Exception {
    525         doStagefrightTest(R.raw.bug_32873375);
    526     }
    527 
    528     @SecurityTest
    529     public void testStagefright_bug_63522067() throws Exception {
    530         doStagefrightTestRawBlob(R.raw.bug_63522067_1_hevc, "video/hevc", 320, 420);
    531         doStagefrightTestRawBlob(R.raw.bug_63522067_2_hevc, "video/hevc", 320, 420);
    532         doStagefrightTestRawBlob(R.raw.bug_63522067_3_hevc, "video/hevc", 320, 420);
    533         doStagefrightTestRawBlob(R.raw.bug_63522067_4_hevc, "video/hevc", 320, 420);
    534     }
    535 
    536     @SecurityTest
    537     public void testStagefright_bug_25765591() throws Exception {
    538         doStagefrightTest(R.raw.bug_25765591);
    539     }
    540 
    541     @SecurityTest
    542     public void testStagefright_bug_62673179() throws Exception {
    543         doStagefrightTest(R.raw.bug_62673179_ts, (4 * 60 * 1000));
    544     }
    545 
    546     @SecurityTest
    547     public void testStagefright_bug_69269702() throws Exception {
    548         doStagefrightTest(R.raw.bug_69269702);
    549     }
    550 
    551     @SecurityTest
    552     public void testStagefright_cve_2015_3867() throws Exception {
    553         doStagefrightTest(R.raw.cve_2015_3867);
    554     }
    555 
    556     @SecurityTest
    557     public void testStagefright_bug_65398821() throws Exception {
    558         doStagefrightTest(R.raw.bug_65398821, ( 4 * 60 * 1000 ) );
    559     }
    560 
    561     @SecurityTest
    562     public void testStagefright_cve_2015_3869() throws Exception {
    563         doStagefrightTest(R.raw.cve_2015_3869);
    564     }
    565 
    566     @SecurityTest
    567     public void testStagefright_bug_23452792() throws Exception {
    568         doStagefrightTest(R.raw.bug_23452792);
    569     }
    570 
    571     @SecurityTest
    572     public void testStagefright_cve_2016_3820() throws Exception {
    573         doStagefrightTest(R.raw.cve_2016_3820);
    574     }
    575 
    576     @SecurityTest
    577     public void testStagefright_cve_2016_3741() throws Exception {
    578         doStagefrightTest(R.raw.cve_2016_3741);
    579     }
    580 
    581     @SecurityTest
    582     public void testStagefright_cve_2016_2506() throws Exception {
    583         doStagefrightTest(R.raw.cve_2016_2506);
    584     }
    585 
    586     @SecurityTest
    587     public void testStagefright_cve_2016_2428() throws Exception {
    588         doStagefrightTest(R.raw.cve_2016_2428);
    589     }
    590 
    591     @SecurityTest
    592     public void testStagefright_bug_36592202() throws Exception {
    593         Resources resources = getInstrumentation().getContext().getResources();
    594         AssetFileDescriptor fd = resources.openRawResourceFd(R.raw.bug_36592202);
    595         int page_size = 25627;
    596         byte [] blob = new byte[page_size];
    597 
    598         // 127 bytes read and  25500 zeros constitute one Ogg page
    599         FileInputStream fis = fd.createInputStream();
    600         int numRead = fis.read(blob);
    601         fis.close();
    602 
    603         // Creating temp file
    604         final File tempFile = File.createTempFile("poc_tmp", ".ogg", null);
    605 
    606         try {
    607             final FileOutputStream tempFos = new FileOutputStream(tempFile.getAbsolutePath());
    608             int bytesWritten = 0;
    609             // Repeat data till size is ~1 GB
    610             for (int i = 0; i < 50000; i++) {
    611                 tempFos.write(blob);
    612                 bytesWritten += page_size;
    613             }
    614             tempFos.close();
    615 
    616             final int fileSize = bytesWritten;
    617             int timeout = (10 * 60 * 1000);
    618 
    619             runWithTimeout(new Runnable() {
    620                 @Override
    621                 public void run() {
    622                     try {
    623                         doStagefrightTestMediaCodec(tempFile.getAbsolutePath());
    624                     } catch (Exception | AssertionError  e) {
    625                         if (!tempFile.delete()) {
    626                             Log.e(TAG, "Failed to delete temporary PoC file");
    627                         }
    628                         fail("Operation was not successful");
    629                     }
    630                 }
    631             }, timeout);
    632         } catch (Exception e) {
    633             fail("Failed to test b/36592202");
    634         } finally {
    635             if (!tempFile.delete()) {
    636                 Log.e(TAG, "Failed to delete temporary PoC file");
    637             }
    638         }
    639     }
    640 
    641     @SecurityTest
    642     public void testStagefright_bug_30822755() throws Exception {
    643         doStagefrightTest(R.raw.bug_30822755);
    644     }
    645 
    646     @SecurityTest
    647     public void testStagefright_bug_32322258() throws Exception {
    648         doStagefrightTest(R.raw.bug_32322258);
    649     }
    650 
    651     @SecurityTest
    652     public void testStagefright_bug_37710346() throws Exception {
    653         UUID CLEARKEY_SCHEME_UUID = new UUID(0x1077efecc0b24d02L, 0xace33c1e52e2fb4bL);
    654 
    655         String drmInitString = "0000003470737368" +
    656                                "01000000" +
    657                                "1077efecc0b24d02" +
    658                                "ace33c1e52e2fb4b" +
    659                                "10000001" +
    660                                "60061e017e477e87" +
    661                                "7e57d00d1ed00d1e" +
    662                                "00000000";
    663         int len = drmInitString.length();
    664         byte[] drmInitData = new byte[len / 2];
    665         for (int i = 0; i < len; i += 2) {
    666             drmInitData[i / 2] = (byte) ((Character.digit(drmInitString.charAt(i), 16) << 4) +
    667                 Character.digit(drmInitString.charAt(i + 1), 16));
    668         }
    669 
    670         try {
    671             MediaDrm drm = new MediaDrm(CLEARKEY_SCHEME_UUID);
    672             byte[] sessionId;
    673             String initDataType = "video/mp4";
    674 
    675             sessionId = drm.openSession();
    676             MediaDrm.KeyRequest drmRequest = drm.getKeyRequest(sessionId, drmInitData,
    677                 initDataType, MediaDrm.KEY_TYPE_STREAMING, null);
    678         } catch (Exception e) {
    679             if (!(e instanceof MediaDrmStateException))
    680                 fail("media drm server died");
    681         }
    682     }
    683 
    684     @SecurityTest
    685     public void testStagefright_cve_2015_3873_b_23248776() throws Exception {
    686         doStagefrightTest(R.raw.cve_2015_3873_b_23248776);
    687     }
    688 
    689     @SecurityTest
    690     public void testStagefright_bug_35472997() throws Exception {
    691         doStagefrightTest(R.raw.bug_35472997);
    692     }
    693 
    694     @SecurityTest
    695     public void testStagefright_cve_2015_3873_b_20718524() throws Exception {
    696         doStagefrightTest(R.raw.cve_2015_3873_b_20718524);
    697     }
    698 
    699     @SecurityTest
    700     public void testStagefright_bug_34896431() throws Exception {
    701         doStagefrightTest(R.raw.bug_34896431);
    702     }
    703 
    704     @SecurityTest
    705     public void testStagefright_cve_2015_3862_b_22954006() throws Exception {
    706         doStagefrightTest(R.raw.cve_2015_3862_b_22954006);
    707     }
    708 
    709     @SecurityTest
    710     public void testStagefright_cve_2015_3867_b_23213430() throws Exception {
    711         doStagefrightTest(R.raw.cve_2015_3867_b_23213430);
    712     }
    713 
    714     @SecurityTest
    715     public void testStagefright_cve_2015_3873_b_21814993() throws Exception {
    716         doStagefrightTest(R.raw.cve_2015_3873_b_21814993);
    717     }
    718 
    719     @SecurityTest
    720     public void testStagefright_bug_25812590() throws Exception {
    721         doStagefrightTest(R.raw.bug_25812590);
    722     }
    723 
    724     public void testStagefright_cve_2015_6600() throws Exception {
    725         doStagefrightTest(R.raw.cve_2015_6600);
    726     }
    727 
    728     public void testStagefright_cve_2015_6603() throws Exception {
    729         doStagefrightTest(R.raw.cve_2015_6603);
    730     }
    731 
    732     public void testStagefright_cve_2015_6604() throws Exception {
    733         doStagefrightTest(R.raw.cve_2015_6604);
    734     }
    735 
    736     @SecurityTest
    737     public void testStagefright_bug_24157524() throws Exception {
    738         doStagefrightTest(R.raw.bug_24157524);
    739     }
    740 
    741     @SecurityTest
    742     public void testStagefright_cve_2015_3871() throws Exception {
    743         doStagefrightTest(R.raw.cve_2015_3871);
    744     }
    745 
    746     public void testStagefright_bug_26070014() throws Exception {
    747         doStagefrightTest(R.raw.bug_26070014);
    748     }
    749 
    750     public void testStagefright_bug_32915871() throws Exception {
    751         doStagefrightTest(R.raw.bug_32915871);
    752     }
    753 
    754     @SecurityTest
    755     public void testStagefright_bug_28333006() throws Exception {
    756         doStagefrightTest(R.raw.bug_28333006);
    757     }
    758 
    759     @SecurityTest
    760     public void testStagefright_bug_14388161() throws Exception {
    761         doStagefrightTestMediaPlayer(R.raw.bug_14388161);
    762     }
    763 
    764     @SecurityTest
    765     public void testStagefright_cve_2016_3755() throws Exception {
    766         doStagefrightTest(R.raw.cve_2016_3755);
    767     }
    768 
    769     @SecurityTest
    770     public void testStagefright_cve_2016_3878_b_29493002() throws Exception {
    771         doStagefrightTest(R.raw.cve_2016_3878_b_29493002);
    772     }
    773 
    774     @SecurityTest
    775     public void testStagefright_cve_2015_6608_b_23680780() throws Exception {
    776         doStagefrightTest(R.raw.cve_2015_6608_b_23680780);
    777     }
    778 
    779     @SecurityTest
    780     public void testStagefright_bug_27855419_CVE_2016_2463() throws Exception {
    781         doStagefrightTest(R.raw.bug_27855419);
    782     }
    783 
    784     public void testStagefright_bug_19779574() throws Exception {
    785         doStagefrightTest(R.raw.bug_19779574);
    786     }
    787 
    788     /***********************************************************
    789      to prevent merge conflicts, add N tests below this comment,
    790      before any existing test methods
    791      ***********************************************************/
    792 
    793     @SecurityTest
    794     public void testStagefright_cve_2017_0474() throws Exception {
    795         doStagefrightTest(R.raw.cve_2017_0474, 120000);
    796     }
    797 
    798     @SecurityTest
    799     public void testStagefright_cve_2017_0765() throws Exception {
    800         doStagefrightTest(R.raw.cve_2017_0765);
    801     }
    802 
    803     @SecurityTest
    804     public void testStagefright_cve_2017_13276() throws Exception {
    805         doStagefrightTest(R.raw.cve_2017_13276);
    806     }
    807 
    808     @SecurityTest
    809     public void testStagefright_cve_2016_6764() throws Exception {
    810         doStagefrightTest(R.raw.cve_2016_6764);
    811     }
    812 
    813     @SecurityTest
    814     public void testStagefright_cve_2017_13214() throws Exception {
    815         doStagefrightTest(R.raw.cve_2017_13214);
    816     }
    817 
    818     @SecurityTest
    819     public void testStagefright_bug_35467107() throws Exception {
    820         doStagefrightTest(R.raw.bug_35467107);
    821     }
    822 
    823     /***********************************************************
    824      to prevent merge conflicts, add O tests below this comment,
    825      before any existing test methods
    826      ***********************************************************/
    827 
    828     @SecurityTest
    829     public void testBug_67737022() throws Exception {
    830         doStagefrightTest(R.raw.bug_67737022);
    831     }
    832 
    833     @SecurityTest
    834     public void testStagefright_bug_37093318() throws Exception {
    835         doStagefrightTest(R.raw.bug_37093318, (4 * 60 * 1000));
    836     }
    837 
    838     @SecurityTest
    839     public void testStagefright_bug_73172046() throws Exception {
    840         doStagefrightTest(R.raw.bug_73172046);
    841 
    842         Bitmap bitmap = BitmapFactory.decodeResource(
    843                 getInstrumentation().getContext().getResources(), R.raw.bug_73172046);
    844         // OK if the decoding failed, but shouldn't cause crashes
    845         if (bitmap != null) {
    846             bitmap.recycle();
    847         }
    848     }
    849 
    850     @SecurityTest
    851     public void testStagefright_cve_2016_0824() throws Exception {
    852         doStagefrightTest(R.raw.cve_2016_0824);
    853     }
    854 
    855     @SecurityTest
    856     public void testStagefright_cve_2016_0815() throws Exception {
    857         doStagefrightTest(R.raw.cve_2016_0815);
    858     }
    859 
    860     @SecurityTest
    861     public void testStagefright_cve_2016_2454() throws Exception {
    862         doStagefrightTest(R.raw.cve_2016_2454);
    863     }
    864 
    865     @SecurityTest
    866     public void testStagefright_cve_2016_6765() throws Exception {
    867         doStagefrightTest(R.raw.cve_2016_6765);
    868     }
    869 
    870     @SecurityTest
    871     public void testStagefright_cve_2016_2508() throws Exception {
    872         doStagefrightTest(R.raw.cve_2016_2508);
    873     }
    874 
    875     @SecurityTest
    876     public void testStagefright_cve_2016_6699() throws Exception {
    877         doStagefrightTest(R.raw.cve_2016_6699);
    878     }
    879 
    880     private void doStagefrightTest(final int rid) throws Exception {
    881         doStagefrightTestMediaPlayer(rid);
    882         doStagefrightTestMediaCodec(rid);
    883         doStagefrightTestMediaMetadataRetriever(rid);
    884 
    885         Context context = getInstrumentation().getContext();
    886         Resources resources =  context.getResources();
    887         CtsTestServer server = new CtsTestServer(context);
    888         String rname = resources.getResourceEntryName(rid);
    889         String url = server.getAssetUrl("raw/" + rname);
    890         verifyServer(rid, url);
    891         doStagefrightTestMediaPlayer(url);
    892         doStagefrightTestMediaCodec(url);
    893         doStagefrightTestMediaMetadataRetriever(url);
    894         server.shutdown();
    895     }
    896 
    897     // verify that CtsTestServer is functional by retrieving the asset
    898     // and comparing it to the resource
    899     private void verifyServer(final int rid, final String uri) throws Exception {
    900         Log.i(TAG, "checking server");
    901         URL url = new URL(uri);
    902         InputStream in1 = new BufferedInputStream(url.openStream());
    903 
    904         AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
    905                         .openRawResourceFd(rid);
    906         InputStream in2 = new BufferedInputStream(fd.createInputStream());
    907 
    908         while (true) {
    909             int b1 = in1.read();
    910             int b2 = in2.read();
    911             assertEquals("CtsTestServer fail", b1, b2);
    912             if (b1 < 0) {
    913                 break;
    914             }
    915         }
    916 
    917         in1.close();
    918         in2.close();
    919         Log.i(TAG, "checked server");
    920     }
    921 
    922     private void doStagefrightTest(final int rid, int timeout) throws Exception {
    923         runWithTimeout(new Runnable() {
    924             @Override
    925             public void run() {
    926                 try {
    927                   doStagefrightTest(rid);
    928                 } catch (Exception e) {
    929                   fail(e.toString());
    930                 }
    931             }
    932         }, timeout);
    933     }
    934 
    935     private void doStagefrightTestANR(final int rid) throws Exception {
    936         doStagefrightTestMediaPlayerANR(rid, null);
    937     }
    938 
    939     private Surface getDummySurface() {
    940         int[] textures = new int[1];
    941         GLES20.glGenTextures(1, textures, 0);
    942         GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
    943         GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
    944                 GLES20.GL_TEXTURE_MIN_FILTER,
    945                 GLES20.GL_NEAREST);
    946         GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
    947                 GLES20.GL_TEXTURE_MAG_FILTER,
    948                 GLES20.GL_LINEAR);
    949         GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
    950                 GLES20.GL_TEXTURE_WRAP_S,
    951                 GLES20.GL_CLAMP_TO_EDGE);
    952         GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
    953                 GLES20.GL_TEXTURE_WRAP_T,
    954                 GLES20.GL_CLAMP_TO_EDGE);
    955         SurfaceTexture surfaceTex = new SurfaceTexture(textures[0]);
    956         surfaceTex.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
    957             @Override
    958             public void onFrameAvailable(SurfaceTexture surfaceTexture) {
    959                 Log.i(TAG, "new frame available");
    960             }
    961         });
    962         return new Surface(surfaceTex);
    963     }
    964 
    965     class MediaPlayerCrashListener
    966     implements MediaPlayer.OnErrorListener,
    967         MediaPlayer.OnPreparedListener,
    968         MediaPlayer.OnCompletionListener {
    969         @Override
    970         public boolean onError(MediaPlayer mp, int newWhat, int extra) {
    971             Log.i(TAG, "error: " + newWhat + "/" + extra);
    972             // don't overwrite a more severe error with a less severe one
    973             if (what != MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
    974                 what = newWhat;
    975             }
    976             lock.lock();
    977             condition.signal();
    978             lock.unlock();
    979 
    980             return true; // don't call oncompletion
    981         }
    982 
    983         @Override
    984         public void onPrepared(MediaPlayer mp) {
    985             mp.start();
    986         }
    987 
    988         @Override
    989         public void onCompletion(MediaPlayer mp) {
    990             // preserve error condition, if any
    991             lock.lock();
    992             completed = true;
    993             condition.signal();
    994             lock.unlock();
    995         }
    996 
    997         public int waitForError() throws InterruptedException {
    998             lock.lock();
    999             if (condition.awaitNanos(TIMEOUT_NS) <= 0) {
   1000                 Log.d(TAG, "timed out on waiting for error");
   1001             }
   1002             lock.unlock();
   1003             if (what != 0) {
   1004                 // Sometimes mediaserver signals a decoding error first, and *then* crashes
   1005                 // due to additional in-flight buffers being processed, so wait a little
   1006                 // and see if more errors show up.
   1007                 SystemClock.sleep(1000);
   1008             }
   1009             return what;
   1010         }
   1011 
   1012         public boolean waitForErrorOrCompletion() throws InterruptedException {
   1013             lock.lock();
   1014             if (condition.awaitNanos(TIMEOUT_NS) <= 0) {
   1015                 Log.d(TAG, "timed out on waiting for error or completion");
   1016             }
   1017             lock.unlock();
   1018             return (what != 0 && what != MediaPlayer.MEDIA_ERROR_SERVER_DIED) || completed;
   1019         }
   1020 
   1021         ReentrantLock lock = new ReentrantLock();
   1022         Condition condition = lock.newCondition();
   1023         int what;
   1024         boolean completed = false;
   1025     }
   1026 
   1027     class LooperThread extends Thread {
   1028         private Looper mLooper;
   1029 
   1030         LooperThread(Runnable runner) {
   1031             super(runner);
   1032         }
   1033 
   1034         @Override
   1035         public void run() {
   1036             Looper.prepare();
   1037             mLooper = Looper.myLooper();
   1038             super.run();
   1039         }
   1040 
   1041         public void stopLooper() {
   1042             mLooper.quitSafely();
   1043         }
   1044     }
   1045 
   1046     private void doStagefrightTestMediaPlayer(final int rid) throws Exception {
   1047         doStagefrightTestMediaPlayer(rid, null);
   1048     }
   1049 
   1050     private void doStagefrightTestMediaPlayer(final String url) throws Exception {
   1051         doStagefrightTestMediaPlayer(-1, url);
   1052     }
   1053 
   1054     private void closeQuietly(AutoCloseable closeable) {
   1055         if (closeable != null) {
   1056             try {
   1057                 closeable.close();
   1058             } catch (RuntimeException rethrown) {
   1059                 throw rethrown;
   1060             } catch (Exception ignored) {
   1061             }
   1062         }
   1063     }
   1064 
   1065     private void doStagefrightTestMediaPlayer(final int rid, final String uri) throws Exception {
   1066 
   1067         String name = uri != null ? uri :
   1068             getInstrumentation().getContext().getResources().getResourceEntryName(rid);
   1069         Log.i(TAG, "start mediaplayer test for: " + name);
   1070 
   1071         final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
   1072 
   1073         LooperThread t = new LooperThread(new Runnable() {
   1074             @Override
   1075             public void run() {
   1076 
   1077                 MediaPlayer mp = new MediaPlayer();
   1078                 mp.setOnErrorListener(mpcl);
   1079                 mp.setOnPreparedListener(mpcl);
   1080                 mp.setOnCompletionListener(mpcl);
   1081                 Surface surface = getDummySurface();
   1082                 mp.setSurface(surface);
   1083                 AssetFileDescriptor fd = null;
   1084                 try {
   1085                     if (uri == null) {
   1086                         fd = getInstrumentation().getContext().getResources()
   1087                                 .openRawResourceFd(rid);
   1088 
   1089                         mp.setDataSource(fd.getFileDescriptor(),
   1090                                          fd.getStartOffset(),
   1091                                          fd.getLength());
   1092 
   1093                     } else {
   1094                         mp.setDataSource(uri);
   1095                     }
   1096                     mp.prepareAsync();
   1097                 } catch (Exception e) {
   1098                 } finally {
   1099                     closeQuietly(fd);
   1100                 }
   1101 
   1102                 Looper.loop();
   1103                 mp.release();
   1104             }
   1105         });
   1106 
   1107         t.start();
   1108         String cve = name.replace("_", "-").toUpperCase();
   1109         assertFalse("Device *IS* vulnerable to " + cve,
   1110                     mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
   1111         t.stopLooper();
   1112         t.join(); // wait for thread to exit so we're sure the player was released
   1113     }
   1114 
   1115     private void doStagefrightTestMediaCodec(final int rid) throws Exception {
   1116         doStagefrightTestMediaCodec(rid, null);
   1117     }
   1118 
   1119     private void doStagefrightTestMediaCodec(final String url) throws Exception {
   1120         doStagefrightTestMediaCodec(-1, url);
   1121     }
   1122 
   1123     private void doStagefrightTestMediaCodec(final int rid, final String url) throws Exception {
   1124 
   1125         final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
   1126 
   1127         LooperThread thr = new LooperThread(new Runnable() {
   1128             @Override
   1129             public void run() {
   1130 
   1131                 MediaPlayer mp = new MediaPlayer();
   1132                 mp.setOnErrorListener(mpcl);
   1133                 try {
   1134                     AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
   1135                         .openRawResourceFd(R.raw.good);
   1136 
   1137                     // the onErrorListener won't receive MEDIA_ERROR_SERVER_DIED until
   1138                     // setDataSource has been called
   1139                     mp.setDataSource(fd.getFileDescriptor(),
   1140                                      fd.getStartOffset(),
   1141                                      fd.getLength());
   1142                     fd.close();
   1143                 } catch (Exception e) {
   1144                     // this is a known-good file, so no failure should occur
   1145                     fail("setDataSource of known-good file failed");
   1146                 }
   1147 
   1148                 synchronized(mpcl) {
   1149                     mpcl.notify();
   1150                 }
   1151                 Looper.loop();
   1152                 mp.release();
   1153             }
   1154         });
   1155         thr.start();
   1156         // wait until the thread has initialized the MediaPlayer
   1157         synchronized(mpcl) {
   1158             mpcl.wait();
   1159         }
   1160 
   1161         Resources resources =  getInstrumentation().getContext().getResources();
   1162         MediaExtractor ex = new MediaExtractor();
   1163         if (url == null) {
   1164             AssetFileDescriptor fd = resources.openRawResourceFd(rid);
   1165             try {
   1166                 ex.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
   1167             } catch (IOException e) {
   1168                 // ignore
   1169             } finally {
   1170                 closeQuietly(fd);
   1171             }
   1172         } else {
   1173             try {
   1174                 ex.setDataSource(url);
   1175             } catch (Exception e) {
   1176                 // indicative of problems with our tame CTS test web server
   1177             }
   1178         }
   1179         int numtracks = ex.getTrackCount();
   1180         String rname = url != null ? url: resources.getResourceEntryName(rid);
   1181         Log.i(TAG, "start mediacodec test for: " + rname + ", which has " + numtracks + " tracks");
   1182         for (int t = 0; t < numtracks; t++) {
   1183             // find all the available decoders for this format
   1184             ArrayList<String> matchingCodecs = new ArrayList<String>();
   1185             MediaFormat format = null;
   1186             try {
   1187                 format = ex.getTrackFormat(t);
   1188             } catch (IllegalArgumentException e) {
   1189                 Log.e(TAG, "could not get track format for track " + t);
   1190                 continue;
   1191             }
   1192             String mime = format.getString(MediaFormat.KEY_MIME);
   1193             int numCodecs = MediaCodecList.getCodecCount();
   1194             for (int i = 0; i < numCodecs; i++) {
   1195                 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
   1196                 if (info.isEncoder()) {
   1197                     continue;
   1198                 }
   1199                 try {
   1200                     MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
   1201                     if (caps != null) {
   1202                         matchingCodecs.add(info.getName());
   1203                         Log.i(TAG, "Found matching codec " + info.getName() + " for track " + t);
   1204                     }
   1205                 } catch (IllegalArgumentException e) {
   1206                     // type is not supported
   1207                 }
   1208             }
   1209 
   1210             if (matchingCodecs.size() == 0) {
   1211                 Log.w(TAG, "no codecs for track " + t + ", type " + mime);
   1212             }
   1213             // decode this track once with each matching codec
   1214             try {
   1215                 ex.selectTrack(t);
   1216             } catch (IllegalArgumentException e) {
   1217                 Log.w(TAG, "couldn't select track " + t);
   1218                 // continue on with codec initialization anyway, since that might still crash
   1219             }
   1220             for (String codecName: matchingCodecs) {
   1221                 Log.i(TAG, "Decoding track " + t + " using codec " + codecName);
   1222                 ex.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
   1223                 MediaCodec codec = MediaCodec.createByCodecName(codecName);
   1224                 Surface surface = null;
   1225                 if (mime.startsWith("video/")) {
   1226                     surface = getDummySurface();
   1227                 }
   1228                 try {
   1229                     codec.configure(format, surface, null, 0);
   1230                     codec.start();
   1231                 } catch (Exception e) {
   1232                     Log.i(TAG, "Failed to start/configure:", e);
   1233                 }
   1234                 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
   1235                 try {
   1236                     ByteBuffer [] inputBuffers = codec.getInputBuffers();
   1237                     while (true) {
   1238                         int flags = ex.getSampleFlags();
   1239                         long time = ex.getSampleTime();
   1240                         ex.getCachedDuration();
   1241                         int bufidx = codec.dequeueInputBuffer(5000);
   1242                         if (bufidx >= 0) {
   1243                             int n = ex.readSampleData(inputBuffers[bufidx], 0);
   1244                             if (n < 0) {
   1245                                 flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
   1246                                 time = 0;
   1247                                 n = 0;
   1248                             }
   1249                             codec.queueInputBuffer(bufidx, 0, n, time, flags);
   1250                             ex.advance();
   1251                         }
   1252                         int status = codec.dequeueOutputBuffer(info, 5000);
   1253                         if (status >= 0) {
   1254                             if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
   1255                                 break;
   1256                             }
   1257                             if (info.presentationTimeUs > TIMEOUT_NS / 1000) {
   1258                                 Log.d(TAG, "stopping after 10 seconds worth of data");
   1259                                 break;
   1260                             }
   1261                             codec.releaseOutputBuffer(status, true);
   1262                         }
   1263                     }
   1264                 } catch (Exception e) {
   1265                     // local exceptions ignored, not security issues
   1266                 } finally {
   1267                     codec.release();
   1268                 }
   1269             }
   1270             ex.unselectTrack(t);
   1271         }
   1272         ex.release();
   1273         String cve = rname.replace("_", "-").toUpperCase();
   1274         assertFalse("Device *IS* vulnerable to " + cve,
   1275                     mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
   1276         thr.stopLooper();
   1277         thr.join();
   1278     }
   1279 
   1280     private void doStagefrightTestMediaMetadataRetriever(final int rid) throws Exception {
   1281         doStagefrightTestMediaMetadataRetriever(rid, null);
   1282     }
   1283 
   1284     private void doStagefrightTestMediaMetadataRetriever(final String url) throws Exception {
   1285         doStagefrightTestMediaMetadataRetriever(-1, url);
   1286     }
   1287 
   1288     private void doStagefrightTestMediaMetadataRetriever(
   1289             final int rid, final String url) throws Exception {
   1290 
   1291         final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
   1292 
   1293         LooperThread thr = new LooperThread(new Runnable() {
   1294             @Override
   1295             public void run() {
   1296 
   1297                 MediaPlayer mp = new MediaPlayer();
   1298                 mp.setOnErrorListener(mpcl);
   1299                 AssetFileDescriptor fd = null;
   1300                 try {
   1301                     fd = getInstrumentation().getContext().getResources()
   1302                         .openRawResourceFd(R.raw.good);
   1303 
   1304                     // the onErrorListener won't receive MEDIA_ERROR_SERVER_DIED until
   1305                     // setDataSource has been called
   1306                     mp.setDataSource(fd.getFileDescriptor(),
   1307                                      fd.getStartOffset(),
   1308                                      fd.getLength());
   1309                     fd.close();
   1310                 } catch (Exception e) {
   1311                     // this is a known-good file, so no failure should occur
   1312                     fail("setDataSource of known-good file failed");
   1313                 }
   1314 
   1315                 synchronized(mpcl) {
   1316                     mpcl.notify();
   1317                 }
   1318                 Looper.loop();
   1319                 mp.release();
   1320             }
   1321         });
   1322         thr.start();
   1323         // wait until the thread has initialized the MediaPlayer
   1324         synchronized(mpcl) {
   1325             mpcl.wait();
   1326         }
   1327 
   1328         Resources resources =  getInstrumentation().getContext().getResources();
   1329         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
   1330         if (url == null) {
   1331             AssetFileDescriptor fd = resources.openRawResourceFd(rid);
   1332             try {
   1333                 retriever.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
   1334             } catch (Exception e) {
   1335                 // ignore
   1336             } finally {
   1337                 closeQuietly(fd);
   1338             }
   1339         } else {
   1340             try {
   1341                 retriever.setDataSource(url, new HashMap<String, String>());
   1342             } catch (Exception e) {
   1343                 // indicative of problems with our tame CTS test web server
   1344             }
   1345         }
   1346         retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
   1347         retriever.getEmbeddedPicture();
   1348         retriever.getFrameAtTime();
   1349 
   1350         retriever.release();
   1351         String rname = url != null ? url : resources.getResourceEntryName(rid);
   1352         String cve = rname.replace("_", "-").toUpperCase();
   1353         assertFalse("Device *IS* vulnerable to " + cve,
   1354                     mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
   1355         thr.stopLooper();
   1356         thr.join();
   1357     }
   1358 
   1359     public void testBug36215950() throws Exception {
   1360         doStagefrightTestRawBlob(R.raw.bug_36215950, "video/hevc", 320, 240);
   1361     }
   1362 
   1363     public void testBug36816007() throws Exception {
   1364         doStagefrightTestRawBlob(R.raw.bug_36816007, "video/avc", 320, 240);
   1365     }
   1366 
   1367     public void testBug36895511() throws Exception {
   1368         doStagefrightTestRawBlob(R.raw.bug_36895511, "video/hevc", 320, 240);
   1369     }
   1370 
   1371     public void testBug64836894() throws Exception {
   1372         doStagefrightTestRawBlob(R.raw.bug_64836894, "video/avc", 320, 240);
   1373     }
   1374 
   1375     @SecurityTest
   1376     public void testCve_2017_0687() throws Exception {
   1377         doStagefrightTestRawBlob(R.raw.cve_2017_0687, "video/avc", 320, 240);
   1378     }
   1379 
   1380     @SecurityTest
   1381     public void testBug_37930177() throws Exception {
   1382         doStagefrightTestRawBlob(R.raw.bug_37930177_hevc, "video/hevc", 320, 240);
   1383     }
   1384 
   1385     @SecurityTest
   1386     public void testBug_37712181() throws Exception {
   1387         doStagefrightTestRawBlob(R.raw.bug_37712181_hevc, "video/hevc", 320, 240);
   1388     }
   1389 
   1390     @SecurityTest
   1391     public void testBug_70897394() throws Exception {
   1392         doStagefrightTestRawBlob(R.raw.bug_70897394_avc, "video/avc", 320, 240);
   1393     }
   1394 
   1395     private int[] getFrameSizes(int rid) throws IOException {
   1396         final Context context = getInstrumentation().getContext();
   1397         final Resources resources =  context.getResources();
   1398         AssetFileDescriptor fd = resources.openRawResourceFd(rid);
   1399         FileInputStream fis = fd.createInputStream();
   1400         byte[] frameInfo = new byte[(int) fd.getLength()];
   1401         fis.read(frameInfo);
   1402         fis.close();
   1403         String[] valueStr = new String(frameInfo).trim().split("\\s+");
   1404         int[] frameSizes = new int[valueStr.length];
   1405         for (int i = 0; i < valueStr.length; i++)
   1406             frameSizes[i] = Integer.parseInt(valueStr[i]);
   1407         return frameSizes;
   1408     }
   1409 
   1410     private void runWithTimeout(Runnable runner, int timeout) {
   1411         Thread t = new Thread(runner);
   1412         t.start();
   1413         try {
   1414             t.join(timeout);
   1415         } catch (InterruptedException e) {
   1416             fail("operation was interrupted");
   1417         }
   1418         if (t.isAlive()) {
   1419             fail("operation not completed within timeout of " + timeout + "ms");
   1420         }
   1421     }
   1422 
   1423     private void releaseCodec(final MediaCodec codec) {
   1424         runWithTimeout(new Runnable() {
   1425             @Override
   1426             public void run() {
   1427                 codec.release();
   1428             }
   1429         }, 5000);
   1430     }
   1431 
   1432     private void doStagefrightTestRawBlob(int rid, String mime, int initWidth, int initHeight) throws Exception {
   1433 
   1434         final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
   1435         final Context context = getInstrumentation().getContext();
   1436         final Resources resources =  context.getResources();
   1437 
   1438         LooperThread thr = new LooperThread(new Runnable() {
   1439             @Override
   1440             public void run() {
   1441 
   1442                 MediaPlayer mp = new MediaPlayer();
   1443                 mp.setOnErrorListener(mpcl);
   1444                 AssetFileDescriptor fd = null;
   1445                 try {
   1446                     fd = resources.openRawResourceFd(R.raw.good);
   1447 
   1448                     // the onErrorListener won't receive MEDIA_ERROR_SERVER_DIED until
   1449                     // setDataSource has been called
   1450                     mp.setDataSource(fd.getFileDescriptor(),
   1451                                      fd.getStartOffset(),
   1452                                      fd.getLength());
   1453                     fd.close();
   1454                 } catch (Exception e) {
   1455                     // this is a known-good file, so no failure should occur
   1456                     fail("setDataSource of known-good file failed");
   1457                 }
   1458 
   1459                 synchronized(mpcl) {
   1460                     mpcl.notify();
   1461                 }
   1462                 Looper.loop();
   1463                 mp.release();
   1464             }
   1465         });
   1466         thr.start();
   1467         // wait until the thread has initialized the MediaPlayer
   1468         synchronized(mpcl) {
   1469             mpcl.wait();
   1470         }
   1471 
   1472         AssetFileDescriptor fd = resources.openRawResourceFd(rid);
   1473         byte [] blob = new byte[(int)fd.getLength()];
   1474         FileInputStream fis = fd.createInputStream();
   1475         int numRead = fis.read(blob);
   1476         fis.close();
   1477         //Log.i("@@@@", "read " + numRead + " bytes");
   1478 
   1479         // find all the available decoders for this format
   1480         ArrayList<String> matchingCodecs = new ArrayList<String>();
   1481         int numCodecs = MediaCodecList.getCodecCount();
   1482         for (int i = 0; i < numCodecs; i++) {
   1483             MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
   1484             if (info.isEncoder()) {
   1485                 continue;
   1486             }
   1487             try {
   1488                 MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
   1489                 if (caps != null) {
   1490                     matchingCodecs.add(info.getName());
   1491                 }
   1492             } catch (IllegalArgumentException e) {
   1493                 // type is not supported
   1494             }
   1495         }
   1496 
   1497         if (matchingCodecs.size() == 0) {
   1498             Log.w(TAG, "no codecs for mime type " + mime);
   1499         }
   1500         String rname = resources.getResourceEntryName(rid);
   1501         // decode this blob once with each matching codec
   1502         for (String codecName: matchingCodecs) {
   1503             Log.i(TAG, "Decoding blob " + rname + " using codec " + codecName);
   1504             MediaCodec codec = MediaCodec.createByCodecName(codecName);
   1505             MediaFormat format = MediaFormat.createVideoFormat(mime, initWidth, initHeight);
   1506             codec.configure(format, null, null, 0);
   1507             codec.start();
   1508 
   1509             try {
   1510                 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
   1511                 ByteBuffer [] inputBuffers = codec.getInputBuffers();
   1512                 // enqueue the bad data a number of times, in case
   1513                 // the codec needs multiple buffers to fail.
   1514                 for(int i = 0; i < 64; i++) {
   1515                     int bufidx = codec.dequeueInputBuffer(5000);
   1516                     if (bufidx >= 0) {
   1517                         Log.i(TAG, "got input buffer of size " + inputBuffers[bufidx].capacity());
   1518                         inputBuffers[bufidx].rewind();
   1519                         inputBuffers[bufidx].put(blob, 0, numRead);
   1520                         codec.queueInputBuffer(bufidx, 0, numRead, 0, 0);
   1521                     } else {
   1522                         Log.i(TAG, "no input buffer");
   1523                     }
   1524                     bufidx = codec.dequeueOutputBuffer(info, 5000);
   1525                     if (bufidx >= 0) {
   1526                         Log.i(TAG, "got output buffer");
   1527                         codec.releaseOutputBuffer(bufidx, false);
   1528                     } else {
   1529                         Log.i(TAG, "no output buffer");
   1530                     }
   1531                 }
   1532             } catch (Exception e) {
   1533                 // ignore, not a security issue
   1534             } finally {
   1535                 releaseCodec(codec);
   1536             }
   1537         }
   1538 
   1539         String cve = rname.replace("_", "-").toUpperCase();
   1540         assertFalse("Device *IS* vulnerable to " + cve,
   1541                     mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
   1542         thr.stopLooper();
   1543         thr.join();
   1544     }
   1545 
   1546     private void doStagefrightTestRawBlob(int rid, String mime, int initWidth, int initHeight,
   1547         int frameSizes[]) throws Exception {
   1548 
   1549         final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
   1550         final Context context = getInstrumentation().getContext();
   1551         final Resources resources =  context.getResources();
   1552 
   1553         LooperThread thr = new LooperThread(new Runnable() {
   1554             @Override
   1555             public void run() {
   1556 
   1557                 MediaPlayer mp = new MediaPlayer();
   1558                 mp.setOnErrorListener(mpcl);
   1559                 AssetFileDescriptor fd = null;
   1560                 try {
   1561                     fd = resources.openRawResourceFd(R.raw.good);
   1562 
   1563                     // the onErrorListener won't receive MEDIA_ERROR_SERVER_DIED until
   1564                     // setDataSource has been called
   1565                     mp.setDataSource(fd.getFileDescriptor(),
   1566                                      fd.getStartOffset(),
   1567                                      fd.getLength());
   1568                     fd.close();
   1569                 } catch (Exception e) {
   1570                     // this is a known-good file, so no failure should occur
   1571                     fail("setDataSource of known-good file failed");
   1572                 }
   1573 
   1574                 synchronized(mpcl) {
   1575                     mpcl.notify();
   1576                 }
   1577                 Looper.loop();
   1578                 mp.release();
   1579             }
   1580         });
   1581         thr.start();
   1582         // wait until the thread has initialized the MediaPlayer
   1583         synchronized(mpcl) {
   1584             mpcl.wait();
   1585         }
   1586 
   1587         AssetFileDescriptor fd = resources.openRawResourceFd(rid);
   1588         byte [] blob = new byte[(int)fd.getLength()];
   1589         FileInputStream fis = fd.createInputStream();
   1590         int numRead = fis.read(blob);
   1591         fis.close();
   1592 
   1593         // find all the available decoders for this format
   1594         ArrayList<String> matchingCodecs = new ArrayList<String>();
   1595         int numCodecs = MediaCodecList.getCodecCount();
   1596         for (int i = 0; i < numCodecs; i++) {
   1597             MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
   1598             if (info.isEncoder()) {
   1599                 continue;
   1600             }
   1601             try {
   1602                 MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
   1603                 if (caps != null) {
   1604                     matchingCodecs.add(info.getName());
   1605                 }
   1606             } catch (IllegalArgumentException e) {
   1607                 // type is not supported
   1608             }
   1609         }
   1610 
   1611         if (matchingCodecs.size() == 0) {
   1612             Log.w(TAG, "no codecs for mime type " + mime);
   1613         }
   1614         String rname = resources.getResourceEntryName(rid);
   1615         // decode this blob once with each matching codec
   1616         for (String codecName: matchingCodecs) {
   1617             Log.i(TAG, "Decoding blob " + rname + " using codec " + codecName);
   1618             MediaCodec codec = MediaCodec.createByCodecName(codecName);
   1619             MediaFormat format = MediaFormat.createVideoFormat(mime, initWidth, initHeight);
   1620             try {
   1621                 codec.configure(format, null, null, 0);
   1622                 codec.start();
   1623             } catch (Exception e) {
   1624                 Log.i(TAG, "Exception from codec " + codecName);
   1625                 releaseCodec(codec);
   1626                 continue;
   1627             }
   1628 
   1629             try {
   1630                 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
   1631                 ByteBuffer [] inputBuffers = codec.getInputBuffers();
   1632                 int numFrames = 0;
   1633                 if (frameSizes != null) {
   1634                     numFrames = frameSizes.length;
   1635                 }
   1636 
   1637                 if (0 == numFrames) {
   1638                     fail("Improper picture length file");
   1639                 }
   1640 
   1641                 int offset = 0;
   1642                 int bytesToFeed = 0;
   1643                 int flags = 0;
   1644                 byte [] tempBlob = new byte[(int)inputBuffers[0].capacity()];
   1645                 for (int j = 0; j < numFrames; j++) {
   1646                     int bufidx = codec.dequeueInputBuffer(5000);
   1647                     if (bufidx >= 0) {
   1648                         inputBuffers[bufidx].rewind();
   1649                         bytesToFeed = Math.min((int)(fd.getLength() - offset),
   1650                                                inputBuffers[bufidx].capacity());
   1651                         if(j == (numFrames - 1)) {
   1652                             flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
   1653                         }
   1654                         System.arraycopy(blob, offset, tempBlob, 0, bytesToFeed);
   1655                         inputBuffers[bufidx].put(tempBlob, 0, inputBuffers[bufidx].capacity());
   1656                         codec.queueInputBuffer(bufidx, 0, bytesToFeed, 0, flags);
   1657                         offset = offset + frameSizes[j];
   1658                     } else {
   1659                         Log.i(TAG, "no input buffer");
   1660                     }
   1661                     bufidx = codec.dequeueOutputBuffer(info, 5000);
   1662                     if (bufidx >= 0) {
   1663                         codec.releaseOutputBuffer(bufidx, false);
   1664                     } else {
   1665                       Log.i(TAG, "no output buffer");
   1666                     }
   1667                 }
   1668             } catch (Exception e) {
   1669                 // ignore, not a security issue
   1670             } finally {
   1671                 releaseCodec(codec);
   1672             }
   1673         }
   1674 
   1675         String cve = rname.replace("_", "-").toUpperCase();
   1676         assertFalse("Device *IS* vulnerable to " + cve,
   1677                     mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
   1678         thr.stopLooper();
   1679         thr.join();
   1680     }
   1681 
   1682     private void doStagefrightTestMediaPlayerANR(final int rid, final String uri) throws Exception {
   1683         String name = uri != null ? uri :
   1684             getInstrumentation().getContext().getResources().getResourceEntryName(rid);
   1685         Log.i(TAG, "start mediaplayerANR test for: " + name);
   1686 
   1687         final MediaPlayerCrashListener mpl = new MediaPlayerCrashListener();
   1688 
   1689         LooperThread t = new LooperThread(new Runnable() {
   1690             @Override
   1691             public void run() {
   1692                 MediaPlayer mp = new MediaPlayer();
   1693                 mp.setOnErrorListener(mpl);
   1694                 mp.setOnPreparedListener(mpl);
   1695                 mp.setOnCompletionListener(mpl);
   1696                 Surface surface = getDummySurface();
   1697                 mp.setSurface(surface);
   1698                 AssetFileDescriptor fd = null;
   1699                 try {
   1700                     if (uri == null) {
   1701                         fd = getInstrumentation().getContext().getResources()
   1702                                 .openRawResourceFd(rid);
   1703 
   1704                         mp.setDataSource(fd.getFileDescriptor(),
   1705                                 fd.getStartOffset(),
   1706                                 fd.getLength());
   1707                     } else {
   1708                         mp.setDataSource(uri);
   1709                     }
   1710                     mp.prepareAsync();
   1711                 } catch (Exception e) {
   1712                 } finally {
   1713                     closeQuietly(fd);
   1714                 }
   1715 
   1716                 Looper.loop();
   1717                 mp.release();
   1718             }
   1719         });
   1720 
   1721         t.start();
   1722         String cve = name.replace("_", "-").toUpperCase();
   1723         assertTrue("Device *IS* vulnerable to " + cve, mpl.waitForErrorOrCompletion());
   1724         t.stopLooper();
   1725         t.join(); // wait for thread to exit so we're sure the player was released
   1726     }
   1727 }
   1728