Home | History | Annotate | Download | only in apk
      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 package com.android.apksig.apk;
     18 
     19 import static org.junit.Assert.assertEquals;
     20 import static org.junit.Assert.assertFalse;
     21 import static org.junit.Assert.assertTrue;
     22 import static org.junit.Assert.fail;
     23 
     24 import java.io.IOException;
     25 import java.nio.ByteBuffer;
     26 import java.security.MessageDigest;
     27 
     28 import org.junit.Test;
     29 import org.junit.runner.RunWith;
     30 import org.junit.runners.JUnit4;
     31 
     32 import com.android.apksig.ApkSigner;
     33 import com.android.apksig.internal.util.HexEncoding;
     34 import com.android.apksig.internal.util.Resources;
     35 import com.android.apksig.util.DataSources;
     36 
     37 @RunWith(JUnit4.class)
     38 public class ApkUtilsTest {
     39 
     40     @Test
     41     public void testGetMinSdkVersionForValidCodename() throws Exception {
     42         assertEquals(1, ApkUtils.getMinSdkVersionForCodename("AAAA"));
     43         assertEquals(2, ApkUtils.getMinSdkVersionForCodename("CUPCAKE"));
     44         assertEquals(7, ApkUtils.getMinSdkVersionForCodename("FROYO"));
     45         assertEquals(23, ApkUtils.getMinSdkVersionForCodename("N"));
     46         assertEquals(23, ApkUtils.getMinSdkVersionForCodename("NMR1"));
     47         assertEquals(25, ApkUtils.getMinSdkVersionForCodename("OMG"));
     48         // Speculative: Q should be 27 or higher (not yet known at the time of writing)
     49         assertEquals(27, ApkUtils.getMinSdkVersionForCodename("QQQ"));
     50     }
     51 
     52     @Test(expected = CodenameMinSdkVersionException.class)
     53     public void testGetMinSdkVersionForEmptyCodename() throws Exception {
     54         ApkUtils.getMinSdkVersionForCodename("");
     55     }
     56 
     57     @Test(expected = CodenameMinSdkVersionException.class)
     58     public void testGetMinSdkVersionForUnexpectedCodename() throws Exception {
     59         ApkUtils.getMinSdkVersionForCodename("1ABC");
     60     }
     61 
     62     @Test
     63     public void testGetMinSdkVersionFromBinaryAndroidManifest() throws Exception {
     64         ByteBuffer manifest = getAndroidManifest("original.apk");
     65         assertEquals(23, ApkUtils.getMinSdkVersionFromBinaryAndroidManifest(manifest));
     66     }
     67 
     68     @Test
     69     public void testGetDebuggableFromBinaryAndroidManifest() throws Exception {
     70         ByteBuffer manifest = getAndroidManifest("original.apk");
     71         assertFalse(ApkUtils.getDebuggableFromBinaryAndroidManifest(manifest));
     72 
     73         manifest = getAndroidManifest("debuggable-boolean.apk");
     74         assertTrue(ApkUtils.getDebuggableFromBinaryAndroidManifest(manifest));
     75 
     76         // android:debuggable value is a resource reference -- this must be rejected
     77         manifest = getAndroidManifest("debuggable-resource.apk");
     78         try {
     79             ApkUtils.getDebuggableFromBinaryAndroidManifest(manifest);
     80             fail();
     81         } catch (ApkFormatException expected) {}
     82     }
     83 
     84     @Test
     85     public void testGetPackageNameFromBinaryAndroidManifest() throws Exception {
     86         ByteBuffer manifest = getAndroidManifest("original.apk");
     87         assertEquals(
     88                 "android.appsecurity.cts.tinyapp",
     89                 ApkUtils.getPackageNameFromBinaryAndroidManifest(manifest));
     90     }
     91 
     92     @Test
     93     public void testGetAndroidManifest() throws Exception {
     94         ByteBuffer manifest = getAndroidManifest("original.apk");
     95         MessageDigest md = MessageDigest.getInstance("SHA-256");
     96         md.update(manifest);
     97         byte[] actualDigest = md.digest();
     98         assertEquals(
     99                 "8b3de63a282652221162cdc327f424924ac3c7c24e642035975a1ee7a395c4dc",
    100                 HexEncoding.encode(actualDigest));
    101     }
    102 
    103     private static ByteBuffer getAndroidManifest(String apkResourceName)
    104             throws IOException, ApkFormatException {
    105         return getAndroidManifest(getResource(apkResourceName));
    106     }
    107 
    108     private static ByteBuffer getAndroidManifest(byte[] apk)
    109             throws IOException, ApkFormatException {
    110         return ApkUtils.getAndroidManifest(DataSources.asDataSource(ByteBuffer.wrap(apk)));
    111     }
    112 
    113     private static byte[] getResource(String resourceName) throws IOException {
    114         return Resources.toByteArray(ApkSigner.class, resourceName);
    115     }
    116 }
    117