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