1 /* 2 * Copyright (C) 2022 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 dalvik.system.DexFile; 18 import dalvik.system.VMRuntime; 19 import java.io.File; 20 import java.io.IOException; 21 22 public class Main { main(String[] args)23 public static void main(String[] args) throws Exception { 24 System.loadLibrary(args[0]); 25 26 // Register the dex file so that the runtime can pick up which 27 // dex file to compile for the image. 28 File file = null; 29 try { 30 file = createTempFile(); 31 String codePath = DEX_LOCATION + "/846-multidex-data-image.jar"; 32 VMRuntime.registerAppInfo( 33 "test.app", 34 file.getPath(), 35 file.getPath(), 36 new String[] {codePath}, 37 VMRuntime.CODE_PATH_TYPE_PRIMARY_APK); 38 } finally { 39 if (file != null) { 40 file.delete(); 41 } 42 } 43 44 if (!hasOatFile() || !hasImage()) { 45 // We only generate an app image if there is at least a vdex file and a boot image. 46 return; 47 } 48 49 if (args.length == 2 && "--second-run".equals(args[1])) { 50 DexFile.OptimizationInfo info = VMRuntime.getBaseApkOptimizationInfo(); 51 if (!info.isOptimized() && !isInImageSpace(Main.class)) { 52 throw new Error("Expected image to be loaded"); 53 } 54 } 55 56 VMRuntime runtime = VMRuntime.getRuntime(); 57 runtime.notifyStartupCompleted(); 58 59 String filter = getCompilerFilter(Main.class); 60 if ("speed-profile".equals(filter) || "speed".equals(filter)) { 61 // We only generate an app image for filters that don't compile. 62 return; 63 } 64 65 String instructionSet = VMRuntime.getCurrentInstructionSet(); 66 // Wait for the file to be generated. 67 File image = new File(DEX_LOCATION + "/" + instructionSet + "/846-multidex-data-image.art"); 68 while (!image.exists()) { 69 Thread.yield(); 70 } 71 72 // Test that we can load a class from the other dex file. We do this after creating the image to 73 // check that the runtime can deal with a missing dex cache. 74 Class.forName("Foo"); 75 } 76 hasOatFile()77 private static native boolean hasOatFile(); hasImage()78 private static native boolean hasImage(); getCompilerFilter(Class<?> cls)79 private static native String getCompilerFilter(Class<?> cls); isInImageSpace(Class<?> cls)80 private static native boolean isInImageSpace(Class<?> cls); 81 82 private static final String TEMP_FILE_NAME_PREFIX = "temp"; 83 private static final String TEMP_FILE_NAME_SUFFIX = "-file"; 84 private static final String DEX_LOCATION = System.getenv("DEX_LOCATION"); 85 createTempFile()86 private static File createTempFile() throws Exception { 87 try { 88 return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); 89 } catch (IOException e) { 90 System.setProperty("java.io.tmpdir", "/data/local/tmp"); 91 try { 92 return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); 93 } catch (IOException e2) { 94 System.setProperty("java.io.tmpdir", "/sdcard"); 95 return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); 96 } 97 } 98 } 99 } 100