diff options
| -rw-r--r-- | core/java/android/os/Environment.java | 6 | ||||
| -rw-r--r-- | core/java/android/os/storage/DiskInfo.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/os/storage/DiskInfo.java | 118 | ||||
| -rw-r--r-- | core/java/android/os/storage/IMountService.java | 55 | ||||
| -rw-r--r-- | core/java/android/os/storage/StorageManager.java | 35 | ||||
| -rw-r--r-- | core/java/android/os/storage/StorageVolume.java | 63 | ||||
| -rw-r--r-- | core/java/android/os/storage/VolumeInfo.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/os/storage/VolumeInfo.java | 255 | ||||
| -rw-r--r-- | core/java/com/android/internal/util/IndentingPrintWriter.java | 5 | ||||
| -rw-r--r-- | media/java/android/mtp/MtpStorage.java | 2 | ||||
| -rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/MountService.java | 384 |
12 files changed, 629 insertions, 338 deletions
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 2db976e..2eb97f1 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -80,11 +80,11 @@ public class Environment { public File[] getExternalDirs() { final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId); - final File[] dirs = new File[volumes.length]; + final File[] files = new File[volumes.length]; for (int i = 0; i < volumes.length; i++) { - dirs[i] = volumes[i].getPathFile(); + files[i] = volumes[i].getPathFile(); } - return dirs; + return files; } @Deprecated diff --git a/core/java/android/os/storage/DiskInfo.aidl b/core/java/android/os/storage/DiskInfo.aidl new file mode 100644 index 0000000..5126c19 --- /dev/null +++ b/core/java/android/os/storage/DiskInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015 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 DiskInfo; diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java new file mode 100644 index 0000000..d676b1e --- /dev/null +++ b/core/java/android/os/storage/DiskInfo.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2015 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.content.Context; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.DebugUtils; + +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; + +/** + * Information about a physical disk which may contain one or more + * {@link VolumeInfo}. + * + * @hide + */ +public class DiskInfo implements Parcelable { + public static final int FLAG_ADOPTABLE = 1 << 0; + public static final int FLAG_DEFAULT_PRIMARY = 1 << 1; + public static final int FLAG_SD = 1 << 2; + public static final int FLAG_USB = 1 << 3; + + public final String id; + public final int flags; + public long size; + public String label; + public String[] volumes; + + public DiskInfo(String id, int flags) { + this.id = Preconditions.checkNotNull(id); + this.flags = flags; + } + + public DiskInfo(Parcel parcel) { + id = parcel.readString(); + flags = parcel.readInt(); + size = parcel.readLong(); + label = parcel.readString(); + volumes = parcel.readStringArray(); + } + + public String getDescription(Context context) { + // TODO: splice vendor label into these strings + if ((flags & FLAG_SD) != 0) { + return context.getString(com.android.internal.R.string.storage_sd_card); + } else if ((flags & FLAG_USB) != 0) { + return context.getString(com.android.internal.R.string.storage_usb); + } else { + return null; + } + } + +// public void partitionPublic() throws NativeDaemonConnectorException { +// mConnector.execute("volume", "partition", id, "public"); +// } +// +// public void partitionPrivate() throws NativeDaemonConnectorException { +// mConnector.execute("volume", "partition", id, "private"); +// } +// +// public void partitionMixed(int frac) throws NativeDaemonConnectorException { +// mConnector.execute("volume", "partition", id, "mixed", frac); +// } + + public void dump(IndentingPrintWriter pw) { + pw.println("DiskInfo:"); + pw.increaseIndent(); + pw.printPair("id", id); + pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags)); + pw.printPair("size", size); + pw.printPair("label", label); + pw.printPair("volumes", volumes); + pw.decreaseIndent(); + pw.println(); + } + + public static final Creator<DiskInfo> CREATOR = new Creator<DiskInfo>() { + @Override + public DiskInfo createFromParcel(Parcel in) { + return new DiskInfo(in); + } + + @Override + public DiskInfo[] newArray(int size) { + return new DiskInfo[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(id); + parcel.writeInt(flags); + parcel.writeLong(size); + parcel.writeString(label); + parcel.writeStringArray(volumes); + } +} diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index fef12d1..4209ad4 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -904,6 +904,40 @@ public interface IMountService extends IInterface { } return; } + + @Override + public DiskInfo[] getDisks() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + DiskInfo[] _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_getDisks, _data, _reply, 0); + _reply.readException(); + _result = _reply.createTypedArray(DiskInfo.CREATOR); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + @Override + public VolumeInfo[] getVolumes() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + VolumeInfo[] _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_getDisks, _data, _reply, 0); + _reply.readException(); + _result = _reply.createTypedArray(VolumeInfo.CREATOR); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } } private static final String DESCRIPTOR = "IMountService"; @@ -996,6 +1030,10 @@ public interface IMountService extends IInterface { static final int TRANSACTION_waitForAsecScan = IBinder.FIRST_CALL_TRANSACTION + 43; + static final int TRANSACTION_getDisks = IBinder.FIRST_CALL_TRANSACTION + 44; + + static final int TRANSACTION_getVolumes = IBinder.FIRST_CALL_TRANSACTION + 45; + /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. @@ -1421,6 +1459,20 @@ public interface IMountService extends IInterface { reply.writeNoException(); return true; } + case TRANSACTION_getDisks: { + data.enforceInterface(DESCRIPTOR); + DiskInfo[] disks = getDisks(); + reply.writeNoException(); + reply.writeTypedArray(disks, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + return true; + } + case TRANSACTION_getVolumes: { + data.enforceInterface(DESCRIPTOR); + VolumeInfo[] volumes = getVolumes(); + reply.writeNoException(); + reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -1707,4 +1759,7 @@ public interface IMountService extends IInterface { public void runMaintenance() throws RemoteException; public void waitForAsecScan() throws RemoteException; + + public DiskInfo[] getDisks() throws RemoteException; + public VolumeInfo[] getVolumes() throws RemoteException; } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 532bf2c..83559fa 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -33,14 +33,13 @@ import android.provider.Settings; import android.util.Log; import android.util.SparseArray; -import libcore.util.EmptyArray; - import com.android.internal.util.Preconditions; import java.io.File; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -64,6 +63,9 @@ import java.util.concurrent.atomic.AtomicInteger; public class StorageManager { private static final String TAG = "StorageManager"; + /** {@hide} */ + public static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical"; + private final Context mContext; private final ContentResolver mResolver; @@ -555,6 +557,24 @@ public class StorageManager { } /** {@hide} */ + public @NonNull List<DiskInfo> getDisks() { + try { + return Arrays.asList(mMountService.getDisks()); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** {@hide} */ + public @NonNull List<VolumeInfo> getVolumes() { + try { + return Arrays.asList(mMountService.getVolumes()); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** {@hide} */ public @Nullable StorageVolume getStorageVolume(File file) { return getStorageVolume(getVolumeList(), file); } @@ -597,16 +617,9 @@ public class StorageManager { } } - /** - * Returns list of all mountable volumes. - * @hide - */ + /** {@hide} */ public @NonNull StorageVolume[] getVolumeList() { - try { - return mMountService.getVolumeList(mContext.getUserId()); - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); - } + return getVolumeList(mContext.getUserId()); } /** {@hide} */ diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java index 0c391ca..d66e228 100644 --- a/core/java/android/os/storage/StorageVolume.java +++ b/core/java/android/os/storage/StorageVolume.java @@ -23,13 +23,17 @@ import android.os.Parcelable; import android.os.UserHandle; import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; import java.io.CharArrayWriter; import java.io.File; /** - * Description of a storage volume and its capabilities, including the - * filesystem path where it may be mounted. + * Information about a storage volume that may be mounted. This is a legacy + * specialization of {@link VolumeInfo} which describes the volume for a + * specific user. + * <p> + * This class may be deprecated in the future. * * @hide */ @@ -37,21 +41,16 @@ public class StorageVolume implements Parcelable { private final String mId; private final int mStorageId; - private final File mPath; - private final int mDescriptionId; + private final String mDescription; private final boolean mPrimary; private final boolean mRemovable; private final boolean mEmulated; private final long mMtpReserveSize; private final boolean mAllowMassStorage; - /** Maximum file size for the storage, or zero for no limit */ private final long mMaxFileSize; - /** When set, indicates exclusive ownership of this volume */ private final UserHandle mOwner; - - private final String mUuid; - private final String mUserLabel; + private final String mFsUuid; private final String mState; // StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING, @@ -59,30 +58,29 @@ public class StorageVolume implements Parcelable { // ACTION_MEDIA_BAD_REMOVAL, ACTION_MEDIA_UNMOUNTABLE and ACTION_MEDIA_EJECT broadcasts. public static final String EXTRA_STORAGE_VOLUME = "storage_volume"; - public StorageVolume(String id, int storageId, File path, int descriptionId, boolean primary, + public StorageVolume(String id, int storageId, File path, String description, boolean primary, boolean removable, boolean emulated, long mtpReserveSize, boolean allowMassStorage, - long maxFileSize, UserHandle owner, String uuid, String userLabel, String state) { - mId = id; + long maxFileSize, UserHandle owner, String fsUuid, String state) { + mId = Preconditions.checkNotNull(id); mStorageId = storageId; - mPath = path; - mDescriptionId = descriptionId; + mPath = Preconditions.checkNotNull(path); + mDescription = Preconditions.checkNotNull(description); mPrimary = primary; mRemovable = removable; mEmulated = emulated; mMtpReserveSize = mtpReserveSize; mAllowMassStorage = allowMassStorage; mMaxFileSize = maxFileSize; - mOwner = owner; - mUuid = uuid; - mUserLabel = userLabel; - mState = state; + mOwner = Preconditions.checkNotNull(owner); + mFsUuid = fsUuid; + mState = Preconditions.checkNotNull(state); } private StorageVolume(Parcel in) { mId = in.readString(); mStorageId = in.readInt(); mPath = new File(in.readString()); - mDescriptionId = in.readInt(); + mDescription = in.readString(); mPrimary = in.readInt() != 0; mRemovable = in.readInt() != 0; mEmulated = in.readInt() != 0; @@ -90,8 +88,7 @@ public class StorageVolume implements Parcelable { mAllowMassStorage = in.readInt() != 0; mMaxFileSize = in.readLong(); mOwner = in.readParcelable(null); - mUuid = in.readString(); - mUserLabel = in.readString(); + mFsUuid = in.readString(); mState = in.readString(); } @@ -118,11 +115,7 @@ public class StorageVolume implements Parcelable { * @return the volume description */ public String getDescription(Context context) { - return context.getResources().getString(mDescriptionId); - } - - public int getDescriptionId() { - return mDescriptionId; + return mDescription; } public boolean isPrimary() { @@ -196,7 +189,7 @@ public class StorageVolume implements Parcelable { } public String getUuid() { - return mUuid; + return mFsUuid; } /** @@ -204,18 +197,18 @@ public class StorageVolume implements Parcelable { * parse or UUID is unknown. */ public int getFatVolumeId() { - if (mUuid == null || mUuid.length() != 9) { + if (mFsUuid == null || mFsUuid.length() != 9) { return -1; } try { - return (int)Long.parseLong(mUuid.replace("-", ""), 16); + return (int) Long.parseLong(mFsUuid.replace("-", ""), 16); } catch (NumberFormatException e) { return -1; } } public String getUserLabel() { - return mUserLabel; + return mDescription; } public String getState() { @@ -249,7 +242,7 @@ public class StorageVolume implements Parcelable { pw.printPair("mId", mId); pw.printPair("mStorageId", mStorageId); pw.printPair("mPath", mPath); - pw.printPair("mDescriptionId", mDescriptionId); + pw.printPair("mDescription", mDescription); pw.printPair("mPrimary", mPrimary); pw.printPair("mRemovable", mRemovable); pw.printPair("mEmulated", mEmulated); @@ -257,8 +250,7 @@ public class StorageVolume implements Parcelable { pw.printPair("mAllowMassStorage", mAllowMassStorage); pw.printPair("mMaxFileSize", mMaxFileSize); pw.printPair("mOwner", mOwner); - pw.printPair("mUuid", mUuid); - pw.printPair("mUserLabel", mUserLabel); + pw.printPair("mFsUuid", mFsUuid); pw.printPair("mState", mState); pw.decreaseIndent(); } @@ -285,7 +277,7 @@ public class StorageVolume implements Parcelable { parcel.writeString(mId); parcel.writeInt(mStorageId); parcel.writeString(mPath.toString()); - parcel.writeInt(mDescriptionId); + parcel.writeString(mDescription); parcel.writeInt(mPrimary ? 1 : 0); parcel.writeInt(mRemovable ? 1 : 0); parcel.writeInt(mEmulated ? 1 : 0); @@ -293,8 +285,7 @@ public class StorageVolume implements Parcelable { parcel.writeInt(mAllowMassStorage ? 1 : 0); parcel.writeLong(mMaxFileSize); parcel.writeParcelable(mOwner, flags); - parcel.writeString(mUuid); - parcel.writeString(mUserLabel); + parcel.writeString(mFsUuid); parcel.writeString(mState); } } diff --git a/core/java/android/os/storage/VolumeInfo.aidl b/core/java/android/os/storage/VolumeInfo.aidl new file mode 100644 index 0000000..32d12da --- /dev/null +++ b/core/java/android/os/storage/VolumeInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015 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 VolumeInfo; diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java new file mode 100644 index 0000000..22bf1e4 --- /dev/null +++ b/core/java/android/os/storage/VolumeInfo.java @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2015 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.content.Context; +import android.content.Intent; +import android.mtp.MtpStorage; +import android.os.Environment; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; +import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.DebugUtils; +import android.util.SparseArray; + +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; + +import java.io.File; + +/** + * Information about a storage volume that may be mounted. A volume may be a + * partition on a physical {@link DiskInfo}, an emulated volume above some other + * storage medium, or a standalone container like an ASEC or OBB. + * + * @hide + */ +public class VolumeInfo implements Parcelable { + public static final String ID_EMULATED_INTERNAL = "emulated"; + + public static final int TYPE_PUBLIC = 0; + public static final int TYPE_PRIVATE = 1; + public static final int TYPE_EMULATED = 2; + public static final int TYPE_ASEC = 3; + public static final int TYPE_OBB = 4; + + public static final int STATE_UNMOUNTED = 0; + public static final int STATE_MOUNTING = 1; + public static final int STATE_MOUNTED = 2; + public static final int STATE_FORMATTING = 3; + public static final int STATE_UNMOUNTING = 4; + + public static final int FLAG_PRIMARY = 1 << 0; + public static final int FLAG_VISIBLE = 1 << 1; + + public static SparseArray<String> sStateToEnvironment = new SparseArray<>(); + public static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>(); + + static { + sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTED, Environment.MEDIA_UNMOUNTED); + sStateToEnvironment.put(VolumeInfo.STATE_MOUNTING, Environment.MEDIA_CHECKING); + sStateToEnvironment.put(VolumeInfo.STATE_MOUNTED, Environment.MEDIA_MOUNTED); + sStateToEnvironment.put(VolumeInfo.STATE_FORMATTING, Environment.MEDIA_UNMOUNTED); + sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTING, Environment.MEDIA_EJECTING); + + 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_EJECTING, Intent.ACTION_MEDIA_EJECT); + } + + /** vold state */ + public final String id; + public final int type; + public int flags = 0; + public int userId = -1; + public int state = STATE_UNMOUNTED; + public String fsType; + public String fsUuid; + public String fsLabel; + public String path; + + /** Framework state */ + public final int mtpIndex; + public String nickname; + + public DiskInfo disk; + + public VolumeInfo(String id, int type, int mtpIndex) { + this.id = Preconditions.checkNotNull(id); + this.type = type; + this.mtpIndex = mtpIndex; + } + + public VolumeInfo(Parcel parcel) { + id = parcel.readString(); + type = parcel.readInt(); + flags = parcel.readInt(); + userId = parcel.readInt(); + state = parcel.readInt(); + fsType = parcel.readString(); + fsUuid = parcel.readString(); + fsLabel = parcel.readString(); + path = parcel.readString(); + mtpIndex = parcel.readInt(); + nickname = parcel.readString(); + } + + public String getDescription(Context context) { + if (ID_EMULATED_INTERNAL.equals(id)) { + return context.getString(com.android.internal.R.string.storage_internal); + } else if (!TextUtils.isEmpty(nickname)) { + return nickname; + } else if (!TextUtils.isEmpty(fsLabel)) { + return fsLabel; + } else { + return null; + } + } + + public boolean isPrimary() { + return (flags & FLAG_PRIMARY) != 0; + } + + public boolean isVisible() { + return (flags & FLAG_VISIBLE) != 0; + } + + public boolean isVisibleToUser(int userId) { + if (type == TYPE_PUBLIC && userId == this.userId) { + return isVisible(); + } else if (type == TYPE_EMULATED) { + return isVisible(); + } else { + return false; + } + } + + public File getPathForUser(int userId) { + if (type == TYPE_PUBLIC && userId == this.userId) { + return new File(path); + } else if (type == TYPE_EMULATED) { + return new File(path, Integer.toString(userId)); + } else { + return null; + } + } + + public StorageVolume buildStorageVolume(Context context, int userId) { + final boolean removable; + final boolean emulated; + final boolean allowMassStorage = false; + final int mtpStorageId = MtpStorage.getStorageIdForIndex(mtpIndex); + + File userPath = getPathForUser(userId); + if (userPath == null) { + userPath = new File("/dev/null"); + } + + String description = getDescription(context); + if (description == null) { + description = context.getString(android.R.string.unknownName); + } + + String envState = sStateToEnvironment.get(state); + if (envState == null) { + envState = Environment.MEDIA_UNKNOWN; + } + + long mtpReserveSize = 0; + long maxFileSize = 0; + + if (type == TYPE_EMULATED) { + emulated = true; + mtpReserveSize = StorageManager.from(context).getStorageLowBytes(userPath); + + if (ID_EMULATED_INTERNAL.equals(id)) { + removable = false; + } else { + removable = true; + } + + } else if (type == TYPE_PUBLIC) { + emulated = false; + removable = true; + + if ("vfat".equals(fsType)) { + maxFileSize = 4294967295L; + } + + } else { + throw new IllegalStateException("Unexpected volume type " + type); + } + + return new StorageVolume(id, mtpStorageId, userPath, description, isPrimary(), removable, + emulated, mtpReserveSize, allowMassStorage, maxFileSize, new UserHandle(userId), + fsUuid, envState); + } + + public void dump(IndentingPrintWriter pw) { + pw.println("VolumeInfo:"); + pw.increaseIndent(); + pw.printPair("id", id); + pw.printPair("type", DebugUtils.valueToString(getClass(), "TYPE_", type)); + pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags)); + pw.printPair("userId", userId); + pw.printPair("state", DebugUtils.valueToString(getClass(), "STATE_", state)); + pw.println(); + pw.printPair("fsType", fsType); + pw.printPair("fsUuid", fsUuid); + pw.printPair("fsLabel", fsLabel); + pw.println(); + pw.printPair("path", path); + pw.printPair("mtpIndex", mtpIndex); + pw.decreaseIndent(); + pw.println(); + } + + public static final Creator<VolumeInfo> CREATOR = new Creator<VolumeInfo>() { + @Override + public VolumeInfo createFromParcel(Parcel in) { + return new VolumeInfo(in); + } + + @Override + public VolumeInfo[] newArray(int size) { + return new VolumeInfo[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(id); + parcel.writeInt(type); + parcel.writeInt(flags); + parcel.writeInt(userId); + parcel.writeInt(state); + parcel.writeString(fsType); + parcel.writeString(fsUuid); + parcel.writeString(fsLabel); + parcel.writeString(path); + parcel.writeInt(mtpIndex); + parcel.writeString(nickname); + } +} diff --git a/core/java/com/android/internal/util/IndentingPrintWriter.java b/core/java/com/android/internal/util/IndentingPrintWriter.java index 6fddd09..f1add27 100644 --- a/core/java/com/android/internal/util/IndentingPrintWriter.java +++ b/core/java/com/android/internal/util/IndentingPrintWriter.java @@ -18,6 +18,7 @@ package com.android.internal.util; import java.io.PrintWriter; import java.io.Writer; +import java.util.Arrays; /** * Lightweight wrapper around {@link PrintWriter} that automatically indents @@ -68,6 +69,10 @@ public class IndentingPrintWriter extends PrintWriter { print(key + "=" + String.valueOf(value) + " "); } + public void printPair(String key, Object[] value) { + print(key + "=" + Arrays.toString(value) + " "); + } + public void printHexPair(String key, int value) { print(key + "=0x" + Integer.toHexString(value) + " "); } diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java index 7b8102b..3641ff5 100644 --- a/media/java/android/mtp/MtpStorage.java +++ b/media/java/android/mtp/MtpStorage.java @@ -38,7 +38,7 @@ public class MtpStorage { public MtpStorage(StorageVolume volume, Context context) { mStorageId = volume.getStorageId(); mPath = volume.getPath(); - mDescription = context.getResources().getString(volume.getDescriptionId()); + mDescription = volume.getDescription(context); mReserveSpace = volume.getMtpReserveSpace() * 1024L * 1024L; mRemovable = volume.isRemovable(); mMaxFileSize = volume.getMaxFileSize(); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 126b4aa..0d61606 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -1502,15 +1502,15 @@ public class SettingsProvider extends ContentProvider { public void onPackageRemovedLocked(String packageName, int userId) { final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER); SettingsState globalSettings = mSettingsStates.get(globalKey); - globalSettings.onPackageRemovedLocked(packageName); + if (globalSettings != null) globalSettings.onPackageRemovedLocked(packageName); final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId); SettingsState secureSettings = mSettingsStates.get(secureKey); - secureSettings.onPackageRemovedLocked(packageName); + if (secureSettings != null) secureSettings.onPackageRemovedLocked(packageName); final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId); SettingsState systemSettings = mSettingsStates.get(systemKey); - systemSettings.onPackageRemovedLocked(packageName); + if (systemSettings != null) systemSettings.onPackageRemovedLocked(packageName); } private SettingsState peekSettingsStateLocked(int key) { diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 61286e8..4d8cb90 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -42,6 +42,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; +import android.os.storage.DiskInfo; import android.os.storage.IMountService; import android.os.storage.IMountServiceListener; import android.os.storage.IMountShutdownObserver; @@ -50,11 +51,11 @@ import android.os.storage.OnObbStateChangeListener; import android.os.storage.StorageManager; import android.os.storage.StorageResultCode; import android.os.storage.StorageVolume; +import android.os.storage.VolumeInfo; import android.text.TextUtils; import android.util.ArrayMap; -import android.util.DebugUtils; +import android.util.Log; import android.util.Slog; -import android.util.SparseArray; import libcore.util.EmptyArray; import libcore.util.HexEncoding; @@ -68,7 +69,6 @@ import com.android.internal.util.Preconditions; import com.android.server.NativeDaemonConnector.Command; import com.android.server.NativeDaemonConnector.SensitiveArg; import com.android.server.pm.PackageManagerService; -import com.google.android.collect.Lists; import java.io.File; import java.io.FileDescriptor; @@ -143,7 +143,6 @@ class MountService extends IMountService.Stub } private static final boolean LOCAL_LOGD = false; - private static final boolean DEBUG_UNMOUNT = false; private static final boolean DEBUG_EVENTS = false; private static final boolean DEBUG_OBB = false; @@ -157,8 +156,6 @@ class MountService extends IMountService.Stub /** Maximum number of ASEC containers allowed to be mounted. */ private static final int MAX_CONTAINERS = 250; - private static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical"; - /* * Internal vold response code constants */ @@ -213,22 +210,6 @@ class MountService extends IMountService.Stub public static final int FstrimCompleted = 700; } - private static SparseArray<String> sStateToEnvironment = new SparseArray<>(); - private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>(); - - static { - sStateToEnvironment.put(Volume.STATE_UNMOUNTED, Environment.MEDIA_UNMOUNTED); - sStateToEnvironment.put(Volume.STATE_MOUNTING, Environment.MEDIA_CHECKING); - sStateToEnvironment.put(Volume.STATE_MOUNTED, Environment.MEDIA_MOUNTED); - sStateToEnvironment.put(Volume.STATE_FORMATTING, Environment.MEDIA_UNMOUNTED); - sStateToEnvironment.put(Volume.STATE_UNMOUNTING, Environment.MEDIA_EJECTING); - - 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_EJECTING, Intent.ACTION_MEDIA_EJECT); - } - /** * <em>Never</em> hold the lock while performing downcalls into vold, since * unsolicited events can suddenly appear to update data structures. @@ -238,14 +219,15 @@ class MountService extends IMountService.Stub @GuardedBy("mLock") private int[] mStartedUsers = EmptyArray.INT; @GuardedBy("mLock") - private ArrayMap<String, Disk> mDisks = new ArrayMap<>(); + private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>(); @GuardedBy("mLock") - private ArrayMap<String, Volume> mVolumes = new ArrayMap<>(); + private ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>(); @Deprecated - private Volume findVolumeByLegacyPath(String legacyPath) { + private VolumeInfo findVolumeByLegacyPath(String legacyPath) { synchronized (mLock) { - for (Volume vol : mVolumes.values()) { + for (int i = 0; i < mVolumes.size(); i++) { + final VolumeInfo vol = mVolumes.valueAt(i); if (vol.path != null && legacyPath.startsWith(vol.path)) { return vol; } @@ -255,198 +237,13 @@ class MountService extends IMountService.Stub return null; } - /** - * Framework-side twin of android::vold::Disk - */ - private class Disk { - public static final int FLAG_ADOPTABLE = 1 << 0; - public static final int FLAG_DEFAULT_PRIMARY = 1 << 1; - public static final int FLAG_SD = 1 << 2; - public static final int FLAG_USB = 1 << 3; - - public final String id; - public final int flags; - public long size; - public String label; - - public ArrayList<Volume> volumes = new ArrayList<>(); - - public Disk(String id, int flags) { - this.id = id; - this.flags = flags; - } - - public void partitionPublic() throws NativeDaemonConnectorException { - mConnector.execute("volume", "partition", id, "public"); - } - - public void partitionPrivate() throws NativeDaemonConnectorException { - mConnector.execute("volume", "partition", id, "private"); - } - - public void partitionMixed(int frac) throws NativeDaemonConnectorException { - mConnector.execute("volume", "partition", id, "mixed", frac); - } - - public void dump(IndentingPrintWriter pw) { - pw.println("Disk:"); - pw.increaseIndent(); - pw.printPair("id", id); - pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags)); - pw.printPair("size", size); - pw.printPair("label", label); - pw.decreaseIndent(); - pw.println(); - } - } - private static int sNextMtpIndex = 1; - /** - * Framework-side twin of android::vold::VolumeBase - */ - private class Volume { - public static final String ID_EMULATED_INTERNAL = "emulated"; - - public static final int TYPE_PUBLIC = 0; - public static final int TYPE_PRIVATE = 1; - public static final int TYPE_EMULATED = 2; - public static final int TYPE_ASEC = 3; - public static final int TYPE_OBB = 4; - - public static final int STATE_UNMOUNTED = 0; - public static final int STATE_MOUNTING = 1; - public static final int STATE_MOUNTED = 2; - public static final int STATE_FORMATTING = 3; - public static final int STATE_UNMOUNTING = 4; - - public static final int FLAG_PRIMARY = 1 << 0; - public static final int FLAG_VISIBLE = 1 << 1; - - /** vold state */ - public final String id; - public final int type; - public int flags = 0; - public int userId = -1; - public int state = STATE_UNMOUNTED; - public String fsType; - public String fsUuid; - public String fsLabel; - public String path = "/dev/null"; - - /** Framework state */ - public final int mtpIndex; - - public Disk disk; - - public Volume(String id, int type) { - this.id = id; - this.type = type; - - if (ID_EMULATED_INTERNAL.equals(id)) { - mtpIndex = 0; - } else { - mtpIndex = sNextMtpIndex++; - } - } - - public boolean isPrimary() { - return (flags & FLAG_PRIMARY) != 0; - } - - public boolean isVisible() { - return (flags & FLAG_VISIBLE) != 0; - } - - public boolean isVisibleToUser(int userId) { - if (type == TYPE_PUBLIC && this.userId == userId) { - return isVisible(); - } else if (type == TYPE_EMULATED) { - return isVisible(); - } else { - return false; - } - } - - public void mount() throws NativeDaemonConnectorException { - mConnector.execute("volume", "mount", id, flags, userId); - } - - public void unmount() throws NativeDaemonConnectorException { - mConnector.execute("volume", "unmount", id); - } - - public void format() throws NativeDaemonConnectorException { - mConnector.execute("volume", "format", id); - } - - public StorageVolume buildVolumeForUser(int userId) { - final File userPath; - final boolean removable; - final boolean emulated; - final boolean allowMassStorage = false; - final int mtpStorageId = MtpStorage.getStorageIdForIndex(mtpIndex); - final String envState = sStateToEnvironment.get(state); - - int descriptionId = com.android.internal.R.string.unknownName; - long mtpReserveSize = 0; - long maxFileSize = 0; - - if (type == TYPE_EMULATED) { - userPath = new File(path, Integer.toString(userId)); - emulated = true; - mtpReserveSize = StorageManager.from(mContext).getStorageLowBytes(userPath); - descriptionId = com.android.internal.R.string.storage_internal; - - if (ID_EMULATED_INTERNAL.equals(id)) { - removable = false; - } else { - removable = true; - } - - } else if (type == TYPE_PUBLIC) { - userPath = new File(path); - emulated = false; - removable = true; - - if (disk != null) { - if ((disk.flags & Disk.FLAG_SD) != 0) { - descriptionId = com.android.internal.R.string.storage_sd_card; - } else if ((disk.flags & Disk.FLAG_USB) != 0) { - descriptionId = com.android.internal.R.string.storage_usb; - } - } - - if ("vfat".equals(fsType)) { - maxFileSize = 4294967295L; - } - - } else { - throw new IllegalStateException("Unexpected volume type " + type); - } - - return new StorageVolume(id, mtpStorageId, userPath, descriptionId, isPrimary(), - removable, emulated, mtpReserveSize, allowMassStorage, maxFileSize, - new UserHandle(userId), fsUuid, fsLabel, envState); - } - - public void dump(IndentingPrintWriter pw) { - pw.println("Volume:"); - pw.increaseIndent(); - pw.printPair("id", id); - pw.printPair("type", DebugUtils.valueToString(getClass(), "TYPE_", type)); - pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags)); - pw.printPair("userId", userId); - pw.printPair("state", DebugUtils.valueToString(getClass(), "STATE_", state)); - pw.println(); - pw.printPair("fsType", fsType); - pw.printPair("fsUuid", fsUuid); - pw.printPair("fsLabel", fsLabel); - pw.println(); - pw.printPair("path", path); - pw.printPair("mtpIndex", mtpIndex); - pw.decreaseIndent(); - pw.println(); + private static int allocateMtpIndex(String volId) { + if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volId)) { + return 0; + } else { + return sNextMtpIndex++; } } @@ -672,9 +469,9 @@ class MountService extends IMountService.Stub break; } case H_VOLUME_MOUNT: { - final Volume vol = (Volume) msg.obj; + final VolumeInfo vol = (VolumeInfo) msg.obj; try { - vol.mount(); + mConnector.execute("volume", "mount", vol.id, vol.flags, vol.userId); } catch (NativeDaemonConnectorException ignored) { } break; @@ -685,7 +482,7 @@ class MountService extends IMountService.Stub Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + state + " to " + userVol.getOwner()); - final String action = sEnvironmentToBroadcast.get(state); + final String action = VolumeInfo.sEnvironmentToBroadcast.get(state); if (action != null) { final Intent intent = new Intent(action, Uri.fromFile(userVol.getPathFile())); @@ -769,9 +566,10 @@ class MountService extends IMountService.Stub // Record user as started so newly mounted volumes kick off events // correctly, then synthesize events for any already-mounted volumes. synchronized (mVolumes) { - for (Volume vol : mVolumes.values()) { - if (vol.isVisibleToUser(userId) && vol.state == Volume.STATE_MOUNTED) { - final StorageVolume userVol = vol.buildVolumeForUser(userId); + for (int i = 0; i < mVolumes.size(); i++) { + final VolumeInfo vol = mVolumes.valueAt(i); + if (vol.isVisibleToUser(userId) && vol.state == VolumeInfo.STATE_MOUNTED) { + final StorageVolume userVol = vol.buildStorageVolume(mContext, userId); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); } } @@ -906,12 +704,12 @@ class MountService extends IMountService.Stub if (cooked.length != 3) break; final String id = cooked[1]; final int flags = Integer.parseInt(cooked[2]); - mDisks.put(id, new Disk(id, flags)); + mDisks.put(id, new DiskInfo(id, flags)); break; } case VoldResponseCode.DISK_SIZE_CHANGED: { if (cooked.length != 3) break; - final Disk disk = mDisks.get(cooked[1]); + final DiskInfo disk = mDisks.get(cooked[1]); if (disk != null) { disk.size = Long.parseLong(cooked[2]); } @@ -919,7 +717,7 @@ class MountService extends IMountService.Stub } case VoldResponseCode.DISK_LABEL_CHANGED: { if (cooked.length != 3) break; - final Disk disk = mDisks.get(cooked[1]); + final DiskInfo disk = mDisks.get(cooked[1]); if (disk != null) { disk.label = cooked[2]; } @@ -927,10 +725,10 @@ class MountService extends IMountService.Stub } case VoldResponseCode.DISK_VOLUME_CREATED: { if (cooked.length != 3) break; - final Disk disk = mDisks.get(cooked[1]); - final Volume vol = mVolumes.get(cooked[2]); - if (disk != null && vol != null) { - disk.volumes.add(vol); + final DiskInfo disk = mDisks.get(cooked[1]); + final String volId = cooked[2]; + if (disk != null) { + disk.volumes = ArrayUtils.appendElement(String.class, disk.volumes, volId); } break; } @@ -944,14 +742,15 @@ class MountService extends IMountService.Stub if (cooked.length != 3) break; final String id = cooked[1]; final int type = Integer.parseInt(cooked[2]); - final Volume vol = new Volume(id, type); + final int mtpIndex = allocateMtpIndex(id); + final VolumeInfo vol = new VolumeInfo(id, type, mtpIndex); mVolumes.put(id, vol); onVolumeCreatedLocked(vol); break; } case VoldResponseCode.VOLUME_STATE_CHANGED: { if (cooked.length != 3) break; - final Volume vol = mVolumes.get(cooked[1]); + final VolumeInfo vol = mVolumes.get(cooked[1]); if (vol != null) { final int oldState = vol.state; final int newState = Integer.parseInt(cooked[2]); @@ -962,7 +761,7 @@ class MountService extends IMountService.Stub } case VoldResponseCode.VOLUME_FS_TYPE_CHANGED: { if (cooked.length != 3) break; - final Volume vol = mVolumes.get(cooked[1]); + final VolumeInfo vol = mVolumes.get(cooked[1]); if (vol != null) { vol.fsType = cooked[2]; } @@ -970,7 +769,7 @@ class MountService extends IMountService.Stub } case VoldResponseCode.VOLUME_FS_UUID_CHANGED: { if (cooked.length != 3) break; - final Volume vol = mVolumes.get(cooked[1]); + final VolumeInfo vol = mVolumes.get(cooked[1]); if (vol != null) { vol.fsUuid = cooked[2]; } @@ -978,7 +777,7 @@ class MountService extends IMountService.Stub } case VoldResponseCode.VOLUME_FS_LABEL_CHANGED: { if (cooked.length != 3) break; - final Volume vol = mVolumes.get(cooked[1]); + final VolumeInfo vol = mVolumes.get(cooked[1]); if (vol != null) { vol.fsLabel = cooked[2]; } @@ -986,13 +785,14 @@ class MountService extends IMountService.Stub } case VoldResponseCode.VOLUME_PATH_CHANGED: { if (cooked.length != 3) break; - final Volume vol = mVolumes.get(cooked[1]); + final VolumeInfo vol = mVolumes.get(cooked[1]); if (vol != null) { vol.path = cooked[2]; } break; } case VoldResponseCode.VOLUME_DESTROYED: { + // TODO: send ACTION_MEDIA_REMOVED broadcast if (cooked.length != 2) break; mVolumes.remove(cooked[1]); break; @@ -1010,18 +810,19 @@ class MountService extends IMountService.Stub return true; } - private void onVolumeCreatedLocked(Volume vol) { - final boolean primaryPhysical = SystemProperties.getBoolean(PROP_PRIMARY_PHYSICAL, false); - if (vol.type == Volume.TYPE_EMULATED && !primaryPhysical) { - vol.flags |= Volume.FLAG_PRIMARY; - vol.flags |= Volume.FLAG_VISIBLE; + private void onVolumeCreatedLocked(VolumeInfo vol) { + final boolean primaryPhysical = SystemProperties.getBoolean( + StorageManager.PROP_PRIMARY_PHYSICAL, false); + if (vol.type == VolumeInfo.TYPE_EMULATED && !primaryPhysical) { + vol.flags |= VolumeInfo.FLAG_PRIMARY; + vol.flags |= VolumeInfo.FLAG_VISIBLE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); - } else if (vol.type == Volume.TYPE_PUBLIC) { + } else if (vol.type == VolumeInfo.TYPE_PUBLIC) { if (primaryPhysical) { - vol.flags |= Volume.FLAG_PRIMARY; + vol.flags |= VolumeInfo.FLAG_PRIMARY; } - vol.flags |= Volume.FLAG_VISIBLE; + vol.flags |= VolumeInfo.FLAG_VISIBLE; vol.userId = UserHandle.USER_OWNER; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); @@ -1030,24 +831,24 @@ class MountService extends IMountService.Stub } } - private void onVolumeStateChangedLocked(Volume vol, int oldState, int newState) { + private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) { // Kick state changed event towards all started users. Any users // started after this point will trigger additional // user-specific broadcasts. for (int userId : mStartedUsers) { if (vol.isVisibleToUser(userId)) { - final StorageVolume userVol = vol.buildVolumeForUser(userId); + final StorageVolume userVol = vol.buildStorageVolume(mContext, userId); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); } } // Tell PackageManager about changes to primary volume state, but only // when not emulated. - if (vol.isPrimary() && vol.type == Volume.TYPE_PUBLIC) { - if (vol.state == Volume.STATE_MOUNTED) { + if (vol.isPrimary() && vol.type == VolumeInfo.TYPE_PUBLIC) { + if (vol.state == VolumeInfo.STATE_MOUNTED) { mPms.updateExternalMediaStatus(true, false); - } else if (vol.state == Volume.STATE_UNMOUNTING) { + } else if (vol.state == VolumeInfo.STATE_UNMOUNTING) { mPms.updateExternalMediaStatus(false, false); // TODO: this should eventually be handled by new ObbVolume state changes @@ -1061,8 +862,8 @@ class MountService extends IMountService.Stub } } - final String oldEnvState = sStateToEnvironment.get(oldState); - final String newEnvState = sStateToEnvironment.get(newState); + final String oldEnvState = VolumeInfo.sStateToEnvironment.get(oldState); + final String newEnvState = VolumeInfo.sStateToEnvironment.get(newState); synchronized (mListeners) { for (int i = mListeners.size() -1; i >= 0; i--) { @@ -1203,22 +1004,16 @@ class MountService extends IMountService.Stub return false; } - /** - * @return state of the volume at the specified mount point - */ @Override @Deprecated public String getVolumeState(String mountPoint) { - // TODO: pretend that we're unmounted when encrypting? - // SystemProperties.get("vold.encrypt_progress") - - final Volume vol = findVolumeByLegacyPath(mountPoint); - return sStateToEnvironment.get(vol.state); + throw new UnsupportedOperationException(); } @Override + @Deprecated public boolean isExternalStorageEmulated() { - return Environment.isExternalStorageEmulated(); + throw new UnsupportedOperationException(); } @Override @@ -1226,13 +1021,13 @@ class MountService extends IMountService.Stub enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); - final Volume vol = findVolumeByLegacyPath(path); + final VolumeInfo vol = findVolumeByLegacyPath(path); if (vol != null) { - if (vol.type == Volume.TYPE_PUBLIC || vol.type == Volume.TYPE_PRIVATE) { + if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) { enforceUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA); } try { - vol.mount(); + mConnector.execute("volume", "mount", vol.id, vol.flags, vol.userId); return 0; } catch (NativeDaemonConnectorException ignored) { } @@ -1247,7 +1042,7 @@ class MountService extends IMountService.Stub enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); - final Volume vol = findVolumeByLegacyPath(path); + final VolumeInfo vol = findVolumeByLegacyPath(path); if (vol != null) { // TODO: expand PMS to know about multiple volumes if (vol.isPrimary()) { @@ -1260,7 +1055,7 @@ class MountService extends IMountService.Stub } try { - vol.unmount(); + mConnector.execute("volume", "unmount", vol.id); } catch (NativeDaemonConnectorException ignored) { } } else { @@ -1273,10 +1068,10 @@ class MountService extends IMountService.Stub enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); waitForReady(); - final Volume vol = findVolumeByLegacyPath(path); + final VolumeInfo vol = findVolumeByLegacyPath(path); if (vol != null) { try { - vol.format(); + mConnector.execute("volume", "format", vol.id); return 0; } catch (NativeDaemonConnectorException ignored) { } @@ -1315,8 +1110,9 @@ class MountService extends IMountService.Stub private void warnOnNotMounted() { synchronized (mLock) { - for (Volume vol : mVolumes.values()) { - if (vol.isPrimary() && vol.state == Volume.STATE_MOUNTED) { + for (int i = 0; i < mVolumes.size(); i++) { + final VolumeInfo vol = mVolumes.valueAt(i); + if (vol.isPrimary() && vol.state == VolumeInfo.STATE_MOUNTED) { // Cool beans, we have a mounted primary volume return; } @@ -2012,17 +1808,14 @@ class MountService extends IMountService.Stub @Override public StorageVolume[] getVolumeList(int userId) { - if (UserHandle.getCallingUserId() != userId) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE, "getVolumeList"); - } - - final ArrayList<StorageVolume> res = Lists.newArrayList(); + final ArrayList<StorageVolume> res = new ArrayList<>(); boolean foundPrimary = false; + synchronized (mLock) { - for (Volume vol : mVolumes.values()) { + for (int i = 0; i < mVolumes.size(); i++) { + final VolumeInfo vol = mVolumes.valueAt(i); if (vol.isVisibleToUser(userId)) { - final StorageVolume userVol = vol.buildVolumeForUser(userId); + final StorageVolume userVol = vol.buildStorageVolume(mContext, userId); if (vol.isPrimary()) { res.add(0, userVol); foundPrimary = true; @@ -2034,14 +1827,14 @@ class MountService extends IMountService.Stub } if (!foundPrimary) { - Slog.w(TAG, "No primary storage defined yet; hacking together a stub"); + Log.w(TAG, "No primary storage defined yet; hacking together a stub"); final boolean primaryPhysical = SystemProperties.getBoolean( - PROP_PRIMARY_PHYSICAL, false); + StorageManager.PROP_PRIMARY_PHYSICAL, false); final String id = "stub_primary"; final File path = Environment.getLegacyExternalStorageDirectory(); - final int descriptionId = android.R.string.unknownName; + final String description = mContext.getString(android.R.string.unknownName); final boolean primary = true; final boolean removable = primaryPhysical; final boolean emulated = !primaryPhysical; @@ -2050,17 +1843,38 @@ class MountService extends IMountService.Stub final long maxFileSize = 0L; final UserHandle owner = new UserHandle(userId); final String uuid = null; - final String userLabel = null; final String state = Environment.MEDIA_REMOVED; res.add(0, new StorageVolume(id, MtpStorage.getStorageIdForIndex(0), path, - descriptionId, primary, removable, emulated, mtpReserveSize, - allowMassStorage, maxFileSize, owner, uuid, userLabel, state)); + description, primary, removable, emulated, mtpReserveSize, + allowMassStorage, maxFileSize, owner, uuid, state)); } return res.toArray(new StorageVolume[res.size()]); } + @Override + public DiskInfo[] getDisks() { + synchronized (mLock) { + final DiskInfo[] res = new DiskInfo[mDisks.size()]; + for (int i = 0; i < mDisks.size(); i++) { + res[i] = mDisks.valueAt(i); + } + return res; + } + } + + @Override + public VolumeInfo[] getVolumes() { + synchronized (mLock) { + final VolumeInfo[] res = new VolumeInfo[mVolumes.size()]; + for (int i = 0; i < mVolumes.size(); i++) { + res[i] = mVolumes.valueAt(i); + } + return res; + } + } + private void addObbStateLocked(ObbState obbState) throws RemoteException { final IBinder binder = obbState.getBinder(); List<ObbState> obbStates = mObbMounts.get(binder); @@ -2601,7 +2415,8 @@ class MountService extends IMountService.Stub pw.println(); pw.println("Disks:"); pw.increaseIndent(); - for (Disk disk : mDisks.values()) { + for (int i = 0; i < mDisks.size(); i++) { + final DiskInfo disk = mDisks.valueAt(i); disk.dump(pw); } pw.decreaseIndent(); @@ -2609,7 +2424,8 @@ class MountService extends IMountService.Stub pw.println(); pw.println("Volumes:"); pw.increaseIndent(); - for (Volume vol : mVolumes.values()) { + for (int i = 0; i < mVolumes.size(); i++) { + final VolumeInfo vol = mVolumes.valueAt(i); vol.dump(pw); } pw.decreaseIndent(); |
