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 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 */ 32 public 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 StorageVolume(File path, int descriptionId, boolean primary, boolean removable, boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize, UserHandle owner)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 StorageVolume(Parcel in)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 fromTemplate(StorageVolume template, File path, UserHandle owner)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 */ getPath()92 public String getPath() { 93 return mPath.toString(); 94 } 95 getPathFile()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 */ getDescription(Context context)105 public String getDescription(Context context) { 106 return context.getResources().getString(mDescriptionId); 107 } 108 getDescriptionId()109 public int getDescriptionId() { 110 return mDescriptionId; 111 } 112 isPrimary()113 public boolean isPrimary() { 114 return mPrimary; 115 } 116 117 /** 118 * Returns true if the volume is removable. 119 * 120 * @return is removable 121 */ isRemovable()122 public boolean isRemovable() { 123 return mRemovable; 124 } 125 126 /** 127 * Returns true if the volume is emulated. 128 * 129 * @return is removable 130 */ isEmulated()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 */ getStorageId()141 public int getStorageId() { 142 return mStorageId; 143 } 144 145 /** 146 * Do not call this unless you are MountService 147 */ setStorageId(int index)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 */ getMtpReserveSpace()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 */ allowMassStorage()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 */ getMaxFileSize()184 public long getMaxFileSize() { 185 return mMaxFileSize; 186 } 187 getOwner()188 public UserHandle getOwner() { 189 return mOwner; 190 } 191 192 @Override equals(Object obj)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 hashCode()202 public int hashCode() { 203 return mPath.hashCode(); 204 } 205 206 @Override toString()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 describeContents()236 public int describeContents() { 237 return 0; 238 } 239 240 @Override writeToParcel(Parcel parcel, int flags)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