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

Commit 9e5fabe8 authored by Alex Buynytskyy's avatar Alex Buynytskyy
Browse files

Create data folder for archived installs.

This fixes the final known discrepancy between install->archive and
install-as-archived.

There is also a minor behavior change - previously we checked all users
on all installs. Now we only do this for the newly installed users.

Bug: 313720942
Test: presubmit
Change-Id: Id1c5a8d4322f0b251d326ba4276ab00048982311
parent d0db470f
Loading
Loading
Loading
Loading
+34 −21
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.CreateAppDataArgs;
import android.os.Environment;
import android.os.FileUtils;
@@ -57,6 +56,7 @@ import dalvik.system.VMRuntime;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
@@ -97,7 +97,22 @@ public class AppDataHelper {
        synchronized (mPm.mLock) {
            ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
        }
        prepareAppDataPostCommitLIF(ps, 0 /* previousAppId */);

        prepareAppDataPostCommitLIF(ps, 0 /* previousAppId */, getInstalledUsersForPackage(ps));
    }

    private int[] getInstalledUsersForPackage(PackageSetting ps) {
        UserManagerInternal umInternal = mInjector.getUserManagerInternal();
        var users = umInternal.getUsers(false /*excludeDying*/);
        int[] userIds = new int[users.size()];
        int userIdsCount = 0;
        for (int i = 0, size = users.size(); i < size; ++i) {
            int userId = users.get(i).id;
            if (ps.getInstalled(userId)) {
                userIds[userIdsCount++] = userId;
            }
        }
        return Arrays.copyOf(userIds, userIdsCount);
    }

    /**
@@ -106,7 +121,7 @@ public class AppDataHelper {
     * @see #prepareAppDataAfterInstallLIF
     */
    @GuardedBy("mPm.mInstallLock")
    public void prepareAppDataPostCommitLIF(PackageSetting ps, int previousAppId) {
    public void prepareAppDataPostCommitLIF(PackageSetting ps, int previousAppId, int[] userIds) {
        synchronized (mPm.mLock) {
            mPm.mSettings.writeKernelMappingLPr(ps);
        }
@@ -121,32 +136,30 @@ public class AppDataHelper {
        UserManagerInternal umInternal = mInjector.getUserManagerInternal();
        StorageManagerInternal smInternal = mInjector.getLocalService(
                StorageManagerInternal.class);
        for (UserInfo user : umInternal.getUsers(false /*excludeDying*/)) {
        for (int userId : userIds) {
            final int flags;
            if (StorageManager.isCeStorageUnlocked(user.id)
                    && smInternal.isCeStoragePrepared(user.id)) {
            if (StorageManager.isCeStorageUnlocked(userId)
                    && smInternal.isCeStoragePrepared(userId)) {
                flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
            } else if (umInternal.isUserRunning(user.id)) {
            } else if (umInternal.isUserRunning(userId)) {
                flags = StorageManager.FLAG_STORAGE_DE;
            } else {
                continue;
            }

            if (ps.getInstalled(user.id)) {
            // TODO: when user data is locked, mark that we're still dirty
                prepareAppData(batch, ps, previousAppId, user.id, flags).thenRun(() -> {
            prepareAppData(batch, ps, previousAppId, userId, flags).thenRun(() -> {
                // Note: this code block is executed with the Installer lock
                // already held, since it's invoked as a side-effect of
                // executeBatchLI()
                    if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
                if (umInternal.isUserUnlockingOrUnlocked(userId)) {
                    // Prepare app data on external storage; currently this is used to
                    // setup any OBB dirs that were created by the installer correctly.
                        int uid = UserHandle.getUid(user.id, ps.getAppId());
                    int uid = UserHandle.getUid(userId, ps.getAppId());
                    smInternal.prepareAppDataAfterInstall(ps.getPackageName(), uid);
                }
            });
        }
        }
        executeBatchLI(batch);
    }

+2 −2
Original line number Diff line number Diff line
@@ -733,7 +733,7 @@ final class InstallPackageHelper {
                    synchronized (mPm.mInstallLock) {
                        // We don't need to freeze for a brand new install
                        mAppDataHelper.prepareAppDataPostCommitLIF(
                                pkgSetting, /* previousAppId= */0);
                                pkgSetting, /* previousAppId= */0, new int[] { userId });
                    }
                }
                // TODO(b/278553670) Store archive state for the user.
@@ -2451,7 +2451,7 @@ final class InstallPackageHelper {
            }

            // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
            mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0);
            mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, installRequest.getNewUsers());
            if (installRequest.isClearCodeCache()) {
                mAppDataHelper.clearAppDataLeafLIF(packageName, ps.getVolumeUuid(),
                        UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
+6 −14
Original line number Diff line number Diff line
@@ -93,8 +93,8 @@ public class PackageUserStateUtils {
     * this object exists means that the package must be installed or has data on at least one user;
     * <li> If it is not installed but still has data (i.e., it was previously uninstalled with
     * {@link PackageManager#DELETE_KEEP_DATA}), return true if the caller requested
     * {@link PackageManager#MATCH_UNINSTALLED_PACKAGES}.
     * Always available for {@link PackageManager#MATCH_ARCHIVED_PACKAGES}.
     * {@link PackageManager#MATCH_UNINSTALLED_PACKAGES} or
     * {@link PackageManager#MATCH_ARCHIVED_PACKAGES};
     * </ul><p>
     */
    public static boolean isAvailable(@NonNull PackageUserState state, long flags) {
@@ -109,19 +109,11 @@ public class PackageUserStateUtils {
        if (state.isInstalled()) {
            if (!state.isHidden()) {
                return true;
            } else return matchDataExists;
        } else {
                return matchDataExists;
            }
        }

            // not installed
        if (matchUninstalled) {
            return state.dataExists();
            return matchDataExists && state.dataExists();
        }

        // archived or installed as archived
        // TODO(b/314808978): Create data folders during install-archived.
        return matchArchived;
    }

    public static boolean reportIfDebug(boolean result, long flags) {