RootInfo.java revision d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8
1724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey/*
2724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project
3724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey *
4724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * you may not use this file except in compliance with the License.
6724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * You may obtain a copy of the License at
7724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey *
8724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey *
10724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * See the License for the specific language governing permissions and
14724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * limitations under the License.
15724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey */
16724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey
17d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKaypackage com.android.documentsui.base;
18724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey
19d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport static com.android.documentsui.base.DocumentInfo.getCursorInt;
20d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport static com.android.documentsui.base.DocumentInfo.getCursorLong;
21d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport static com.android.documentsui.base.DocumentInfo.getCursorString;
22d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.Shared.DEBUG;
23d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.Shared.compareToIgnoreCaseNullable;
24724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey
2555c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKayimport android.annotation.IntDef;
26a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tanimport android.annotation.Nullable;
27724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkeyimport android.content.Context;
28724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkeyimport android.database.Cursor;
29724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkeyimport android.graphics.drawable.Drawable;
3031e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKayimport android.net.Uri;
31a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport android.os.Parcel;
32a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport android.os.Parcelable;
3331e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKayimport android.provider.DocumentsContract;
34724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkeyimport android.provider.DocumentsContract.Root;
35a35ac2dd16a64014a524d1441fb20d5a02b40836Jeff Sharkeyimport android.text.TextUtils;
366695fdf0f06e13d500ebea00093185a864c384f8Steve McKayimport android.util.Log;
37724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey
385629ec5989006bfc4ad3cb19a92163d581ff02e6Jeff Sharkeyimport com.android.documentsui.IconUtils;
3906c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkeyimport com.android.documentsui.R;
405629ec5989006bfc4ad3cb19a92163d581ff02e6Jeff Sharkey
41a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport java.io.DataInputStream;
42a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport java.io.DataOutputStream;
43a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tanimport java.io.FileNotFoundException;
44a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport java.io.IOException;
4555c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKayimport java.lang.annotation.Retention;
4655c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKayimport java.lang.annotation.RetentionPolicy;
47a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport java.net.ProtocolException;
48d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkeyimport java.util.Objects;
49d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey
50724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey/**
51724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * Representation of a {@link Root}.
52724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey */
5355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKaypublic class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
546695fdf0f06e13d500ebea00093185a864c384f8Steve McKay
556695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    private static final String TAG = "RootInfo";
56a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    private static final int VERSION_INIT = 1;
579dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    private static final int VERSION_DROP_TYPE = 2;
58a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
5985c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    // The values of these constants determine the sort order of various roots in the RootsFragment.
6050254fee5f12df77409db0e5bcfbc663ebccdde9Jeff Sharkey    @IntDef(flag = false, value = {
6155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_IMAGES,
6255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_VIDEO,
6355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_AUDIO,
6455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_RECENTS,
6555c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_DOWNLOADS,
6655c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_LOCAL,
6755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_MTP,
686695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            TYPE_SD,
696695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            TYPE_USB,
7055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_OTHER
7155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    })
7255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    @Retention(RetentionPolicy.SOURCE)
7355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    public @interface RootType {}
7485c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_IMAGES = 1;
7585c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_VIDEO = 2;
7685c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_AUDIO = 3;
7785c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_RECENTS = 4;
7885c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_DOWNLOADS = 5;
7985c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_LOCAL = 6;
809fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    public static final int TYPE_MTP = 7;
816695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public static final int TYPE_SD = 8;
826695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public static final int TYPE_USB = 9;
836695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public static final int TYPE_OTHER = 10;
8485c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa
85724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String authority;
86724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String rootId;
87724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public int flags;
88724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public int icon;
89724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String title;
90724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String summary;
91724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String documentId;
92724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public long availableBytes;
93a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public String mimeTypes;
94a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
95a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    /** Derived fields that aren't persisted */
96a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public String[] derivedMimeTypes;
97a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public int derivedIcon;
9855c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    public @RootType int derivedType;
995668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    // Currently, we are not persisting this and we should be asking Provider whether a Root
1005668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    // is in the process of eject. Provider does not have this available yet.
1015668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    public transient boolean ejecting;
102a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
103a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public RootInfo() {
104a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        reset();
105a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
106a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
107a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
108a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public void reset() {
109a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        authority = null;
110a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        rootId = null;
111a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        flags = 0;
112a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        icon = 0;
113a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        title = null;
114a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        summary = null;
115a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        documentId = null;
116a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        availableBytes = -1;
117a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        mimeTypes = null;
1185668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin        ejecting = false;
119a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
120a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        derivedMimeTypes = null;
121a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        derivedIcon = 0;
12285c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa        derivedType = 0;
123a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
124a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
125a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
126a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public void read(DataInputStream in) throws IOException {
127a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        final int version = in.readInt();
128a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        switch (version) {
1299dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            case VERSION_DROP_TYPE:
130a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                authority = DurableUtils.readNullableString(in);
131a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                rootId = DurableUtils.readNullableString(in);
132a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                flags = in.readInt();
133a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                icon = in.readInt();
134a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                title = DurableUtils.readNullableString(in);
135a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                summary = DurableUtils.readNullableString(in);
136a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                documentId = DurableUtils.readNullableString(in);
137a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                availableBytes = in.readLong();
138a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                mimeTypes = DurableUtils.readNullableString(in);
139a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                deriveFields();
140a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                break;
141a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            default:
142a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                throw new ProtocolException("Unknown version " + version);
143a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        }
144a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
145a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
146a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
147a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public void write(DataOutputStream out) throws IOException {
1489dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        out.writeInt(VERSION_DROP_TYPE);
149a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, authority);
150a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, rootId);
151a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        out.writeInt(flags);
152a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        out.writeInt(icon);
153a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, title);
154a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, summary);
155a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, documentId);
156a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        out.writeLong(availableBytes);
157a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, mimeTypes);
158a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
159a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
160a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
161a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public int describeContents() {
162a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        return 0;
163a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
164a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
165a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
166a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public void writeToParcel(Parcel dest, int flags) {
167a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeToParcel(dest, this);
168a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
169a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
170a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public static final Creator<RootInfo> CREATOR = new Creator<RootInfo>() {
171a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        @Override
172a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        public RootInfo createFromParcel(Parcel in) {
173a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            final RootInfo root = new RootInfo();
174a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            DurableUtils.readFromParcel(in, root);
175a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            return root;
176a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        }
177a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
178a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        @Override
179a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        public RootInfo[] newArray(int size) {
180a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            return new RootInfo[size];
181a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        }
182a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    };
183724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey
184724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public static RootInfo fromRootsCursor(String authority, Cursor cursor) {
185724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        final RootInfo root = new RootInfo();
186724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.authority = authority;
187724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.rootId = getCursorString(cursor, Root.COLUMN_ROOT_ID);
188724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.flags = getCursorInt(cursor, Root.COLUMN_FLAGS);
189724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.icon = getCursorInt(cursor, Root.COLUMN_ICON);
190724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.title = getCursorString(cursor, Root.COLUMN_TITLE);
191724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.summary = getCursorString(cursor, Root.COLUMN_SUMMARY);
192724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.documentId = getCursorString(cursor, Root.COLUMN_DOCUMENT_ID);
193724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.availableBytes = getCursorLong(cursor, Root.COLUMN_AVAILABLE_BYTES);
194a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        root.mimeTypes = getCursorString(cursor, Root.COLUMN_MIME_TYPES);
195a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        root.deriveFields();
196a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        return root;
197a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
198e1a2ceef30fe9c514152c3fab3cedcb99bdb68dfJeff Sharkey
199a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    private void deriveFields() {
200a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        derivedMimeTypes = (mimeTypes != null) ? mimeTypes.split("\n") : null;
201e1a2ceef30fe9c514152c3fab3cedcb99bdb68dfJeff Sharkey
20212ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        if (isHome()) {
20312ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay            derivedType = TYPE_LOCAL;
2046695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_root_documents;
2056695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        } else if (isMtp()) {
2066695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedType = TYPE_MTP;
2076695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_usb_storage;
2086695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        } else if (isUsb()) {
2096695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedType = TYPE_USB;
2106695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_usb_storage;
2116695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        } else if (isSd()) {
2126695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedType = TYPE_SD;
2136695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_sd_storage;
21412ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        } else if (isExternalStorage()) {
21585c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_LOCAL;
2166695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_root_smartphone;
2179dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        } else if (isDownloads()) {
21885c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_DOWNLOADS;
2196695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_root_download;
2209dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        } else if (isImages()) {
22185c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_IMAGES;
222f8ed15b0ceebb6d0a2cf2bd97fdc6a3981dfc980Daniel Nishi            derivedIcon = com.android.internal.R.drawable.ic_doc_image;
2239dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        } else if (isVideos()) {
22485c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_VIDEO;
225f8ed15b0ceebb6d0a2cf2bd97fdc6a3981dfc980Daniel Nishi            derivedIcon = com.android.internal.R.drawable.ic_doc_video;
2269dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        } else if (isAudio()) {
22785c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_AUDIO;
228f8ed15b0ceebb6d0a2cf2bd97fdc6a3981dfc980Daniel Nishi            derivedIcon = com.android.internal.R.drawable.ic_doc_audio;
22985c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa        } else if (isRecents()) {
23085c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_RECENTS;
23185c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa        } else {
23212ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay            derivedType = TYPE_OTHER;
23306c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey        }
2346695fdf0f06e13d500ebea00093185a864c384f8Steve McKay
235c88f83c0a58581c1da3da28b218b319a2b03c468Steve McKay        if (DEBUG) Log.v(TAG, "Deriving fields: " + this);
2369dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2379dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
23831e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    public Uri getUri() {
23931e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay        return DocumentsContract.buildRootUri(authority, rootId);
24031e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    }
24131e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay
2429dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isRecents() {
2439dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        return authority == null && rootId == null;
2449dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2459dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
24612ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay    public boolean isHome() {
24712ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        // Note that "home" is the expected root id for the auto-created
24812ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        // user home directory on external storage. The "home" value should
24912ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        // match ExternalStorageProvider.ROOT_ID_HOME.
25012ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        return isExternalStorage() && "home".equals(rootId);
25112ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay    }
25212ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay
2539dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isExternalStorage() {
2549dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        return "com.android.externalstorage.documents".equals(authority);
2559dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2569dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
2579dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isDownloads() {
2589dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        return "com.android.providers.downloads.documents".equals(authority);
2599dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2609dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
2619dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isImages() {
2629dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        return "com.android.providers.media.documents".equals(authority)
2639dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey                && "images_root".equals(rootId);
2649dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2659dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
2669dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isVideos() {
2679dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        return "com.android.providers.media.documents".equals(authority)
2689dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey                && "videos_root".equals(rootId);
2699dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2709dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
2719dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isAudio() {
2729dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        return "com.android.providers.media.documents".equals(authority)
2739dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey                && "audio_root".equals(rootId);
274a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
27506c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey
2769fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    public boolean isMtp() {
2779fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono        return "com.android.mtp.documents".equals(authority);
2789fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    }
2799fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono
2809fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    public boolean isLibrary() {
2811aeb3955403a44ef58082de11c26890ca98070e7Steve McKay        return derivedType == TYPE_IMAGES
2821aeb3955403a44ef58082de11c26890ca98070e7Steve McKay                || derivedType == TYPE_VIDEO
2831aeb3955403a44ef58082de11c26890ca98070e7Steve McKay                || derivedType == TYPE_AUDIO
2841aeb3955403a44ef58082de11c26890ca98070e7Steve McKay                || derivedType == TYPE_RECENTS;
2859fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    }
2869fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono
28736787540589e768fce222629a75e951904383250Steve McKay    public boolean hasSettings() {
28836787540589e768fce222629a75e951904383250Steve McKay        return (flags & Root.FLAG_HAS_SETTINGS) != 0;
28936787540589e768fce222629a75e951904383250Steve McKay    }
29036787540589e768fce222629a75e951904383250Steve McKay
291323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    public boolean supportsChildren() {
292323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay        return (flags & Root.FLAG_SUPPORTS_IS_CHILD) != 0;
293323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    }
294323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay
295323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    public boolean supportsCreate() {
296323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay        return (flags & Root.FLAG_SUPPORTS_CREATE) != 0;
297323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    }
298323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay
2991aeb3955403a44ef58082de11c26890ca98070e7Steve McKay    public boolean supportsRecents() {
3001aeb3955403a44ef58082de11c26890ca98070e7Steve McKay        return (flags & Root.FLAG_SUPPORTS_RECENTS) != 0;
3011aeb3955403a44ef58082de11c26890ca98070e7Steve McKay    }
3021aeb3955403a44ef58082de11c26890ca98070e7Steve McKay
3031aeb3955403a44ef58082de11c26890ca98070e7Steve McKay    public boolean supportsSearch() {
3041aeb3955403a44ef58082de11c26890ca98070e7Steve McKay        return (flags & Root.FLAG_SUPPORTS_SEARCH) != 0;
3051aeb3955403a44ef58082de11c26890ca98070e7Steve McKay    }
3061aeb3955403a44ef58082de11c26890ca98070e7Steve McKay
3075668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    public boolean supportsEject() {
3085668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin        return (flags & Root.FLAG_SUPPORTS_EJECT) != 0;
3095668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    }
3105668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin
311bffe6601327a4cb2eb79c8d8e2bf08cabcb8e56bAga Wronska    public boolean isAdvanced() {
312bffe6601327a4cb2eb79c8d8e2bf08cabcb8e56bAga Wronska        return (flags & Root.FLAG_ADVANCED) != 0;
313bffe6601327a4cb2eb79c8d8e2bf08cabcb8e56bAga Wronska    }
314bffe6601327a4cb2eb79c8d8e2bf08cabcb8e56bAga Wronska
315323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    public boolean isLocalOnly() {
316323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay        return (flags & Root.FLAG_LOCAL_ONLY) != 0;
317323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    }
318323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay
319323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    public boolean isEmpty() {
320323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay        return (flags & Root.FLAG_EMPTY) != 0;
321323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    }
322323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay
3236695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public boolean isSd() {
3246695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        return (flags & Root.FLAG_REMOVABLE_SD) != 0;
3256695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    }
3266695fdf0f06e13d500ebea00093185a864c384f8Steve McKay
3276695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public boolean isUsb() {
3286695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        return (flags & Root.FLAG_REMOVABLE_USB) != 0;
3296695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    }
3306695fdf0f06e13d500ebea00093185a864c384f8Steve McKay
331724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public Drawable loadIcon(Context context) {
332a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        if (derivedIcon != 0) {
33361791445af80ab126478e4bc956fe5d44086cf38Alan Viverette            return context.getDrawable(derivedIcon);
33406c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey        } else {
33506c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey            return IconUtils.loadPackageIcon(context, authority, icon);
33606c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey        }
337724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    }
338d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey
3397e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey    public Drawable loadDrawerIcon(Context context) {
3407e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey        if (derivedIcon != 0) {
3417e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey            return IconUtils.applyTintColor(context, derivedIcon, R.color.item_root_icon);
3427e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey        } else {
3437e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey            return IconUtils.loadPackageIcon(context, authority, icon);
3447e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey        }
3457e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey    }
3467e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey
3475668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    public Drawable loadEjectIcon(Context context) {
3485668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin        return IconUtils.applyTintColor(context, R.drawable.ic_eject, R.color.item_eject_icon);
3495668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    }
3505668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin
351a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan    /**
352a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan     * Gets the {@link DocumentInfo} of the root folder of this root.
353a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan     */
354a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan    public @Nullable DocumentInfo getRootDocumentBlocking(Context context) {
355a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan        try {
356a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan            final Uri uri = DocumentsContract.buildDocumentUri(authority, documentId);
357a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan            return DocumentInfo.fromUri(context.getContentResolver(), uri);
358a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan        } catch (FileNotFoundException e) {
359a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan            Log.w(TAG, "Failed to find root", e);
360a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan            return null;
361a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan        }
362a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan    }
363a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tan
364d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    @Override
365d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    public boolean equals(Object o) {
366405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        if (o == null) {
367d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey            return false;
368d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey        }
369405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay
370405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        if (this == o) {
371405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay            return true;
372405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        }
373405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay
374405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        if (o instanceof RootInfo) {
375405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay            RootInfo other = (RootInfo) o;
376405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay            return Objects.equals(authority, other.authority)
377405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay                    && Objects.equals(rootId, other.rootId);
378405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        }
379405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay
380405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        return false;
381d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    }
382d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey
383d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    @Override
384d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    public int hashCode() {
385d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey        return Objects.hash(authority, rootId);
386d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    }
387d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey
38831e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    @Override
38955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    public int compareTo(RootInfo other) {
39055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        // Sort by root type, then title, then summary.
39155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        int score = derivedType - other.derivedType;
39255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        if (score != 0) {
39355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            return score;
39455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        }
39555c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay
39655c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        score = compareToIgnoreCaseNullable(title, other.title);
39755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        if (score != 0) {
39855c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            return score;
39955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        }
40055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay
40155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        return compareToIgnoreCaseNullable(summary, other.summary);
40255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    }
40355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay
40455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    @Override
40531e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    public String toString() {
4066695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        return "Root{"
4076695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + "authority=" + authority
4086695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", rootId=" + rootId
4096695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", title=" + title
4106695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", isUsb=" + isUsb()
4116695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", isSd=" + isSd()
4126695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", isMtp=" + isMtp()
4136695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + "}";
41431e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    }
41531e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay
416d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    public String getDirectoryString() {
417a35ac2dd16a64014a524d1441fb20d5a02b40836Jeff Sharkey        return !TextUtils.isEmpty(summary) ? summary : title;
418d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    }
419724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey}
420