Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31c0fb48 authored by Songchun Fan's avatar Songchun Fan
Browse files

[pm] make ApplicationInfo.dataDir null if the data dir is deleted

To reflect the actual existence of the data dir. Also changes dumpsys to
print it for each user, because it's supposed to be different per user.

BUG: 288142708
Test: atest
android.content.pm.cts.PackageManagerShellCommandMultiUserTest#testUninstallWithKeepDataMultiUser

Change-Id: Ib761d55c907f7ac1836e282fcc0d4563fbf790fb
parent 2570fffb
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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());
+8 −5
Original line number Diff line number Diff line
@@ -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();
+5 −2
Original line number Diff line number Diff line
@@ -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);
+26 −5
Original line number Diff line number Diff line
@@ -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,
+3 −0
Original line number Diff line number Diff line
@@ -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);