diff options
| author | 2017-07-17 15:12:01 -0700 | |
|---|---|---|
| committer | 2017-10-31 14:51:57 -0700 | |
| commit | dea3fd8cf1000d786ff40e1036a8bf76a55d5fcd (patch) | |
| tree | 410c1ad05d42c927224b122648d1fd5a6657e405 | |
| parent | 3aeca17aa911394e7a4d2c1536b28423cb135b53 (diff) | |
Refactor the arguments passed to dexopt invocations
Wrap the arguments passed to the various performDexopt calls into the
DexoptOptions object.
This will make adding extra arguments (like compile only a split) much
easier and avoid extending quite a few internal methods.
(cherry picked from commit 1d0e83d2cee794ba576d573119e826905a4422cd)
Bug: 38138251
Test: adb shell cmd package compile ....
adb shell cmd package bg-dexopt-job ...
install new apps and check that they compiled
runtest -x
services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
Merged-In: Ia9930edd2dceb7535d6168eceb8e3199c82b6306
Change-Id: Ia9930edd2dceb7535d6168eceb8e3199c82b6306
8 files changed, 347 insertions, 154 deletions
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index e5e7b779ff6a..3fc95c669622 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -508,14 +508,6 @@ interface IPackageManager { in boolean isSharedModule, IDexModuleRegisterCallback callback); /** - * Ask the package manager to perform a dex-opt for the given reason. The package - * manager will map the reason to a compiler filter according to the current system - * configuration. - */ - boolean performDexOpt(String packageName, boolean checkProfiles, - int compileReason, boolean force, boolean bootComplete, boolean downgrade); - - /** * Ask the package manager to perform a dex-opt with the given compiler filter. * * Note: exposed only for the shell command to allow moving packages explicitly to a diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 34092ad6607a..914e81e64ef6 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -37,6 +37,7 @@ import android.util.Log; import com.android.server.pm.dex.DexManager; import com.android.server.LocalServices; import com.android.server.PinnerService; +import com.android.server.pm.dex.DexoptOptions; import java.io.File; import java.util.Set; @@ -217,12 +218,10 @@ public class BackgroundDexOptService extends JobService { // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a // trade-off worth doing to save boot time work. - int result = pm.performDexOptWithStatus(pkg, - /* checkProfiles */ false, + int result = pm.performDexOptWithStatus(new DexoptOptions( + pkg, PackageManagerService.REASON_BOOT, - /* force */ false, - /* bootComplete */ true, - /* downgrade */ false); + DexoptOptions.DEXOPT_BOOT_COMPLETE)); if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) { updatedPackages.add(pkg); } @@ -334,22 +333,22 @@ public class BackgroundDexOptService extends JobService { // Optimize package if needed. Note that there can be no race between // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. boolean success; + int dexoptFlags = + DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES | + DexoptOptions.DEXOPT_BOOT_COMPLETE | + (downgrade ? DexoptOptions.DEXOPT_DOWNGRADE : 0); if (is_for_primary_dex) { - int result = pm.performDexOptWithStatus(pkg, - /* checkProfiles */ true, - reason, - false /* forceCompile*/, - true /* bootComplete */, - downgrade); + int result = pm.performDexOptWithStatus(new DexoptOptions(pkg, + PackageManagerService.REASON_BACKGROUND_DEXOPT, + dexoptFlags)); success = result != PackageDexOptimizer.DEX_OPT_FAILED; if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) { updatedPackages.add(pkg); } } else { - success = pm.performDexOptSecondary(pkg, - reason, - false /* force */, - downgrade); + success = pm.performDexOpt(new DexoptOptions(pkg, + PackageManagerService.REASON_BACKGROUND_DEXOPT, + dexoptFlags | DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX)); } if (success) { // Dexopt succeeded, remove package from the list of failing ones. diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 4ff6cbf1e1c8..241d76f8a0ac 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -18,7 +18,6 @@ package com.android.server.pm; import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; -import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason; import android.annotation.Nullable; import android.content.Context; @@ -35,6 +34,7 @@ import android.util.Slog; import com.android.internal.logging.MetricsLogger; import com.android.server.pm.Installer.InstallerException; +import com.android.server.pm.dex.DexoptOptions; import java.io.File; import java.io.FileDescriptor; @@ -314,19 +314,19 @@ public class OtaDexoptService extends IOtaDexopt.Stub { libraryDependencies = NO_LIBRARIES; } + optimizer.performDexOpt(pkg, libraryDependencies, - null /* ISAs */, false /* checkProfiles */, - getCompilerFilterForReason(compilationReason), + null /* ISAs */, null /* CompilerStats.PackageStats */, mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), - true /* bootComplete */, - false /* downgrade */); - - mPackageManagerService.getDexManager().dexoptSecondaryDex(pkg.packageName, - getCompilerFilterForReason(compilationReason), - false /* force */, - false /* compileOnlySharedDex */, - false /* downgrade */); + new DexoptOptions(pkg.packageName, compilationReason, + DexoptOptions.DEXOPT_BOOT_COMPLETE)); + + mPackageManagerService.getDexManager().dexoptSecondaryDex( + new DexoptOptions(pkg.packageName, compilationReason, + DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX | + DexoptOptions.DEXOPT_BOOT_COMPLETE)); + return commands; } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 644bab1fc260..406466507606 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -19,9 +19,7 @@ package com.android.server.pm; import android.annotation.Nullable; import android.content.Context; import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; import android.content.pm.PackageParser; -import android.os.Environment; import android.os.FileUtils; import android.os.PowerManager; import android.os.SystemClock; @@ -35,6 +33,7 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.pm.Installer.InstallerException; +import com.android.server.pm.dex.DexoptOptions; import java.io.File; import java.io.IOException; @@ -123,18 +122,16 @@ public class PackageDexOptimizer { * synchronized on {@link #mInstallLock}. */ int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries, - String[] instructionSets, boolean checkProfiles, String targetCompilationFilter, - CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps, - boolean bootComplete, boolean downgrade) { + String[] instructionSets, CompilerStats.PackageStats packageStats, + boolean isUsedByOtherApps, DexoptOptions options) { if (!canOptimizePackage(pkg)) { return DEX_OPT_SKIPPED; } synchronized (mInstallLock) { final long acquireTime = acquireWakeLockLI(pkg.applicationInfo.uid); try { - return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles, - targetCompilationFilter, packageStats, isUsedByOtherApps, bootComplete, - downgrade); + return performDexOptLI(pkg, sharedLibraries, instructionSets, + packageStats, isUsedByOtherApps, options); } finally { releaseWakeLockLI(acquireTime); } @@ -147,9 +144,8 @@ public class PackageDexOptimizer { */ @GuardedBy("mInstallLock") private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries, - String[] targetInstructionSets, boolean checkForProfileUpdates, - String targetCompilerFilter, CompilerStats.PackageStats packageStats, - boolean isUsedByOtherApps, boolean bootComplete, boolean downgrade) { + String[] targetInstructionSets, CompilerStats.PackageStats packageStats, + boolean isUsedByOtherApps, DexoptOptions options) { final String[] instructionSets = targetInstructionSets != null ? targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); @@ -157,13 +153,13 @@ public class PackageDexOptimizer { final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo, - targetCompilerFilter, isUsedByOtherApps); - final boolean profileUpdated = checkForProfileUpdates && + options.getCompilerFilter(), isUsedByOtherApps); + final boolean profileUpdated = options.isCheckForProfileUpdates() && isProfileUpdated(pkg, sharedGid, compilerFilter); final String sharedLibrariesPath = getSharedLibrariesPath(sharedLibraries); // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct flags. - final int dexoptFlags = getDexFlags(pkg, compilerFilter, bootComplete); + final int dexoptFlags = getDexFlags(pkg, compilerFilter, options.isBootComplete()); // Get the dependencies of each split in the package. For each code path in the package, // this array contains the relative paths of each split it depends on, separated by colons. String[] splitDependencies = getSplitDependencies(pkg); @@ -187,7 +183,7 @@ public class PackageDexOptimizer { for (String dexCodeIsa : dexCodeInstructionSets) { int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter, profileUpdated, sharedLibrariesPathWithSplits, dexoptFlags, sharedGid, packageStats, - downgrade); + options.isDowngrade()); // The end result is: // - FAILED if any path failed, // - PERFORMED if at least one path needed compilation, diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 6d501bb94299..0b126a4d87d9 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -280,6 +280,7 @@ import com.android.server.pm.PermissionsState.PermissionState; import com.android.server.pm.Settings.DatabaseVersion; import com.android.server.pm.Settings.VersionInfo; import com.android.server.pm.dex.DexManager; +import com.android.server.pm.dex.DexoptOptions; import com.android.server.pm.dex.PackageDexUsage; import com.android.server.storage.DeviceStorageMonitorInternal; @@ -9394,22 +9395,23 @@ public class PackageManagerService extends IPackageManager.Stub // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a // trade-off worth doing to save boot time work. - int primaryDexOptStaus = performDexOptTraced(pkg.packageName, - false /* checkProfiles */, + int dexoptFlags = bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0; + int primaryDexOptStaus = performDexOptTraced(new DexoptOptions( + pkg.packageName, compilerFilter, - false /* force */, - bootComplete, - false /* downgrade */); + dexoptFlags)); boolean secondaryDexOptStatus = true; if (pkg.isSystemApp()) { // Only dexopt shared secondary dex files belonging to system apps to not slow down // too much boot after an OTA. - secondaryDexOptStatus = mDexManager.dexoptSecondaryDex(pkg.packageName, + int secondaryDexoptFlags = dexoptFlags | + DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX | + DexoptOptions.DEXOPT_ONLY_SHARED_DEX; + mDexManager.dexoptSecondaryDex(new DexoptOptions( + pkg.packageName, compilerFilter, - false /* force */, - true /* compileOnlySharedDex */, - false /* downgrade */); + secondaryDexoptFlags)); } if (secondaryDexOptStatus) { @@ -9495,19 +9497,52 @@ public class PackageManagerService extends IPackageManager.Stub } } + /** + * Ask the package manager to perform a dex-opt with the given compiler filter. + * + * Note: exposed only for the shell command to allow moving packages explicitly to a + * definite state. + */ + @Override + public boolean performDexOptMode(String packageName, + boolean checkProfiles, String targetCompilerFilter, boolean force, + boolean bootComplete) { + int flags = (checkProfiles ? DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES : 0) | + (force ? DexoptOptions.DEXOPT_FORCE : 0) | + (bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0); + return performDexOpt(new DexoptOptions(packageName, targetCompilerFilter, flags)); + } + + /** + * Ask the package manager to perform a dex-opt with the given compiler filter on the + * secondary dex files belonging to the given package. + * + * Note: exposed only for the shell command to allow moving packages explicitly to a + * definite state. + */ @Override - public boolean performDexOpt(String packageName, - boolean checkProfiles, int compileReason, boolean force, boolean bootComplete, - boolean downgrade) { + public boolean performDexOptSecondary(String packageName, String compilerFilter, + boolean force) { + int flags = DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX | + DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES | + DexoptOptions.DEXOPT_BOOT_COMPLETE | + (force ? DexoptOptions.DEXOPT_FORCE : 0); + return performDexOpt(new DexoptOptions(packageName, compilerFilter, flags)); + } + + /*package*/ boolean performDexOpt(DexoptOptions options) { if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return false; - } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) { + } else if (isInstantApp(options.getPackageName(), UserHandle.getCallingUserId())) { return false; } - int dexoptStatus = performDexOptWithStatus( - packageName, checkProfiles, compileReason, force, bootComplete, - downgrade); - return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED; + + if (options.isDexoptOnlySecondaryDex()) { + return mDexManager.dexoptSecondaryDex(options); + } else { + int dexoptStatus = performDexOptWithStatus(options); + return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED; + } } /** @@ -9516,34 +9551,14 @@ public class PackageManagerService extends IPackageManager.Stub * {@link PackageDexOptimizer#DEX_OPT_PERFORMED} * {@link PackageDexOptimizer#DEX_OPT_FAILED} */ - /* package */ int performDexOptWithStatus(String packageName, - boolean checkProfiles, int compileReason, boolean force, boolean bootComplete, - boolean downgrade) { - return performDexOptTraced(packageName, checkProfiles, - getCompilerFilterForReason(compileReason), force, bootComplete, downgrade); + /* package */ int performDexOptWithStatus(DexoptOptions options) { + return performDexOptTraced(options); } - @Override - public boolean performDexOptMode(String packageName, - boolean checkProfiles, String targetCompilerFilter, boolean force, - boolean bootComplete) { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { - return false; - } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) { - return false; - } - int dexOptStatus = performDexOptTraced(packageName, checkProfiles, - targetCompilerFilter, force, bootComplete, false /* downgrade */); - return dexOptStatus != PackageDexOptimizer.DEX_OPT_FAILED; - } - - private int performDexOptTraced(String packageName, - boolean checkProfiles, String targetCompilerFilter, boolean force, - boolean bootComplete, boolean downgrade) { + private int performDexOptTraced(DexoptOptions options) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); try { - return performDexOptInternal(packageName, checkProfiles, - targetCompilerFilter, force, bootComplete, downgrade); + return performDexOptInternal(options); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } @@ -9551,12 +9566,10 @@ public class PackageManagerService extends IPackageManager.Stub // Run dexopt on a given package. Returns true if dexopt did not fail, i.e. // if the package can now be considered up to date for the given filter. - private int performDexOptInternal(String packageName, - boolean checkProfiles, String targetCompilerFilter, boolean force, - boolean bootComplete, boolean downgrade) { + private int performDexOptInternal(DexoptOptions options) { PackageParser.Package p; synchronized (mPackages) { - p = mPackages.get(packageName); + p = mPackages.get(options.getPackageName()); if (p == null) { // Package could not be found. Report failure. return PackageDexOptimizer.DEX_OPT_FAILED; @@ -9567,8 +9580,7 @@ public class PackageManagerService extends IPackageManager.Stub long callingId = Binder.clearCallingIdentity(); try { synchronized (mInstallLock) { - return performDexOptInternalWithDependenciesLI(p, checkProfiles, - targetCompilerFilter, force, bootComplete, downgrade); + return performDexOptInternalWithDependenciesLI(p, options); } } finally { Binder.restoreCallingIdentity(callingId); @@ -9588,12 +9600,11 @@ public class PackageManagerService extends IPackageManager.Stub } private int performDexOptInternalWithDependenciesLI(PackageParser.Package p, - boolean checkProfiles, String targetCompilerFilter, - boolean force, boolean bootComplete, boolean downgrade) { + DexoptOptions options) { // Select the dex optimizer based on the force parameter. // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to // allocate an object here. - PackageDexOptimizer pdo = force + PackageDexOptimizer pdo = options.isForce() ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer) : mPackageDexOptimizer; @@ -9610,37 +9621,14 @@ public class PackageManagerService extends IPackageManager.Stub for (PackageParser.Package depPackage : deps) { // TODO: Analyze and investigate if we (should) profile libraries. pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets, - false /* checkProfiles */, - targetCompilerFilter, getOrCreateCompilerPackageStats(depPackage), true /* isUsedByOtherApps */, - bootComplete, - downgrade); + options); } } - return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, checkProfiles, - targetCompilerFilter, getOrCreateCompilerPackageStats(p), - mDexManager.isUsedByOtherApps(p.packageName), bootComplete, downgrade); - } - - // Performs dexopt on the used secondary dex files belonging to the given package. - // Returns true if all dex files were process successfully (which could mean either dexopt or - // skip). Returns false if any of the files caused errors. - @Override - public boolean performDexOptSecondary(String packageName, String compilerFilter, - boolean force) { - if (getInstantAppPackageName(Binder.getCallingUid()) != null) { - return false; - } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) { - return false; - } - return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force, - false /* compileOnlySharedDex */, false /* downgrade */); - } - - public boolean performDexOptSecondary(String packageName, int compileReason, - boolean force, boolean downgrade) { - return mDexManager.dexoptSecondaryDex(packageName, compileReason, force, downgrade); + return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, + getOrCreateCompilerPackageStats(p), + mDexManager.isUsedByOtherApps(p.packageName), options); } /** @@ -9816,11 +9804,11 @@ public class PackageManagerService extends IPackageManager.Stub // Whoever is calling forceDexOpt wants a compiled package. // Don't use profiles since that may cause compilation to be skipped. - final int res = performDexOptInternalWithDependenciesLI(pkg, - false /* checkProfiles */, getDefaultCompilerFilter(), - true /* force */, - true /* bootComplete */, - false /* downgrade */); + final int res = performDexOptInternalWithDependenciesLI( + pkg, + new DexoptOptions(packageName, + getDefaultCompilerFilter(), + DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE)); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) { @@ -18284,13 +18272,14 @@ public class PackageManagerService extends IPackageManager.Stub // method because `pkg` may not be in `mPackages` yet. // // Also, don't fail application installs if the dexopt step fails. + DexoptOptions dexoptOptions = new DexoptOptions(pkg.packageName, + REASON_INSTALL, + DexoptOptions.DEXOPT_BOOT_COMPLETE); mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles, - null /* instructionSets */, false /* checkProfiles */, - getCompilerFilterForReason(REASON_INSTALL), + null /* instructionSets */, getOrCreateCompilerPackageStats(pkg), mDexManager.isUsedByOtherApps(pkg.packageName), - true /* bootComplete */, - false /* downgrade */); + dexoptOptions); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 441994d8c590..0d4df4d4c9b4 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -300,33 +300,21 @@ public class DexManager { } /** - * Perform dexopt on the package {@code packageName} secondary dex files. + * Perform dexopt on with the given {@code options} on the secondary dex files. * @return true if all secondary dex files were processed successfully (compiled or skipped * because they don't need to be compiled).. */ - public boolean dexoptSecondaryDex(String packageName, int compilerReason, boolean force, - boolean downgrade) { - return dexoptSecondaryDex(packageName, - PackageManagerServiceCompilerMapping.getCompilerFilterForReason(compilerReason), - force, /* compileOnlySharedDex */ false, downgrade); - } - - /** - * Perform dexopt on the package {@code packageName} secondary dex files. - * @return true if all secondary dex files were processed successfully (compiled or skipped - * because they don't need to be compiled).. - */ - public boolean dexoptSecondaryDex(String packageName, String compilerFilter, boolean force, - boolean compileOnlySharedDex, boolean downgrade) { + public boolean dexoptSecondaryDex(DexoptOptions options) { // Select the dex optimizer based on the force parameter. // Forced compilation is done through ForcedUpdatePackageDexOptimizer which will adjust // the necessary dexopt flags to make sure that compilation is not skipped. This avoid // passing the force flag through the multitude of layers. // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to // allocate an object here. - PackageDexOptimizer pdo = force + PackageDexOptimizer pdo = options.isForce() ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer) : mPackageDexOptimizer; + String packageName = options.getPackageName(); PackageUseInfo useInfo = getPackageUseInfo(packageName); if (useInfo == null || useInfo.getDexUseInfoMap().isEmpty()) { if (DEBUG) { @@ -339,7 +327,7 @@ public class DexManager { for (Map.Entry<String, DexUseInfo> entry : useInfo.getDexUseInfoMap().entrySet()) { String dexPath = entry.getKey(); DexUseInfo dexUseInfo = entry.getValue(); - if (compileOnlySharedDex && !dexUseInfo.isUsedByOtherApps()) { + if (options.isDexoptOnlySharedDex() && !dexUseInfo.isUsedByOtherApps()) { continue; } PackageInfo pkg = null; @@ -361,8 +349,8 @@ public class DexManager { } int result = pdo.dexOptSecondaryDexPath(pkg.applicationInfo, dexPath, - dexUseInfo.getLoaderIsas(), compilerFilter, dexUseInfo.isUsedByOtherApps(), - downgrade); + dexUseInfo.getLoaderIsas(), options.getCompilerFilter(), + dexUseInfo.isUsedByOtherApps(), options.isDowngrade()); success = success && (result != PackageDexOptimizer.DEX_OPT_FAILED); } return success; diff --git a/services/core/java/com/android/server/pm/dex/DexoptOptions.java b/services/core/java/com/android/server/pm/dex/DexoptOptions.java new file mode 100644 index 000000000000..f6f261c36d5f --- /dev/null +++ b/services/core/java/com/android/server/pm/dex/DexoptOptions.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.pm.dex; + +import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason; + +/** + * Options used for dexopt invocations. + */ +public final class DexoptOptions { + // When set, the profiles will be checked for updates before calling dexopt. If + // the apps profiles didn't update in a meaningful way (decided by the compiler), dexopt + // will be skipped. + // Currently this only affects the optimization of primary apks. Secondary dex files + // will always check the profiles for updates. + public static final int DEXOPT_CHECK_FOR_PROFILES_UPDATES = 1 << 0; + + // When set, dexopt will execute unconditionally (even if not needed). + public static final int DEXOPT_FORCE = 1 << 1; + + // Whether or not the invocation of dexopt is done after the boot is completed. This is used + // in order to adjust the priority of the compilation thread. + public static final int DEXOPT_BOOT_COMPLETE = 1 << 2; + + // When set, the dexopt invocation will optimize only the secondary dex files. If false, dexopt + // will only consider the primary apk. + public static final int DEXOPT_ONLY_SECONDARY_DEX = 1 << 3; + + // When set, dexopt will optimize only dex files that are used by other apps. + // Currently, this flag is ignored for primary apks. + public static final int DEXOPT_ONLY_SHARED_DEX = 1 << 4; + + // When set, dexopt will attempt to scale down the optimizations previously applied in order + // save disk space. + public static final int DEXOPT_DOWNGRADE = 1 << 5; + + // The name of package to optimize. + private final String mPackageName; + + // The intended target compiler filter. Note that dexopt might adjust the filter before the + // execution based on factors like: vmSafeMode and packageUsedByOtherApps. + private final String mCompilerFilter; + + // The set of flags for the dexopt options. It's a mix of the DEXOPT_* flags. + private final int mFlags; + + public DexoptOptions(String packageName, String compilerFilter, int flags) { + int validityMask = + DEXOPT_CHECK_FOR_PROFILES_UPDATES | + DEXOPT_FORCE | + DEXOPT_BOOT_COMPLETE | + DEXOPT_ONLY_SECONDARY_DEX | + DEXOPT_ONLY_SHARED_DEX | + DEXOPT_DOWNGRADE; + if ((flags & (~validityMask)) != 0) { + throw new IllegalArgumentException("Invalid flags : " + Integer.toHexString(flags)); + } + + mPackageName = packageName; + mCompilerFilter = compilerFilter; + mFlags = flags; + } + + public DexoptOptions(String packageName, int compilerReason, int flags) { + this(packageName, getCompilerFilterForReason(compilerReason), flags); + } + + public String getPackageName() { + return mPackageName; + } + + public boolean isCheckForProfileUpdates() { + return (mFlags & DEXOPT_CHECK_FOR_PROFILES_UPDATES) != 0; + } + + public String getCompilerFilter() { + return mCompilerFilter; + } + + public boolean isForce() { + return (mFlags & DEXOPT_FORCE) != 0; + } + + public boolean isBootComplete() { + return (mFlags & DEXOPT_BOOT_COMPLETE) != 0; + } + + public boolean isDexoptOnlySecondaryDex() { + return (mFlags & DEXOPT_ONLY_SECONDARY_DEX) != 0; + } + + public boolean isDexoptOnlySharedDex() { + return (mFlags & DEXOPT_ONLY_SHARED_DEX) != 0; + } + + public boolean isDowngrade() { + return (mFlags & DEXOPT_DOWNGRADE) != 0; + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java new file mode 100644 index 000000000000..2c684b96cc2a --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.pm.dex; + + +import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason; + +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.android.server.pm.PackageManagerService; +import com.android.server.pm.PackageManagerServiceCompilerMapping; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class DexoptOptionsTests { + private final static String mPackageName = "test.android.com"; + private final static String mCompilerFilter = + PackageManagerServiceCompilerMapping.getDefaultCompilerFilter(); + + @Test + public void testCreateDexoptOptionsEmpty() { + DexoptOptions opt = new DexoptOptions(mPackageName, mCompilerFilter, /*flags*/ 0); + assertEquals(mPackageName, opt.getPackageName()); + assertEquals(mCompilerFilter, opt.getCompilerFilter()); + assertFalse(opt.isBootComplete()); + assertFalse(opt.isCheckForProfileUpdates()); + assertFalse(opt.isDexoptOnlySecondaryDex()); + assertFalse(opt.isDexoptOnlySharedDex()); + assertFalse(opt.isDowngrade()); + assertFalse(opt.isForce()); + } + + @Test + public void testCreateDexoptOptionsFull() { + int flags = + DexoptOptions.DEXOPT_FORCE | + DexoptOptions.DEXOPT_BOOT_COMPLETE | + DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES | + DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX | + DexoptOptions.DEXOPT_ONLY_SHARED_DEX | + DexoptOptions.DEXOPT_DOWNGRADE; + + DexoptOptions opt = new DexoptOptions(mPackageName, mCompilerFilter, flags); + assertEquals(mPackageName, opt.getPackageName()); + assertEquals(mCompilerFilter, opt.getCompilerFilter()); + assertTrue(opt.isBootComplete()); + assertTrue(opt.isCheckForProfileUpdates()); + assertTrue(opt.isDexoptOnlySecondaryDex()); + assertTrue(opt.isDexoptOnlySharedDex()); + assertTrue(opt.isDowngrade()); + assertTrue(opt.isForce()); + } + + @Test + public void testCreateDexoptOptionsReason() { + int flags = + DexoptOptions.DEXOPT_FORCE | + DexoptOptions.DEXOPT_BOOT_COMPLETE | + DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES; + + int[] reasons = new int[] { + PackageManagerService.REASON_FIRST_BOOT, + PackageManagerService.REASON_BOOT, + PackageManagerService.REASON_INSTALL, + PackageManagerService.REASON_BACKGROUND_DEXOPT, + PackageManagerService.REASON_AB_OTA, + PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE}; + + for (int reason : reasons) { + DexoptOptions opt = new DexoptOptions(mPackageName, reason, flags); + assertEquals(mPackageName, opt.getPackageName()); + assertEquals(getCompilerFilterForReason(reason), opt.getCompilerFilter()); + assertTrue(opt.isBootComplete()); + assertTrue(opt.isCheckForProfileUpdates()); + assertFalse(opt.isDexoptOnlySecondaryDex()); + assertFalse(opt.isDexoptOnlySharedDex()); + assertFalse(opt.isDowngrade()); + assertTrue(opt.isForce()); + } + } + + @Test + public void testCreateDexoptInvalid() { + boolean gotException = false; + try { + int invalidFlags = 999; + new DexoptOptions(mPackageName, mCompilerFilter, invalidFlags); + } catch (IllegalArgumentException ignore) { + gotException = true; + } + + assertTrue(gotException); + } +}
\ No newline at end of file |