import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
import static com.android.server.pm.Installer.DEXOPT_PUBLIC;
import static com.android.server.pm.Installer.DEXOPT_SAFEMODE;
-import static com.android.server.pm.Installer.DEXOPT_USEJIT;
+import static com.android.server.pm.Installer.DEXOPT_EXTRACTONLY;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
* {@link PackageManagerService#mInstallLock}.
*/
int performDexOpt(PackageParser.Package pkg, String[] instructionSets,
- boolean inclDependencies, String volumeUuid, boolean useProfiles) {
+ boolean inclDependencies, String volumeUuid, boolean useProfiles, boolean extractOnly) {
ArraySet<String> done;
if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
done = new ArraySet<String>();
mDexoptWakeLock.acquire();
}
try {
- return performDexOptLI(pkg, instructionSets, done, volumeUuid, useProfiles);
+ return performDexOptLI(pkg, instructionSets, done, volumeUuid, useProfiles,
+ extractOnly);
} finally {
if (useLock) {
mDexoptWakeLock.release();
}
private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
- ArraySet<String> done, String volumeUuid, boolean useProfiles) {
+ ArraySet<String> done, String volumeUuid, boolean useProfiles, boolean extractOnly) {
final String[] instructionSets = targetInstructionSets != null ?
targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+ pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+ " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
- + " oatDir = " + oatDir);
+ + " extractOnly=" + extractOnly + " oatDir = " + oatDir);
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
final int dexFlags =
(!pkg.isForwardLocked() ? DEXOPT_PUBLIC : 0)
| (vmSafeMode ? DEXOPT_SAFEMODE : 0)
| (debuggable ? DEXOPT_DEBUGGABLE : 0)
+ | (extractOnly ? DEXOPT_EXTRACTONLY : 0)
| DEXOPT_BOOTCOMPLETE;
try {
mPackageManagerService.mInstaller.dexopt(path, sharedGid,
}
}
- // At this point we haven't failed dexopt and we haven't deferred dexopt. We must
- // either have either succeeded dexopt, or have had getDexOptNeeded tell us
- // it isn't required. We therefore mark that this package doesn't need dexopt unless
- // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped
- // it.
- pkg.mDexOptPerformed.add(dexCodeInstructionSet);
+ if (!extractOnly) {
+ // At this point we haven't failed dexopt and we haven't deferred dexopt. We must
+ // either have either succeeded dexopt, or have had getDexOptNeeded tell us
+ // it isn't required. We therefore mark that this package doesn't need dexopt unless
+ // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped
+ // it.
+ pkg.mDexOptPerformed.add(dexCodeInstructionSet);
+ }
}
// If we've gotten here, we're sure that no error occurred and that we haven't
// TODO: Analyze and investigate if we (should) profile libraries.
// Currently this will do a full compilation of the library.
performDexOptLI(libPkg, instructionSets, done,
- StorageManager.UUID_PRIVATE_INTERNAL, /*useProfiles*/ false);
+ StorageManager.UUID_PRIVATE_INTERNAL, /*useProfiles*/ false,
+ /* extractOnly */ false);
}
}
}
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_DEXOPT;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
import static android.content.pm.PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID;
// List of packages names to keep cached, even if they are uninstalled for all users
private List<String> mKeepUninstalledPackages;
+ private boolean mUseJitProfiles =
+ SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
+
private static class IFVerificationParams {
PackageParser.Package pkg;
boolean replacing;
}
}
+ @Override
+ public void extractPackagesIfNeeded() {
+ enforceSystemOrRoot("Only the system can request package extraction");
+
+ // Extract pacakges only if profile-guided compilation is enabled because
+ // otherwise BackgroundDexOptService will not dexopt them later.
+ if (mUseJitProfiles) {
+ ArraySet<String> pkgs = getOptimizablePackages();
+ if (pkgs != null) {
+ for (String pkg : pkgs) {
+ performDexOpt(pkg, null /* instructionSet */, false /* useProfiles */,
+ true /* extractOnly */);
+ }
+ }
+ }
+ }
+
private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
List<ResolveInfo> ris = null;
try {
// TODO: this is not used nor needed. Delete it.
@Override
public boolean performDexOptIfNeeded(String packageName, String instructionSet) {
- return performDexOptTraced(packageName, instructionSet, false);
+ return performDexOptTraced(packageName, instructionSet, false /* useProfiles */,
+ false /* extractOnly */);
}
- public boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles) {
- return performDexOptTraced(packageName, instructionSet, useProfiles);
+ public boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles,
+ boolean extractOnly) {
+ return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly);
}
private boolean performDexOptTraced(String packageName, String instructionSet,
- boolean useProfiles) {
+ boolean useProfiles, boolean extractOnly) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
try {
- return performDexOptInternal(packageName, instructionSet, useProfiles);
+ return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
private boolean performDexOptInternal(String packageName, String instructionSet,
- boolean useProfiles) {
+ boolean useProfiles, boolean extractOnly) {
PackageParser.Package p;
final String targetInstructionSet;
synchronized (mPackages) {
synchronized (mInstallLock) {
final String[] instructionSets = new String[] { targetInstructionSet };
int result = mPackageDexOptimizer.performDexOpt(p, instructionSets,
- true /* inclDependencies */, p.volumeUuid, useProfiles);
+ true /* inclDependencies */, p.volumeUuid, useProfiles, extractOnly);
return result == PackageDexOptimizer.DEX_OPT_PERFORMED;
}
} finally {
// Whoever is calling forceDexOpt wants a fully compiled package.
// Don't use profiles since that may cause compilation to be skipped.
final int res = mPackageDexOptimizer.performDexOpt(pkg, instructionSets,
- true /* inclDependencies */, pkg.volumeUuid, false /* useProfiles */);
+ true /* inclDependencies */, pkg.volumeUuid, false /* useProfiles */,
+ false /* extractOnly */);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");
return;
}
+
+ // Extract package to save the VM unzipping the APK in memory during
+ // launch. Only do this if profile-guided compilation is enabled because
+ // otherwise BackgroundDexOptService will not dexopt the package later.
+ if (mUseJitProfiles) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+ // Do not run PackageDexOptimizer through the local performDexOpt
+ // method because `pkg` is not in `mPackages` yet.
+ int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
+ false /* inclDependencies */, volumeUuid, false /* useProfiles */,
+ true /* extractOnly */);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
+ String msg = "Extracking package failed for " + pkgName;
+ res.setError(INSTALL_FAILED_DEXOPT, msg);
+ return;
+ }
+ }
}
if (!args.doRename(res.returnCode, pkg, oldCodePath)) {