Merge changes from topic 'secondary-dex1'

* changes:
  Use DexManager logic to decide if a package is used by other apps
  Skip class path checking for secondary dex files
This commit is contained in:
Calin Juravle
2017-03-03 03:42:33 +00:00
committed by Gerrit Code Review
5 changed files with 37 additions and 48 deletions

View File

@@ -313,7 +313,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
optimizer.performDexOpt(pkg, libraryDependencies,
null /* ISAs */, false /* checkProfiles */,
getCompilerFilterForReason(compilationReason),
null /* CompilerStats.PackageStats */);
null /* CompilerStats.PackageStats */,
mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName));
return commands;
}

View File

@@ -66,6 +66,9 @@ public class PackageDexOptimizer {
public static final int DEX_OPT_PERFORMED = 1;
public static final int DEX_OPT_FAILED = -1;
/** Special library name that skips shared libraries check during compilation. */
public static final String SKIP_SHARED_LIBRARY_CHECK = "&";
private final Installer mInstaller;
private final Object mInstallLock;
@@ -101,7 +104,7 @@ public class PackageDexOptimizer {
*/
int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries,
String[] instructionSets, boolean checkProfiles, String targetCompilationFilter,
CompilerStats.PackageStats packageStats) {
CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps) {
if (!canOptimizePackage(pkg)) {
return DEX_OPT_SKIPPED;
}
@@ -116,7 +119,7 @@ public class PackageDexOptimizer {
}
try {
return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles,
targetCompilationFilter, packageStats);
targetCompilationFilter, packageStats, isUsedByOtherApps);
} finally {
if (useLock) {
mDexoptWakeLock.release();
@@ -132,7 +135,8 @@ public class PackageDexOptimizer {
@GuardedBy("mInstallLock")
private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries,
String[] targetInstructionSets, boolean checkForProfileUpdates,
String targetCompilerFilter, CompilerStats.PackageStats packageStats) {
String targetCompilerFilter, CompilerStats.PackageStats packageStats,
boolean isUsedByOtherApps) {
final String[] instructionSets = targetInstructionSets != null ?
targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
@@ -140,7 +144,7 @@ public class PackageDexOptimizer {
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo,
targetCompilerFilter, isUsedByOtherApps(pkg));
targetCompilerFilter, isUsedByOtherApps);
final boolean profileUpdated = checkForProfileUpdates &&
isProfileUpdated(pkg, sharedGid, compilerFilter);
@@ -274,7 +278,7 @@ public class PackageDexOptimizer {
// TODO(calin): maybe add a separate call.
mInstaller.dexopt(path, info.uid, info.packageName, isa, /*dexoptNeeded*/ 0,
/*oatDir*/ null, dexoptFlags,
compilerFilter, info.volumeUuid, /*sharedLibrariesPath*/ null);
compilerFilter, info.volumeUuid, SKIP_SHARED_LIBRARY_CHECK);
}
return DEX_OPT_PERFORMED;
@@ -474,40 +478,6 @@ public class PackageDexOptimizer {
mSystemReady = true;
}
/**
* Returns true if the profiling data collected for the given app indicate
* that the apps's APK has been loaded by another app.
* Note that this returns false for all forward-locked apps and apps without
* any collected profiling data.
*/
public static boolean isUsedByOtherApps(PackageParser.Package pkg) {
if (pkg.isForwardLocked()) {
// Skip the check for forward locked packages since they don't share their code.
return false;
}
for (String apkPath : pkg.getAllCodePathsExcludingResourceOnly()) {
try {
apkPath = PackageManagerServiceUtils.realpath(new File(apkPath));
} catch (IOException e) {
// Log an error but continue without it.
Slog.w(TAG, "Failed to get canonical path", e);
continue;
}
String useMarker = apkPath.replace('/', '@');
final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
for (int i = 0; i < currentUserIds.length; i++) {
File profileDir =
Environment.getDataProfilesDeForeignDexDirectory(currentUserIds[i]);
File foreignUseMark = new File(profileDir, useMarker);
if (foreignUseMark.exists()) {
return true;
}
}
}
return false;
}
private String printDexoptFlags(int flags) {
ArrayList<String> flagsList = new ArrayList<>();

View File

@@ -524,9 +524,6 @@ public class PackageManagerService extends IPackageManager.Stub {
public static final int REASON_LAST = REASON_CORE_APP;
/** Special library name that skips shared libraries check during compilation. */
private static final String SKIP_SHARED_LIBRARY_CHECK = "&";
final ServiceThread mHandlerThread;
final PackageHandler mHandler;
@@ -2260,7 +2257,7 @@ public class PackageManagerService extends IPackageManager.Stub {
DEXOPT_PUBLIC,
getCompilerFilterForReason(REASON_SHARED_APK),
StorageManager.UUID_PRIVATE_INTERNAL,
SKIP_SHARED_LIBRARY_CHECK);
PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK);
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " + lib);
@@ -7501,11 +7498,13 @@ public class PackageManagerService extends IPackageManager.Stub {
pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets,
false /* checkProfiles */,
getCompilerFilterForReason(REASON_NON_SYSTEM_LIBRARY),
getOrCreateCompilerPackageStats(depPackage));
getOrCreateCompilerPackageStats(depPackage),
mDexManager.isUsedByOtherApps(p.packageName));
}
}
return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, checkProfiles,
targetCompilerFilter, getOrCreateCompilerPackageStats(p));
targetCompilerFilter, getOrCreateCompilerPackageStats(p),
mDexManager.isUsedByOtherApps(p.packageName));
}
// Performs dexopt on the used secondary dex files belonging to the given package.
@@ -15324,7 +15323,8 @@ public class PackageManagerService extends IPackageManager.Stub {
mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
null /* instructionSets */, false /* checkProfiles */,
getCompilerFilterForReason(REASON_INSTALL),
getOrCreateCompilerPackageStats(pkg));
getOrCreateCompilerPackageStats(pkg),
mDexManager.isUsedByOtherApps(pkg.packageName));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
// Notify BackgroundDexOptService that the package has been changed.

View File

@@ -133,7 +133,8 @@ public class PackageManagerServiceUtils {
sortTemp, packageManagerService);
// Give priority to apps used by other apps.
applyPackageFilter((pkg) -> PackageDexOptimizer.isUsedByOtherApps(pkg), result,
applyPackageFilter((pkg) ->
packageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), result,
remainingPkgs, sortTemp, packageManagerService);
// Filter out packages that aren't recently used, add all remaining apps.

View File

@@ -358,6 +358,23 @@ public class DexManager {
return mPackageDexUsage.getAllPackagesWithSecondaryDexFiles();
}
/**
* Return true if the profiling data collected for the given app indicate
* that the apps's APK has been loaded by another app.
* Note that this returns false for all apps without any collected profiling data.
*/
public boolean isUsedByOtherApps(String packageName) {
PackageUseInfo useInfo = getPackageUseInfo(packageName);
if (useInfo == null) {
// No use info, means the package was not used or it was used but not by other apps.
// Note that right now we might prune packages which are not used by other apps.
// TODO(calin): maybe we should not (prune) so we can have an accurate view when we try
// to access the package use.
return false;
}
return useInfo.isUsedByOtherApps();
}
/**
* Retrieves the package which owns the given dexPath.
*/