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() {
@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);
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) {