14a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil/*
24a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil * Copyright (C) 2018 The Android Open Source Project
34a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil *
44a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil * Licensed under the Apache License, Version 2.0 (the "License");
54a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil * you may not use this file except in compliance with the License.
64a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil * You may obtain a copy of the License at
74a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil *
84a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil *      http://www.apache.org/licenses/LICENSE-2.0
94a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil *
104a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil * Unless required by applicable law or agreed to in writing, software
114a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil * distributed under the License is distributed on an "AS IS" BASIS,
124a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil * See the License for the specific language governing permissions and
144a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil * limitations under the License.
154a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil */
164a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
174a13ed4f3b134e76a4238061952b5d3814750b94David Brazdilimport java.io.File;
184a13ed4f3b134e76a4238061952b5d3814750b94David Brazdilimport java.lang.reflect.Method;
194a13ed4f3b134e76a4238061952b5d3814750b94David Brazdilimport java.util.Base64;
204a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
214a13ed4f3b134e76a4238061952b5d3814750b94David Brazdilpublic class Main {
224a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  public static void main(String[] args) throws Exception {
234a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    System.loadLibrary(args[0]);
244a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
254a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    // Run the initialization routine. This will enable hidden API checks in
264a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    // the runtime, in case they are not enabled by default.
274a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    init();
284a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
294a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    // Load the '-ex' APK and attach it to the boot class path.
304a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    appendToBootClassLoader(DEX_EXTRA);
314a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
324a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    // Find the test class in boot class loader and verify that its members are hidden.
334a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    Class<?> klass = Class.forName("art.Test999", true, BOOT_CLASS_LOADER);
344a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    assertMethodIsHidden(klass, "before redefinition");
354a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    assertFieldIsHidden(klass, "before redefinition");
364a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
374a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    // Redefine the class using JVMTI.
384a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    art.Redefinition.setTestConfiguration(art.Redefinition.Config.COMMON_REDEFINE);
394a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    art.Redefinition.doCommonClassRedefinition(klass, CLASS_BYTES, DEX_BYTES);
404a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
414a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    // Verify that the class members are still hidden.
424a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    assertMethodIsHidden(klass, "after redefinition");
434a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    assertFieldIsHidden(klass, "after redefinition");
444a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  }
454a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
464a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  private static void assertMethodIsHidden(Class<?> klass, String msg) throws Exception {
474a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    try {
484a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil      klass.getDeclaredMethod("foo");
494a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil      // Unexpected. Should have thrown NoSuchMethodException.
504a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil      throw new Exception("Method should not be accessible " + msg);
514a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    } catch (NoSuchMethodException ex) {
524a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil      // Expected.
534a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    }
544a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  }
554a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
564a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  private static void assertFieldIsHidden(Class<?> klass, String msg) throws Exception {
574a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    try {
584a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil      klass.getDeclaredField("bar");
594a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil      // Unexpected. Should have thrown NoSuchFieldException.
604a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil      throw new Exception("Field should not be accessible " + msg);
614a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    } catch (NoSuchFieldException ex) {
624a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil      // Expected.
634a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    }
644a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  }
654a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
664a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  private static final String DEX_EXTRA =
674a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil      new File(System.getenv("DEX_LOCATION"), "999-redefine-hiddenapi-ex.jar").getAbsolutePath();
684a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
694a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  private static ClassLoader BOOT_CLASS_LOADER = Object.class.getClassLoader();
704a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
714a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  // Native functions. Note that these are implemented in 674-hiddenapi/hiddenapi.cc.
724a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  private static native void appendToBootClassLoader(String dexPath);
734a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  private static native void init();
744a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil
754a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  /**
764a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   * base64 encoded class/dex file for
774a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   *
784a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   * public class Test999 {
794a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   *   public void foo() {
804a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   *     System.out.println("Goodbye");
814a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   *   }
824a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   *
834a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   *   public int bar = 64;
844a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   * }
854a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil   */
864a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
874a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "yv66vgAAADUAIAoABwARCQAGABIJABMAFAgAFQoAFgAXBwAYBwAZAQADYmFyAQABSQEABjxpbml0" +
884a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAANmb28BAApTb3VyY2VGaWxlAQAMVGVz" +
894a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "dDk5OS5qYXZhDAAKAAsMAAgACQcAGgwAGwAcAQAHR29vZGJ5ZQcAHQwAHgAfAQALYXJ0L1Rlc3Q5" +
904a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "OTkBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lv" +
914a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "L1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xh" +
924a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "bmcvU3RyaW5nOylWACEABgAHAAAAAQABAAgACQAAAAIAAQAKAAsAAQAMAAAAJwACAAEAAAALKrcA" +
934a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "ASoQQLUAArEAAAABAA0AAAAKAAIAAAATAAQAGAABAA4ACwABAAwAAAAlAAIAAQAAAAmyAAMSBLYA" +
944a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "BbEAAAABAA0AAAAKAAIAAAAVAAgAFgABAA8AAAACABA=");
954a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil  private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
964a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "ZGV4CjAzNQD0dZ+IWxOi+cJDSWjfTnUerlZj1Lll3ONIAwAAcAAAAHhWNBIAAAAAAAAAAJwCAAAQ" +
974a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "AAAAcAAAAAcAAACwAAAAAgAAAMwAAAACAAAA5AAAAAQAAAD0AAAAAQAAABQBAAAUAgAANAEAAIYB" +
984a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "AACOAQAAlwEAAJoBAACpAQAAwAEAANQBAADoAQAA/AEAAAoCAAANAgAAEQIAABYCAAAbAgAAIAIA" +
994a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "ACkCAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAJAAAACQAAAAYAAAAAAAAACgAAAAYAAACAAQAA" +
1004a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "AQAAAAsAAAAFAAIADQAAAAEAAAAAAAAAAQAAAAwAAAACAAEADgAAAAMAAAAAAAAAAQAAAAEAAAAD" +
1014a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "AAAAAAAAAAgAAAAAAAAAhwIAAAAAAAACAAEAAQAAAHQBAAAIAAAAcBADAAEAEwBAAFkQAAAOAAMA" +
1024a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "AQACAAAAeQEAAAgAAABiAAEAGgEBAG4gAgAQAA4AEwAOQAAVAA54AAAAAQAAAAQABjxpbml0PgAH" +
1034a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "R29vZGJ5ZQABSQANTGFydC9UZXN0OTk5OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9s" +
1044a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "YW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AAxUZXN0" +
1054a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "OTk5LmphdmEAAVYAAlZMAANiYXIAA2ZvbwADb3V0AAdwcmludGxuAFx+fkQ4eyJtaW4tYXBpIjox" +
1064a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "LCJzaGEtMSI6IjU2YzJlMzBmNTIzM2I4NDRmZjZkZGQ4N2ZiNTNkMzRmYjE3MjM3ZGYiLCJ2ZXJz" +
1074a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "aW9uIjoidjEuMi4xNS1kZXYifQAAAQEBAAEAgYAEtAIBAdQCAAAAAAAOAAAAAAAAAAEAAAAAAAAA" +
1084a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "AQAAABAAAABwAAAAAgAAAAcAAACwAAAAAwAAAAIAAADMAAAABAAAAAIAAADkAAAABQAAAAQAAAD0" +
1094a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "AAAABgAAAAEAAAAUAQAAASAAAAIAAAA0AQAAAyAAAAIAAAB0AQAAARAAAAEAAACAAQAAAiAAABAA" +
1104a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil    "AACGAQAAACAAAAEAAACHAgAAAxAAAAEAAACYAgAAABAAAAEAAACcAgAA");
1114a13ed4f3b134e76a4238061952b5d3814750b94David Brazdil}
112