1 /* 2 * Copyright (C) 2015 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.annotation.Nullable; 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.content.Context; 22 import android.os.Build; 23 import android.os.Environment; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.os.UserHandle; 27 import android.util.DebugUtils; 28 import android.util.TimeUtils; 29 30 import com.android.internal.util.IndentingPrintWriter; 31 import com.android.internal.util.Preconditions; 32 33 import java.io.File; 34 import java.util.Locale; 35 import java.util.Objects; 36 37 /** 38 * Metadata for a storage volume which may not be currently present. 39 * 40 * @hide 41 */ 42 public class VolumeRecord implements Parcelable { 43 public static final String EXTRA_FS_UUID = 44 "android.os.storage.extra.FS_UUID"; 45 46 public static final int USER_FLAG_INITED = 1 << 0; 47 public static final int USER_FLAG_SNOOZED = 1 << 1; 48 49 public final int type; 50 public final String fsUuid; 51 public String partGuid; 52 public String nickname; 53 public int userFlags; 54 public long createdMillis; 55 public long lastSeenMillis; 56 public long lastTrimMillis; 57 public long lastBenchMillis; 58 VolumeRecord(int type, String fsUuid)59 public VolumeRecord(int type, String fsUuid) { 60 this.type = type; 61 this.fsUuid = Preconditions.checkNotNull(fsUuid); 62 } 63 64 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) VolumeRecord(Parcel parcel)65 public VolumeRecord(Parcel parcel) { 66 type = parcel.readInt(); 67 fsUuid = parcel.readString(); 68 partGuid = parcel.readString(); 69 nickname = parcel.readString(); 70 userFlags = parcel.readInt(); 71 createdMillis = parcel.readLong(); 72 lastSeenMillis = parcel.readLong(); 73 lastTrimMillis = parcel.readLong(); 74 lastBenchMillis = parcel.readLong(); 75 } 76 getType()77 public int getType() { 78 return type; 79 } 80 getFsUuid()81 public String getFsUuid() { 82 return fsUuid; 83 } 84 getNormalizedFsUuid()85 public String getNormalizedFsUuid() { 86 return fsUuid != null ? fsUuid.toLowerCase(Locale.US) : null; 87 } 88 getNickname()89 public String getNickname() { 90 return nickname; 91 } 92 isInited()93 public boolean isInited() { 94 return (userFlags & USER_FLAG_INITED) != 0; 95 } 96 isSnoozed()97 public boolean isSnoozed() { 98 return (userFlags & USER_FLAG_SNOOZED) != 0; 99 } 100 buildStorageVolume(Context context)101 public StorageVolume buildStorageVolume(Context context) { 102 final String id = "unknown:" + fsUuid; 103 final File userPath = new File("/dev/null"); 104 final File internalPath = new File("/dev/null"); 105 final boolean primary = false; 106 final boolean removable = true; 107 final boolean emulated = false; 108 final boolean allowMassStorage = false; 109 final long maxFileSize = 0; 110 final UserHandle user = new UserHandle(UserHandle.USER_NULL); 111 final String envState = Environment.MEDIA_UNKNOWN; 112 113 String description = nickname; 114 if (description == null) { 115 description = context.getString(android.R.string.unknownName); 116 } 117 118 return new StorageVolume(id, userPath, internalPath, description, primary, removable, 119 emulated, allowMassStorage, maxFileSize, user, null /* uuid */, fsUuid, envState); 120 } 121 dump(IndentingPrintWriter pw)122 public void dump(IndentingPrintWriter pw) { 123 pw.println("VolumeRecord:"); 124 pw.increaseIndent(); 125 pw.printPair("type", DebugUtils.valueToString(VolumeInfo.class, "TYPE_", type)); 126 pw.printPair("fsUuid", fsUuid); 127 pw.printPair("partGuid", partGuid); 128 pw.println(); 129 pw.printPair("nickname", nickname); 130 pw.printPair("userFlags", 131 DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags)); 132 pw.println(); 133 pw.printPair("createdMillis", TimeUtils.formatForLogging(createdMillis)); 134 pw.printPair("lastSeenMillis", TimeUtils.formatForLogging(lastSeenMillis)); 135 pw.printPair("lastTrimMillis", TimeUtils.formatForLogging(lastTrimMillis)); 136 pw.printPair("lastBenchMillis", TimeUtils.formatForLogging(lastBenchMillis)); 137 pw.decreaseIndent(); 138 pw.println(); 139 } 140 141 @Override clone()142 public VolumeRecord clone() { 143 final Parcel temp = Parcel.obtain(); 144 try { 145 writeToParcel(temp, 0); 146 temp.setDataPosition(0); 147 return CREATOR.createFromParcel(temp); 148 } finally { 149 temp.recycle(); 150 } 151 } 152 153 @Override equals(@ullable Object o)154 public boolean equals(@Nullable Object o) { 155 if (o instanceof VolumeRecord) { 156 return Objects.equals(fsUuid, ((VolumeRecord) o).fsUuid); 157 } else { 158 return false; 159 } 160 } 161 162 @Override hashCode()163 public int hashCode() { 164 return fsUuid.hashCode(); 165 } 166 167 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 168 public static final @android.annotation.NonNull Creator<VolumeRecord> CREATOR = new Creator<VolumeRecord>() { 169 @Override 170 public VolumeRecord createFromParcel(Parcel in) { 171 return new VolumeRecord(in); 172 } 173 174 @Override 175 public VolumeRecord[] newArray(int size) { 176 return new VolumeRecord[size]; 177 } 178 }; 179 180 @Override describeContents()181 public int describeContents() { 182 return 0; 183 } 184 185 @Override writeToParcel(Parcel parcel, int flags)186 public void writeToParcel(Parcel parcel, int flags) { 187 parcel.writeInt(type); 188 parcel.writeString(fsUuid); 189 parcel.writeString(partGuid); 190 parcel.writeString(nickname); 191 parcel.writeInt(userFlags); 192 parcel.writeLong(createdMillis); 193 parcel.writeLong(lastSeenMillis); 194 parcel.writeLong(lastTrimMillis); 195 parcel.writeLong(lastBenchMillis); 196 } 197 } 198