blob: 3f14a5506adf0c283c8e7bc0087b865cf8d128a4 [file] [log] [blame]
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -07001/*
2 * Copyright (C) 2013 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 com.android.documentsui.model;
18
19import static com.android.documentsui.model.DocumentInfo.getCursorInt;
20import static com.android.documentsui.model.DocumentInfo.getCursorLong;
21import static com.android.documentsui.model.DocumentInfo.getCursorString;
22
23import android.content.Context;
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -070024import android.database.Cursor;
25import android.graphics.drawable.Drawable;
Steve McKaydbdaa492015-12-02 11:20:54 -080026import android.net.Uri;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070027import android.os.Parcel;
28import android.os.Parcelable;
Steve McKaydbdaa492015-12-02 11:20:54 -080029import android.provider.DocumentsContract;
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -070030import android.provider.DocumentsContract.Root;
Jeff Sharkey4ec97392013-09-10 12:04:26 -070031import android.text.TextUtils;
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -070032
Jeff Sharkey0b14db32013-09-04 18:03:18 -070033import com.android.documentsui.IconUtils;
Jeff Sharkey6d97d3c2013-09-06 10:43:45 -070034import com.android.documentsui.R;
Jeff Sharkey0b14db32013-09-04 18:03:18 -070035
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070036import java.io.DataInputStream;
37import java.io.DataOutputStream;
38import java.io.IOException;
39import java.net.ProtocolException;
Jeff Sharkey251097b2013-09-02 15:07:28 -070040import java.util.Objects;
41
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -070042/**
43 * Representation of a {@link Root}.
44 */
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070045public class RootInfo implements Durable, Parcelable {
46 private static final int VERSION_INIT = 1;
Jeff Sharkey6efba222013-09-27 16:44:11 -070047 private static final int VERSION_DROP_TYPE = 2;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070048
Ben Kwa0c643082015-10-09 07:48:00 -070049 // The values of these constants determine the sort order of various roots in the RootsFragment.
50 public static final int TYPE_IMAGES = 1;
51 public static final int TYPE_VIDEO = 2;
52 public static final int TYPE_AUDIO = 3;
53 public static final int TYPE_RECENTS = 4;
54 public static final int TYPE_DOWNLOADS = 5;
55 public static final int TYPE_LOCAL = 6;
Daichi Hironoabf39742015-10-23 08:36:10 +090056 public static final int TYPE_MTP = 7;
Steve McKayc6a4cd82015-11-18 14:56:50 -080057 public static final int TYPE_OTHER = 8;
Ben Kwa0c643082015-10-09 07:48:00 -070058
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -070059 public String authority;
60 public String rootId;
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -070061 public int flags;
62 public int icon;
63 public String title;
64 public String summary;
65 public String documentId;
66 public long availableBytes;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070067 public String mimeTypes;
68
69 /** Derived fields that aren't persisted */
70 public String[] derivedMimeTypes;
71 public int derivedIcon;
Ben Kwa0c643082015-10-09 07:48:00 -070072 public int derivedType;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070073
74 public RootInfo() {
75 reset();
76 }
77
78 @Override
79 public void reset() {
80 authority = null;
81 rootId = null;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070082 flags = 0;
83 icon = 0;
84 title = null;
85 summary = null;
86 documentId = null;
87 availableBytes = -1;
88 mimeTypes = null;
89
90 derivedMimeTypes = null;
91 derivedIcon = 0;
Ben Kwa0c643082015-10-09 07:48:00 -070092 derivedType = 0;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070093 }
94
95 @Override
96 public void read(DataInputStream in) throws IOException {
97 final int version = in.readInt();
98 switch (version) {
Jeff Sharkey6efba222013-09-27 16:44:11 -070099 case VERSION_DROP_TYPE:
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700100 authority = DurableUtils.readNullableString(in);
101 rootId = DurableUtils.readNullableString(in);
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700102 flags = in.readInt();
103 icon = in.readInt();
104 title = DurableUtils.readNullableString(in);
105 summary = DurableUtils.readNullableString(in);
106 documentId = DurableUtils.readNullableString(in);
107 availableBytes = in.readLong();
108 mimeTypes = DurableUtils.readNullableString(in);
109 deriveFields();
110 break;
111 default:
112 throw new ProtocolException("Unknown version " + version);
113 }
114 }
115
116 @Override
117 public void write(DataOutputStream out) throws IOException {
Jeff Sharkey6efba222013-09-27 16:44:11 -0700118 out.writeInt(VERSION_DROP_TYPE);
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700119 DurableUtils.writeNullableString(out, authority);
120 DurableUtils.writeNullableString(out, rootId);
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700121 out.writeInt(flags);
122 out.writeInt(icon);
123 DurableUtils.writeNullableString(out, title);
124 DurableUtils.writeNullableString(out, summary);
125 DurableUtils.writeNullableString(out, documentId);
126 out.writeLong(availableBytes);
127 DurableUtils.writeNullableString(out, mimeTypes);
128 }
129
130 @Override
131 public int describeContents() {
132 return 0;
133 }
134
135 @Override
136 public void writeToParcel(Parcel dest, int flags) {
137 DurableUtils.writeToParcel(dest, this);
138 }
139
140 public static final Creator<RootInfo> CREATOR = new Creator<RootInfo>() {
141 @Override
142 public RootInfo createFromParcel(Parcel in) {
143 final RootInfo root = new RootInfo();
144 DurableUtils.readFromParcel(in, root);
145 return root;
146 }
147
148 @Override
149 public RootInfo[] newArray(int size) {
150 return new RootInfo[size];
151 }
152 };
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -0700153
154 public static RootInfo fromRootsCursor(String authority, Cursor cursor) {
155 final RootInfo root = new RootInfo();
156 root.authority = authority;
157 root.rootId = getCursorString(cursor, Root.COLUMN_ROOT_ID);
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -0700158 root.flags = getCursorInt(cursor, Root.COLUMN_FLAGS);
159 root.icon = getCursorInt(cursor, Root.COLUMN_ICON);
160 root.title = getCursorString(cursor, Root.COLUMN_TITLE);
161 root.summary = getCursorString(cursor, Root.COLUMN_SUMMARY);
162 root.documentId = getCursorString(cursor, Root.COLUMN_DOCUMENT_ID);
163 root.availableBytes = getCursorLong(cursor, Root.COLUMN_AVAILABLE_BYTES);
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700164 root.mimeTypes = getCursorString(cursor, Root.COLUMN_MIME_TYPES);
165 root.deriveFields();
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -0700166 return root;
167 }
168
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700169 private void deriveFields() {
170 derivedMimeTypes = (mimeTypes != null) ? mimeTypes.split("\n") : null;
171
172 // TODO: remove these special case icons
Steve McKayc6a4cd82015-11-18 14:56:50 -0800173 if (isHome()) {
174 derivedIcon = R.drawable.ic_root_home;
175 derivedType = TYPE_LOCAL;
176 } else if (isExternalStorage()) {
Aga Wronska7587fd02016-01-04 12:53:18 -0800177 derivedIcon = R.drawable.ic_root_smartphone;
Ben Kwa0c643082015-10-09 07:48:00 -0700178 derivedType = TYPE_LOCAL;
Steve McKayefa17612016-01-29 18:15:39 -0800179 // TODO: Apply SD card icon to SD devices.
Jeff Sharkey6efba222013-09-27 16:44:11 -0700180 } else if (isDownloads()) {
Jeff Sharkeyc29dd612014-08-08 13:08:56 -0700181 derivedIcon = R.drawable.ic_root_download;
Ben Kwa0c643082015-10-09 07:48:00 -0700182 derivedType = TYPE_DOWNLOADS;
Jeff Sharkey6efba222013-09-27 16:44:11 -0700183 } else if (isImages()) {
Jeff Sharkeyc29dd612014-08-08 13:08:56 -0700184 derivedIcon = R.drawable.ic_doc_image;
Ben Kwa0c643082015-10-09 07:48:00 -0700185 derivedType = TYPE_IMAGES;
Jeff Sharkey6efba222013-09-27 16:44:11 -0700186 } else if (isVideos()) {
Jeff Sharkeyc29dd612014-08-08 13:08:56 -0700187 derivedIcon = R.drawable.ic_doc_video;
Ben Kwa0c643082015-10-09 07:48:00 -0700188 derivedType = TYPE_VIDEO;
Jeff Sharkey6efba222013-09-27 16:44:11 -0700189 } else if (isAudio()) {
Jeff Sharkeyc29dd612014-08-08 13:08:56 -0700190 derivedIcon = R.drawable.ic_doc_audio;
Ben Kwa0c643082015-10-09 07:48:00 -0700191 derivedType = TYPE_AUDIO;
192 } else if (isRecents()) {
193 derivedType = TYPE_RECENTS;
Daichi Hironoabf39742015-10-23 08:36:10 +0900194 } else if (isMtp()) {
195 derivedType = TYPE_MTP;
Ben Kwa0c643082015-10-09 07:48:00 -0700196 } else {
Steve McKayc6a4cd82015-11-18 14:56:50 -0800197 derivedType = TYPE_OTHER;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700198 }
Jeff Sharkey6efba222013-09-27 16:44:11 -0700199 }
200
Steve McKaydbdaa492015-12-02 11:20:54 -0800201 public Uri getUri() {
202 return DocumentsContract.buildRootUri(authority, rootId);
203 }
204
Jeff Sharkey6efba222013-09-27 16:44:11 -0700205 public boolean isRecents() {
206 return authority == null && rootId == null;
207 }
208
Steve McKayc6a4cd82015-11-18 14:56:50 -0800209 public boolean isHome() {
210 // Note that "home" is the expected root id for the auto-created
211 // user home directory on external storage. The "home" value should
212 // match ExternalStorageProvider.ROOT_ID_HOME.
213 return isExternalStorage() && "home".equals(rootId);
214 }
215
Jeff Sharkey6efba222013-09-27 16:44:11 -0700216 public boolean isExternalStorage() {
217 return "com.android.externalstorage.documents".equals(authority);
218 }
219
220 public boolean isDownloads() {
221 return "com.android.providers.downloads.documents".equals(authority);
222 }
223
224 public boolean isImages() {
225 return "com.android.providers.media.documents".equals(authority)
226 && "images_root".equals(rootId);
227 }
228
229 public boolean isVideos() {
230 return "com.android.providers.media.documents".equals(authority)
231 && "videos_root".equals(rootId);
232 }
233
234 public boolean isAudio() {
235 return "com.android.providers.media.documents".equals(authority)
236 && "audio_root".equals(rootId);
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700237 }
238
Daichi Hironoabf39742015-10-23 08:36:10 +0900239 public boolean isMtp() {
240 return "com.android.mtp.documents".equals(authority);
241 }
242
243 public boolean isLibrary() {
244 return derivedType == TYPE_IMAGES || derivedType == TYPE_VIDEO || derivedType == TYPE_AUDIO
245 || derivedType == TYPE_RECENTS || derivedType == TYPE_DOWNLOADS;
246 }
247
Steve McKayefa17612016-01-29 18:15:39 -0800248 public boolean hasSettings() {
249 return (flags & Root.FLAG_HAS_SETTINGS) != 0;
250 }
251
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -0700252 public Drawable loadIcon(Context context) {
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700253 if (derivedIcon != 0) {
Alan Viverette03d30a52014-08-14 12:59:10 -0700254 return context.getDrawable(derivedIcon);
Jeff Sharkey6d97d3c2013-09-06 10:43:45 -0700255 } else {
256 return IconUtils.loadPackageIcon(context, authority, icon);
257 }
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -0700258 }
Jeff Sharkey251097b2013-09-02 15:07:28 -0700259
Jeff Sharkeycbce4702014-08-29 15:38:27 -0700260 public Drawable loadDrawerIcon(Context context) {
261 if (derivedIcon != 0) {
262 return IconUtils.applyTintColor(context, derivedIcon, R.color.item_root_icon);
263 } else {
264 return IconUtils.loadPackageIcon(context, authority, icon);
265 }
266 }
267
Jeff Sharkeyc29dd612014-08-08 13:08:56 -0700268 public Drawable loadToolbarIcon(Context context) {
269 if (derivedIcon != 0) {
Jeff Sharkeycbce4702014-08-29 15:38:27 -0700270 return IconUtils.applyTintAttr(context, derivedIcon,
Jeff Sharkeyc29dd612014-08-08 13:08:56 -0700271 android.R.attr.colorControlNormal);
272 } else {
273 return IconUtils.loadPackageIcon(context, authority, icon);
Jeff Sharkeya847d792014-07-29 17:33:36 -0700274 }
275 }
276
Jeff Sharkey251097b2013-09-02 15:07:28 -0700277 @Override
278 public boolean equals(Object o) {
279 if (o instanceof RootInfo) {
280 final RootInfo root = (RootInfo) o;
281 return Objects.equals(authority, root.authority) && Objects.equals(rootId, root.rootId);
282 } else {
283 return false;
284 }
285 }
286
287 @Override
288 public int hashCode() {
289 return Objects.hash(authority, rootId);
290 }
291
Steve McKaydbdaa492015-12-02 11:20:54 -0800292 @Override
293 public String toString() {
294 return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}";
295 }
296
Jeff Sharkey251097b2013-09-02 15:07:28 -0700297 public String getDirectoryString() {
Jeff Sharkey4ec97392013-09-10 12:04:26 -0700298 return !TextUtils.isEmpty(summary) ? summary : title;
Jeff Sharkey251097b2013-09-02 15:07:28 -0700299 }
Jeff Sharkeyae9b51b2013-08-31 15:02:20 -0700300}