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