1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.os.storage;
18 
19 import android.content.Context;
20 import android.net.TrafficStats;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.os.UserHandle;
24 
25 import com.android.internal.util.IndentingPrintWriter;
26 import com.android.internal.util.Preconditions;
27 
28 import java.io.CharArrayWriter;
29 import java.io.File;
30 
31 /**
32  * Information about a storage volume that may be mounted. This is a legacy
33  * specialization of {@link VolumeInfo} which describes the volume for a
34  * specific user.
35  * <p>
36  * This class may be deprecated in the future.
37  *
38  * @hide
39  */
40 public class StorageVolume implements Parcelable {
41 
42     private final String mId;
43     private final int mStorageId;
44     private final File mPath;
45     private final String mDescription;
46     private final boolean mPrimary;
47     private final boolean mRemovable;
48     private final boolean mEmulated;
49     private final long mMtpReserveSize;
50     private final boolean mAllowMassStorage;
51     private final long mMaxFileSize;
52     private final UserHandle mOwner;
53     private final String mFsUuid;
54     private final String mState;
55 
56     // StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
57     // ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
58     // ACTION_MEDIA_BAD_REMOVAL, ACTION_MEDIA_UNMOUNTABLE and ACTION_MEDIA_EJECT broadcasts.
59     public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
60 
61     public static final int STORAGE_ID_INVALID = 0x00000000;
62     public static final int STORAGE_ID_PRIMARY = 0x00010001;
63 
StorageVolume(String id, int storageId, File path, String description, boolean primary, boolean removable, boolean emulated, long mtpReserveSize, boolean allowMassStorage, long maxFileSize, UserHandle owner, String fsUuid, String state)64     public StorageVolume(String id, int storageId, File path, String description, boolean primary,
65             boolean removable, boolean emulated, long mtpReserveSize, boolean allowMassStorage,
66             long maxFileSize, UserHandle owner, String fsUuid, String state) {
67         mId = Preconditions.checkNotNull(id);
68         mStorageId = storageId;
69         mPath = Preconditions.checkNotNull(path);
70         mDescription = Preconditions.checkNotNull(description);
71         mPrimary = primary;
72         mRemovable = removable;
73         mEmulated = emulated;
74         mMtpReserveSize = mtpReserveSize;
75         mAllowMassStorage = allowMassStorage;
76         mMaxFileSize = maxFileSize;
77         mOwner = Preconditions.checkNotNull(owner);
78         mFsUuid = fsUuid;
79         mState = Preconditions.checkNotNull(state);
80     }
81 
StorageVolume(Parcel in)82     private StorageVolume(Parcel in) {
83         mId = in.readString();
84         mStorageId = in.readInt();
85         mPath = new File(in.readString());
86         mDescription = in.readString();
87         mPrimary = in.readInt() != 0;
88         mRemovable = in.readInt() != 0;
89         mEmulated = in.readInt() != 0;
90         mMtpReserveSize = in.readLong();
91         mAllowMassStorage = in.readInt() != 0;
92         mMaxFileSize = in.readLong();
93         mOwner = in.readParcelable(null);
94         mFsUuid = in.readString();
95         mState = in.readString();
96     }
97 
getId()98     public String getId() {
99         return mId;
100     }
101 
102     /**
103      * Returns the mount path for the volume.
104      *
105      * @return the mount path
106      */
getPath()107     public String getPath() {
108         return mPath.toString();
109     }
110 
getPathFile()111     public File getPathFile() {
112         return mPath;
113     }
114 
115     /**
116      * Returns a user visible description of the volume.
117      *
118      * @return the volume description
119      */
getDescription(Context context)120     public String getDescription(Context context) {
121         return mDescription;
122     }
123 
isPrimary()124     public boolean isPrimary() {
125         return mPrimary;
126     }
127 
128     /**
129      * Returns true if the volume is removable.
130      *
131      * @return is removable
132      */
isRemovable()133     public boolean isRemovable() {
134         return mRemovable;
135     }
136 
137     /**
138      * Returns true if the volume is emulated.
139      *
140      * @return is removable
141      */
isEmulated()142     public boolean isEmulated() {
143         return mEmulated;
144     }
145 
146     /**
147      * Returns the MTP storage ID for the volume.
148      * this is also used for the storage_id column in the media provider.
149      *
150      * @return MTP storage ID
151      */
getStorageId()152     public int getStorageId() {
153         return mStorageId;
154     }
155 
156     /**
157      * Number of megabytes of space to leave unallocated by MTP.
158      * MTP will subtract this value from the free space it reports back
159      * to the host via GetStorageInfo, and will not allow new files to
160      * be added via MTP if there is less than this amount left free in the storage.
161      * If MTP has dedicated storage this value should be zero, but if MTP is
162      * sharing storage with the rest of the system, set this to a positive value
163      * to ensure that MTP activity does not result in the storage being
164      * too close to full.
165      *
166      * @return MTP reserve space
167      */
getMtpReserveSpace()168     public int getMtpReserveSpace() {
169         return (int) (mMtpReserveSize / TrafficStats.MB_IN_BYTES);
170     }
171 
172     /**
173      * Returns true if this volume can be shared via USB mass storage.
174      *
175      * @return whether mass storage is allowed
176      */
allowMassStorage()177     public boolean allowMassStorage() {
178         return mAllowMassStorage;
179     }
180 
181     /**
182      * Returns maximum file size for the volume, or zero if it is unbounded.
183      *
184      * @return maximum file size
185      */
getMaxFileSize()186     public long getMaxFileSize() {
187         return mMaxFileSize;
188     }
189 
getOwner()190     public UserHandle getOwner() {
191         return mOwner;
192     }
193 
getUuid()194     public String getUuid() {
195         return mFsUuid;
196     }
197 
198     /**
199      * Parse and return volume UUID as FAT volume ID, or return -1 if unable to
200      * parse or UUID is unknown.
201      */
getFatVolumeId()202     public int getFatVolumeId() {
203         if (mFsUuid == null || mFsUuid.length() != 9) {
204             return -1;
205         }
206         try {
207             return (int) Long.parseLong(mFsUuid.replace("-", ""), 16);
208         } catch (NumberFormatException e) {
209             return -1;
210         }
211     }
212 
getUserLabel()213     public String getUserLabel() {
214         return mDescription;
215     }
216 
getState()217     public String getState() {
218         return mState;
219     }
220 
221     @Override
equals(Object obj)222     public boolean equals(Object obj) {
223         if (obj instanceof StorageVolume && mPath != null) {
224             StorageVolume volume = (StorageVolume)obj;
225             return (mPath.equals(volume.mPath));
226         }
227         return false;
228     }
229 
230     @Override
hashCode()231     public int hashCode() {
232         return mPath.hashCode();
233     }
234 
235     @Override
toString()236     public String toString() {
237         final CharArrayWriter writer = new CharArrayWriter();
238         dump(new IndentingPrintWriter(writer, "    ", 80));
239         return writer.toString();
240     }
241 
dump(IndentingPrintWriter pw)242     public void dump(IndentingPrintWriter pw) {
243         pw.println("StorageVolume:");
244         pw.increaseIndent();
245         pw.printPair("mId", mId);
246         pw.printPair("mStorageId", mStorageId);
247         pw.printPair("mPath", mPath);
248         pw.printPair("mDescription", mDescription);
249         pw.printPair("mPrimary", mPrimary);
250         pw.printPair("mRemovable", mRemovable);
251         pw.printPair("mEmulated", mEmulated);
252         pw.printPair("mMtpReserveSize", mMtpReserveSize);
253         pw.printPair("mAllowMassStorage", mAllowMassStorage);
254         pw.printPair("mMaxFileSize", mMaxFileSize);
255         pw.printPair("mOwner", mOwner);
256         pw.printPair("mFsUuid", mFsUuid);
257         pw.printPair("mState", mState);
258         pw.decreaseIndent();
259     }
260 
261     public static final Creator<StorageVolume> CREATOR = new Creator<StorageVolume>() {
262         @Override
263         public StorageVolume createFromParcel(Parcel in) {
264             return new StorageVolume(in);
265         }
266 
267         @Override
268         public StorageVolume[] newArray(int size) {
269             return new StorageVolume[size];
270         }
271     };
272 
273     @Override
describeContents()274     public int describeContents() {
275         return 0;
276     }
277 
278     @Override
writeToParcel(Parcel parcel, int flags)279     public void writeToParcel(Parcel parcel, int flags) {
280         parcel.writeString(mId);
281         parcel.writeInt(mStorageId);
282         parcel.writeString(mPath.toString());
283         parcel.writeString(mDescription);
284         parcel.writeInt(mPrimary ? 1 : 0);
285         parcel.writeInt(mRemovable ? 1 : 0);
286         parcel.writeInt(mEmulated ? 1 : 0);
287         parcel.writeLong(mMtpReserveSize);
288         parcel.writeInt(mAllowMassStorage ? 1 : 0);
289         parcel.writeLong(mMaxFileSize);
290         parcel.writeParcelable(mOwner, flags);
291         parcel.writeString(mFsUuid);
292         parcel.writeString(mState);
293     }
294 }
295