diff options
author | Narayan Kamath <narayan@google.com> | 2014-07-16 19:08:02 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-07-16 01:00:53 +0000 |
commit | ce83a28c244b69e9602af84d120494d302decbeb (patch) | |
tree | b76fbf22dddaf8a7f065f4a171aed07665e15c5e | |
parent | 95a18a8f961cdd760b667ad975e4c00d7bd713eb (diff) | |
parent | 2053168eb4506e2f8795afdbe9731c6451e1589c (diff) | |
download | frameworks_base-ce83a28c244b69e9602af84d120494d302decbeb.zip frameworks_base-ce83a28c244b69e9602af84d120494d302decbeb.tar.gz frameworks_base-ce83a28c244b69e9602af84d120494d302decbeb.tar.bz2 |
Merge "Dexopt for Context.createPackageContext when code is included." into lmp-dev
6 files changed, 64 insertions, 28 deletions
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 12e18cc..38614a0 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -56,6 +56,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; +import java.util.Objects; final class IntentReceiverLeaked extends AndroidRuntimeException { public IntentReceiverLeaked(String msg) { @@ -252,6 +253,22 @@ public final class LoadedApk { } if (mIncludeCode && !mPackageName.equals("android")) { + // Avoid the binder call when the package is the current application package. + // The activity manager will perform ensure that dexopt is performed before + // spinning up the process. + if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) { + final String isa = VMRuntime.getRuntime().vmInstructionSet(); + try { + // TODO: We can probably do away with the isa argument since + // the AM and PM have enough information to figure this out + // themselves. If we do need it, we should match it against the + // list of devices ISAs before sending it down to installd. + ActivityThread.getPackageManager().performDexOptIfNeeded(mPackageName, isa); + } catch (RemoteException re) { + // Ignored. + } + } + final ArrayList<String> zipPaths = new ArrayList<>(); final ArrayList<String> libPaths = new ArrayList<>(); diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 3a98f5d..eb46cf0 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -384,10 +384,16 @@ interface IPackageManager { /** * Ask the package manager to perform dex-opt (if needed) on the given - * package, if it already hasn't done mode. Only does this if running - * in the special development "no pre-dexopt" mode. + * package and for the given instruction set if it already hasn't done + * so. + * + * If the supplied instructionSet is null, the package manager will use + * the packages default instruction set. + * + * In most cases, apps are dexopted in advance and this function will + * be a no-op. */ - boolean performDexOpt(String packageName); + boolean performDexOptIfNeeded(String packageName, String instructionSet); /** * Update status of external media on the package manager to scan and diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 43c2b15..ab33d75 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -4201,7 +4201,7 @@ public class PackageParser { public int mPreferredOrder = 0; // For use by package manager to keep track of where it needs to do dexopt. - public boolean mDexOptNeeded = true; + public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4); // For use by package manager to keep track of when a package was last used. public long mLastPackageUsageTimeInMills; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 79cb60e..1316da1 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2809,7 +2809,7 @@ public final class ActivityManagerService extends ActivityManagerNative void ensurePackageDexOpt(String packageName) { IPackageManager pm = AppGlobals.getPackageManager(); try { - if (pm.performDexOpt(packageName)) { + if (pm.performDexOptIfNeeded(packageName, null /* instruction set */)) { mDidDexOpt = true; } } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 1d53016..355f34f 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -75,7 +75,7 @@ public class BackgroundDexOptService extends JobService { schedule(BackgroundDexOptService.this); return; } - pm.performDexOpt(pkg, false); + pm.performDexOpt(pkg, null /* instruction set */, false); } // ran to completion, so we abandon our timeslice and do not reschedule jobFinished(jobParams, false); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 6513c88..0ad3a68 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -26,7 +26,6 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; import static android.content.pm.PackageManager.INSTALL_EXTERNAL; import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS; import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER; -import static android.content.pm.PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE; import static android.content.pm.PackageManager.INSTALL_FAILED_DEXOPT; import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE; import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION; @@ -4542,24 +4541,29 @@ public class PackageManagerService extends IPackageManager.Stub { } PackageParser.Package p = pkg; synchronized (mInstallLock) { - if (p.mDexOptNeeded) { - performDexOptLI(p, false /* force dex */, false /* defer */, - true /* include dependencies */); - } + performDexOptLI(p, null /* instruction sets */, false /* force dex */, false /* defer */, + true /* include dependencies */); } } } } @Override - public boolean performDexOpt(String packageName) { - enforceSystemOrRoot("Only the system can request dexopt be performed"); - return performDexOpt(packageName, true); + public boolean performDexOptIfNeeded(String packageName, String instructionSet) { + return performDexOpt(packageName, instructionSet, true); } - public boolean performDexOpt(String packageName, boolean updateUsage) { + private static String getPrimaryInstructionSet(ApplicationInfo info) { + if (info.primaryCpuAbi == null) { + return getPreferredInstructionSet(); + } + + return VMRuntime.getInstructionSet(info.primaryCpuAbi); + } + public boolean performDexOpt(String packageName, String instructionSet, boolean updateUsage) { PackageParser.Package p; + final String targetInstructionSet; synchronized (mPackages) { p = mPackages.get(packageName); if (p == null) { @@ -4569,13 +4573,17 @@ public class PackageManagerService extends IPackageManager.Stub { p.mLastPackageUsageTimeInMills = System.currentTimeMillis(); } mPackageUsage.write(false); - if (!p.mDexOptNeeded) { + + targetInstructionSet = instructionSet != null ? instructionSet : + getPrimaryInstructionSet(p.applicationInfo); + if (p.mDexOptPerformed.contains(targetInstructionSet)) { return false; } } synchronized (mInstallLock) { - return performDexOptLI(p, false /* force dex */, false /* defer */, + final String[] instructionSets = new String[] { targetInstructionSet }; + return performDexOptLI(p, instructionSets, false /* force dex */, false /* defer */, true /* include dependencies */) == DEX_OPT_PERFORMED; } } @@ -4585,9 +4593,9 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { for (PackageParser.Package p : mPackages.values()) { if (DEBUG_DEXOPT) { - Log.i(TAG, p.packageName + " mDexOptNeeded=" + p.mDexOptNeeded); + Log.i(TAG, p.packageName + " mDexOptPerformed=" + p.mDexOptPerformed.toArray()); } - if (!p.mDexOptNeeded) { + if (!p.mDexOptPerformed.isEmpty()) { continue; } if (pkgs == null) { @@ -4655,6 +4663,10 @@ public class PackageManagerService extends IPackageManager.Stub { // 3.) we are skipping an unneeded dexopt for (String path : paths) { for (String instructionSet : instructionSets) { + if (!forceDex && pkg.mDexOptPerformed.contains(instructionSet)) { + continue; + } + try { final boolean isDexOptNeeded = DexFile.isDexOptNeededInternal(path, pkg.packageName, instructionSet, defer); @@ -4669,10 +4681,10 @@ public class PackageManagerService extends IPackageManager.Stub { // Don't bother running dexopt again if we failed, it will probably // just result in an error again. Also, don't bother dexopting for other // paths & ISAs. - pkg.mDexOptNeeded = false; return DEX_OPT_FAILED; } else { performedDexOpt = true; + pkg.mDexOptPerformed.add(instructionSet); } } @@ -4706,7 +4718,6 @@ public class PackageManagerService extends IPackageManager.Stub { // deferred dex-opt. We've either dex-opted one more paths or instruction sets or // we've skipped all of them because they are up to date. In both cases this // package doesn't need dexopt any longer. - pkg.mDexOptNeeded = false; return performedDexOpt ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; } @@ -4762,8 +4773,8 @@ public class PackageManagerService extends IPackageManager.Stub { return allInstructionSets; } - private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer, - boolean inclDependencies) { + private int performDexOptLI(PackageParser.Package pkg, String[] instructionSets, + boolean forceDex, boolean defer, boolean inclDependencies) { HashSet<String> done; if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) { done = new HashSet<String>(); @@ -4771,7 +4782,7 @@ public class PackageManagerService extends IPackageManager.Stub { } else { done = null; } - return performDexOptLI(pkg, null /* target instruction sets */, forceDex, defer, done); + return performDexOptLI(pkg, instructionSets, forceDex, defer, done); } private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) { @@ -5569,7 +5580,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if ((scanMode&SCAN_NO_DEX) == 0) { - if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false) + if (performDexOptLI(pkg, null /* instruction sets */, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) { if ((scanMode & SCAN_DELETE_DATA_ON_FAILURES) != 0) { removeDataDirsLI(pkg.packageName); @@ -5648,7 +5659,8 @@ public class PackageManagerService extends IPackageManager.Stub { if ((scanMode&SCAN_NO_DEX) == 0) { for (int i=0; i<clientLibPkgs.size(); i++) { PackageParser.Package clientPkg = clientLibPkgs.get(i); - if (performDexOptLI(clientPkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false) + if (performDexOptLI(clientPkg, null /* instruction sets */, + forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) { if ((scanMode & SCAN_DELETE_DATA_ON_FAILURES) != 0) { removeDataDirsLI(pkg.packageName); @@ -6128,7 +6140,8 @@ public class PackageManagerService extends IPackageManager.Stub { ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi; Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + adjustedAbi); - if (performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true) == DEX_OPT_FAILED) { + if (performDexOptLI(ps.pkg, null /* instruction sets */, forceDexOpt, + deferDexOpt, true) == DEX_OPT_FAILED) { ps.primaryCpuAbiString = null; ps.pkg.applicationInfo.primaryCpuAbi = null; return; @@ -10235,7 +10248,7 @@ public class PackageManagerService extends IPackageManager.Stub { * remove the target to make sure there isn't a stale * file from a previous version of the package. */ - newPackage.mDexOptNeeded = true; + newPackage.mDexOptPerformed.clear(); mInstaller.rmdex(oldCodePath, instructionSet); mInstaller.rmdex(newPackage.baseCodePath, instructionSet); } |