You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
5.0 KiB
111 lines
5.0 KiB
8 months ago
|
/*
|
||
|
* Copyright (C) 2018 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
import java.io.File;
|
||
|
import java.lang.reflect.Method;
|
||
|
import java.util.Base64;
|
||
|
|
||
|
public class Main {
|
||
|
public static void main(String[] args) throws ClassNotFoundException {
|
||
|
System.loadLibrary(args[0]);
|
||
|
|
||
|
// Run the initialization routine. This will enable hidden API checks in
|
||
|
// the runtime, in case they are not enabled by default.
|
||
|
init();
|
||
|
|
||
|
// Load the '-ex' APK and attach it to the boot class path.
|
||
|
appendToBootClassLoader(DEX_EXTRA, /* isCorePlatform */ false);
|
||
|
|
||
|
// Find the test class in boot class loader and verify that its members are hidden.
|
||
|
Class<?> klass = Class.forName("art.Test999", true, BOOT_CLASS_LOADER);
|
||
|
assertFieldIsHidden(klass, "before redefinition");
|
||
|
assertMethodIsHidden(klass, "before redefinition");
|
||
|
|
||
|
// Redefine the class using JVMTI. Use dex file without hiddenapi flags.
|
||
|
art.Redefinition.setTestConfiguration(art.Redefinition.Config.COMMON_REDEFINE);
|
||
|
art.Redefinition.doCommonClassRedefinition(klass, CLASS_BYTES, DEX_BYTES);
|
||
|
|
||
|
// Verify that the class members are still hidden.
|
||
|
assertFieldIsHidden(klass, "after first redefinition");
|
||
|
assertMethodIsHidden(klass, "after first redefinition");
|
||
|
}
|
||
|
|
||
|
private static void assertMethodIsHidden(Class<?> klass, String msg) {
|
||
|
try {
|
||
|
klass.getDeclaredMethod("foo");
|
||
|
// Unexpected. Should have thrown NoSuchMethodException.
|
||
|
throw new RuntimeException("Method should not be accessible " + msg);
|
||
|
} catch (NoSuchMethodException ex) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void assertFieldIsHidden(Class<?> klass, String msg) {
|
||
|
try {
|
||
|
klass.getDeclaredField("bar");
|
||
|
// Unexpected. Should have thrown NoSuchFieldException.
|
||
|
throw new RuntimeException("Field should not be accessible " + msg);
|
||
|
} catch (NoSuchFieldException ex) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static final String DEX_EXTRA =
|
||
|
new File(System.getenv("DEX_LOCATION"), "999-redefine-hiddenapi-ex.jar").getAbsolutePath();
|
||
|
|
||
|
private static ClassLoader BOOT_CLASS_LOADER = Object.class.getClassLoader();
|
||
|
|
||
|
// Native functions. Note that these are implemented in 674-hiddenapi/hiddenapi.cc.
|
||
|
private static native void appendToBootClassLoader(String dexPath, boolean isCorePlatform);
|
||
|
private static native void init();
|
||
|
|
||
|
/**
|
||
|
* base64 encoded class/dex file for
|
||
|
*
|
||
|
* public class Test999 {
|
||
|
* public void foo() {
|
||
|
* System.out.println("Goodbye");
|
||
|
* }
|
||
|
*
|
||
|
* public int bar = 64;
|
||
|
* }
|
||
|
*/
|
||
|
private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
|
||
|
"yv66vgAAADUAIAoABwARCQAGABIJABMAFAgAFQoAFgAXBwAYBwAZAQADYmFyAQABSQEABjxpbml0" +
|
||
|
"PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAANmb28BAApTb3VyY2VGaWxlAQAMVGVz" +
|
||
|
"dDk5OS5qYXZhDAAKAAsMAAgACQcAGgwAGwAcAQAHR29vZGJ5ZQcAHQwAHgAfAQALYXJ0L1Rlc3Q5" +
|
||
|
"OTkBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lv" +
|
||
|
"L1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xh" +
|
||
|
"bmcvU3RyaW5nOylWACEABgAHAAAAAQABAAgACQAAAAIAAQAKAAsAAQAMAAAAJwACAAEAAAALKrcA" +
|
||
|
"ASoQQLUAArEAAAABAA0AAAAKAAIAAAATAAQAGAABAA4ACwABAAwAAAAlAAIAAQAAAAmyAAMSBLYA" +
|
||
|
"BbEAAAABAA0AAAAKAAIAAAAVAAgAFgABAA8AAAACABA=");
|
||
|
private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
|
||
|
"ZGV4CjAzNQDlfmgFfKulToQpDF+P4dsgeOkgfzzH+5lgAwAAcAAAAHhWNBIAAAAAAAAAALQCAAAQ" +
|
||
|
"AAAAcAAAAAcAAACwAAAAAgAAAMwAAAACAAAA5AAAAAQAAAD0AAAAAQAAABQBAAAsAgAANAEAAIYB" +
|
||
|
"AACOAQAAlwEAAJoBAACpAQAAwAEAANQBAADoAQAA/AEAAAoCAAANAgAAEQIAABYCAAAbAgAAIAIA" +
|
||
|
"ACkCAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAJAAAACQAAAAYAAAAAAAAACgAAAAYAAACAAQAA" +
|
||
|
"AQAAAAsAAAAFAAIADQAAAAEAAAAAAAAAAQAAAAwAAAACAAEADgAAAAMAAAAAAAAAAQAAAAEAAAAD" +
|
||
|
"AAAAAAAAAAgAAAAAAAAAoAIAAAAAAAACAAEAAQAAAHQBAAAIAAAAcBADAAEAEwBAAFkQAAAOAAMA" +
|
||
|
"AQACAAAAeQEAAAgAAABiAAEAGgEBAG4gAgAQAA4AEwAOQAAVAA54AAAAAQAAAAQABjxpbml0PgAH" +
|
||
|
"R29vZGJ5ZQABSQANTGFydC9UZXN0OTk5OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9s" +
|
||
|
"YW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AAxUZXN0" +
|
||
|
"OTk5LmphdmEAAVYAAlZMAANiYXIAA2ZvbwADb3V0AAdwcmludGxuAHV+fkQ4eyJjb21waWxhdGlv" +
|
||
|
"bi1tb2RlIjoiZGVidWciLCJtaW4tYXBpIjoxLCJzaGEtMSI6ImQyMmFiNGYxOWI3NTYxNDQ3NTI4" +
|
||
|
"NTdjYTg2YjJjZWU0ZGQ5Y2ExNjYiLCJ2ZXJzaW9uIjoiMS40LjktZGV2In0AAAEBAQABAIGABLQC" +
|
||
|
"AQHUAgAAAAAOAAAAAAAAAAEAAAAAAAAAAQAAABAAAABwAAAAAgAAAAcAAACwAAAAAwAAAAIAAADM" +
|
||
|
"AAAABAAAAAIAAADkAAAABQAAAAQAAAD0AAAABgAAAAEAAAAUAQAAASAAAAIAAAA0AQAAAyAAAAIA" +
|
||
|
"AAB0AQAAARAAAAEAAACAAQAAAiAAABAAAACGAQAAACAAAAEAAACgAgAAAxAAAAEAAACwAgAAABAA" +
|
||
|
"AAEAAAC0AgAA");
|
||
|
}
|