OSDN Git Service

Avoid redundant getAllocatableBytes() calls.
authorJeff Sharkey <jsharkey@android.com>
Tue, 1 May 2018 19:09:28 +0000 (13:09 -0600)
committerJeff Sharkey <jsharkey@android.com>
Tue, 1 May 2018 19:09:30 +0000 (13:09 -0600)
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

core/java/com/android/internal/content/PackageHelper.java

index 8a456d1..e2b8f7d 100644 (file)
@@ -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,42 +176,43 @@ 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 (availBytes >= params.sizeBytes) {
-                    allCandidates.add(vol.fsUuid);
+                if (isInternalStorage) {
+                    fitsOnInternal = (params.sizeBytes <= availBytes);
                 }
-                if (availBytes >= bestCandidateAvailBytes) {
-                    bestCandidate = vol;
-                    bestCandidateAvailBytes = availBytes;
+                if (!isInternalStorage || allow3rdPartyOnInternal) {
+                    if (availBytes >= params.sizeBytes) {
+                        allCandidates.add(vol.fsUuid);
+                    }
+                    if (availBytes >= bestCandidateAvailBytes) {
+                        bestCandidate = vol;
+                        bestCandidateAvailBytes = availBytes;
+                    }
                 }
             }
         }
 
+        // 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
                 && params.installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {