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