diff options
author | Jeff Sharkey <jsharkey@android.com> | 2015-04-18 23:25:29 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-04-18 23:25:31 +0000 |
commit | 355df8f16ae4c428997d88ba86f1ce07e5eca35e (patch) | |
tree | 2eea9e7e59f9e9b847922292cbd024a3975024f4 | |
parent | 774afb9a8e9f8f5a4d31d0573d94efeb3e5c3655 (diff) | |
parent | 27de30d31c3e79bc429cb71aed9681c55243f18d (diff) | |
download | frameworks_base-355df8f16ae4c428997d88ba86f1ce07e5eca35e.zip frameworks_base-355df8f16ae4c428997d88ba86f1ce07e5eca35e.tar.gz frameworks_base-355df8f16ae4c428997d88ba86f1ce07e5eca35e.tar.bz2 |
Merge "Wire up non-visible volumes, more states."
6 files changed, 214 insertions, 124 deletions
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index b49c14e..efa3ef2 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -506,6 +506,16 @@ public class StorageManager { } /** {@hide} */ + public @Nullable VolumeInfo findPrivateForEmulated(VolumeInfo emulatedVol) { + return findVolumeById(emulatedVol.getId().replace("emulated", "private")); + } + + /** {@hide} */ + public @Nullable VolumeInfo findEmulatedForPrivate(VolumeInfo privateVol) { + return findVolumeById(privateVol.getId().replace("private", "emulated")); + } + + /** {@hide} */ public @NonNull List<VolumeInfo> getVolumes() { return getVolumes(0); } @@ -523,10 +533,9 @@ public class StorageManager { public @Nullable String getBestVolumeDescription(VolumeInfo vol) { String descrip = vol.getDescription(); - if (vol.diskId != null) { - final DiskInfo disk = findDiskById(vol.diskId); - if (disk != null && TextUtils.isEmpty(descrip)) { - descrip = disk.getDescription(); + if (vol.disk != null) { + if (TextUtils.isEmpty(descrip)) { + descrip = vol.disk.getDescription(); } } diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index 4177380..375a86a 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -101,23 +101,27 @@ public class VolumeInfo implements Parcelable { sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTED, Environment.MEDIA_UNMOUNTED); sStateToEnvironment.put(VolumeInfo.STATE_CHECKING, Environment.MEDIA_CHECKING); sStateToEnvironment.put(VolumeInfo.STATE_MOUNTED, Environment.MEDIA_MOUNTED); + sStateToEnvironment.put(VolumeInfo.STATE_MOUNTED_READ_ONLY, Environment.MEDIA_MOUNTED_READ_ONLY); sStateToEnvironment.put(VolumeInfo.STATE_FORMATTING, Environment.MEDIA_UNMOUNTED); sStateToEnvironment.put(VolumeInfo.STATE_EJECTING, Environment.MEDIA_EJECTING); sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTABLE, Environment.MEDIA_UNMOUNTABLE); sStateToEnvironment.put(VolumeInfo.STATE_REMOVED, Environment.MEDIA_REMOVED); + sStateToEnvironment.put(VolumeInfo.STATE_BAD_REMOVAL, Environment.MEDIA_BAD_REMOVAL); sEnvironmentToBroadcast.put(Environment.MEDIA_UNMOUNTED, Intent.ACTION_MEDIA_UNMOUNTED); sEnvironmentToBroadcast.put(Environment.MEDIA_CHECKING, Intent.ACTION_MEDIA_CHECKING); sEnvironmentToBroadcast.put(Environment.MEDIA_MOUNTED, Intent.ACTION_MEDIA_MOUNTED); + sEnvironmentToBroadcast.put(Environment.MEDIA_MOUNTED_READ_ONLY, Intent.ACTION_MEDIA_MOUNTED); sEnvironmentToBroadcast.put(Environment.MEDIA_EJECTING, Intent.ACTION_MEDIA_EJECT); sEnvironmentToBroadcast.put(Environment.MEDIA_UNMOUNTABLE, Intent.ACTION_MEDIA_UNMOUNTABLE); sEnvironmentToBroadcast.put(Environment.MEDIA_REMOVED, Intent.ACTION_MEDIA_REMOVED); + sEnvironmentToBroadcast.put(Environment.MEDIA_BAD_REMOVAL, Intent.ACTION_MEDIA_BAD_REMOVAL); } /** vold state */ public final String id; public final int type; - public final String diskId; + public final DiskInfo disk; public int mountFlags = 0; public int mountUserId = -1; public int state = STATE_UNMOUNTED; @@ -131,17 +135,21 @@ public class VolumeInfo implements Parcelable { public String nickname; public int userFlags = 0; - public VolumeInfo(String id, int type, String diskId, int mtpIndex) { + public VolumeInfo(String id, int type, DiskInfo disk, int mtpIndex) { this.id = Preconditions.checkNotNull(id); this.type = type; - this.diskId = diskId; + this.disk = disk; this.mtpIndex = mtpIndex; } public VolumeInfo(Parcel parcel) { id = parcel.readString(); type = parcel.readInt(); - diskId = parcel.readString(); + if (parcel.readInt() != 0) { + disk = DiskInfo.CREATOR.createFromParcel(parcel); + } else { + disk = null; + } mountFlags = parcel.readInt(); mountUserId = parcel.readInt(); state = parcel.readInt(); @@ -179,8 +187,12 @@ public class VolumeInfo implements Parcelable { return id; } + public @Nullable DiskInfo getDisk() { + return disk; + } + public @Nullable String getDiskId() { - return diskId; + return (disk != null) ? disk.id : null; } public int getType() { @@ -199,6 +211,10 @@ public class VolumeInfo implements Parcelable { return nickname; } + public int getMountUserId() { + return mountUserId; + } + public @Nullable String getDescription() { if (ID_PRIVATE_INTERNAL.equals(id)) { return Resources.getSystem().getString(com.android.internal.R.string.storage_internal); @@ -211,6 +227,14 @@ public class VolumeInfo implements Parcelable { } } + public boolean isMountedReadable() { + return state == STATE_MOUNTED || state == STATE_MOUNTED_READ_ONLY; + } + + public boolean isMountedWritable() { + return state == STATE_MOUNTED; + } + public boolean isPrimary() { return (mountFlags & MOUNT_FLAG_PRIMARY) != 0; } @@ -253,6 +277,19 @@ public class VolumeInfo implements Parcelable { } } + /** + * Path which is accessible to apps holding + * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}. + */ + public File getInternalPathForUser(int userId) { + if (type == TYPE_PUBLIC) { + // TODO: plumb through cleaner path from vold + return new File(path.replace("/storage/", "/mnt/media_rw/")); + } else { + return getPathForUser(userId); + } + } + public StorageVolume buildStorageVolume(Context context, int userId) { final boolean removable; final boolean emulated; @@ -339,7 +376,7 @@ public class VolumeInfo implements Parcelable { pw.println("VolumeInfo{" + id + "}:"); pw.increaseIndent(); pw.printPair("type", DebugUtils.valueToString(getClass(), "TYPE_", type)); - pw.printPair("diskId", diskId); + pw.printPair("diskId", getDiskId()); pw.printPair("mountFlags", DebugUtils.flagsToString(getClass(), "MOUNT_FLAG_", mountFlags)); pw.printPair("mountUserId", mountUserId); pw.printPair("state", DebugUtils.valueToString(getClass(), "STATE_", state)); @@ -403,7 +440,12 @@ public class VolumeInfo implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(id); parcel.writeInt(type); - parcel.writeString(diskId); + if (disk != null) { + parcel.writeInt(1); + disk.writeToParcel(parcel, flags); + } else { + parcel.writeInt(0); + } parcel.writeInt(mountFlags); parcel.writeInt(mountUserId); parcel.writeInt(state); diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java index 255f1fd..b04ddf4 100644 --- a/core/java/com/android/internal/content/PackageHelper.java +++ b/core/java/com/android/internal/content/PackageHelper.java @@ -361,7 +361,7 @@ public class PackageHelper { VolumeInfo bestCandidate = null; long bestCandidateAvailBytes = Long.MIN_VALUE; for (VolumeInfo vol : storageManager.getVolumes()) { - if (vol.type == VolumeInfo.TYPE_PRIVATE && vol.state == VolumeInfo.STATE_MOUNTED) { + if (vol.type == VolumeInfo.TYPE_PRIVATE && vol.isMountedWritable()) { final long availBytes = storageManager.getStorageBytesUntilLow(new File(vol.path)); if (availBytes >= sizeBytes) { allCandidates.add(vol.fsUuid); diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 8f73118..aff57bf 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -26,34 +26,35 @@ import android.database.MatrixCursor.RowBuilder; import android.graphics.Point; import android.net.Uri; import android.os.CancellationSignal; -import android.os.Environment; import android.os.FileObserver; import android.os.FileUtils; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor.OnCloseListener; +import android.os.UserHandle; import android.os.storage.StorageManager; -import android.os.storage.StorageVolume; +import android.os.storage.VolumeInfo; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; import android.provider.DocumentsContract.Root; import android.provider.DocumentsProvider; import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.DebugUtils; import android.util.Log; import android.webkit.MimeTypeMap; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.google.android.collect.Lists; -import com.google.android.collect.Maps; +import com.android.internal.util.IndentingPrintWriter; import java.io.File; +import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; +import java.io.PrintWriter; import java.util.LinkedList; -import java.util.Map; +import java.util.List; import java.util.Objects; public class ExternalStorageProvider extends DocumentsProvider { @@ -80,6 +81,8 @@ public class ExternalStorageProvider extends DocumentsProvider { public int flags; public String title; public String docId; + public File visiblePath; + public File path; } private static final String ROOT_ID_PRIMARY_EMULATED = "primary"; @@ -90,26 +93,17 @@ public class ExternalStorageProvider extends DocumentsProvider { private final Object mRootsLock = new Object(); @GuardedBy("mRootsLock") - private ArrayList<RootInfo> mRoots; - @GuardedBy("mRootsLock") - private HashMap<String, RootInfo> mIdToRoot; - @GuardedBy("mRootsLock") - private HashMap<String, File> mIdToPath; + private ArrayMap<String, RootInfo> mRoots = new ArrayMap<>(); @GuardedBy("mObservers") - private Map<File, DirectoryObserver> mObservers = Maps.newHashMap(); + private ArrayMap<File, DirectoryObserver> mObservers = new ArrayMap<>(); @Override public boolean onCreate() { mStorageManager = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE); mHandler = new Handler(); - mRoots = Lists.newArrayList(); - mIdToRoot = Maps.newHashMap(); - mIdToPath = Maps.newHashMap(); - updateVolumes(); - return true; } @@ -121,52 +115,53 @@ public class ExternalStorageProvider extends DocumentsProvider { private void updateVolumesLocked() { mRoots.clear(); - mIdToPath.clear(); - mIdToRoot.clear(); - final StorageVolume[] volumes = mStorageManager.getVolumeList(); - for (StorageVolume volume : volumes) { - final boolean mounted = Environment.MEDIA_MOUNTED.equals(volume.getState()) - || Environment.MEDIA_MOUNTED_READ_ONLY.equals(volume.getState()); - if (!mounted) continue; + final int userId = UserHandle.myUserId(); + final List<VolumeInfo> volumes = mStorageManager.getVolumes(); + for (VolumeInfo volume : volumes) { + if (!volume.isMountedReadable()) continue; final String rootId; - if (volume.isPrimary() && volume.isEmulated()) { + if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) { rootId = ROOT_ID_PRIMARY_EMULATED; - } else if (volume.getUuid() != null) { - rootId = volume.getUuid(); + } else if (volume.getType() == VolumeInfo.TYPE_EMULATED) { + final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume); + rootId = privateVol.getFsUuid(); + } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { + rootId = volume.getFsUuid(); } else { - Log.d(TAG, "Missing UUID for " + volume.getPath() + "; skipping"); + // Unsupported volume; ignore continue; } - if (mIdToPath.containsKey(rootId)) { - Log.w(TAG, "Duplicate UUID " + rootId + "; skipping"); + if (TextUtils.isEmpty(rootId)) { + Log.d(TAG, "Missing UUID for " + volume.getId() + "; skipping"); + continue; + } + if (mRoots.containsKey(rootId)) { + Log.w(TAG, "Duplicate UUID " + rootId + " for " + volume.getId() + "; skipping"); continue; } try { - final File path = volume.getPathFile(); - mIdToPath.put(rootId, path); - final RootInfo root = new RootInfo(); + mRoots.put(rootId, root); + root.rootId = rootId; root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD; if (ROOT_ID_PRIMARY_EMULATED.equals(rootId)) { root.title = getContext().getString(R.string.root_internal_storage); } else { - final String userLabel = volume.getUserLabel(); - if (!TextUtils.isEmpty(userLabel)) { - root.title = userLabel; - } else { - root.title = volume.getDescription(getContext()); - } + root.title = mStorageManager.getBestVolumeDescription(volume); + } + if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { root.flags |= Root.FLAG_HAS_SETTINGS; } - root.docId = getDocIdForFile(path); - mRoots.add(root); - mIdToRoot.put(rootId, root); + root.visiblePath = volume.getPathForUser(userId); + root.path = volume.getInternalPathForUser(userId); + root.docId = getDocIdForFile(root.path); + } catch (FileNotFoundException e) { throw new IllegalStateException(e); } @@ -190,23 +185,26 @@ public class ExternalStorageProvider extends DocumentsProvider { String path = file.getAbsolutePath(); // Find the most-specific root path - Map.Entry<String, File> mostSpecific = null; + String mostSpecificId = null; + String mostSpecificPath = null; synchronized (mRootsLock) { - for (Map.Entry<String, File> root : mIdToPath.entrySet()) { - final String rootPath = root.getValue().getPath(); - if (path.startsWith(rootPath) && (mostSpecific == null - || rootPath.length() > mostSpecific.getValue().getPath().length())) { - mostSpecific = root; + for (int i = 0; i < mRoots.size(); i++) { + final String rootId = mRoots.keyAt(i); + final String rootPath = mRoots.valueAt(i).path.getAbsolutePath(); + if (path.startsWith(rootPath) && (mostSpecificPath == null + || rootPath.length() > mostSpecificPath.length())) { + mostSpecificId = rootId; + mostSpecificPath = rootPath; } } } - if (mostSpecific == null) { + if (mostSpecificPath == null) { throw new FileNotFoundException("Failed to find root that contains " + path); } // Start at first char of path under root - final String rootPath = mostSpecific.getValue().getPath(); + final String rootPath = mostSpecificPath; if (rootPath.equals(path)) { path = ""; } else if (rootPath.endsWith("/")) { @@ -215,21 +213,30 @@ public class ExternalStorageProvider extends DocumentsProvider { path = path.substring(rootPath.length() + 1); } - return mostSpecific.getKey() + ':' + path; + return mostSpecificId + ':' + path; } private File getFileForDocId(String docId) throws FileNotFoundException { + return getFileForDocId(docId, false); + } + + private File getFileForDocId(String docId, boolean visible) throws FileNotFoundException { final int splitIndex = docId.indexOf(':', 1); final String tag = docId.substring(0, splitIndex); final String path = docId.substring(splitIndex + 1); - File target; + RootInfo root; synchronized (mRootsLock) { - target = mIdToPath.get(tag); + root = mRoots.get(tag); } - if (target == null) { + if (root == null) { throw new FileNotFoundException("No root for " + tag); } + + File target = visible ? root.visiblePath : root.path; + if (target == null) { + return null; + } if (!target.exists()) { target.mkdirs(); } @@ -286,16 +293,13 @@ public class ExternalStorageProvider extends DocumentsProvider { public Cursor queryRoots(String[] projection) throws FileNotFoundException { final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection)); synchronized (mRootsLock) { - for (String rootId : mIdToPath.keySet()) { - final RootInfo root = mIdToRoot.get(rootId); - final File path = mIdToPath.get(rootId); - + for (RootInfo root : mRoots.values()) { final RowBuilder row = result.newRow(); row.add(Root.COLUMN_ROOT_ID, root.rootId); row.add(Root.COLUMN_FLAGS, root.flags); row.add(Root.COLUMN_TITLE, root.title); row.add(Root.COLUMN_DOCUMENT_ID, root.docId); - row.add(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace()); + row.add(Root.COLUMN_AVAILABLE_BYTES, root.path.getFreeSpace()); } } return result; @@ -464,7 +468,7 @@ public class ExternalStorageProvider extends DocumentsProvider { final File parent; synchronized (mRootsLock) { - parent = mIdToPath.get(rootId); + parent = mRoots.get(rootId).path; } final LinkedList<File> pending = new LinkedList<File>(); @@ -494,8 +498,10 @@ public class ExternalStorageProvider extends DocumentsProvider { String documentId, String mode, CancellationSignal signal) throws FileNotFoundException { final File file = getFileForDocId(documentId); + final File visibleFile = getFileForDocId(documentId, true); + final int pfdMode = ParcelFileDescriptor.parseMode(mode); - if (pfdMode == ParcelFileDescriptor.MODE_READ_ONLY) { + if (pfdMode == ParcelFileDescriptor.MODE_READ_ONLY || visibleFile == null) { return ParcelFileDescriptor.open(file, pfdMode); } else { try { @@ -505,7 +511,7 @@ public class ExternalStorageProvider extends DocumentsProvider { public void onClose(IOException e) { final Intent intent = new Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - intent.setData(Uri.fromFile(file)); + intent.setData(Uri.fromFile(visibleFile)); getContext().sendBroadcast(intent); } }); @@ -523,6 +529,27 @@ public class ExternalStorageProvider extends DocumentsProvider { return DocumentsContract.openImageThumbnail(file); } + @Override + public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160); + synchronized (mRootsLock) { + for (int i = 0; i < mRoots.size(); i++) { + final RootInfo root = mRoots.valueAt(i); + pw.println("Root{" + root.rootId + "}:"); + pw.increaseIndent(); + pw.printPair("flags", DebugUtils.flagsToString(Root.class, "FLAG_", root.flags)); + pw.println(); + pw.printPair("title", root.title); + pw.printPair("docId", root.docId); + pw.println(); + pw.printPair("path", root.path); + pw.printPair("visiblePath", root.visiblePath); + pw.decreaseIndent(); + pw.println(); + } + } + } + private static String getTypeForFile(File file) { if (file.isDirectory()) { return Document.MIME_TYPE_DIR; diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java index 4a441c7..ecd1a2f 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java +++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java @@ -60,7 +60,7 @@ public class StorageNotification extends SystemUI { // Avoid kicking notifications when getting early metadata before // mounted. If already mounted, we're being kicked because of a // nickname or init'ed change. - if (vol.getState() == VolumeInfo.STATE_MOUNTED) { + if (vol.isMountedReadable()) { onVolumeStateChangedInternal(vol, vol.getState(), vol.getState()); } } @@ -111,6 +111,7 @@ public class StorageNotification extends SystemUI { onVolumeChecking(vol); break; case VolumeInfo.STATE_MOUNTED: + case VolumeInfo.STATE_MOUNTED_READ_ONLY: onVolumeMounted(vol); break; case VolumeInfo.STATE_FORMATTING: @@ -136,7 +137,7 @@ public class StorageNotification extends SystemUI { } private void onVolumeChecking(VolumeInfo vol) { - final DiskInfo disk = mStorageManager.findDiskById(vol.getDiskId()); + final DiskInfo disk = vol.getDisk(); final CharSequence title = mContext.getString( R.string.ext_media_checking_notification_title, disk.getDescription()); final CharSequence text = mContext.getString( @@ -156,7 +157,7 @@ public class StorageNotification extends SystemUI { // Don't annoy when user dismissed in past if (vol.isSnoozed()) return; - final DiskInfo disk = mStorageManager.findDiskById(vol.getDiskId()); + final DiskInfo disk = vol.getDisk(); final Notification notif; if (disk.isAdoptable() && !vol.isInited()) { final CharSequence title = disk.getDescription(); @@ -198,7 +199,7 @@ public class StorageNotification extends SystemUI { } private void onVolumeEjecting(VolumeInfo vol) { - final DiskInfo disk = mStorageManager.findDiskById(vol.getDiskId()); + final DiskInfo disk = vol.getDisk(); final CharSequence title = mContext.getString( R.string.ext_media_unmounting_notification_title, disk.getDescription()); final CharSequence text = mContext.getString( @@ -215,7 +216,7 @@ public class StorageNotification extends SystemUI { } private void onVolumeUnmountable(VolumeInfo vol) { - final DiskInfo disk = mStorageManager.findDiskById(vol.getDiskId()); + final DiskInfo disk = vol.getDisk(); final CharSequence title = mContext.getString( R.string.ext_media_unmountable_notification_title, disk.getDescription()); final CharSequence text = mContext.getString( @@ -236,7 +237,7 @@ public class StorageNotification extends SystemUI { return; } - final DiskInfo disk = mStorageManager.findDiskById(vol.getDiskId()); + final DiskInfo disk = vol.getDisk(); final CharSequence title = mContext.getString( R.string.ext_media_nomedia_notification_title, disk.getDescription()); final CharSequence text = mContext.getString( @@ -256,7 +257,7 @@ public class StorageNotification extends SystemUI { return; } - final DiskInfo disk = mStorageManager.findDiskById(vol.getDiskId()); + final DiskInfo disk = vol.getDisk(); final CharSequence title = mContext.getString( R.string.ext_media_badremoval_notification_title, disk.getDescription()); final CharSequence text = mContext.getString( diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 34a9559..cc27cfc 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -103,7 +103,6 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -688,12 +687,12 @@ class MountService extends IMountService.Stub synchronized (mVolumes) { for (int i = 0; i < mVolumes.size(); i++) { final VolumeInfo vol = mVolumes.valueAt(i); - if (vol.isVisibleToUser(userId) && vol.state == VolumeInfo.STATE_MOUNTED) { + if (vol.isVisibleToUser(userId) && vol.isMountedReadable()) { final StorageVolume userVol = vol.buildStorageVolume(mContext, userId); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); - mCallbacks.notifyStorageStateChanged(userVol.getPath(), - Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED); + final String envState = VolumeInfo.getEnvironmentForState(vol.getState()); + mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState); } } mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userId); @@ -822,13 +821,13 @@ class MountService extends IMountService.Stub break; } case VoldResponseCode.DISK_LABEL_CHANGED: { - if (cooked.length != 3) break; final DiskInfo disk = mDisks.get(cooked[1]); if (disk != null) { - disk.label = cooked[2]; - } - if (disk.label != null) { - disk.label = disk.label.trim(); + final StringBuilder builder = new StringBuilder(); + for (int i = 2; i < cooked.length; i++) { + builder.append(cooked[i]).append(' '); + } + disk.label = builder.toString().trim(); } break; } @@ -848,8 +847,9 @@ class MountService extends IMountService.Stub final String id = cooked[1]; final int type = Integer.parseInt(cooked[2]); final String diskId = (cooked.length == 4) ? cooked[3] : null; + final DiskInfo disk = mDisks.get(diskId); final int mtpIndex = allocateMtpIndex(id); - final VolumeInfo vol = new VolumeInfo(id, type, diskId, mtpIndex); + final VolumeInfo vol = new VolumeInfo(id, type, disk, mtpIndex); mVolumes.put(id, vol); onVolumeCreatedLocked(vol); break; @@ -885,10 +885,13 @@ class MountService extends IMountService.Stub break; } case VoldResponseCode.VOLUME_FS_LABEL_CHANGED: { - if (cooked.length != 3) break; final VolumeInfo vol = mVolumes.get(cooked[1]); if (vol != null) { - vol.fsLabel = cooked[2]; + final StringBuilder builder = new StringBuilder(); + for (int i = 2; i < cooked.length; i++) { + builder.append(cooked[i]).append(' '); + } + vol.fsLabel = builder.toString().trim(); } mCallbacks.notifyVolumeMetadataChanged(vol.clone()); break; @@ -1351,7 +1354,7 @@ class MountService extends IMountService.Stub synchronized (mLock) { for (int i = 0; i < mVolumes.size(); i++) { final VolumeInfo vol = mVolumes.valueAt(i); - if (vol.isPrimary() && vol.state == VolumeInfo.STATE_MOUNTED) { + if (vol.isPrimary() && vol.isMountedWritable()) { // Cool beans, we have a mounted primary volume return; } @@ -2711,40 +2714,17 @@ class MountService extends IMountService.Stub protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); - final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160); - - synchronized (mObbMounts) { - pw.println("mObbMounts:"); - pw.increaseIndent(); - final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet() - .iterator(); - while (binders.hasNext()) { - Entry<IBinder, List<ObbState>> e = binders.next(); - pw.println(e.getKey() + ":"); - pw.increaseIndent(); - final List<ObbState> obbStates = e.getValue(); - for (final ObbState obbState : obbStates) { - pw.println(obbState); + for (String arg : args) { + if ("--clear-metadata".equals(arg)) { + synchronized (mLock) { + mMetadata.clear(); + writeMetadataLocked(); } - pw.decreaseIndent(); - } - pw.decreaseIndent(); - - pw.println(); - pw.println("mObbPathToStateMap:"); - pw.increaseIndent(); - final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator(); - while (maps.hasNext()) { - final Entry<String, ObbState> e = maps.next(); - pw.print(e.getKey()); - pw.print(" -> "); - pw.println(e.getValue()); } - pw.decreaseIndent(); } + final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160); synchronized (mLock) { - pw.println(); pw.println("Disks:"); pw.increaseIndent(); for (int i = 0; i < mDisks.size(); i++) { @@ -2773,6 +2753,37 @@ class MountService extends IMountService.Stub pw.decreaseIndent(); } + synchronized (mObbMounts) { + pw.println(); + pw.println("mObbMounts:"); + pw.increaseIndent(); + final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet() + .iterator(); + while (binders.hasNext()) { + Entry<IBinder, List<ObbState>> e = binders.next(); + pw.println(e.getKey() + ":"); + pw.increaseIndent(); + final List<ObbState> obbStates = e.getValue(); + for (final ObbState obbState : obbStates) { + pw.println(obbState); + } + pw.decreaseIndent(); + } + pw.decreaseIndent(); + + pw.println(); + pw.println("mObbPathToStateMap:"); + pw.increaseIndent(); + final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator(); + while (maps.hasNext()) { + final Entry<String, ObbState> e = maps.next(); + pw.print(e.getKey()); + pw.print(" -> "); + pw.println(e.getValue()); + } + pw.decreaseIndent(); + } + pw.println(); pw.println("mConnection:"); pw.increaseIndent(); |