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 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