summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@android.com>2011-05-09 19:08:06 -0700
committerMike Lockwood <lockwood@android.com>2011-05-16 14:29:23 -0400
commit2f6a3885533a52758c2cd4f81f6123a712be8ae6 (patch)
treec4f6de0abad5d579cbd236194f1b6bd1f8a8eb93
parent084d3490a5283088426058d3c15532b176367926 (diff)
downloadframeworks_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.java45
-rw-r--r--core/java/android/os/storage/IMountService.java14
-rw-r--r--core/java/android/os/storage/StorageManager.java27
-rw-r--r--core/java/android/os/storage/StorageVolume.aidl19
-rw-r--r--core/java/android/os/storage/StorageVolume.java147
-rwxr-xr-xcore/res/res/values/attrs.xml17
-rw-r--r--core/res/res/values/config.xml50
-rwxr-xr-xcore/res/res/values/strings.xml8
-rw-r--r--core/res/res/xml/storage_list.xml40
-rw-r--r--media/java/android/media/MediaScanner.java3
-rw-r--r--services/java/com/android/server/MountService.java109
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;
}