StorageVolume.java revision 5aca2b8dc4f4ff2d466a64587d06666c7bbd9749
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
17package android.os.storage;
18
19import android.content.Context;
20import android.os.Parcel;
21import android.os.Parcelable;
22import android.os.UserHandle;
23
24import com.android.internal.util.IndentingPrintWriter;
25
26import java.io.CharArrayWriter;
27import java.io.File;
28
29/**
30 * Description of a storage volume and its capabilities, including the
31 * filesystem path where it may be mounted.
32 *
33 * @hide
34 */
35public class StorageVolume implements Parcelable {
36
37    // TODO: switch to more durable token
38    private int mStorageId;
39
40    private final File mPath;
41    private final int mDescriptionId;
42    private final boolean mPrimary;
43    private final boolean mRemovable;
44    private final boolean mEmulated;
45    private final int mMtpReserveSpace;
46    private final boolean mAllowMassStorage;
47    /** Maximum file size for the storage, or zero for no limit */
48    private final long mMaxFileSize;
49    /** When set, indicates exclusive ownership of this volume */
50    private final UserHandle mOwner;
51
52    private String mUuid;
53    private String mUserLabel;
54
55    // StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
56    // ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
57    // ACTION_MEDIA_BAD_REMOVAL, ACTION_MEDIA_UNMOUNTABLE and ACTION_MEDIA_EJECT broadcasts.
58    public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
59
60    public StorageVolume(File path, int descriptionId, boolean primary, boolean removable,
61            boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize,
62            UserHandle owner) {
63        mPath = path;
64        mDescriptionId = descriptionId;
65        mPrimary = primary;
66        mRemovable = removable;
67        mEmulated = emulated;
68        mMtpReserveSpace = mtpReserveSpace;
69        mAllowMassStorage = allowMassStorage;
70        mMaxFileSize = maxFileSize;
71        mOwner = owner;
72    }
73
74    private StorageVolume(Parcel in) {
75        mStorageId = in.readInt();
76        mPath = new File(in.readString());
77        mDescriptionId = in.readInt();
78        mPrimary = in.readInt() != 0;
79        mRemovable = in.readInt() != 0;
80        mEmulated = in.readInt() != 0;
81        mMtpReserveSpace = in.readInt();
82        mAllowMassStorage = in.readInt() != 0;
83        mMaxFileSize = in.readLong();
84        mOwner = in.readParcelable(null);
85        mUuid = in.readString();
86        mUserLabel = in.readString();
87    }
88
89    public static StorageVolume fromTemplate(StorageVolume template, File path, UserHandle owner) {
90        return new StorageVolume(path, template.mDescriptionId, template.mPrimary,
91                template.mRemovable, template.mEmulated, template.mMtpReserveSpace,
92                template.mAllowMassStorage, template.mMaxFileSize, owner);
93    }
94
95    /**
96     * Returns the mount path for the volume.
97     *
98     * @return the mount path
99     */
100    public String getPath() {
101        return mPath.toString();
102    }
103
104    public File getPathFile() {
105        return mPath;
106    }
107
108    /**
109     * Returns a user visible description of the volume.
110     *
111     * @return the volume description
112     */
113    public String getDescription(Context context) {
114        return context.getResources().getString(mDescriptionId);
115    }
116
117    public int getDescriptionId() {
118        return mDescriptionId;
119    }
120
121    public boolean isPrimary() {
122        return mPrimary;
123    }
124
125    /**
126     * Returns true if the volume is removable.
127     *
128     * @return is removable
129     */
130    public boolean isRemovable() {
131        return mRemovable;
132    }
133
134    /**
135     * Returns true if the volume is emulated.
136     *
137     * @return is removable
138     */
139    public boolean isEmulated() {
140        return mEmulated;
141    }
142
143    /**
144     * Returns the MTP storage ID for the volume.
145     * this is also used for the storage_id column in the media provider.
146     *
147     * @return MTP storage ID
148     */
149    public int getStorageId() {
150        return mStorageId;
151    }
152
153    /**
154     * Do not call this unless you are MountService
155     */
156    public void setStorageId(int index) {
157        // storage ID is 0x00010001 for primary storage,
158        // then 0x00020001, 0x00030001, etc. for secondary storages
159        mStorageId = ((index + 1) << 16) + 1;
160    }
161
162    /**
163     * Number of megabytes of space to leave unallocated by MTP.
164     * MTP will subtract this value from the free space it reports back
165     * to the host via GetStorageInfo, and will not allow new files to
166     * be added via MTP if there is less than this amount left free in the storage.
167     * If MTP has dedicated storage this value should be zero, but if MTP is
168     * sharing storage with the rest of the system, set this to a positive value
169     * to ensure that MTP activity does not result in the storage being
170     * too close to full.
171     *
172     * @return MTP reserve space
173     */
174    public int getMtpReserveSpace() {
175        return mMtpReserveSpace;
176    }
177
178    /**
179     * Returns true if this volume can be shared via USB mass storage.
180     *
181     * @return whether mass storage is allowed
182     */
183    public boolean allowMassStorage() {
184        return mAllowMassStorage;
185    }
186
187    /**
188     * Returns maximum file size for the volume, or zero if it is unbounded.
189     *
190     * @return maximum file size
191     */
192    public long getMaxFileSize() {
193        return mMaxFileSize;
194    }
195
196    public UserHandle getOwner() {
197        return mOwner;
198    }
199
200    public void setUuid(String uuid) {
201        mUuid = uuid;
202    }
203
204    public String getUuid() {
205        return mUuid;
206    }
207
208    /**
209     * Parse and return volume UUID as FAT volume ID, or return -1 if unable to
210     * parse or UUID is unknown.
211     */
212    public int getFatVolumeId() {
213        if (mUuid == null || mUuid.length() != 9) {
214            return -1;
215        }
216        try {
217            return Integer.parseInt(mUuid.replace("-", ""), 16);
218        } catch (NumberFormatException e) {
219            return -1;
220        }
221    }
222
223    public void setUserLabel(String userLabel) {
224        mUserLabel = userLabel;
225    }
226
227    public String getUserLabel() {
228        return mUserLabel;
229    }
230
231    @Override
232    public boolean equals(Object obj) {
233        if (obj instanceof StorageVolume && mPath != null) {
234            StorageVolume volume = (StorageVolume)obj;
235            return (mPath.equals(volume.mPath));
236        }
237        return false;
238    }
239
240    @Override
241    public int hashCode() {
242        return mPath.hashCode();
243    }
244
245    @Override
246    public String toString() {
247        final CharArrayWriter writer = new CharArrayWriter();
248        dump(new IndentingPrintWriter(writer, "    ", 80));
249        return writer.toString();
250    }
251
252    public void dump(IndentingPrintWriter pw) {
253        pw.println("StorageVolume:");
254        pw.increaseIndent();
255        pw.printPair("mStorageId", mStorageId);
256        pw.printPair("mPath", mPath);
257        pw.printPair("mDescriptionId", mDescriptionId);
258        pw.printPair("mPrimary", mPrimary);
259        pw.printPair("mRemovable", mRemovable);
260        pw.printPair("mEmulated", mEmulated);
261        pw.printPair("mMtpReserveSpace", mMtpReserveSpace);
262        pw.printPair("mAllowMassStorage", mAllowMassStorage);
263        pw.printPair("mMaxFileSize", mMaxFileSize);
264        pw.printPair("mOwner", mOwner);
265        pw.printPair("mUuid", mUuid);
266        pw.printPair("mUserLabel", mUserLabel);
267        pw.decreaseIndent();
268    }
269
270    public static final Creator<StorageVolume> CREATOR = new Creator<StorageVolume>() {
271        @Override
272        public StorageVolume createFromParcel(Parcel in) {
273            return new StorageVolume(in);
274        }
275
276        @Override
277        public StorageVolume[] newArray(int size) {
278            return new StorageVolume[size];
279        }
280    };
281
282    @Override
283    public int describeContents() {
284        return 0;
285    }
286
287    @Override
288    public void writeToParcel(Parcel parcel, int flags) {
289        parcel.writeInt(mStorageId);
290        parcel.writeString(mPath.toString());
291        parcel.writeInt(mDescriptionId);
292        parcel.writeInt(mPrimary ? 1 : 0);
293        parcel.writeInt(mRemovable ? 1 : 0);
294        parcel.writeInt(mEmulated ? 1 : 0);
295        parcel.writeInt(mMtpReserveSpace);
296        parcel.writeInt(mAllowMassStorage ? 1 : 0);
297        parcel.writeLong(mMaxFileSize);
298        parcel.writeParcelable(mOwner, flags);
299        parcel.writeString(mUuid);
300        parcel.writeString(mUserLabel);
301    }
302}
303