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