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 import java.io.File;
17 import java.io.IOException;
18 import java.lang.reflect.Method;
19 
20 public class Main {
21 
main(String[] args)22   public static void main(String[] args) throws Exception {
23     System.loadLibrary(args[0]);
24 
25     File file = null;
26     try {
27       file = createTempFile();
28       // String codePath = getDexBaseLocation();
29       String codePath = System.getenv("DEX_LOCATION") + "/595-profile-saving.jar";
30       VMRuntime.registerAppInfo(file.getPath(),
31                                 new String[] {codePath});
32 
33       // Test that the profile saves an app method with a profiling info.
34       Method appMethod = Main.class.getDeclaredMethod("testAddMethodToProfile",
35           File.class, Method.class);
36       testAddMethodToProfile(file, appMethod);
37 
38       // Test that the profile saves a boot class path method with a profiling info.
39       Method bootMethod = File.class.getDeclaredMethod("delete");
40       if (bootMethod.getDeclaringClass().getClassLoader() != Object.class.getClassLoader()) {
41         System.out.println("Class loader does not match boot class");
42       }
43       testAddMethodToProfile(file, bootMethod);
44 
45       System.out.println("IsForBootImage: " + isForBootImage(file.getPath()));
46     } finally {
47       if (file != null) {
48         file.delete();
49       }
50     }
51   }
52 
testAddMethodToProfile(File file, Method m)53   static void testAddMethodToProfile(File file, Method m) {
54     // Make sure we have a profile info for this method without the need to loop.
55     ensureProfilingInfo(m);
56     // Make sure the profile gets saved.
57     ensureProfileProcessing();
58     // Verify that the profile was saved and contains the method.
59     if (!presentInProfile(file.getPath(), m)) {
60       throw new RuntimeException("Method with index " + m + " not in the profile");
61     }
62   }
63 
64   // Ensure a method has a profiling info.
ensureProfilingInfo(Method method)65   public static native void ensureProfilingInfo(Method method);
66   // Ensures the profile saver does its usual processing.
ensureProfileProcessing()67   public static native void ensureProfileProcessing();
68   // Checks if the profiles saver knows about the method.
presentInProfile(String profile, Method method)69   public static native boolean presentInProfile(String profile, Method method);
70   // Returns true if the profile is for the boot image.
isForBootImage(String profile)71   public static native boolean isForBootImage(String profile);
72 
73   private static final String TEMP_FILE_NAME_PREFIX = "temp";
74   private static final String TEMP_FILE_NAME_SUFFIX = "-file";
75 
getProfileInfoDump( String filename)76   static native String getProfileInfoDump(
77       String filename);
78 
createTempFile()79   private static File createTempFile() throws Exception {
80     try {
81       return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
82     } catch (IOException e) {
83       System.setProperty("java.io.tmpdir", "/data/local/tmp");
84       try {
85         return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
86       } catch (IOException e2) {
87         System.setProperty("java.io.tmpdir", "/sdcard");
88         return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
89       }
90     }
91   }
92 
93   private static class VMRuntime {
94     private static final Method registerAppInfoMethod;
95     static {
96       try {
97         Class<? extends Object> c = Class.forName("dalvik.system.VMRuntime");
98         registerAppInfoMethod = c.getDeclaredMethod("registerAppInfo",
99             String.class, String[].class);
100       } catch (Exception e) {
101         throw new RuntimeException(e);
102       }
103     }
104 
registerAppInfo(String profile, String[] codePaths)105     public static void registerAppInfo(String profile, String[] codePaths)
106         throws Exception {
107       registerAppInfoMethod.invoke(null, profile, codePaths);
108     }
109   }
110 }
111