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