Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2018 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 import java.io.File;
     18 import java.lang.reflect.Method;
     19 import java.util.Base64;
     20 
     21 public class Main {
     22   public static void main(String[] args) throws Exception {
     23     System.loadLibrary(args[0]);
     24 
     25     // Run the initialization routine. This will enable hidden API checks in
     26     // the runtime, in case they are not enabled by default.
     27     init();
     28 
     29     // Load the '-ex' APK and attach it to the boot class path.
     30     appendToBootClassLoader(DEX_EXTRA);
     31 
     32     // Find the test class in boot class loader and verify that its members are hidden.
     33     Class<?> klass = Class.forName("art.Test999", true, BOOT_CLASS_LOADER);
     34     assertMethodIsHidden(klass, "before redefinition");
     35     assertFieldIsHidden(klass, "before redefinition");
     36 
     37     // Redefine the class using JVMTI.
     38     art.Redefinition.setTestConfiguration(art.Redefinition.Config.COMMON_REDEFINE);
     39     art.Redefinition.doCommonClassRedefinition(klass, CLASS_BYTES, DEX_BYTES);
     40 
     41     // Verify that the class members are still hidden.
     42     assertMethodIsHidden(klass, "after redefinition");
     43     assertFieldIsHidden(klass, "after redefinition");
     44   }
     45 
     46   private static void assertMethodIsHidden(Class<?> klass, String msg) throws Exception {
     47     try {
     48       klass.getDeclaredMethod("foo");
     49       // Unexpected. Should have thrown NoSuchMethodException.
     50       throw new Exception("Method should not be accessible " + msg);
     51     } catch (NoSuchMethodException ex) {
     52       // Expected.
     53     }
     54   }
     55 
     56   private static void assertFieldIsHidden(Class<?> klass, String msg) throws Exception {
     57     try {
     58       klass.getDeclaredField("bar");
     59       // Unexpected. Should have thrown NoSuchFieldException.
     60       throw new Exception("Field should not be accessible " + msg);
     61     } catch (NoSuchFieldException ex) {
     62       // Expected.
     63     }
     64   }
     65 
     66   private static final String DEX_EXTRA =
     67       new File(System.getenv("DEX_LOCATION"), "999-redefine-hiddenapi-ex.jar").getAbsolutePath();
     68 
     69   private static ClassLoader BOOT_CLASS_LOADER = Object.class.getClassLoader();
     70 
     71   // Native functions. Note that these are implemented in 674-hiddenapi/hiddenapi.cc.
     72   private static native void appendToBootClassLoader(String dexPath);
     73   private static native void init();
     74 
     75   /**
     76    * base64 encoded class/dex file for
     77    *
     78    * public class Test999 {
     79    *   public void foo() {
     80    *     System.out.println("Goodbye");
     81    *   }
     82    *
     83    *   public int bar = 64;
     84    * }
     85    */
     86   private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
     87     "yv66vgAAADUAIAoABwARCQAGABIJABMAFAgAFQoAFgAXBwAYBwAZAQADYmFyAQABSQEABjxpbml0" +
     88     "PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAANmb28BAApTb3VyY2VGaWxlAQAMVGVz" +
     89     "dDk5OS5qYXZhDAAKAAsMAAgACQcAGgwAGwAcAQAHR29vZGJ5ZQcAHQwAHgAfAQALYXJ0L1Rlc3Q5" +
     90     "OTkBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lv" +
     91     "L1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xh" +
     92     "bmcvU3RyaW5nOylWACEABgAHAAAAAQABAAgACQAAAAIAAQAKAAsAAQAMAAAAJwACAAEAAAALKrcA" +
     93     "ASoQQLUAArEAAAABAA0AAAAKAAIAAAATAAQAGAABAA4ACwABAAwAAAAlAAIAAQAAAAmyAAMSBLYA" +
     94     "BbEAAAABAA0AAAAKAAIAAAAVAAgAFgABAA8AAAACABA=");
     95   private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
     96     "ZGV4CjAzNQD0dZ+IWxOi+cJDSWjfTnUerlZj1Lll3ONIAwAAcAAAAHhWNBIAAAAAAAAAAJwCAAAQ" +
     97     "AAAAcAAAAAcAAACwAAAAAgAAAMwAAAACAAAA5AAAAAQAAAD0AAAAAQAAABQBAAAUAgAANAEAAIYB" +
     98     "AACOAQAAlwEAAJoBAACpAQAAwAEAANQBAADoAQAA/AEAAAoCAAANAgAAEQIAABYCAAAbAgAAIAIA" +
     99     "ACkCAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAJAAAACQAAAAYAAAAAAAAACgAAAAYAAACAAQAA" +
    100     "AQAAAAsAAAAFAAIADQAAAAEAAAAAAAAAAQAAAAwAAAACAAEADgAAAAMAAAAAAAAAAQAAAAEAAAAD" +
    101     "AAAAAAAAAAgAAAAAAAAAhwIAAAAAAAACAAEAAQAAAHQBAAAIAAAAcBADAAEAEwBAAFkQAAAOAAMA" +
    102     "AQACAAAAeQEAAAgAAABiAAEAGgEBAG4gAgAQAA4AEwAOQAAVAA54AAAAAQAAAAQABjxpbml0PgAH" +
    103     "R29vZGJ5ZQABSQANTGFydC9UZXN0OTk5OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9s" +
    104     "YW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AAxUZXN0" +
    105     "OTk5LmphdmEAAVYAAlZMAANiYXIAA2ZvbwADb3V0AAdwcmludGxuAFx+fkQ4eyJtaW4tYXBpIjox" +
    106     "LCJzaGEtMSI6IjU2YzJlMzBmNTIzM2I4NDRmZjZkZGQ4N2ZiNTNkMzRmYjE3MjM3ZGYiLCJ2ZXJz" +
    107     "aW9uIjoidjEuMi4xNS1kZXYifQAAAQEBAAEAgYAEtAIBAdQCAAAAAAAOAAAAAAAAAAEAAAAAAAAA" +
    108     "AQAAABAAAABwAAAAAgAAAAcAAACwAAAAAwAAAAIAAADMAAAABAAAAAIAAADkAAAABQAAAAQAAAD0" +
    109     "AAAABgAAAAEAAAAUAQAAASAAAAIAAAA0AQAAAyAAAAIAAAB0AQAAARAAAAEAAACAAQAAAiAAABAA" +
    110     "AACGAQAAACAAAAEAAACHAgAAAxAAAAEAAACYAgAAABAAAAEAAACcAgAA");
    111 }
    112