summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2015-04-18 23:25:29 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-04-18 23:25:31 +0000
commit355df8f16ae4c428997d88ba86f1ce07e5eca35e (patch)
tree2eea9e7e59f9e9b847922292cbd024a3975024f4
parent774afb9a8e9f8f5a4d31d0573d94efeb3e5c3655 (diff)
parent27de30d31c3e79bc429cb71aed9681c55243f18d (diff)
downloadframeworks_base-355df8f16ae4c428997d88ba86f1ce07e5eca35e.zip
frameworks_base-355df8f16ae4c428997d88ba86f1ce07e5eca35e.tar.gz
frameworks_base-355df8f16ae4c428997d88ba86f1ce07e5eca35e.tar.bz2
Merge "Wire up non-visible volumes, more states."
-rw-r--r--core/java/android/os/storage/StorageManager.java17
-rw-r--r--core/java/android/os/storage/VolumeInfo.java56
-rw-r--r--core/java/com/android/internal/content/PackageHelper.java2
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java153
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java15
-rw-r--r--services/core/java/com/android/server/MountService.java95
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();