diff options
author | Jeff Sharkey <jsharkey@android.com> | 2015-04-23 19:36:02 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2015-04-23 20:32:17 -0700 |
commit | 620b32b316fd4f1bab4eef55ec8802d14a55e7dd (patch) | |
tree | afedbccf5c135e8d19ba52db199316ab0932a277 /core | |
parent | 61044cfd9c7f02d3806338a6b8f137f50e1b1e0f (diff) | |
download | frameworks_base-620b32b316fd4f1bab4eef55ec8802d14a55e7dd.zip frameworks_base-620b32b316fd4f1bab4eef55ec8802d14a55e7dd.tar.gz frameworks_base-620b32b316fd4f1bab4eef55ec8802d14a55e7dd.tar.bz2 |
Package and storage movement callbacks.
Since package and primary storage movement can take quite awhile,
we want to have SystemUI surface progress and allow the Settings
app to be torn down while the movement proceeds in the background.
Movement requests now return a unique ID that identifies an ongoing
operation, and interested parties can observe ongoing progress and
final status. Internally, progress and status are overloaded so
the values 0-100 are progress, and any values outside that range
are terminal status.
Add explicit constants for special-cased volume UUIDs, and change
the APIs to accept VolumeInfo to reduce confusion. Internally the
UUID value "null" means internal storage, and "primary_physical"
means the current primary physical volume. These values are used
for both package and primary storage movement destinations.
Persist the current primary storage location in MountService
metadata, since it can be moved over time.
Surface disk scanned events with separate volume count so we can
determine when it's partitioned successfully. Also send broadcast
to support TvSettings launching into adoption flow.
Bug: 19993667
Change-Id: Ic8a4034033c3cb3262023dba4a642efc6795af10
Diffstat (limited to 'core')
12 files changed, 346 insertions, 139 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index dfe7e18..10f5960 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -62,6 +62,9 @@ import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.SystemProperties; @@ -81,7 +84,9 @@ import com.android.internal.util.UserIcons; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.Objects; /*package*/ final class ApplicationPackageManager extends PackageManager { @@ -98,6 +103,9 @@ final class ApplicationPackageManager extends PackageManager { @GuardedBy("mLock") private PackageInstaller mInstaller; + @GuardedBy("mDelegates") + private final ArrayList<MoveCallbackDelegate> mDelegates = new ArrayList<>(); + UserManager getUserManager() { synchronized (mLock) { if (mUserManager == null) { @@ -1410,57 +1418,100 @@ final class ApplicationPackageManager extends PackageManager { } @Override - public void movePackage(String packageName, IPackageMoveObserver observer, int flags) { + public String getInstallerPackageName(String packageName) { + try { + return mPM.getInstallerPackageName(packageName); + } catch (RemoteException e) { + // Should never happen! + } + return null; + } + + @Override + public int getMoveStatus(int moveId) { try { - mPM.movePackage(packageName, observer, flags); + return mPM.getMoveStatus(moveId); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } @Override - public void movePackageAndData(String packageName, String volumeUuid, - IPackageMoveObserver observer) { + public void registerMoveCallback(MoveCallback callback, Handler handler) { + synchronized (mDelegates) { + final MoveCallbackDelegate delegate = new MoveCallbackDelegate(callback, + handler.getLooper()); + try { + mPM.registerMoveCallback(delegate); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + mDelegates.add(delegate); + } + } + + @Override + public void unregisterMoveCallback(MoveCallback callback) { + synchronized (mDelegates) { + for (Iterator<MoveCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) { + final MoveCallbackDelegate delegate = i.next(); + if (delegate.mCallback == callback) { + try { + mPM.unregisterMoveCallback(delegate); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + i.remove(); + } + } + } + } + + @Override + public int movePackage(String packageName, VolumeInfo vol) { try { - mPM.movePackageAndData(packageName, volumeUuid, observer); + final String volumeUuid; + if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) { + volumeUuid = StorageManager.UUID_PRIVATE_INTERNAL; + } else if (vol.isPrimaryPhysical()) { + volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL; + } else { + volumeUuid = Preconditions.checkNotNull(vol.fsUuid); + } + + return mPM.movePackage(packageName, volumeUuid); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } @Override - public @NonNull VolumeInfo getApplicationCurrentVolume(ApplicationInfo app) { + public @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app) { final StorageManager storage = mContext.getSystemService(StorageManager.class); if (app.isInternal()) { - return Preconditions.checkNotNull( - storage.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL)); + return storage.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL); } else if (app.isExternalAsec()) { - final List<VolumeInfo> vols = storage.getVolumes(); - for (VolumeInfo vol : vols) { - if ((vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isPrimary()) { - return vol; - } - } - throw new IllegalStateException("Failed to find primary public volume"); + return storage.getPrimaryPhysicalVolume(); } else { - return Preconditions.checkNotNull(storage.findVolumeByUuid(app.volumeUuid)); + return storage.findVolumeByUuid(app.volumeUuid); } } @Override - public @NonNull List<VolumeInfo> getApplicationCandidateVolumes(ApplicationInfo app) { + public @NonNull List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) { final StorageManager storage = mContext.getSystemService(StorageManager.class); + final VolumeInfo currentVol = getPackageCurrentVolume(app); final List<VolumeInfo> vols = storage.getVolumes(); final List<VolumeInfo> candidates = new ArrayList<>(); for (VolumeInfo vol : vols) { - if (isCandidateVolume(app, vol)) { + if (Objects.equals(vol, currentVol) || isPackageCandidateVolume(app, vol)) { candidates.add(vol); } } return candidates; } - private static boolean isCandidateVolume(ApplicationInfo app, VolumeInfo vol) { + private static boolean isPackageCandidateVolume(ApplicationInfo app, VolumeInfo vol) { // Private internal is always an option if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) { return true; @@ -1473,10 +1524,14 @@ final class ApplicationPackageManager extends PackageManager { return false; } - // Moving into an ASEC on public primary is only an option when app is - // internal, or already in ASEC - if ((vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isPrimary()) { - return app.isInternal() || app.isExternalAsec(); + // Gotta be able to write there + if (!vol.isMountedWritable()) { + return false; + } + + // Moving into an ASEC on public primary is only option internal + if (vol.isPrimaryPhysical()) { + return app.isInternal(); } // Otherwise we can move to any private volume @@ -1484,13 +1539,66 @@ final class ApplicationPackageManager extends PackageManager { } @Override - public String getInstallerPackageName(String packageName) { + public int movePrimaryStorage(VolumeInfo vol) { try { - return mPM.getInstallerPackageName(packageName); + final String volumeUuid; + if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) { + volumeUuid = StorageManager.UUID_PRIVATE_INTERNAL; + } else if (vol.isPrimaryPhysical()) { + volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL; + } else { + volumeUuid = Preconditions.checkNotNull(vol.fsUuid); + } + + return mPM.movePrimaryStorage(volumeUuid); } catch (RemoteException e) { - // Should never happen! + throw e.rethrowAsRuntimeException(); } - return null; + } + + public @Nullable VolumeInfo getPrimaryStorageCurrentVolume() { + final StorageManager storage = mContext.getSystemService(StorageManager.class); + final String volumeUuid = storage.getPrimaryStorageUuid(); + if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) { + return storage.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL); + } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { + return storage.getPrimaryPhysicalVolume(); + } else { + return storage.findVolumeByUuid(volumeUuid); + } + } + + public @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() { + final StorageManager storage = mContext.getSystemService(StorageManager.class); + final VolumeInfo currentVol = getPrimaryStorageCurrentVolume(); + final List<VolumeInfo> vols = storage.getVolumes(); + final List<VolumeInfo> candidates = new ArrayList<>(); + for (VolumeInfo vol : vols) { + if (Objects.equals(vol, currentVol) || isPrimaryStorageCandidateVolume(vol)) { + candidates.add(vol); + } + } + return candidates; + } + + private static boolean isPrimaryStorageCandidateVolume(VolumeInfo vol) { + // Private internal is always an option + if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) { + return true; + } + + // Gotta be able to write there + if (!vol.isMountedWritable()) { + return false; + } + + // We can move to public volumes on legacy devices + if ((vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.getDisk().isDefaultPrimary()) { + return true; + } + + // Otherwise we can move to any private volume + return (vol.getType() == VolumeInfo.TYPE_PRIVATE); } @Override @@ -1941,6 +2049,45 @@ final class ApplicationPackageManager extends PackageManager { return null; } + /** {@hide} */ + private static class MoveCallbackDelegate extends IPackageMoveObserver.Stub implements + Handler.Callback { + private static final int MSG_STARTED = 1; + private static final int MSG_STATUS_CHANGED = 2; + + final MoveCallback mCallback; + final Handler mHandler; + + public MoveCallbackDelegate(MoveCallback callback, Looper looper) { + mCallback = callback; + mHandler = new Handler(looper, this); + } + + @Override + public boolean handleMessage(Message msg) { + final int moveId = msg.arg1; + switch (msg.what) { + case MSG_STARTED: + mCallback.onStarted(moveId, (String) msg.obj); + return true; + case MSG_STATUS_CHANGED: + mCallback.onStatusChanged(moveId, msg.arg2, (long) msg.obj); + return true; + } + return false; + } + + @Override + public void onStarted(int moveId, String title) { + mHandler.obtainMessage(MSG_STARTED, moveId, 0, title).sendToTarget(); + } + + @Override + public void onStatusChanged(int moveId, int status, long estMillis) { + mHandler.obtainMessage(MSG_STATUS_CHANGED, moveId, status, estMillis).sendToTarget(); + } + } + private final ContextImpl mContext; private final IPackageManager mPM; diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 447c668..ae59bfc 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -50,7 +50,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.content.IntentSender; -import com.android.internal.os.IResultReceiver; /** * See {@link PackageManager} for documentation on most of the APIs @@ -431,8 +430,13 @@ interface IPackageManager { PackageCleanItem nextPackageToClean(in PackageCleanItem lastPackage); - void movePackage(String packageName, IPackageMoveObserver observer, int flags); - void movePackageAndData(String packageName, String volumeUuid, IPackageMoveObserver observer); + int getMoveStatus(int moveId); + + void registerMoveCallback(in IPackageMoveObserver callback); + void unregisterMoveCallback(in IPackageMoveObserver callback); + + int movePackage(in String packageName, in String volumeUuid); + int movePrimaryStorage(in String volumeUuid); boolean addPermissionAsync(in PermissionInfo info); diff --git a/core/java/android/content/pm/IPackageMoveObserver.aidl b/core/java/android/content/pm/IPackageMoveObserver.aidl index baa1595..50ab3b5 100644 --- a/core/java/android/content/pm/IPackageMoveObserver.aidl +++ b/core/java/android/content/pm/IPackageMoveObserver.aidl @@ -22,6 +22,6 @@ package android.content.pm; * @hide */ oneway interface IPackageMoveObserver { - void packageMoved(in String packageName, int returnCode); + void onStarted(int moveId, String title); + void onStatusChanged(int moveId, int status, long estMillis); } - diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e4108b1..e1c271d 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -42,6 +42,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Environment; +import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; import android.os.storage.VolumeInfo; @@ -875,7 +876,8 @@ public abstract class PackageManager { * * @hide */ - public static final int MOVE_SUCCEEDED = 1; + public static final int MOVE_SUCCEEDED = -100; + /** * Error code that is passed to the {@link IPackageMoveObserver} by * {@link #movePackage(android.net.Uri, IPackageMoveObserver)} @@ -941,6 +943,7 @@ public abstract class PackageManager { * been installed on external media. * @hide */ + @Deprecated public static final int MOVE_INTERNAL = 0x00000001; /** @@ -948,8 +951,12 @@ public abstract class PackageManager { * the package should be moved to external media. * @hide */ + @Deprecated public static final int MOVE_EXTERNAL_MEDIA = 0x00000002; + /** {@hide} */ + public static final String EXTRA_MOVE_ID = "android.content.pm.extra.MOVE_ID"; + /** * Usable by the required verifier as the {@code verificationCode} argument * for {@link PackageManager#verifyPendingInstall} to indicate that it will @@ -4183,17 +4190,42 @@ public abstract class PackageManager { * @hide */ @Deprecated - public abstract void movePackage(String packageName, IPackageMoveObserver observer, int flags); + public void movePackage(String packageName, IPackageMoveObserver observer, int flags) { + throw new UnsupportedOperationException(); + } /** {@hide} */ - public abstract void movePackageAndData(String packageName, String volumeUuid, - IPackageMoveObserver observer); + public static boolean isMoveStatusFinished(int status) { + return (status < 0 || status > 100); + } + + /** {@hide} */ + public static abstract class MoveCallback { + public abstract void onStarted(int moveId, String title); + public abstract void onStatusChanged(int moveId, int status, long estMillis); + } /** {@hide} */ - public abstract @Nullable VolumeInfo getApplicationCurrentVolume(ApplicationInfo app); + public abstract int getMoveStatus(int moveId); /** {@hide} */ - public abstract @NonNull List<VolumeInfo> getApplicationCandidateVolumes(ApplicationInfo app); + public abstract void registerMoveCallback(MoveCallback callback, Handler handler); + /** {@hide} */ + public abstract void unregisterMoveCallback(MoveCallback callback); + + /** {@hide} */ + public abstract int movePackage(String packageName, VolumeInfo vol); + /** {@hide} */ + public abstract @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app); + /** {@hide} */ + public abstract @NonNull List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app); + + /** {@hide} */ + public abstract int movePrimaryStorage(VolumeInfo vol); + /** {@hide} */ + public abstract @Nullable VolumeInfo getPrimaryStorageCurrentVolume(); + /** {@hide} */ + public abstract @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes(); /** * Returns the device identity that verifiers can use to associate their scheme to a particular diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java index 64f2a05..9623695 100644 --- a/core/java/android/os/storage/DiskInfo.java +++ b/core/java/android/os/storage/DiskInfo.java @@ -36,7 +36,10 @@ import java.util.Objects; * @hide */ public class DiskInfo implements Parcelable { - public static final String EXTRA_DISK_ID = "android.os.storage.extra.DISK_ID"; + public static final String ACTION_DISK_SCANNED = + "android.os.storage.action.DISK_SCANNED"; + public static final String EXTRA_DISK_ID = + "android.os.storage.extra.DISK_ID"; public static final int FLAG_ADOPTABLE = 1 << 0; public static final int FLAG_DEFAULT_PRIMARY = 1 << 1; @@ -96,6 +99,14 @@ public class DiskInfo implements Parcelable { } } + public boolean isAdoptable() { + return (flags & FLAG_ADOPTABLE) != 0; + } + + public boolean isDefaultPrimary() { + return (flags & FLAG_DEFAULT_PRIMARY) != 0; + } + public boolean isSd() { return (flags & FLAG_SD) != 0; } @@ -104,10 +115,6 @@ public class DiskInfo implements Parcelable { return (flags & FLAG_USB) != 0; } - public boolean isAdoptable() { - return (flags & FLAG_ADOPTABLE) != 0; - } - @Override public String toString() { final CharArrayWriter writer = new CharArrayWriter(); diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 0a8187e..0b1031c 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -1063,6 +1063,38 @@ public interface IMountService extends IInterface { _data.recycle(); } } + + @Override + public String getPrimaryStorageUuid() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + String _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_getPrimaryStorageUuid, _data, _reply, 0); + _reply.readException(); + _result = _reply.readString(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + @Override + public void setPrimaryStorageUuid(String volumeUuid) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(volumeUuid); + mRemote.transact(Stub.TRANSACTION_setPrimaryStorageUuid, _data, _reply, 0); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + } } private static final String DESCRIPTOR = "IMountService"; @@ -1169,6 +1201,9 @@ public interface IMountService extends IInterface { static final int TRANSACTION_setVolumeNickname = IBinder.FIRST_CALL_TRANSACTION + 52; static final int TRANSACTION_setVolumeUserFlags = IBinder.FIRST_CALL_TRANSACTION + 53; + static final int TRANSACTION_getPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 54; + static final int TRANSACTION_setPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 55; + /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. @@ -1669,6 +1704,20 @@ public interface IMountService extends IInterface { reply.writeNoException(); return true; } + case TRANSACTION_getPrimaryStorageUuid: { + data.enforceInterface(DESCRIPTOR); + String volumeUuid = getPrimaryStorageUuid(); + reply.writeNoException(); + reply.writeString(volumeUuid); + return true; + } + case TRANSACTION_setPrimaryStorageUuid: { + data.enforceInterface(DESCRIPTOR); + String volumeUuid = data.readString(); + setPrimaryStorageUuid(volumeUuid); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -1969,4 +2018,7 @@ public interface IMountService extends IInterface { public void setVolumeNickname(String volId, String nickname) throws RemoteException; public void setVolumeUserFlags(String volId, int flags, int mask) throws RemoteException; + + public String getPrimaryStorageUuid() throws RemoteException; + public void setPrimaryStorageUuid(String volumeUuid) throws RemoteException; } diff --git a/core/java/android/os/storage/IMountServiceListener.java b/core/java/android/os/storage/IMountServiceListener.java index 8e878a4..fcb4779 100644 --- a/core/java/android/os/storage/IMountServiceListener.java +++ b/core/java/android/os/storage/IMountServiceListener.java @@ -98,10 +98,11 @@ public interface IMountServiceListener extends IInterface { reply.writeNoException(); return true; } - case TRANSACTION_onDiskUnsupported: { + case TRANSACTION_onDiskScanned: { data.enforceInterface(DESCRIPTOR); final DiskInfo disk = (DiskInfo) data.readParcelable(null); - onDiskUnsupported(disk); + final int volumeCount = data.readInt(); + onDiskScanned(disk, volumeCount); reply.writeNoException(); return true; } @@ -207,13 +208,14 @@ public interface IMountServiceListener extends IInterface { } @Override - public void onDiskUnsupported(DiskInfo disk) throws RemoteException { + public void onDiskScanned(DiskInfo disk, int volumeCount) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeParcelable(disk, 0); - mRemote.transact(Stub.TRANSACTION_onDiskUnsupported, _data, _reply, + _data.writeInt(volumeCount); + mRemote.transact(Stub.TRANSACTION_onDiskScanned, _data, _reply, android.os.IBinder.FLAG_ONEWAY); _reply.readException(); } finally { @@ -224,12 +226,10 @@ public interface IMountServiceListener extends IInterface { } static final int TRANSACTION_onUsbMassStorageConnectionChanged = (IBinder.FIRST_CALL_TRANSACTION + 0); - static final int TRANSACTION_onStorageStateChanged = (IBinder.FIRST_CALL_TRANSACTION + 1); - static final int TRANSACTION_onVolumeStateChanged = (IBinder.FIRST_CALL_TRANSACTION + 2); static final int TRANSACTION_onVolumeMetadataChanged = (IBinder.FIRST_CALL_TRANSACTION + 3); - static final int TRANSACTION_onDiskUnsupported = (IBinder.FIRST_CALL_TRANSACTION + 4); + static final int TRANSACTION_onDiskScanned = (IBinder.FIRST_CALL_TRANSACTION + 4); } /** @@ -255,5 +255,5 @@ public interface IMountServiceListener extends IInterface { public void onVolumeMetadataChanged(VolumeInfo vol) throws RemoteException; - public void onDiskUnsupported(DiskInfo disk) throws RemoteException; + public void onDiskScanned(DiskInfo disk, int volumeCount) throws RemoteException; } diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java index ad2fae0..6a0140e 100644 --- a/core/java/android/os/storage/StorageEventListener.java +++ b/core/java/android/os/storage/StorageEventListener.java @@ -44,6 +44,6 @@ public class StorageEventListener { public void onVolumeMetadataChanged(VolumeInfo vol) { } - public void onDiskUnsupported(DiskInfo disk) { + public void onDiskScanned(DiskInfo disk, int volumeCount) { } } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index f101352..747fb40 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -73,6 +73,11 @@ public class StorageManager { public static final String PROP_FORCE_ADOPTABLE = "persist.fw.force_adoptable"; /** {@hide} */ + public static final String UUID_PRIVATE_INTERNAL = null; + /** {@hide} */ + public static final String UUID_PRIMARY_PHYSICAL = "primary_physical"; + + /** {@hide} */ public static final int FLAG_ALL_METADATA = 1 << 0; private final Context mContext; @@ -89,7 +94,7 @@ public class StorageManager { private static final int MSG_STORAGE_STATE_CHANGED = 1; private static final int MSG_VOLUME_STATE_CHANGED = 2; private static final int MSG_VOLUME_METADATA_CHANGED = 3; - private static final int MSG_DISK_UNSUPPORTED = 4; + private static final int MSG_DISK_SCANNED = 4; final StorageEventListener mCallback; final Handler mHandler; @@ -116,8 +121,8 @@ public class StorageManager { mCallback.onVolumeMetadataChanged((VolumeInfo) args.arg1); args.recycle(); return true; - case MSG_DISK_UNSUPPORTED: - mCallback.onDiskUnsupported((DiskInfo) args.arg1); + case MSG_DISK_SCANNED: + mCallback.onDiskScanned((DiskInfo) args.arg1, args.argi2); args.recycle(); return true; } @@ -156,10 +161,11 @@ public class StorageManager { } @Override - public void onDiskUnsupported(DiskInfo disk) { + public void onDiskScanned(DiskInfo disk, int volumeCount) { final SomeArgs args = SomeArgs.obtain(); args.arg1 = disk; - mHandler.obtainMessage(MSG_DISK_UNSUPPORTED, args).sendToTarget(); + args.argi2 = volumeCount; + mHandler.obtainMessage(MSG_DISK_SCANNED, args).sendToTarget(); } } @@ -534,17 +540,26 @@ public class StorageManager { /** {@hide} */ public @Nullable String getBestVolumeDescription(VolumeInfo vol) { String descrip = vol.getDescription(); - if (vol.disk != null) { if (TextUtils.isEmpty(descrip)) { descrip = vol.disk.getDescription(); } } - return descrip; } /** {@hide} */ + public @Nullable VolumeInfo getPrimaryPhysicalVolume() { + final List<VolumeInfo> vols = getVolumes(); + for (VolumeInfo vol : vols) { + if (vol.isPrimaryPhysical()) { + return vol; + } + } + return null; + } + + /** {@hide} */ public void mount(String volId) { try { mMountService.mount(volId); @@ -628,6 +643,24 @@ public class StorageManager { } /** {@hide} */ + public String getPrimaryStorageUuid() { + try { + return mMountService.getPrimaryStorageUuid(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** {@hide} */ + public void setPrimaryStorageUuid(String volumeUuid) { + try { + mMountService.setPrimaryStorageUuid(volumeUuid); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** {@hide} */ public @Nullable StorageVolume getStorageVolume(File file) { return getStorageVolume(getVolumeList(), file); } diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index f3498d5..4e9cfc7 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -242,6 +242,10 @@ public class VolumeInfo implements Parcelable { return (mountFlags & MOUNT_FLAG_PRIMARY) != 0; } + public boolean isPrimaryPhysical() { + return isPrimary() && (getType() == TYPE_PUBLIC); + } + public boolean isVisible() { return (mountFlags & MOUNT_FLAG_VISIBLE) != 0; } diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java index 414b7bc..b692a18 100644 --- a/core/java/com/android/internal/util/Preconditions.java +++ b/core/java/com/android/internal/util/Preconditions.java @@ -24,6 +24,12 @@ import java.util.Collection; */ public class Preconditions { + public static void checkArgument(boolean expression) { + if (!expression) { + throw new IllegalArgumentException(); + } + } + /** * Ensures that an object reference passed as a parameter to the calling * method is not null. diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index 279bfbf..baa772e 100644 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -1587,91 +1587,13 @@ public class PackageManagerTests extends AndroidTestCase { } } - private class PackageMoveObserver extends IPackageMoveObserver.Stub { - public int returnCode; - - private boolean doneFlag = false; - - public String packageName; - - public PackageMoveObserver(String pkgName) { - packageName = pkgName; - } - - public void packageMoved(String packageName, int returnCode) { - Log.i("DEBUG_MOVE::", "pkg = " + packageName + ", " + "ret = " + returnCode); - if (!packageName.equals(this.packageName)) { - return; - } - synchronized (this) { - this.returnCode = returnCode; - doneFlag = true; - notifyAll(); - } - } - - public boolean isDone() { - return doneFlag; - } - } - public boolean invokeMovePackage(String pkgName, int flags, GenericReceiver receiver) throws Exception { - PackageMoveObserver observer = new PackageMoveObserver(pkgName); - final boolean received = false; - mContext.registerReceiver(receiver, receiver.filter); - try { - // Wait on observer - synchronized (observer) { - synchronized (receiver) { - getPm().movePackage(pkgName, observer, flags); - long waitTime = 0; - while ((!observer.isDone()) && (waitTime < MAX_WAIT_TIME)) { - observer.wait(WAIT_TIME_INCR); - waitTime += WAIT_TIME_INCR; - } - if (!observer.isDone()) { - throw new Exception("Timed out waiting for pkgmove callback"); - } - if (observer.returnCode != PackageManager.MOVE_SUCCEEDED) { - return false; - } - // Verify we received the broadcast - waitTime = 0; - while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) { - receiver.wait(WAIT_TIME_INCR); - waitTime += WAIT_TIME_INCR; - } - if (!receiver.isDone()) { - throw new Exception("Timed out waiting for MOVE notifications"); - } - return receiver.received; - } - } - } finally { - mContext.unregisterReceiver(receiver); - } + throw new UnsupportedOperationException(); } private boolean invokeMovePackageFail(String pkgName, int flags, int errCode) throws Exception { - PackageMoveObserver observer = new PackageMoveObserver(pkgName); - try { - // Wait on observer - synchronized (observer) { - getPm().movePackage(pkgName, observer, flags); - long waitTime = 0; - while ((!observer.isDone()) && (waitTime < MAX_WAIT_TIME)) { - observer.wait(WAIT_TIME_INCR); - waitTime += WAIT_TIME_INCR; - } - if (!observer.isDone()) { - throw new Exception("Timed out waiting for pkgmove callback"); - } - assertEquals(errCode, observer.returnCode); - } - } finally { - } - return true; + throw new UnsupportedOperationException(); } private int getDefaultInstallLoc() { |