1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker import dalvik.system.PathClassLoader; 18*795d594fSAndroid Build Coastguard Worker import java.io.File; 19*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method; 20*795d594fSAndroid Build Coastguard Worker import java.nio.file.Files; 21*795d594fSAndroid Build Coastguard Worker import java.util.Arrays; 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Worker public class Main { 24*795d594fSAndroid Build Coastguard Worker main(String[] args)25*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 26*795d594fSAndroid Build Coastguard Worker System.loadLibrary(args[0]); 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker // Enable hidden API checks in case they are disabled by default. 29*795d594fSAndroid Build Coastguard Worker init(); 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker // Put the classes with hiddenapi bits in the boot classpath. 32*795d594fSAndroid Build Coastguard Worker appendToBootClassLoader(DEX_PARENT_BOOT, /* isCorePlatform */ false); 33*795d594fSAndroid Build Coastguard Worker 34*795d594fSAndroid Build Coastguard Worker // Create a new class loader so the TestCase class sees the InheritAbstract classes in the boot 35*795d594fSAndroid Build Coastguard Worker // classpath. 36*795d594fSAndroid Build Coastguard Worker ClassLoader childLoader = new PathClassLoader(DEX_CHILD, Object.class.getClassLoader()); 37*795d594fSAndroid Build Coastguard Worker Class<?> cls = Class.forName("TestCase", true, childLoader); 38*795d594fSAndroid Build Coastguard Worker Method m = cls.getDeclaredMethod("test"); 39*795d594fSAndroid Build Coastguard Worker m.invoke(null); 40*795d594fSAndroid Build Coastguard Worker 41*795d594fSAndroid Build Coastguard Worker // Create a new native library which 'childLoader' can load. 42*795d594fSAndroid Build Coastguard Worker String absoluteLibraryPath = getNativeLibFileName(args[0]); 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker // Do the test for JNI code. 45*795d594fSAndroid Build Coastguard Worker m = cls.getDeclaredMethod("testNative", String.class); 46*795d594fSAndroid Build Coastguard Worker m.invoke(null, createNativeLibCopy(absoluteLibraryPath)); 47*795d594fSAndroid Build Coastguard Worker } 48*795d594fSAndroid Build Coastguard Worker 49*795d594fSAndroid Build Coastguard Worker // Tries to find the absolute path of the native library whose basename is 'arg'. getNativeLibFileName(String arg)50*795d594fSAndroid Build Coastguard Worker private static String getNativeLibFileName(String arg) throws Exception { 51*795d594fSAndroid Build Coastguard Worker String libName = System.mapLibraryName(arg); 52*795d594fSAndroid Build Coastguard Worker Method libPathsMethod = Runtime.class.getDeclaredMethod("getLibPaths"); 53*795d594fSAndroid Build Coastguard Worker libPathsMethod.setAccessible(true); 54*795d594fSAndroid Build Coastguard Worker String[] libPaths = (String[]) libPathsMethod.invoke(Runtime.getRuntime()); 55*795d594fSAndroid Build Coastguard Worker String nativeLibFileName = null; 56*795d594fSAndroid Build Coastguard Worker for (String p : libPaths) { 57*795d594fSAndroid Build Coastguard Worker String candidate = p + libName; 58*795d594fSAndroid Build Coastguard Worker if (new File(candidate).exists()) { 59*795d594fSAndroid Build Coastguard Worker nativeLibFileName = candidate; 60*795d594fSAndroid Build Coastguard Worker break; 61*795d594fSAndroid Build Coastguard Worker } 62*795d594fSAndroid Build Coastguard Worker } 63*795d594fSAndroid Build Coastguard Worker if (nativeLibFileName == null) { 64*795d594fSAndroid Build Coastguard Worker throw new IllegalStateException("Didn't find " + libName + " in " + 65*795d594fSAndroid Build Coastguard Worker Arrays.toString(libPaths)); 66*795d594fSAndroid Build Coastguard Worker } 67*795d594fSAndroid Build Coastguard Worker return nativeLibFileName; 68*795d594fSAndroid Build Coastguard Worker } 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker // Copy native library to a new file with a unique name so it does not 71*795d594fSAndroid Build Coastguard Worker // conflict with other loaded instance of the same binary file. createNativeLibCopy(String nativeLibFileName)72*795d594fSAndroid Build Coastguard Worker private static String createNativeLibCopy(String nativeLibFileName) throws Exception { 73*795d594fSAndroid Build Coastguard Worker String tempFileName = System.mapLibraryName("hiddenapitest"); 74*795d594fSAndroid Build Coastguard Worker File tempFile = new File(System.getenv("DEX_LOCATION"), tempFileName); 75*795d594fSAndroid Build Coastguard Worker Files.copy(new File(nativeLibFileName).toPath(), tempFile.toPath()); 76*795d594fSAndroid Build Coastguard Worker tempFile.setWritable(false); 77*795d594fSAndroid Build Coastguard Worker return tempFile.getAbsolutePath(); 78*795d594fSAndroid Build Coastguard Worker } 79*795d594fSAndroid Build Coastguard Worker 80*795d594fSAndroid Build Coastguard Worker private static final String DEX_PARENT_BOOT = 81*795d594fSAndroid Build Coastguard Worker new File(new File(System.getenv("DEX_LOCATION"), "res"), "boot.jar").getAbsolutePath(); 82*795d594fSAndroid Build Coastguard Worker private static final String DEX_CHILD = 83*795d594fSAndroid Build Coastguard Worker new File(System.getenv("DEX_LOCATION"), "817-hiddenapi-ex.jar").getAbsolutePath(); 84*795d594fSAndroid Build Coastguard Worker appendToBootClassLoader(String dexPath, boolean isCorePlatform)85*795d594fSAndroid Build Coastguard Worker private static native int appendToBootClassLoader(String dexPath, boolean isCorePlatform); init()86*795d594fSAndroid Build Coastguard Worker private static native void init(); 87*795d594fSAndroid Build Coastguard Worker } 88