diff options
5 files changed, 46 insertions, 14 deletions
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 307867c4e272..d2adfddb4be3 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -4893,8 +4893,6 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile pw.print("]"); } pw.println(); - File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId()); - pw.print(prefix); pw.print(" dataDir="); pw.println(dataDir.getAbsolutePath()); if (pkg != null) { pw.print(prefix); pw.print(" versionName="); pw.println(pkg.getVersionName()); pw.print(prefix); pw.print(" usesNonSdkApi="); pw.println(pkg.isNonSdkApiRequested()); @@ -5195,6 +5193,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile pw.print(" installReason="); pw.println(userState.getInstallReason()); + final File dataDir = PackageInfoUtils.getDataDir(ps, user.id); + pw.print(" dataDir="); + pw.println(dataDir == null ? "null" : dataDir.getAbsolutePath()); + final PackageUserStateInternal pus = ps.readUserState(user.id); pw.print(" firstInstallTime="); date.setTime(pus.getFirstInstallTimeMillis()); diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index 31856f1630bb..f4f03f4c9c4e 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -544,11 +544,6 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { */ public boolean compileLayouts(@NonNull PackageStateInternal ps, @NonNull AndroidPackage pkg) { try { - final String packageName = pkg.getPackageName(); - final String apkPath = pkg.getSplits().get(0).getPath(); - // TODO(b/143971007): Use a cross-user directory - File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId()); - final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex"; if (ps.isPrivileged() || pkg.isUseEmbeddedDex() || pkg.isDefaultToDeviceProtectedStorage()) { // Privileged apps prefer to load trusted code so they don't use compiled views. @@ -558,6 +553,14 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { // selinux permissions required for writing to user_de. return false; } + final String packageName = pkg.getPackageName(); + final String apkPath = pkg.getSplits().get(0).getPath(); + final File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId()); + if (dataDir == null) { + // The app is not installed on the target user and doesn't have a data dir + return false; + } + final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex"; Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath + ") to " + outDexFile); final long callingId = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/pm/dex/ViewCompiler.java b/services/core/java/com/android/server/pm/dex/ViewCompiler.java index 6405ea5667d3..c5b65a3641c1 100644 --- a/services/core/java/com/android/server/pm/dex/ViewCompiler.java +++ b/services/core/java/com/android/server/pm/dex/ViewCompiler.java @@ -40,8 +40,11 @@ public class ViewCompiler { public boolean compileLayouts(PackageStateInternal ps, String apkPath) { try { final String packageName = ps.getPackageName(); - // TODO(b/143971007): Use a cross-user directory - File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId()); + final File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId()); + if (dataDir == null) { + // The app is not installed on the target user and doesn't have a data dir + return false; + } final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex"; Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath + ") to " + outDexFile); diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java index 27812dffd215..fc079093c9e3 100644 --- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java +++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java @@ -443,7 +443,7 @@ public class PackageInfoUtils { updateApplicationInfo(info, flags, state); - initForUser(info, pkg, userId); + initForUser(info, pkg, userId, state); // TODO(b/135203078): Remove PackageParser1/toAppInfoWithoutState and clean all this up PackageStateUnserialized pkgState = pkgSetting.getTransientState(); @@ -689,7 +689,7 @@ public class PackageInfoUtils { info.splitDependencies = pkg.getSplitDependencies().size() == 0 ? null : pkg.getSplitDependencies(); - initForUser(info, pkg, userId); + initForUser(info, pkg, userId, state); info.primaryCpuAbi = pkgSetting.getPrimaryCpuAbi(); info.secondaryCpuAbi = pkgSetting.getSecondaryCpuAbi(); @@ -1001,7 +1001,7 @@ public class PackageInfoUtils { } private static void initForUser(ApplicationInfo output, AndroidPackage input, - @UserIdInt int userId) { + @UserIdInt int userId, PackageUserStateInternal state) { PackageImpl pkg = ((PackageImpl) input); String packageName = input.getPackageName(); output.uid = UserHandle.getUid(userId, UserHandle.getAppId(input.getUid())); @@ -1011,6 +1011,12 @@ public class PackageInfoUtils { return; } + if (!pkg.isSystem() && state.getCeDataInode() <= 0) { + // The data dir has been deleted + output.dataDir = null; + return; + } + // For performance reasons, all these paths are built as strings if (userId == UserHandle.USER_SYSTEM) { output.credentialProtectedDataDir = @@ -1045,7 +1051,7 @@ public class PackageInfoUtils { // This duplicates the ApplicationInfo variant because it uses field assignment and the classes // don't inherit from each other, unfortunately. Consolidating logic would introduce overhead. private static void initForUser(InstrumentationInfo output, AndroidPackage input, - @UserIdInt int userId) { + @UserIdInt int userId, PackageUserStateInternal state) { PackageImpl pkg = ((PackageImpl) input); String packageName = input.getPackageName(); if ("android".equals(packageName)) { @@ -1053,6 +1059,12 @@ public class PackageInfoUtils { return; } + if (!pkg.isSystem() && state.getCeDataInode() <= 0) { + // The data dir has been deleted + output.dataDir = null; + return; + } + // For performance reasons, all these paths are built as strings if (userId == UserHandle.USER_SYSTEM) { output.credentialProtectedDataDir = @@ -1084,12 +1096,21 @@ public class PackageInfoUtils { } } - @NonNull + /** + * Returns the data dir of the app for the target user. Return null if the app isn't installed + * on the target user and doesn't have a data dir on the target user. + */ + @Nullable public static File getDataDir(PackageStateInternal ps, int userId) { if ("android".equals(ps.getPackageName())) { return Environment.getDataSystemDirectory(); } + if (!ps.isSystem() && ps.getUserStateOrDefault(userId).getCeDataInode() <= 0) { + // The data dir has been deleted + return null; + } + if (ps.isDefaultToDeviceProtectedStorage() && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { return Environment.getDataUserDePackageDirectory(ps.getVolumeUuid(), userId, diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java index e2939c1aff3b..98c6c424e223 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java @@ -612,6 +612,9 @@ public class ScanTests { final PackageSetting pkgSetting = scanResult.mPkgSetting; assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting); + // pretend that the data dir has been set up already, so that the generated applicationInfo + // includes the expected data dir string + pkgSetting.setCeDataInode(/* ceDataInode= */100, /* userId= */0); final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo( pkgSetting.getPkg(), 0, pkgSetting.getUserStateOrDefault(0), 0, pkgSetting); |