diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index e308c2c48a8d8..1f3f6d9565b6c 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 { *
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 27da3c3448809..c2dc8aeefc435 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 234057b8632e3..6fd1d002fa847 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 0000000000000..d689917905191
--- /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 0000000000000..d79f6c8f17924
--- /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