Loading cmds/pm/src/com/android/commands/pm/Pm.java +36 −5 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageInstaller; import android.content.pm.IPackageManager; import android.content.pm.IPackageMoveObserver; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; Loading Loading @@ -237,8 +236,12 @@ public final class Pm { return runForceDexOpt(); } if ("move".equals(op)) { return runMove(); if ("move-package".equals(op)) { return runMovePackage(); } if ("move-primary-storage".equals(op)) { return runMovePrimaryStorage(); } try { Loading Loading @@ -1285,7 +1288,7 @@ public final class Pm { } } public int runMove() { public int runMovePackage() { final String packageName = nextArg(); String volumeUuid = nextArg(); if ("internal".equals(volumeUuid)) { Loading Loading @@ -1313,6 +1316,33 @@ public final class Pm { } } public int runMovePrimaryStorage() { String volumeUuid = nextArg(); if ("internal".equals(volumeUuid)) { volumeUuid = null; } try { final int moveId = mPm.movePrimaryStorage(volumeUuid); int status = mPm.getMoveStatus(moveId); while (!PackageManager.isMoveStatusFinished(status)) { SystemClock.sleep(DateUtils.SECOND_IN_MILLIS); status = mPm.getMoveStatus(moveId); } if (status == PackageManager.MOVE_SUCCEEDED) { System.out.println("Success"); return 0; } else { System.err.println("Failure [" + status + "]"); return 1; } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } private int runUninstall() throws RemoteException { int flags = 0; int userId = UserHandle.USER_ALL; Loading Loading @@ -1860,7 +1890,8 @@ public final class Pm { System.err.println(" pm install-abandon SESSION_ID"); System.err.println(" pm uninstall [-k] [--user USER_ID] PACKAGE"); System.err.println(" pm set-installer PACKAGE INSTALLER"); System.err.println(" pm move PACKAGE [internal|UUID]"); System.err.println(" pm move-package PACKAGE [internal|UUID]"); System.err.println(" pm move-primary-storage [internal|UUID]"); System.err.println(" pm clear [--user USER_ID] PACKAGE"); System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT"); System.err.println(" pm disable [--user USER_ID] PACKAGE_OR_COMPONENT"); Loading core/java/android/app/ApplicationPackageManager.java +2 −0 Original line number Diff line number Diff line Loading @@ -1556,6 +1556,7 @@ final class ApplicationPackageManager extends PackageManager { } } @Override public @Nullable VolumeInfo getPrimaryStorageCurrentVolume() { final StorageManager storage = mContext.getSystemService(StorageManager.class); final String volumeUuid = storage.getPrimaryStorageUuid(); Loading @@ -1568,6 +1569,7 @@ final class ApplicationPackageManager extends PackageManager { } } @Override public @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() { final StorageManager storage = mContext.getSystemService(StorageManager.class); final VolumeInfo currentVol = getPrimaryStorageCurrentVolume(); Loading core/java/android/os/storage/IMountService.java +9 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.os.storage; import android.content.pm.IPackageMoveObserver; import android.os.Binder; import android.os.IBinder; import android.os.IInterface; Loading Loading @@ -1082,12 +1083,14 @@ public interface IMountService extends IInterface { } @Override public void setPrimaryStorageUuid(String volumeUuid) throws RemoteException { public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(volumeUuid); _data.writeStrongBinder((callback != null ? callback.asBinder() : null)); mRemote.transact(Stub.TRANSACTION_setPrimaryStorageUuid, _data, _reply, 0); _reply.readException(); } finally { Loading Loading @@ -1714,7 +1717,9 @@ public interface IMountService extends IInterface { case TRANSACTION_setPrimaryStorageUuid: { data.enforceInterface(DESCRIPTOR); String volumeUuid = data.readString(); setPrimaryStorageUuid(volumeUuid); IPackageMoveObserver listener = IPackageMoveObserver.Stub.asInterface( data.readStrongBinder()); setPrimaryStorageUuid(volumeUuid, listener); reply.writeNoException(); return true; } Loading Loading @@ -2020,5 +2025,6 @@ public interface IMountService extends IInterface { public void setVolumeUserFlags(String volId, int flags, int mask) throws RemoteException; public String getPrimaryStorageUuid() throws RemoteException; public void setPrimaryStorageUuid(String volumeUuid) throws RemoteException; public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) throws RemoteException; } core/java/android/os/storage/StorageManager.java +16 −4 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; Loading Loading @@ -642,7 +644,12 @@ public class StorageManager { } } /** {@hide} */ /** * This is not the API you're looking for. * * @see PackageManager#getPrimaryStorageCurrentVolume() * @hide */ public String getPrimaryStorageUuid() { try { return mMountService.getPrimaryStorageUuid(); Loading @@ -651,10 +658,15 @@ public class StorageManager { } } /** {@hide} */ public void setPrimaryStorageUuid(String volumeUuid) { /** * This is not the API you're looking for. * * @see PackageManager#movePrimaryStorage(VolumeInfo) * @hide */ public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) { try { mMountService.setPrimaryStorageUuid(volumeUuid); mMountService.setPrimaryStorageUuid(volumeUuid, callback); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } Loading services/core/java/com/android/server/MountService.java +121 −22 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.ObbInfo; import android.mtp.MtpStorage; Loading Loading @@ -178,6 +180,9 @@ class MountService extends IMountService.Stub /** Maximum number of ASEC containers allowed to be mounted. */ private static final int MAX_CONTAINERS = 250; /** Magic value sent by MoveTask.cpp */ private static final int MOVE_STATUS_COPY_FINISHED = 82; /* * Internal vold response code constants */ Loading Loading @@ -226,6 +231,8 @@ class MountService extends IMountService.Stub public static final int VOLUME_PATH_CHANGED = 655; public static final int VOLUME_DESTROYED = 659; public static final int MOVE_STATUS = 660; /* * 700 series - fstrim */ Loading Loading @@ -314,6 +321,11 @@ class MountService extends IMountService.Stub @GuardedBy("mLock") private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>(); @GuardedBy("mLock") private IPackageMoveObserver mMoveCallback; @GuardedBy("mLock") private String mMoveTargetUuid; private DiskInfo findDiskById(String id) { synchronized (mLock) { final DiskInfo disk = mDisks.get(id); Loading Loading @@ -347,6 +359,17 @@ class MountService extends IMountService.Stub throw new IllegalArgumentException("No volume found for path " + path); } private 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); } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { return storage.getPrimaryPhysicalVolume(); } else { return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid)); } } private VolumeMetadata findOrCreateMetadataLocked(VolumeInfo vol) { VolumeMetadata meta = mMetadata.get(vol.fsUuid); if (meta == null) { Loading Loading @@ -937,6 +960,12 @@ class MountService extends IMountService.Stub break; } case VoldResponseCode.MOVE_STATUS: { final int status = Integer.parseInt(cooked[1]); onMoveStatusLocked(status); break; } case VoldResponseCode.FstrimCompleted: { EventLogTags.writeFstrimFinish(SystemClock.elapsedRealtime()); break; Loading Loading @@ -972,24 +1001,36 @@ class MountService extends IMountService.Stub } private void onVolumeCreatedLocked(VolumeInfo vol) { final boolean primaryPhysical = SystemProperties.getBoolean( StorageManager.PROP_PRIMARY_PHYSICAL, false); // TODO: enable switching to another emulated primary if (VolumeInfo.ID_EMULATED_INTERNAL.equals(vol.id) && !primaryPhysical) { if (vol.type == VolumeInfo.TYPE_EMULATED) { final StorageManager storage = mContext.getSystemService(StorageManager.class); final VolumeInfo privateVol = storage.findPrivateForEmulated(vol); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid) && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) { Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) { Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } } else if (vol.type == VolumeInfo.TYPE_PUBLIC) { if (primaryPhysical) { // TODO: only look at first public partition if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid) && vol.disk.isDefaultPrimary()) { Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; } // Adoptable public disks are visible to apps, since they meet // public API requirement of being in a stable location. final DiskInfo disk = mDisks.get(vol.getDiskId()); if (disk != null && disk.isAdoptable()) { if (vol.disk.isAdoptable()) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; } Loading Loading @@ -1066,6 +1107,35 @@ class MountService extends IMountService.Stub } } private void onMoveStatusLocked(int status) { if (mMoveCallback == null) { Slog.w(TAG, "Odd, status but no move requested"); return; } // TODO: estimate remaining time try { mMoveCallback.onStatusChanged(-1, status, -1); } catch (RemoteException ignored) { } // We've finished copying and we're about to clean up old data, so // remember that move was successful if we get rebooted if (status == MOVE_STATUS_COPY_FINISHED) { Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting"); mPrimaryStorageUuid = mMoveTargetUuid; writeMetadataLocked(); } if (PackageManager.isMoveStatusFinished(status)) { Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status); mMoveCallback = null; mMoveTargetUuid = null; } } /** * Refresh latest metadata into any currently active {@link VolumeInfo}. */ Loading Loading @@ -1322,13 +1392,18 @@ class MountService extends IMountService.Stub final VolumeInfo vol = findVolumeById(volId); // TODO: expand PMS to know about multiple volumes if (vol.isPrimary()) { if (vol.isPrimaryPhysical()) { final long ident = Binder.clearCallingIdentity(); try { synchronized (mUnmountLock) { mUnmountSignal = new CountDownLatch(1); mPms.updateExternalMediaStatus(false, true); waitForLatch(mUnmountSignal, "mUnmountSignal"); mUnmountSignal = null; } } finally { Binder.restoreCallingIdentity(ident); } } try { Loading Loading @@ -1424,20 +1499,41 @@ class MountService extends IMountService.Stub } @Override public String getPrimaryStorageUuid() throws RemoteException { public String getPrimaryStorageUuid() { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); synchronized (mLock) { return mPrimaryStorageUuid; } } @Override public void setPrimaryStorageUuid(String volumeUuid) throws RemoteException { public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); synchronized (mLock) { Slog.d(TAG, "Changing primary storage UUID to " + volumeUuid); mPrimaryStorageUuid = volumeUuid; writeMetadataLocked(); final VolumeInfo from = Preconditions.checkNotNull( findStorageForUuid(mPrimaryStorageUuid)); final VolumeInfo to = Preconditions.checkNotNull( findStorageForUuid(volumeUuid)); if (Objects.equals(from, to)) { throw new IllegalArgumentException("Primary storage already at " + from); } if (mMoveCallback != null) { throw new IllegalStateException("Move already in progress"); } mMoveCallback = callback; mMoveTargetUuid = volumeUuid; // TODO: reevaluate all volumes we know about! try { mConnector.execute("volume", "move_storage", from.id, to.id); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } } } Loading Loading @@ -2875,6 +2971,9 @@ class MountService extends IMountService.Stub meta.dump(pw); } pw.decreaseIndent(); pw.println(); pw.println("Primary storage UUID: " + mPrimaryStorageUuid); } synchronized (mObbMounts) { Loading Loading
cmds/pm/src/com/android/commands/pm/Pm.java +36 −5 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageInstaller; import android.content.pm.IPackageManager; import android.content.pm.IPackageMoveObserver; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; Loading Loading @@ -237,8 +236,12 @@ public final class Pm { return runForceDexOpt(); } if ("move".equals(op)) { return runMove(); if ("move-package".equals(op)) { return runMovePackage(); } if ("move-primary-storage".equals(op)) { return runMovePrimaryStorage(); } try { Loading Loading @@ -1285,7 +1288,7 @@ public final class Pm { } } public int runMove() { public int runMovePackage() { final String packageName = nextArg(); String volumeUuid = nextArg(); if ("internal".equals(volumeUuid)) { Loading Loading @@ -1313,6 +1316,33 @@ public final class Pm { } } public int runMovePrimaryStorage() { String volumeUuid = nextArg(); if ("internal".equals(volumeUuid)) { volumeUuid = null; } try { final int moveId = mPm.movePrimaryStorage(volumeUuid); int status = mPm.getMoveStatus(moveId); while (!PackageManager.isMoveStatusFinished(status)) { SystemClock.sleep(DateUtils.SECOND_IN_MILLIS); status = mPm.getMoveStatus(moveId); } if (status == PackageManager.MOVE_SUCCEEDED) { System.out.println("Success"); return 0; } else { System.err.println("Failure [" + status + "]"); return 1; } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } private int runUninstall() throws RemoteException { int flags = 0; int userId = UserHandle.USER_ALL; Loading Loading @@ -1860,7 +1890,8 @@ public final class Pm { System.err.println(" pm install-abandon SESSION_ID"); System.err.println(" pm uninstall [-k] [--user USER_ID] PACKAGE"); System.err.println(" pm set-installer PACKAGE INSTALLER"); System.err.println(" pm move PACKAGE [internal|UUID]"); System.err.println(" pm move-package PACKAGE [internal|UUID]"); System.err.println(" pm move-primary-storage [internal|UUID]"); System.err.println(" pm clear [--user USER_ID] PACKAGE"); System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT"); System.err.println(" pm disable [--user USER_ID] PACKAGE_OR_COMPONENT"); Loading
core/java/android/app/ApplicationPackageManager.java +2 −0 Original line number Diff line number Diff line Loading @@ -1556,6 +1556,7 @@ final class ApplicationPackageManager extends PackageManager { } } @Override public @Nullable VolumeInfo getPrimaryStorageCurrentVolume() { final StorageManager storage = mContext.getSystemService(StorageManager.class); final String volumeUuid = storage.getPrimaryStorageUuid(); Loading @@ -1568,6 +1569,7 @@ final class ApplicationPackageManager extends PackageManager { } } @Override public @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() { final StorageManager storage = mContext.getSystemService(StorageManager.class); final VolumeInfo currentVol = getPrimaryStorageCurrentVolume(); Loading
core/java/android/os/storage/IMountService.java +9 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.os.storage; import android.content.pm.IPackageMoveObserver; import android.os.Binder; import android.os.IBinder; import android.os.IInterface; Loading Loading @@ -1082,12 +1083,14 @@ public interface IMountService extends IInterface { } @Override public void setPrimaryStorageUuid(String volumeUuid) throws RemoteException { public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(volumeUuid); _data.writeStrongBinder((callback != null ? callback.asBinder() : null)); mRemote.transact(Stub.TRANSACTION_setPrimaryStorageUuid, _data, _reply, 0); _reply.readException(); } finally { Loading Loading @@ -1714,7 +1717,9 @@ public interface IMountService extends IInterface { case TRANSACTION_setPrimaryStorageUuid: { data.enforceInterface(DESCRIPTOR); String volumeUuid = data.readString(); setPrimaryStorageUuid(volumeUuid); IPackageMoveObserver listener = IPackageMoveObserver.Stub.asInterface( data.readStrongBinder()); setPrimaryStorageUuid(volumeUuid, listener); reply.writeNoException(); return true; } Loading Loading @@ -2020,5 +2025,6 @@ public interface IMountService extends IInterface { public void setVolumeUserFlags(String volId, int flags, int mask) throws RemoteException; public String getPrimaryStorageUuid() throws RemoteException; public void setPrimaryStorageUuid(String volumeUuid) throws RemoteException; public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) throws RemoteException; }
core/java/android/os/storage/StorageManager.java +16 −4 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; Loading Loading @@ -642,7 +644,12 @@ public class StorageManager { } } /** {@hide} */ /** * This is not the API you're looking for. * * @see PackageManager#getPrimaryStorageCurrentVolume() * @hide */ public String getPrimaryStorageUuid() { try { return mMountService.getPrimaryStorageUuid(); Loading @@ -651,10 +658,15 @@ public class StorageManager { } } /** {@hide} */ public void setPrimaryStorageUuid(String volumeUuid) { /** * This is not the API you're looking for. * * @see PackageManager#movePrimaryStorage(VolumeInfo) * @hide */ public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) { try { mMountService.setPrimaryStorageUuid(volumeUuid); mMountService.setPrimaryStorageUuid(volumeUuid, callback); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } Loading
services/core/java/com/android/server/MountService.java +121 −22 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.ObbInfo; import android.mtp.MtpStorage; Loading Loading @@ -178,6 +180,9 @@ class MountService extends IMountService.Stub /** Maximum number of ASEC containers allowed to be mounted. */ private static final int MAX_CONTAINERS = 250; /** Magic value sent by MoveTask.cpp */ private static final int MOVE_STATUS_COPY_FINISHED = 82; /* * Internal vold response code constants */ Loading Loading @@ -226,6 +231,8 @@ class MountService extends IMountService.Stub public static final int VOLUME_PATH_CHANGED = 655; public static final int VOLUME_DESTROYED = 659; public static final int MOVE_STATUS = 660; /* * 700 series - fstrim */ Loading Loading @@ -314,6 +321,11 @@ class MountService extends IMountService.Stub @GuardedBy("mLock") private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>(); @GuardedBy("mLock") private IPackageMoveObserver mMoveCallback; @GuardedBy("mLock") private String mMoveTargetUuid; private DiskInfo findDiskById(String id) { synchronized (mLock) { final DiskInfo disk = mDisks.get(id); Loading Loading @@ -347,6 +359,17 @@ class MountService extends IMountService.Stub throw new IllegalArgumentException("No volume found for path " + path); } private 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); } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { return storage.getPrimaryPhysicalVolume(); } else { return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid)); } } private VolumeMetadata findOrCreateMetadataLocked(VolumeInfo vol) { VolumeMetadata meta = mMetadata.get(vol.fsUuid); if (meta == null) { Loading Loading @@ -937,6 +960,12 @@ class MountService extends IMountService.Stub break; } case VoldResponseCode.MOVE_STATUS: { final int status = Integer.parseInt(cooked[1]); onMoveStatusLocked(status); break; } case VoldResponseCode.FstrimCompleted: { EventLogTags.writeFstrimFinish(SystemClock.elapsedRealtime()); break; Loading Loading @@ -972,24 +1001,36 @@ class MountService extends IMountService.Stub } private void onVolumeCreatedLocked(VolumeInfo vol) { final boolean primaryPhysical = SystemProperties.getBoolean( StorageManager.PROP_PRIMARY_PHYSICAL, false); // TODO: enable switching to another emulated primary if (VolumeInfo.ID_EMULATED_INTERNAL.equals(vol.id) && !primaryPhysical) { if (vol.type == VolumeInfo.TYPE_EMULATED) { final StorageManager storage = mContext.getSystemService(StorageManager.class); final VolumeInfo privateVol = storage.findPrivateForEmulated(vol); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid) && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) { Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) { Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } } else if (vol.type == VolumeInfo.TYPE_PUBLIC) { if (primaryPhysical) { // TODO: only look at first public partition if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid) && vol.disk.isDefaultPrimary()) { Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; } // Adoptable public disks are visible to apps, since they meet // public API requirement of being in a stable location. final DiskInfo disk = mDisks.get(vol.getDiskId()); if (disk != null && disk.isAdoptable()) { if (vol.disk.isAdoptable()) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; } Loading Loading @@ -1066,6 +1107,35 @@ class MountService extends IMountService.Stub } } private void onMoveStatusLocked(int status) { if (mMoveCallback == null) { Slog.w(TAG, "Odd, status but no move requested"); return; } // TODO: estimate remaining time try { mMoveCallback.onStatusChanged(-1, status, -1); } catch (RemoteException ignored) { } // We've finished copying and we're about to clean up old data, so // remember that move was successful if we get rebooted if (status == MOVE_STATUS_COPY_FINISHED) { Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting"); mPrimaryStorageUuid = mMoveTargetUuid; writeMetadataLocked(); } if (PackageManager.isMoveStatusFinished(status)) { Slog.d(TAG, "Move to " + mMoveTargetUuid + " finished with status " + status); mMoveCallback = null; mMoveTargetUuid = null; } } /** * Refresh latest metadata into any currently active {@link VolumeInfo}. */ Loading Loading @@ -1322,13 +1392,18 @@ class MountService extends IMountService.Stub final VolumeInfo vol = findVolumeById(volId); // TODO: expand PMS to know about multiple volumes if (vol.isPrimary()) { if (vol.isPrimaryPhysical()) { final long ident = Binder.clearCallingIdentity(); try { synchronized (mUnmountLock) { mUnmountSignal = new CountDownLatch(1); mPms.updateExternalMediaStatus(false, true); waitForLatch(mUnmountSignal, "mUnmountSignal"); mUnmountSignal = null; } } finally { Binder.restoreCallingIdentity(ident); } } try { Loading Loading @@ -1424,20 +1499,41 @@ class MountService extends IMountService.Stub } @Override public String getPrimaryStorageUuid() throws RemoteException { public String getPrimaryStorageUuid() { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); synchronized (mLock) { return mPrimaryStorageUuid; } } @Override public void setPrimaryStorageUuid(String volumeUuid) throws RemoteException { public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); synchronized (mLock) { Slog.d(TAG, "Changing primary storage UUID to " + volumeUuid); mPrimaryStorageUuid = volumeUuid; writeMetadataLocked(); final VolumeInfo from = Preconditions.checkNotNull( findStorageForUuid(mPrimaryStorageUuid)); final VolumeInfo to = Preconditions.checkNotNull( findStorageForUuid(volumeUuid)); if (Objects.equals(from, to)) { throw new IllegalArgumentException("Primary storage already at " + from); } if (mMoveCallback != null) { throw new IllegalStateException("Move already in progress"); } mMoveCallback = callback; mMoveTargetUuid = volumeUuid; // TODO: reevaluate all volumes we know about! try { mConnector.execute("volume", "move_storage", from.id, to.id); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } } } Loading Loading @@ -2875,6 +2971,9 @@ class MountService extends IMountService.Stub meta.dump(pw); } pw.decreaseIndent(); pw.println(); pw.println("Primary storage UUID: " + mPrimaryStorageUuid); } synchronized (mObbMounts) { Loading