diff options
author | Mike Lockwood <lockwood@android.com> | 2011-05-09 19:08:06 -0700 |
---|---|---|
committer | Mike Lockwood <lockwood@android.com> | 2011-05-16 14:29:23 -0400 |
commit | 2f6a3885533a52758c2cd4f81f6123a712be8ae6 (patch) | |
tree | c4f6de0abad5d579cbd236194f1b6bd1f8a8eb93 | |
parent | 084d3490a5283088426058d3c15532b176367926 (diff) | |
download | frameworks_base-2f6a3885533a52758c2cd4f81f6123a712be8ae6.zip frameworks_base-2f6a3885533a52758c2cd4f81f6123a712be8ae6.tar.gz frameworks_base-2f6a3885533a52758c2cd4f81f6123a712be8ae6.tar.bz2 |
StorageManager: Clean up and generalize storage configuration resources
Replace config_emulateExternalStorage, config_externalStorageRemovable,
config_externalStoragePaths, config_externalStorageDescriptions and
config_mtpReserveSpaceMegabytes resources with an XML resource file
to describe the external storages that are available.
Add android.os.storage.StorageVolume class
StorageManager.getVolumeList() now returns an array of StorageVolume
Change-Id: I06ce1451ebf08b82f0ee825d56d59ebf72eacd3d
Signed-off-by: Mike Lockwood <lockwood@android.com>
-rw-r--r-- | core/java/android/os/Environment.java | 45 | ||||
-rw-r--r-- | core/java/android/os/storage/IMountService.java | 14 | ||||
-rw-r--r-- | core/java/android/os/storage/StorageManager.java | 27 | ||||
-rw-r--r-- | core/java/android/os/storage/StorageVolume.aidl | 19 | ||||
-rw-r--r-- | core/java/android/os/storage/StorageVolume.java | 147 | ||||
-rwxr-xr-x | core/res/res/values/attrs.xml | 17 | ||||
-rw-r--r-- | core/res/res/values/config.xml | 50 | ||||
-rwxr-xr-x | core/res/res/values/strings.xml | 8 | ||||
-rw-r--r-- | core/res/res/xml/storage_list.xml | 40 | ||||
-rw-r--r-- | media/java/android/media/MediaScanner.java | 3 | ||||
-rw-r--r-- | services/java/com/android/server/MountService.java | 109 |
11 files changed, 389 insertions, 90 deletions
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index e308c2c..1f3f6d9 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -20,6 +20,7 @@ import java.io.File; import android.content.res.Resources; import android.os.storage.IMountService; +import android.os.storage.StorageVolume; import android.util.Log; /** @@ -35,7 +36,25 @@ public class Environment { private static final Object mLock = new Object(); - private volatile static Boolean mIsExternalStorageEmulated = null; + private volatile static StorageVolume mPrimaryVolume = null; + + private static StorageVolume getPrimaryVolume() { + if (mPrimaryVolume == null) { + synchronized (mLock) { + if (mPrimaryVolume == null) { + try { + IMountService mountService = IMountService.Stub.asInterface(ServiceManager + .getService("mount")); + Parcelable[] volumes = mountService.getVolumeList(); + mPrimaryVolume = (StorageVolume)volumes[0]; + } catch (Exception e) { + Log.e(TAG, "couldn't talk to MountService", e); + } + } + } + } + return mPrimaryVolume; + } /** * Gets the Android root directory. @@ -416,9 +435,8 @@ public class Environment { * <p>See {@link #getExternalStorageDirectory()} for more information. */ public static boolean isExternalStorageRemovable() { - if (isExternalStorageEmulated()) return false; - return Resources.getSystem().getBoolean( - com.android.internal.R.bool.config_externalStorageRemovable); + StorageVolume volume = getPrimaryVolume(); + return (volume != null && volume.isRemovable()); } /** @@ -435,23 +453,8 @@ public class Environment { * android.content.ComponentName, boolean)} for additional details. */ public static boolean isExternalStorageEmulated() { - if (mIsExternalStorageEmulated == null) { - synchronized (mLock) { - if (mIsExternalStorageEmulated == null) { - boolean externalStorageEmulated; - try { - IMountService mountService = IMountService.Stub.asInterface(ServiceManager - .getService("mount")); - externalStorageEmulated = mountService.isExternalStorageEmulated(); - mIsExternalStorageEmulated = Boolean.valueOf(externalStorageEmulated); - } catch (Exception e) { - Log.e(TAG, "couldn't talk to MountService", e); - return false; - } - } - } - } - return mIsExternalStorageEmulated; + StorageVolume volume = getPrimaryVolume(); + return (volume != null && volume.isEmulated()); } static File getDirectory(String variableName, String defaultPath) { diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 27da3c3..c2dc8ae 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -20,7 +20,9 @@ import android.os.Binder; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; +import android.os.storage.StorageVolume; /** * WARNING! Update IMountService.h and IMountService.cpp if you change this @@ -638,15 +640,15 @@ public interface IMountService extends IInterface { return _result; } - public String[] getVolumeList() throws RemoteException { + public Parcelable[] getVolumeList() throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); - String[] _result; + Parcelable[] _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getVolumeList, _data, _reply, 0); _reply.readException(); - _result = _reply.readStringArray(); + _result = _reply.readParcelableArray(StorageVolume.class.getClassLoader()); } finally { _reply.recycle(); _data.recycle(); @@ -1024,9 +1026,9 @@ public interface IMountService extends IInterface { } case TRANSACTION_getVolumeList: { data.enforceInterface(DESCRIPTOR); - String[] result = getVolumeList(); + Parcelable[] result = getVolumeList(); reply.writeNoException(); - reply.writeStringArray(result); + reply.writeParcelableArray(result, 0); return true; } } @@ -1207,5 +1209,5 @@ public interface IMountService extends IInterface { /** * Returns list of all mountable volumes. */ - public String[] getVolumeList() throws RemoteException; + public Parcelable[] getVolumeList() throws RemoteException; } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 234057b..6fd1d00 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -19,6 +19,7 @@ package android.os.storage; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; @@ -545,12 +546,34 @@ public class StorageManager * Returns list of all mountable volumes. * @hide */ - public String[] getVolumeList() { + public StorageVolume[] getVolumeList() { try { - return mMountService.getVolumeList(); + Parcelable[] list = mMountService.getVolumeList(); + if (list == null) return new StorageVolume[0]; + int length = list.length; + StorageVolume[] result = new StorageVolume[length]; + for (int i = 0; i < length; i++) { + result[i] = (StorageVolume)list[i]; + } + return result; } catch (RemoteException e) { Log.e(TAG, "Failed to get volume list", e); return null; } } + + /** + * Returns list of paths for all mountable volumes. + * @hide + */ + public String[] getVolumePaths() { + StorageVolume[] volumes = getVolumeList(); + if (volumes == null) return null; + int count = volumes.length; + String[] paths = new String[count]; + for (int i = 0; i < count; i++) { + paths[i] = volumes[i].getPath(); + } + return paths; + } } diff --git a/core/java/android/os/storage/StorageVolume.aidl b/core/java/android/os/storage/StorageVolume.aidl new file mode 100644 index 0000000..d689917 --- /dev/null +++ b/core/java/android/os/storage/StorageVolume.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os.storage; + +parcelable StorageVolume; diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java new file mode 100644 index 0000000..d79f6c8 --- /dev/null +++ b/core/java/android/os/storage/StorageVolume.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os.storage; + +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +/** + * A class representing a storage volume + * @hide + */ +public class StorageVolume implements Parcelable { + + private static final String TAG = "StorageVolume"; + + private final String mPath; + private final String mDescription; + private final boolean mRemovable; + private final boolean mEmulated; + private final int mMtpReserveSpace; + + public StorageVolume(String path, String description, + boolean removable, boolean emulated, + int mtpReserveSpace) { + mPath = path; + mDescription = description; + mRemovable = removable; + mEmulated = emulated; + mMtpReserveSpace = mtpReserveSpace; + } + + /** + * Returns the mount path for the volume. + * + * @return the mount path + */ + public String getPath() { + return mPath; + } + + /** + * Returns a user visible description of the volume. + * + * @return the volume description + */ + public String getDescription() { + return mDescription; + } + + /** + * Returns true if the volume is removable. + * + * @return is removable + */ + public boolean isRemovable() { + return mRemovable; + } + + /** + * Returns true if the volume is emulated. + * + * @return is removable + */ + public boolean isEmulated() { + return mEmulated; + } + + /** + * Number of megabytes of space to leave unallocated by MTP. + * MTP will subtract this value from the free space it reports back + * to the host via GetStorageInfo, and will not allow new files to + * be added via MTP if there is less than this amount left free in the storage. + * If MTP has dedicated storage this value should be zero, but if MTP is + * sharing storage with the rest of the system, set this to a positive value + * to ensure that MTP activity does not result in the storage being + * too close to full. + * + * @return MTP reserve space + */ + public int getMtpReserveSpace() { + return mMtpReserveSpace; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof StorageVolume && mPath != null) { + StorageVolume volume = (StorageVolume)obj; + return (mPath.equals(volume.mPath)); + } + return false; + } + + @Override + public int hashCode() { + return mPath.hashCode(); + } + + @Override + public String toString() { + return mPath; + } + + public static final Parcelable.Creator<StorageVolume> CREATOR = + new Parcelable.Creator<StorageVolume>() { + public StorageVolume createFromParcel(Parcel in) { + String path = in.readString(); + String description = in.readString(); + int removable = in.readInt(); + int emulated = in.readInt(); + int mtpReserveSpace = in.readInt(); + return new StorageVolume(path, description, + removable == 1, emulated == 1, mtpReserveSpace); + } + + public StorageVolume[] newArray(int size) { + return new StorageVolume[size]; + } + }; + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(mPath); + parcel.writeString(mDescription); + parcel.writeInt(mRemovable ? 1 : 0); + parcel.writeInt(mEmulated ? 1 : 0); + parcel.writeInt(mMtpReserveSpace); + } +} diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 71a8b2a..004b755 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4878,4 +4878,21 @@ <!-- Y coordinate of the icon hot spot. --> <attr name="hotSpotY" format="float" /> </declare-styleable> + + <declare-styleable name="Storage"> + <!-- path to mount point for the storage --> + <attr name="mountPoint" format="string" /> + <!-- user visible description of the storage --> + <attr name="storageDescription" format="string" /> + <!-- true if the storage is the primary external storage --> + <attr name="primary" format="boolean" /> + <!-- true if the storage is removable --> + <attr name="removable" format="boolean" /> + <!-- true if the storage is emulated via the FUSE sdcard daemon --> + <attr name="emulated" format="boolean" /> + <!-- number of megabytes of storage MTP should reserve for free storage + (used for emulated storage that is shared with system's data partition) --> + <attr name="mtpReserve" format="integer" /> + </declare-styleable> + </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 27c7a4d..49bbd82 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -89,52 +89,10 @@ when there's no network connection. If the scan doesn't timeout, use zero --> <integer name="config_radioScanningTimeout">0</integer> - <!-- Set to true if the location returned Environment.getExternalStorageDirectory() - is actually a subdirectory of the internal storage. - If this is set then Environment.getExternalStorageState() will always return - MEDIA_MOUNTED and Intent.ACTION_MEDIA_MOUNTED will be broadcast at boot time - for backward compatibility with apps that require external storage. --> - <bool name="config_emulateExternalStorage">false</bool> - - <!-- Set to true if external storage is case sensitive. - Typically external storage is FAT, which is case insensitive. --> - <bool name="config_caseSensitiveExternalStorage">false</bool> - - <!-- A product with no SD card == not removable. --> - <bool name="config_externalStorageRemovable" product="nosdcard">false</bool> - <!-- Configures whether the primary external storage device is - removable. For example, if external storage is on an SD card, - it is removable; if it is built in to the device, it is not removable. - The default product has external storage on an SD card, which is - removable. --> - <bool name="config_externalStorageRemovable" product="default">true</bool> - - <!-- List of mount points for external storage devices. - The first item on the list should be the primary external storage and should match the - value returned by Environment.getExternalStorageDirectory (/mnt/sdcard). - MTP storage IDs will be generated based on the position of the mountpoint in this list: - 0x00010001 - ID for primary external storage (/mnt/sdcard) - 0x00020001 - ID for first secondary external storage - 0x00030001 - ID for second secondary external storage - etc. --> - <string-array translatable="false" name="config_externalStoragePaths"> - <item>"/mnt/sdcard"</item> - </string-array> - - <!-- User visible descriptions of the volumes in the config_externalStoragePaths array. --> - <string-array translatable="true" name="config_externalStorageDescriptions"> - <item>"SD card"</item> - </string-array> - - <!-- Number of megabytes of space to leave unallocated by MTP. - MTP will subtract this value from the free space it reports back - to the host via GetStorageInfo, and will not allow new files to - be added via MTP if there is less than this amount left free in the storage. - If MTP has dedicated storage this value should be zero, but if MTP is - sharing storage with the rest of the system, set this to a positive value - to ensure that MTP activity does not result in the storage being - too close to full. --> - <integer name="config_mtpReserveSpaceMegabytes">0</integer> + <!-- Storage lists for default and nosdcard products. + Both have a single SD card storage, but the storage is not removable in the nosdcard case --> + <integer name="config_storageListId" product="nosdcard">@xml/storage_list_nosdcard</integer> + <integer name="config_storageListId" product="default">@xml/storage_list</integer> <!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION. Please don't copy them, copy anything else. --> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 8ef9a3b..b713b51 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2808,4 +2808,12 @@ <!-- Description of the button to decrement the NumberPicker value. [CHAR LIMIT=NONE] --> <string name="number_picker_decrement_button">Decrement</string> + <!-- Storage description for internal storage. [CHAR LIMIT=NONE] --> + <string name="storage_internal">Internal Storage</string> + + <!-- Storage description for the SD card. [CHAR LIMIT=NONE] --> + <string name="storage_sd_card">SD Card</string> + + <!-- Storage description for USB storage. [CHAR LIMIT=NONE] --> + <string name="storage_usb">USB storage</string> </resources> diff --git a/core/res/res/xml/storage_list.xml b/core/res/res/xml/storage_list.xml new file mode 100644 index 0000000..944bb3a --- /dev/null +++ b/core/res/res/xml/storage_list.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License") +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<!-- The <device> element should contain one or more <storage> elements. + Exactly one of these should have the attribute primary="true". + This storage will be the primary external storage and should have mountPoint="/mnt/sdcard". + Each storage should have both a mountPoint and storageDescription attribute. + The following attributes are optional: + + primary: (boolean) this storage is the primary external storage + removable: (boolean) this is removable storage (for example, a real SD card) + emulated: (boolean) the storage is emulated via the FUSE sdcard daemon + mtpReserve: (integer) number of megabytes of storage MTP should reserve for free storage + (used for emulated storage that is shared with system's data partition) + + A storage should not have both emulated and removable set to true +--> + +<StorageList xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- removable is not set in nosdcard product --> + <storage android:mountPoint="/mnt/sdcard" + android:storageDescription="@string/storage_usb" + android:primary="true" /> +</StorageList> diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index d1eb388..55b0045 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -1147,8 +1147,7 @@ public class MediaScanner mGenresUri = Genres.getContentUri(volumeName); mPlaylistsUri = Playlists.getContentUri(volumeName); - mCaseInsensitivePaths = !mContext.getResources().getBoolean( - com.android.internal.R.bool.config_caseSensitiveExternalStorage); + mCaseInsensitivePaths = true; if (!Process.supportsProcesses()) { // Simulator uses host file system, so it should be case sensitive. mCaseInsensitivePaths = false; diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index a100f1f..376d42f 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -17,6 +17,7 @@ package com.android.server; import com.android.internal.app.IMediaContainerService; +import com.android.internal.util.XmlUtils; import com.android.server.am.ActivityManagerService; import android.Manifest; @@ -28,6 +29,9 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.res.ObbInfo; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; import android.net.Uri; import android.os.Binder; import android.os.Environment; @@ -36,6 +40,7 @@ import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -46,8 +51,14 @@ import android.os.storage.IMountShutdownObserver; import android.os.storage.IObbActionListener; import android.os.storage.OnObbStateChangeListener; import android.os.storage.StorageResultCode; +import android.os.storage.StorageVolume; import android.text.TextUtils; +import android.util.AttributeSet; import android.util.Slog; +import android.util.Xml; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; import java.io.FileDescriptor; import java.io.IOException; @@ -145,6 +156,8 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC private Context mContext; private NativeDaemonConnector mConnector; + private final ArrayList<StorageVolume> mVolumes = new ArrayList<StorageVolume>(); + private StorageVolume mPrimaryVolume; private final HashMap<String, String> mVolumeStates = new HashMap<String, String>(); private String mExternalStoragePath; private PackageManagerService mPms; @@ -1068,6 +1081,74 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC } } + // Storage list XML tags + private static final String TAG_STORAGE_LIST = "StorageList"; + private static final String TAG_STORAGE = "storage"; + + private void readStorageList(Resources resources) { + int id = com.android.internal.R.xml.storage_list; + XmlResourceParser parser = resources.getXml(id); + AttributeSet attrs = Xml.asAttributeSet(parser); + + try { + XmlUtils.beginDocument(parser, TAG_STORAGE_LIST); + while (true) { + XmlUtils.nextElement(parser); + + String element = parser.getName(); + if (element == null) break; + + if (TAG_STORAGE.equals(element)) { + TypedArray a = resources.obtainAttributes(attrs, + com.android.internal.R.styleable.Storage); + + CharSequence path = a.getText( + com.android.internal.R.styleable.Storage_mountPoint); + CharSequence description = a.getText( + com.android.internal.R.styleable.Storage_storageDescription); + boolean primary = a.getBoolean( + com.android.internal.R.styleable.Storage_primary, false); + boolean removable = a.getBoolean( + com.android.internal.R.styleable.Storage_removable, false); + boolean emulated = a.getBoolean( + com.android.internal.R.styleable.Storage_emulated, false); + int mtpReserve = a.getInt( + com.android.internal.R.styleable.Storage_mtpReserve, 0); + + Slog.d(TAG, "got storage path: " + path + " description: " + description + + " primary: " + primary + " removable: " + removable + + " emulated: " + emulated + " mtpReserve: " + mtpReserve); + if (path == null || description == null) { + Slog.e(TAG, "path or description is null in readStorageList"); + } else { + StorageVolume volume = new StorageVolume(path.toString(), + description.toString(), removable, emulated, mtpReserve); + if (primary) { + if (mPrimaryVolume == null) { + mPrimaryVolume = volume; + } else { + Slog.e(TAG, "multiple primary volumes in storage list"); + } + } + if (mPrimaryVolume == volume) { + // primay volume must be first + mVolumes.add(0, volume); + } else { + mVolumes.add(volume); + } + } + a.recycle(); + } + } + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + parser.close(); + } + } + /** * Constructs a new MountService instance * @@ -1075,13 +1156,16 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC */ public MountService(Context context) { mContext = context; + Resources resources = context.getResources(); + readStorageList(resources); - mExternalStoragePath = Environment.getExternalStorageDirectory().getPath(); - mEmulateExternalStorage = context.getResources().getBoolean( - com.android.internal.R.bool.config_emulateExternalStorage); - if (mEmulateExternalStorage) { - Slog.d(TAG, "using emulated external storage"); - mVolumeStates.put(mExternalStoragePath, Environment.MEDIA_MOUNTED); + if (mPrimaryVolume != null) { + mExternalStoragePath = mPrimaryVolume.getPath(); + mEmulateExternalStorage = mPrimaryVolume.isEmulated(); + if (mEmulateExternalStorage) { + Slog.d(TAG, "using emulated external storage"); + mVolumeStates.put(mExternalStoragePath, Environment.MEDIA_MOUNTED); + } } // XXX: This will go away soon in favor of IMountServiceObserver @@ -1753,13 +1837,12 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC } } - public String[] getVolumeList() { - synchronized(mVolumeStates) { - Set<String> volumes = mVolumeStates.keySet(); - String[] result = new String[volumes.size()]; - int i = 0; - for (String volume : volumes) { - result[i++] = volume; + public Parcelable[] getVolumeList() { + synchronized(mVolumes) { + int size = mVolumes.size(); + Parcelable[] result = new Parcelable[size]; + for (int i = 0; i < size; i++) { + result[i] = mVolumes.get(i); } return result; } |