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

Commit 41afa659 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Avoid redundant getAllocatableBytes() calls.

Shuffle around the ordering of resolveInstallVolume() so that we
determine the fitsOnInternal value while doing a drive-by of all
possible target volumes.  This way we only call getAllocatableBytes()
internal storage once.

Bug: 70985520
Test: atest android.content.pm.PackageHelperTests
Change-Id: I8273c239af4a13b1db17f320e15ee0ef2dc89186
parent 68f36d6b
Loading
Loading
Loading
Loading
+26 −32
Original line number Diff line number Diff line
@@ -94,14 +94,6 @@ public class PackageHelper {
        abstract public boolean getAllow3rdPartyOnInternalConfig(Context context);
        abstract public ApplicationInfo getExistingAppInfo(Context context, String packageName);
        abstract public File getDataDirectory();

        public boolean fitsOnInternalStorage(Context context, SessionParams params)
                throws IOException {
            StorageManager storage = getStorageManager(context);
            final UUID target = storage.getUuidForPath(getDataDirectory());
            return (params.sizeBytes <= storage.getAllocatableBytes(target,
                    translateAllocateFlags(params.installFlags)));
        }
    }

    private synchronized static TestableInterface getDefaultTestableInterface() {
@@ -175,6 +167,7 @@ public class PackageHelper {
    @VisibleForTesting
    public static String resolveInstallVolume(Context context, SessionParams params,
            TestableInterface testInterface) throws IOException {
        final StorageManager storageManager = testInterface.getStorageManager(context);
        final boolean forceAllowOnExternal = testInterface.getForceAllowOnExternalSetting(context);
        final boolean allow3rdPartyOnInternal =
                testInterface.getAllow3rdPartyOnInternalConfig(context);
@@ -183,32 +176,21 @@ public class PackageHelper {
        ApplicationInfo existingInfo = testInterface.getExistingAppInfo(context,
                params.appPackageName);

        final boolean fitsOnInternal = testInterface.fitsOnInternalStorage(context, params);
        final StorageManager storageManager =
                testInterface.getStorageManager(context);

        // System apps always forced to internal storage
        if (existingInfo != null && existingInfo.isSystemApp()) {
            if (fitsOnInternal) {
                return StorageManager.UUID_PRIVATE_INTERNAL;
            } else {
                throw new IOException("Not enough space on existing volume "
                        + existingInfo.volumeUuid + " for system app " + params.appPackageName
                        + " upgrade");
            }
        }

        // Now deal with non-system apps.
        // Figure out best candidate volume, and also if we fit on internal
        final ArraySet<String> allCandidates = new ArraySet<>();
        boolean fitsOnInternal = false;
        VolumeInfo bestCandidate = null;
        long bestCandidateAvailBytes = Long.MIN_VALUE;
        for (VolumeInfo vol : storageManager.getVolumes()) {
            boolean isInternalStorage = ID_PRIVATE_INTERNAL.equals(vol.id);
            if (vol.type == VolumeInfo.TYPE_PRIVATE && vol.isMountedWritable()
                    && (!isInternalStorage || allow3rdPartyOnInternal)) {
            if (vol.type == VolumeInfo.TYPE_PRIVATE && vol.isMountedWritable()) {
                final boolean isInternalStorage = ID_PRIVATE_INTERNAL.equals(vol.id);
                final UUID target = storageManager.getUuidForPath(new File(vol.path));
                final long availBytes = storageManager.getAllocatableBytes(target,
                        translateAllocateFlags(params.installFlags));
                if (isInternalStorage) {
                    fitsOnInternal = (params.sizeBytes <= availBytes);
                }
                if (!isInternalStorage || allow3rdPartyOnInternal) {
                    if (availBytes >= params.sizeBytes) {
                        allCandidates.add(vol.fsUuid);
                    }
@@ -218,6 +200,18 @@ public class PackageHelper {
                    }
                }
            }
        }

        // System apps always forced to internal storage
        if (existingInfo != null && existingInfo.isSystemApp()) {
            if (fitsOnInternal) {
                return StorageManager.UUID_PRIVATE_INTERNAL;
            } else {
                throw new IOException("Not enough space on existing volume "
                        + existingInfo.volumeUuid + " for system app " + params.appPackageName
                        + " upgrade");
            }
        }

        // If app expresses strong desire for internal storage, honor it
        if (!forceAllowOnExternal