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.NonNull;
20  import android.annotation.Nullable;
21  import android.compat.annotation.UnsupportedAppUsage;
22  import android.content.res.Resources;
23  import android.os.Build;
24  import android.os.Parcel;
25  import android.os.Parcelable;
26  import android.text.TextUtils;
27  import android.util.DebugUtils;
28  
29  import com.android.internal.util.IndentingPrintWriter;
30  import com.android.internal.util.Preconditions;
31  
32  import java.io.CharArrayWriter;
33  import java.util.Objects;
34  
35  /**
36   * Information about a physical disk which may contain one or more
37   * {@link VolumeInfo}.
38   *
39   * @hide
40   */
41  public class DiskInfo implements Parcelable {
42      public static final String ACTION_DISK_SCANNED =
43              "android.os.storage.action.DISK_SCANNED";
44      public static final String EXTRA_DISK_ID =
45              "android.os.storage.extra.DISK_ID";
46      public static final String EXTRA_VOLUME_COUNT =
47              "android.os.storage.extra.VOLUME_COUNT";
48  
49      public static final int FLAG_ADOPTABLE = 1 << 0;
50      public static final int FLAG_DEFAULT_PRIMARY = 1 << 1;
51      public static final int FLAG_SD = 1 << 2;
52      public static final int FLAG_USB = 1 << 3;
53      /** The FLAG_STUB_VISIBLE is set from vold, which gets the flag from outside (e.g., ChromeOS) */
54      public static final int FLAG_STUB_VISIBLE = 1 << 6;
55  
56      public final String id;
57      @UnsupportedAppUsage
58      public final int flags;
59      @UnsupportedAppUsage
60      public long size;
61      @UnsupportedAppUsage
62      public String label;
63      /** Hacky; don't rely on this count */
64      public int volumeCount;
65      public String sysPath;
66  
DiskInfo(String id, int flags)67      public DiskInfo(String id, int flags) {
68          this.id = Preconditions.checkNotNull(id);
69          this.flags = flags;
70      }
71  
72      @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
DiskInfo(Parcel parcel)73      public DiskInfo(Parcel parcel) {
74          id = parcel.readString();
75          flags = parcel.readInt();
76          size = parcel.readLong();
77          label = parcel.readString();
78          volumeCount = parcel.readInt();
79          sysPath = parcel.readString();
80      }
81  
82      @UnsupportedAppUsage
getId()83      public @NonNull String getId() {
84          return id;
85      }
86  
isInteresting(String label)87      private boolean isInteresting(String label) {
88          if (TextUtils.isEmpty(label)) {
89              return false;
90          }
91          if (label.equalsIgnoreCase("ata")) {
92              return false;
93          }
94          if (label.toLowerCase().contains("generic")) {
95              return false;
96          }
97          if (label.toLowerCase().startsWith("usb")) {
98              return false;
99          }
100          if (label.toLowerCase().startsWith("multiple")) {
101              return false;
102          }
103          return true;
104      }
105  
106      @UnsupportedAppUsage
getDescription()107      public @Nullable String getDescription() {
108          final Resources res = Resources.getSystem();
109          if ((flags & FLAG_SD) != 0) {
110              if (isInteresting(label)) {
111                  return res.getString(com.android.internal.R.string.storage_sd_card_label, label);
112              } else {
113                  return res.getString(com.android.internal.R.string.storage_sd_card);
114              }
115          } else if ((flags & FLAG_USB) != 0) {
116              if (isInteresting(label)) {
117                  return res.getString(com.android.internal.R.string.storage_usb_drive_label, label);
118              } else {
119                  return res.getString(com.android.internal.R.string.storage_usb_drive);
120              }
121          } else {
122              return null;
123          }
124      }
125  
getShortDescription()126      public @Nullable String getShortDescription() {
127          final Resources res = Resources.getSystem();
128          if (isSd()) {
129              return res.getString(com.android.internal.R.string.storage_sd_card);
130          } else if (isUsb()) {
131              return res.getString(com.android.internal.R.string.storage_usb_drive);
132          } else {
133              return null;
134          }
135      }
136  
137      @UnsupportedAppUsage
isAdoptable()138      public boolean isAdoptable() {
139          return (flags & FLAG_ADOPTABLE) != 0;
140      }
141  
142      @UnsupportedAppUsage
isDefaultPrimary()143      public boolean isDefaultPrimary() {
144          return (flags & FLAG_DEFAULT_PRIMARY) != 0;
145      }
146  
147      @UnsupportedAppUsage
isSd()148      public boolean isSd() {
149          return (flags & FLAG_SD) != 0;
150      }
151  
152      @UnsupportedAppUsage
isUsb()153      public boolean isUsb() {
154          return (flags & FLAG_USB) != 0;
155      }
156  
isStubVisible()157      public boolean isStubVisible() {
158          return (flags & FLAG_STUB_VISIBLE) != 0;
159      }
160  
161      @Override
toString()162      public String toString() {
163          final CharArrayWriter writer = new CharArrayWriter();
164          dump(new IndentingPrintWriter(writer, "    ", 80));
165          return writer.toString();
166      }
167  
dump(IndentingPrintWriter pw)168      public void dump(IndentingPrintWriter pw) {
169          pw.println("DiskInfo{" + id + "}:");
170          pw.increaseIndent();
171          pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags));
172          pw.printPair("size", size);
173          pw.printPair("label", label);
174          pw.println();
175          pw.printPair("sysPath", sysPath);
176          pw.decreaseIndent();
177          pw.println();
178      }
179  
180      @Override
clone()181      public DiskInfo clone() {
182          final Parcel temp = Parcel.obtain();
183          try {
184              writeToParcel(temp, 0);
185              temp.setDataPosition(0);
186              return CREATOR.createFromParcel(temp);
187          } finally {
188              temp.recycle();
189          }
190      }
191  
192      @Override
equals(@ullable Object o)193      public boolean equals(@Nullable Object o) {
194          if (o instanceof DiskInfo) {
195              return Objects.equals(id, ((DiskInfo) o).id);
196          } else {
197              return false;
198          }
199      }
200  
201      @Override
hashCode()202      public int hashCode() {
203          return id.hashCode();
204      }
205  
206      @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
207      public static final @android.annotation.NonNull Creator<DiskInfo> CREATOR = new Creator<DiskInfo>() {
208          @Override
209          public DiskInfo createFromParcel(Parcel in) {
210              return new DiskInfo(in);
211          }
212  
213          @Override
214          public DiskInfo[] newArray(int size) {
215              return new DiskInfo[size];
216          }
217      };
218  
219      @Override
describeContents()220      public int describeContents() {
221          return 0;
222      }
223  
224      @Override
writeToParcel(Parcel parcel, int flags)225      public void writeToParcel(Parcel parcel, int flags) {
226          parcel.writeString(id);
227          parcel.writeInt(this.flags);
228          parcel.writeLong(size);
229          parcel.writeString(label);
230          parcel.writeInt(volumeCount);
231          parcel.writeString(sysPath);
232      }
233  }
234