Handle missing migration source volume.
Users can try migrating primary storage while the current location
is missing/unmounted. Fail gracefully instead of runtime restarting.
Bug: 21927076
Change-Id: I40645f8ccea05154e7cbacd188f6cba5f4dbbdc4
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index d28766f..f03e04e 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -557,12 +557,20 @@
/** {@hide} */
public @Nullable VolumeInfo findPrivateForEmulated(VolumeInfo emulatedVol) {
- return findVolumeById(emulatedVol.getId().replace("emulated", "private"));
+ if (emulatedVol != null) {
+ return findVolumeById(emulatedVol.getId().replace("emulated", "private"));
+ } else {
+ return null;
+ }
}
/** {@hide} */
public @Nullable VolumeInfo findEmulatedForPrivate(VolumeInfo privateVol) {
- return findVolumeById(privateVol.getId().replace("private", "emulated"));
+ if (privateVol != null) {
+ return findVolumeById(privateVol.getId().replace("private", "emulated"));
+ } else {
+ return null;
+ }
}
/** {@hide} */
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 92cfaa1..180d918 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -499,8 +499,10 @@
final PendingIntent intent;
if (privateVol != null && privateVol.getDisk() != null) {
intent = buildWizardReadyPendingIntent(privateVol.getDisk());
- } else {
+ } else if (privateVol != null) {
intent = buildVolumeSettingsPendingIntent(privateVol);
+ } else {
+ intent = null;
}
final Notification notif = new Notification.Builder(mContext)
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index dc0c471..894f513 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -28,6 +28,7 @@
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.Manifest;
+import android.annotation.Nullable;
import android.app.ActivityManagerNative;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
@@ -314,7 +315,7 @@
throw new IllegalArgumentException("No disk found for ID " + id);
}
- private VolumeInfo findVolumeById(String id) {
+ private VolumeInfo findVolumeByIdOrThrow(String id) {
synchronized (mLock) {
final VolumeInfo vol = mVolumes.get(id);
if (vol != null) {
@@ -324,7 +325,7 @@
throw new IllegalArgumentException("No volume found for ID " + id);
}
- private String findVolumeIdForPath(String path) {
+ private String findVolumeIdForPathOrThrow(String path) {
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
@@ -361,10 +362,10 @@
}
}
- private VolumeInfo findStorageForUuid(String volumeUuid) {
+ private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) {
final StorageManager storage = mContext.getSystemService(StorageManager.class);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
- return findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
+ return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL);
} else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
return storage.getPrimaryPhysicalVolume();
} else {
@@ -1537,18 +1538,18 @@
@Override
public int mountVolume(String path) {
- mount(findVolumeIdForPath(path));
+ mount(findVolumeIdForPathOrThrow(path));
return 0;
}
@Override
public void unmountVolume(String path, boolean force, boolean removeEncryption) {
- unmount(findVolumeIdForPath(path));
+ unmount(findVolumeIdForPathOrThrow(path));
}
@Override
public int formatVolume(String path) {
- format(findVolumeIdForPath(path));
+ format(findVolumeIdForPathOrThrow(path));
return 0;
}
@@ -1557,7 +1558,7 @@
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
waitForReady();
- final VolumeInfo vol = findVolumeById(volId);
+ final VolumeInfo vol = findVolumeByIdOrThrow(volId);
if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
enforceUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
}
@@ -1573,7 +1574,7 @@
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
waitForReady();
- final VolumeInfo vol = findVolumeById(volId);
+ final VolumeInfo vol = findVolumeByIdOrThrow(volId);
// TODO: expand PMS to know about multiple volumes
if (vol.isPrimaryPhysical()) {
@@ -1602,7 +1603,7 @@
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
waitForReady();
- final VolumeInfo vol = findVolumeById(volId);
+ final VolumeInfo vol = findVolumeByIdOrThrow(volId);
try {
mConnector.execute("volume", "format", vol.id, "auto");
} catch (NativeDaemonConnectorException e) {
@@ -1829,10 +1830,18 @@
resetIfReadyAndConnectedLocked();
} else {
- final VolumeInfo from = Preconditions.checkNotNull(
- findStorageForUuid(mPrimaryStorageUuid));
- final VolumeInfo to = Preconditions.checkNotNull(
- findStorageForUuid(volumeUuid));
+ final VolumeInfo from = findStorageForUuid(mPrimaryStorageUuid);
+ final VolumeInfo to = findStorageForUuid(volumeUuid);
+
+ if (from == null) {
+ Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
+ onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
+ return;
+ } else if (to == null) {
+ Slog.w(TAG, "Failing move due to missing to volume " + volumeUuid);
+ onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
+ return;
+ }
try {
mConnector.execute("volume", "move_storage", from.id, to.id);