17487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov/* 27487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * Copyright (C) 2015 The Android Open Source Project 37487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * 47487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * Licensed under the Apache License, Version 2.0 (the "License"); 57487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * you may not use this file except in compliance with the License. 67487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * You may obtain a copy of the License at 77487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * 87487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * http://www.apache.org/licenses/LICENSE-2.0 97487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * 107487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * Unless required by applicable law or agreed to in writing, software 117487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * distributed under the License is distributed on an "AS IS" BASIS, 127487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * See the License for the specific language governing permissions and 147487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * limitations under the License 157487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov */ 167487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 177487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovpackage com.android.server.pm; 187487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 19b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolovimport android.annotation.Nullable; 20a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolovimport android.content.Context; 217487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport android.content.pm.ApplicationInfo; 227487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport android.content.pm.PackageParser; 23d479b52d12fc782f18df6b5ae15c19e022f0ec14Calin Juravleimport android.os.Environment; 24a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolovimport android.os.PowerManager; 257487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport android.os.UserHandle; 26a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolovimport android.os.WorkSource; 277487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport android.util.Log; 287487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport android.util.Slog; 297487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 30fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkeyimport com.android.internal.os.InstallerConnection.InstallerException; 3188eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamathimport com.android.internal.util.IndentingPrintWriter; 32fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey 33b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolovimport java.io.File; 347487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport java.io.IOException; 357487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport java.util.List; 367487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 377487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport dalvik.system.DexFile; 387487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 39fa54ab7950b7ad7605cb842b47826b71a685bc28Todd Kennedyimport static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE; 40fa54ab7950b7ad7605cb842b47826b71a685bc28Todd Kennedyimport static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE; 41bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampeimport static com.android.server.pm.Installer.DEXOPT_PROFILE_GUIDED; 42fa54ab7950b7ad7605cb842b47826b71a685bc28Todd Kennedyimport static com.android.server.pm.Installer.DEXOPT_PUBLIC; 43fa54ab7950b7ad7605cb842b47826b71a685bc28Todd Kennedyimport static com.android.server.pm.Installer.DEXOPT_SAFEMODE; 447487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport static com.android.server.pm.InstructionSets.getAppDexInstructionSets; 457487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolovimport static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; 4647c170a7460e8455ffc07981916c400fa980433aAndreas Gampeimport static com.android.server.pm.PackageManagerServiceCompilerMapping.getNonProfileGuidedCompilerFilter; 477487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 487487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov/** 497487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * Helper class for running dexopt command on packages. 507487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov */ 51a89087542f774c585b6a6ec535fc294721710521Andreas Gampeclass PackageDexOptimizer { 52b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov private static final String TAG = "PackageManager.DexOptimizer"; 53b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov static final String OAT_DIR_NAME = "oat"; 54b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov // TODO b/19550105 Remove error codes and use exceptions 557487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov static final int DEX_OPT_SKIPPED = 0; 567487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov static final int DEX_OPT_PERFORMED = 1; 577487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov static final int DEX_OPT_FAILED = -1; 587487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 59a89087542f774c585b6a6ec535fc294721710521Andreas Gampe private final Installer mInstaller; 60a89087542f774c585b6a6ec535fc294721710521Andreas Gampe private final Object mInstallLock; 617487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 62a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov private final PowerManager.WakeLock mDexoptWakeLock; 63a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov private volatile boolean mSystemReady; 64a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov 65a89087542f774c585b6a6ec535fc294721710521Andreas Gampe PackageDexOptimizer(Installer installer, Object installLock, Context context, 66a89087542f774c585b6a6ec535fc294721710521Andreas Gampe String wakeLockTag) { 67a89087542f774c585b6a6ec535fc294721710521Andreas Gampe this.mInstaller = installer; 68a89087542f774c585b6a6ec535fc294721710521Andreas Gampe this.mInstallLock = installLock; 69a89087542f774c585b6a6ec535fc294721710521Andreas Gampe 70a89087542f774c585b6a6ec535fc294721710521Andreas Gampe PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 71a89087542f774c585b6a6ec535fc294721710521Andreas Gampe mDexoptWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLockTag); 72a89087542f774c585b6a6ec535fc294721710521Andreas Gampe } 73a89087542f774c585b6a6ec535fc294721710521Andreas Gampe 74a89087542f774c585b6a6ec535fc294721710521Andreas Gampe protected PackageDexOptimizer(PackageDexOptimizer from) { 75a89087542f774c585b6a6ec535fc294721710521Andreas Gampe this.mInstaller = from.mInstaller; 76a89087542f774c585b6a6ec535fc294721710521Andreas Gampe this.mInstallLock = from.mInstallLock; 77a89087542f774c585b6a6ec535fc294721710521Andreas Gampe this.mDexoptWakeLock = from.mDexoptWakeLock; 78a89087542f774c585b6a6ec535fc294721710521Andreas Gampe this.mSystemReady = from.mSystemReady; 797487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov } 807487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 81db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle static boolean canOptimizePackage(PackageParser.Package pkg) { 826dfd83dbe88bd461f5aab224ced0830b07db1c03Calin Juravle return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0; 83db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle } 84db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle 857487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov /** 867487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * Performs dexopt on all code paths and libraries of the specified package for specified 877487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * instruction sets. 887487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov * 89a89087542f774c585b6a6ec535fc294721710521Andreas Gampe * <p>Calls to {@link com.android.server.pm.Installer#dexopt} on {@link #mInstaller} are 90a89087542f774c585b6a6ec535fc294721710521Andreas Gampe * synchronized on {@link #mInstallLock}. 917487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov */ 92c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries, 9337e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe String[] instructionSets, boolean checkProfiles, String targetCompilationFilter, 9437e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe CompilerStats.PackageStats packageStats) { 95a89087542f774c585b6a6ec535fc294721710521Andreas Gampe synchronized (mInstallLock) { 96a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov final boolean useLock = mSystemReady; 97a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov if (useLock) { 98a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov mDexoptWakeLock.setWorkSource(new WorkSource(pkg.applicationInfo.uid)); 99a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov mDexoptWakeLock.acquire(); 100a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov } 101a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov try { 102c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles, 10337e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe targetCompilationFilter, packageStats); 104a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov } finally { 105a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov if (useLock) { 106a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov mDexoptWakeLock.release(); 107a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov } 108a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov } 1097487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov } 1107487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov } 1117487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 112a89087542f774c585b6a6ec535fc294721710521Andreas Gampe /** 113a89087542f774c585b6a6ec535fc294721710521Andreas Gampe * Adjust the given dexopt-needed value. Can be overridden to influence the decision to 114a89087542f774c585b6a6ec535fc294721710521Andreas Gampe * optimize or not (and in what way). 115a89087542f774c585b6a6ec535fc294721710521Andreas Gampe */ 116a89087542f774c585b6a6ec535fc294721710521Andreas Gampe protected int adjustDexoptNeeded(int dexoptNeeded) { 117a89087542f774c585b6a6ec535fc294721710521Andreas Gampe return dexoptNeeded; 118a89087542f774c585b6a6ec535fc294721710521Andreas Gampe } 119a89087542f774c585b6a6ec535fc294721710521Andreas Gampe 120a89087542f774c585b6a6ec535fc294721710521Andreas Gampe /** 121a89087542f774c585b6a6ec535fc294721710521Andreas Gampe * Adjust the given dexopt flags that will be passed to the installer. 122a89087542f774c585b6a6ec535fc294721710521Andreas Gampe */ 123a89087542f774c585b6a6ec535fc294721710521Andreas Gampe protected int adjustDexoptFlags(int dexoptFlags) { 124a89087542f774c585b6a6ec535fc294721710521Andreas Gampe return dexoptFlags; 125a89087542f774c585b6a6ec535fc294721710521Andreas Gampe } 126a89087542f774c585b6a6ec535fc294721710521Andreas Gampe 12788eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath /** 12888eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath * Dumps the dexopt state of the given package {@code pkg} to the given {@code PrintWriter}. 12988eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath */ 13088eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath void dumpDexoptState(IndentingPrintWriter pw, PackageParser.Package pkg) { 13188eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo); 13288eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); 13388eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath 13488eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly(); 13588eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath 13688eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath for (String instructionSet : dexCodeInstructionSets) { 13788eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath pw.println("Instruction Set: " + instructionSet); 13888eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath pw.increaseIndent(); 13988eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath for (String path : paths) { 14088eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath String status = null; 14188eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath try { 14288eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath status = DexFile.getDexFileStatus(path, instructionSet); 14388eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath } catch (IOException ioe) { 14488eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath status = "[Exception]: " + ioe.getMessage(); 14588eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath } 14688eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath pw.println("path: " + path); 14788eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath pw.println("status: " + status); 14888eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath } 14988eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath pw.decreaseIndent(); 15088eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath } 15188eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath } 15288eea9e580a6b2ee804a092f851b5325355fcdceNarayan Kamath 153c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries, 15437e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe String[] targetInstructionSets, boolean checkProfiles, String targetCompilerFilter, 15537e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe CompilerStats.PackageStats packageStats) { 1567487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov final String[] instructionSets = targetInstructionSets != null ? 1577487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); 1587487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 159db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle if (!canOptimizePackage(pkg)) { 1607487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov return DEX_OPT_SKIPPED; 1617487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov } 1627487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 163bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly(); 164bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); 165bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe 166bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe boolean isProfileGuidedFilter = DexFile.isProfileGuidedCompilerFilter(targetCompilerFilter); 167bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe // If any part of the app is used by other apps, we cannot use profile-guided 168bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe // compilation. 16990e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil if (isProfileGuidedFilter && isUsedByOtherApps(pkg)) { 17090e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil checkProfiles = false; 171bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe 17290e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil targetCompilerFilter = getNonProfileGuidedCompilerFilter(targetCompilerFilter); 17390e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil if (DexFile.isProfileGuidedCompilerFilter(targetCompilerFilter)) { 17490e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil throw new IllegalStateException(targetCompilerFilter); 175bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe } 17690e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil isProfileGuidedFilter = false; 177bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe } 178bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe 179bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe // If we're asked to take profile updates into account, check now. 180bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe boolean newProfile = false; 181bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe if (checkProfiles && isProfileGuidedFilter) { 182bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe // Merge profiles, see if we need to do anything. 183bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe try { 184bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe newProfile = mInstaller.mergeProfiles(sharedGid, pkg.packageName); 185bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe } catch (InstallerException e) { 186bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe Slog.w(TAG, "Failed to merge profiles", e); 187bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe } 188bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe } 189bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe 1907487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov final boolean vmSafeMode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0; 1917487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov final boolean debuggable = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; 1927487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 1937487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov boolean performedDexOpt = false; 1946a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil boolean successfulDexOpt = true; 1956a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil 1967487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); 1977487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov for (String dexCodeInstructionSet : dexCodeInstructionSets) { 1987487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov for (String path : paths) { 199db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle int dexoptNeeded; 200a89087542f774c585b6a6ec535fc294721710521Andreas Gampe try { 201693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle dexoptNeeded = DexFile.getDexOptNeeded(path, 202bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe dexCodeInstructionSet, targetCompilerFilter, newProfile); 203a89087542f774c585b6a6ec535fc294721710521Andreas Gampe } catch (IOException ioe) { 204a89087542f774c585b6a6ec535fc294721710521Andreas Gampe Slog.w(TAG, "IOException reading apk: " + path, ioe); 205a89087542f774c585b6a6ec535fc294721710521Andreas Gampe return DEX_OPT_FAILED; 20601dcb76fec4ee2ff3a3dc4516a37c144d771f18cNarayan Kamath } 207a89087542f774c585b6a6ec535fc294721710521Andreas Gampe dexoptNeeded = adjustDexoptNeeded(dexoptNeeded); 20847c170a7460e8455ffc07981916c400fa980433aAndreas Gampe if (PackageManagerService.DEBUG_DEXOPT) { 20947c170a7460e8455ffc07981916c400fa980433aAndreas Gampe Log.i(TAG, "DexoptNeeded for " + path + "@" + targetCompilerFilter + " is " + 21047c170a7460e8455ffc07981916c400fa980433aAndreas Gampe dexoptNeeded); 21147c170a7460e8455ffc07981916c400fa980433aAndreas Gampe } 2127b08b35bde3df58816b171b88712bcc6d21dcbe8Richard Uhler 213db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle final String dexoptType; 214db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle String oatDir = null; 215693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle switch (dexoptNeeded) { 216693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle case DexFile.NO_DEXOPT_NEEDED: 217693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle continue; 218693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle case DexFile.DEX2OAT_NEEDED: 219693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle dexoptType = "dex2oat"; 220693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet); 221693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle break; 222693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle case DexFile.PATCHOAT_NEEDED: 223693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle dexoptType = "patchoat"; 224693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle break; 225693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle case DexFile.SELF_PATCHOAT_NEEDED: 226693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle dexoptType = "self patchoat"; 227693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle break; 228693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle default: 229693f997cc8b8c2ba8d3ed29627b2641dd86392a5Calin Juravle throw new IllegalStateException("Invalid dexopt:" + dexoptNeeded); 230db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle } 23101dcb76fec4ee2ff3a3dc4516a37c144d771f18cNarayan Kamath 232c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao String sharedLibrariesPath = null; 233c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao if (sharedLibraries != null && sharedLibraries.length != 0) { 234c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao StringBuilder sb = new StringBuilder(); 235c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao for (String lib : sharedLibraries) { 236c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao if (sb.length() != 0) { 237c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao sb.append(":"); 238c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao } 239c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao sb.append(lib); 240c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao } 241c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao sharedLibrariesPath = sb.toString(); 242c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao } 243db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg=" 244db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet 245db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable 246c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao + " target-filter=" + targetCompilerFilter + " oatDir = " + oatDir 247c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao + " sharedLibraries=" + sharedLibrariesPath); 248d479b52d12fc782f18df6b5ae15c19e022f0ec14Calin Juravle // Profile guide compiled oat files should not be public. 249bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe final boolean isPublic = !pkg.isForwardLocked() && !isProfileGuidedFilter; 250bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe final int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0; 251a89087542f774c585b6a6ec535fc294721710521Andreas Gampe final int dexFlags = adjustDexoptFlags( 252d479b52d12fc782f18df6b5ae15c19e022f0ec14Calin Juravle ( isPublic ? DEXOPT_PUBLIC : 0) 253db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle | (vmSafeMode ? DEXOPT_SAFEMODE : 0) 254db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle | (debuggable ? DEXOPT_DEBUGGABLE : 0) 255bdd30d86ef98456161069d11481b2ccd25a11b4eAndreas Gampe | profileFlag 256a89087542f774c585b6a6ec535fc294721710521Andreas Gampe | DEXOPT_BOOTCOMPLETE); 257a89087542f774c585b6a6ec535fc294721710521Andreas Gampe 258db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle try { 25937e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe long startTime = System.currentTimeMillis(); 26037e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe 261a89087542f774c585b6a6ec535fc294721710521Andreas Gampe mInstaller.dexopt(path, sharedGid, pkg.packageName, dexCodeInstructionSet, 262c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao dexoptNeeded, oatDir, dexFlags, targetCompilerFilter, pkg.volumeUuid, 263c7b9482b0c4bb2d378e63541b96be45c50094e05Jeff Hao sharedLibrariesPath); 264db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle performedDexOpt = true; 26537e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe 26637e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe if (packageStats != null) { 26737e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe long endTime = System.currentTimeMillis(); 26837e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe packageStats.setCompileTime(path, (int)(endTime - startTime)); 26937e5fdc6b4963f3533caecdd92b129f79da69dd8Andreas Gampe } 270db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle } catch (InstallerException e) { 271db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle Slog.w(TAG, "Failed to dexopt", e); 2726a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil successfulDexOpt = false; 2737487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov } 2747487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov } 2757487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov } 2767487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 2776a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil if (successfulDexOpt) { 2786a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil // If we've gotten here, we're sure that no error occurred. We've either 2796a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil // dex-opted one or more paths or instruction sets or we've skipped 2806a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil // all of them because they are up to date. In both cases this package 2816a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil // doesn't need dexopt any longer. 2826a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil return performedDexOpt ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; 2836a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil } else { 2846a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil return DEX_OPT_FAILED; 2856a3b2d2bc63254a412eb546ed371fce8f4337434David Brazdil } 2867487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov } 2877487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov 288b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov /** 289b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov * Creates oat dir for the specified package. In certain cases oat directory 290b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov * <strong>cannot</strong> be created: 291b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov * <ul> 292b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov * <li>{@code pkg} is a system app, which is not updated.</li> 293b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov * <li>Package location is not a directory, i.e. monolithic install.</li> 294b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov * </ul> 295b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov * 2967b08b35bde3df58816b171b88712bcc6d21dcbe8Richard Uhler * @return Absolute path to the oat directory or null, if oat directory 2977b08b35bde3df58816b171b88712bcc6d21dcbe8Richard Uhler * cannot be created. 298b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov */ 299b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov @Nullable 30027c24fb8b85c36298de053699b1967a808c6d308Todd Kennedy private String createOatDirIfSupported(PackageParser.Package pkg, String dexInstructionSet) { 301ebcac16cb1405bf7d0b570e11a287df078edfc1cFyodor Kupolov if (!pkg.canHaveOatDir()) { 302b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov return null; 303b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov } 304b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov File codePath = new File(pkg.codePath); 305b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov if (codePath.isDirectory()) { 306b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov File oatDir = getOatDir(codePath); 307fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey try { 308a89087542f774c585b6a6ec535fc294721710521Andreas Gampe mInstaller.createOatDir(oatDir.getAbsolutePath(), dexInstructionSet); 309fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } catch (InstallerException e) { 310fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey Slog.w(TAG, "Failed to create oat dir", e); 311fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey return null; 312fdeeeea6cfdebdb98dd70a7dd48965743af01750Jeff Sharkey } 3137b08b35bde3df58816b171b88712bcc6d21dcbe8Richard Uhler return oatDir.getAbsolutePath(); 314b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov } 315b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov return null; 316b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov } 317b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov 318b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov static File getOatDir(File codePath) { 319b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov return new File(codePath, OAT_DIR_NAME); 320b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov } 321b94c1657eb0140f7b91f5372a9f76de5a3d87e36Fyodor Kupolov 322a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov void systemReady() { 323a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov mSystemReady = true; 324a627c094e67f640dfe3b2ac0b633edcf51270cf4Fyodor Kupolov } 325a89087542f774c585b6a6ec535fc294721710521Andreas Gampe 32690e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil /** 32790e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil * Returns true if the profiling data collected for the given app indicate 32890e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil * that the apps's APK has been loaded by another app. 32990e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil * Note that this returns false for all forward-locked apps and apps without 33090e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil * any collected profiling data. 33190e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil */ 33290e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil public static boolean isUsedByOtherApps(PackageParser.Package pkg) { 33390e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil if (pkg.isForwardLocked()) { 33490e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil // Skip the check for forward locked packages since they don't share their code. 33590e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil return false; 336d479b52d12fc782f18df6b5ae15c19e022f0ec14Calin Juravle } 33790e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil 33890e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil for (String apkPath : pkg.getAllCodePathsExcludingResourceOnly()) { 33990e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil try { 3406d99f796711882ba60977c211d0f92252fe7ad4aNarayan Kamath apkPath = PackageManagerServiceUtils.realpath(new File(apkPath)); 34190e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil } catch (IOException e) { 34290e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil // Log an error but continue without it. 34390e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil Slog.w(TAG, "Failed to get canonical path", e); 3446d99f796711882ba60977c211d0f92252fe7ad4aNarayan Kamath continue; 34590e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil } 34690e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil String useMarker = apkPath.replace('/', '@'); 34790e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); 34890e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil for (int i = 0; i < currentUserIds.length; i++) { 34990e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil File profileDir = 35090e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil Environment.getDataProfilesDeForeignDexDirectory(currentUserIds[i]); 35190e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil File foreignUseMark = new File(profileDir, useMarker); 35290e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil if (foreignUseMark.exists()) { 35390e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil return true; 35490e269917e1d8f9fadb12c3528b8c360b2271e82David Brazdil } 355d479b52d12fc782f18df6b5ae15c19e022f0ec14Calin Juravle } 356d479b52d12fc782f18df6b5ae15c19e022f0ec14Calin Juravle } 357d479b52d12fc782f18df6b5ae15c19e022f0ec14Calin Juravle return false; 358d479b52d12fc782f18df6b5ae15c19e022f0ec14Calin Juravle } 359d479b52d12fc782f18df6b5ae15c19e022f0ec14Calin Juravle 360a89087542f774c585b6a6ec535fc294721710521Andreas Gampe /** 361a89087542f774c585b6a6ec535fc294721710521Andreas Gampe * A specialized PackageDexOptimizer that overrides already-installed checks, forcing a 362a89087542f774c585b6a6ec535fc294721710521Andreas Gampe * dexopt path. 363a89087542f774c585b6a6ec535fc294721710521Andreas Gampe */ 364a89087542f774c585b6a6ec535fc294721710521Andreas Gampe public static class ForcedUpdatePackageDexOptimizer extends PackageDexOptimizer { 365a89087542f774c585b6a6ec535fc294721710521Andreas Gampe 366a89087542f774c585b6a6ec535fc294721710521Andreas Gampe public ForcedUpdatePackageDexOptimizer(Installer installer, Object installLock, 367a89087542f774c585b6a6ec535fc294721710521Andreas Gampe Context context, String wakeLockTag) { 368a89087542f774c585b6a6ec535fc294721710521Andreas Gampe super(installer, installLock, context, wakeLockTag); 369a89087542f774c585b6a6ec535fc294721710521Andreas Gampe } 370a89087542f774c585b6a6ec535fc294721710521Andreas Gampe 371a89087542f774c585b6a6ec535fc294721710521Andreas Gampe public ForcedUpdatePackageDexOptimizer(PackageDexOptimizer from) { 372a89087542f774c585b6a6ec535fc294721710521Andreas Gampe super(from); 373a89087542f774c585b6a6ec535fc294721710521Andreas Gampe } 374a89087542f774c585b6a6ec535fc294721710521Andreas Gampe 375a89087542f774c585b6a6ec535fc294721710521Andreas Gampe @Override 376a89087542f774c585b6a6ec535fc294721710521Andreas Gampe protected int adjustDexoptNeeded(int dexoptNeeded) { 377a89087542f774c585b6a6ec535fc294721710521Andreas Gampe // Ensure compilation, no matter the current state. 378a89087542f774c585b6a6ec535fc294721710521Andreas Gampe // TODO: The return value is wrong when patchoat is needed. 379a89087542f774c585b6a6ec535fc294721710521Andreas Gampe return DexFile.DEX2OAT_NEEDED; 380a89087542f774c585b6a6ec535fc294721710521Andreas Gampe } 381a89087542f774c585b6a6ec535fc294721710521Andreas Gampe } 3827487657ee9f3f91a1fb4e52ce2a03b56496ac1f4Fyodor Kupolov} 383