Merge "Wire up non-visible volumes, more states."

This commit is contained in:
Jeff Sharkey
2015-04-18 23:25:29 +00:00
committed by Android (Google) Code Review
6 changed files with 215 additions and 125 deletions

View File

@@ -505,6 +505,16 @@ public class StorageManager {
return null;
}
/** {@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();
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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(

View File

@@ -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,9 +2714,47 @@ class MountService extends IMountService.Stub
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
for (String arg : args) {
if ("--clear-metadata".equals(arg)) {
synchronized (mLock) {
mMetadata.clear();
writeMetadataLocked();
}
}
}
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
synchronized (mLock) {
pw.println("Disks:");
pw.increaseIndent();
for (int i = 0; i < mDisks.size(); i++) {
final DiskInfo disk = mDisks.valueAt(i);
disk.dump(pw);
}
pw.decreaseIndent();
pw.println();
pw.println("Volumes:");
pw.increaseIndent();
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
vol.dump(pw);
}
pw.decreaseIndent();
pw.println();
pw.println("Metadata:");
pw.increaseIndent();
for (int i = 0; i < mMetadata.size(); i++) {
final VolumeMetadata meta = mMetadata.valueAt(i);
meta.dump(pw);
}
pw.decreaseIndent();
}
synchronized (mObbMounts) {
pw.println();
pw.println("mObbMounts:");
pw.increaseIndent();
final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
@@ -2743,36 +2784,6 @@ class MountService extends IMountService.Stub
pw.decreaseIndent();
}
synchronized (mLock) {
pw.println();
pw.println("Disks:");
pw.increaseIndent();
for (int i = 0; i < mDisks.size(); i++) {
final DiskInfo disk = mDisks.valueAt(i);
disk.dump(pw);
}
pw.decreaseIndent();
pw.println();
pw.println("Volumes:");
pw.increaseIndent();
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
vol.dump(pw);
}
pw.decreaseIndent();
pw.println();
pw.println("Metadata:");
pw.increaseIndent();
for (int i = 0; i < mMetadata.size(); i++) {
final VolumeMetadata meta = mMetadata.valueAt(i);
meta.dump(pw);
}
pw.decreaseIndent();
}
pw.println();
pw.println("mConnection:");
pw.increaseIndent();