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;
2230535bce902104c97bbf70783d684ee673cb7637Steve McKayimport static com.android.documentsui.base.Shared.VERBOSE;
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
380f5ec83eeee1d68f344c036cdff0c31ff68e6ee8Steve McKayimport com.android.documentsui.DocumentsAccess;
395629ec5989006bfc4ad3cb19a92163d581ff02e6Jeff Sharkeyimport com.android.documentsui.IconUtils;
4006c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkeyimport com.android.documentsui.R;
415629ec5989006bfc4ad3cb19a92163d581ff02e6Jeff Sharkey
42a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport java.io.DataInputStream;
43a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport java.io.DataOutputStream;
44a5588b65d55bc1b8b5ba943f8b660db26a7eac5cGarfield, Tanimport java.io.FileNotFoundException;
45a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport java.io.IOException;
4655c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKayimport java.lang.annotation.Retention;
4755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKayimport java.lang.annotation.RetentionPolicy;
48a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkeyimport java.net.ProtocolException;
49d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkeyimport java.util.Objects;
50d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey
51724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey/**
52724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey * Representation of a {@link Root}.
53724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey */
5455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKaypublic class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
556695fdf0f06e13d500ebea00093185a864c384f8Steve McKay
566695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    private static final String TAG = "RootInfo";
57a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    private static final int VERSION_INIT = 1;
589dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    private static final int VERSION_DROP_TYPE = 2;
59a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
6085c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    // The values of these constants determine the sort order of various roots in the RootsFragment.
6150254fee5f12df77409db0e5bcfbc663ebccdde9Jeff Sharkey    @IntDef(flag = false, value = {
6255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_IMAGES,
6355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_VIDEO,
6455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_AUDIO,
6555c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_RECENTS,
6655c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_DOWNLOADS,
6755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_LOCAL,
6855c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_MTP,
696695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            TYPE_SD,
706695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            TYPE_USB,
7155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            TYPE_OTHER
7255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    })
7355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    @Retention(RetentionPolicy.SOURCE)
7455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    public @interface RootType {}
7585c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_IMAGES = 1;
7685c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_VIDEO = 2;
7785c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_AUDIO = 3;
7885c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_RECENTS = 4;
7985c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_DOWNLOADS = 5;
8085c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa    public static final int TYPE_LOCAL = 6;
819fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    public static final int TYPE_MTP = 7;
826695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public static final int TYPE_SD = 8;
836695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public static final int TYPE_USB = 9;
846695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public static final int TYPE_OTHER = 10;
8585c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa
86724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String authority;
87724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String rootId;
88724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public int flags;
89724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public int icon;
90724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String title;
91724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String summary;
92724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public String documentId;
93724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public long availableBytes;
94a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public String mimeTypes;
95a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
96a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    /** Derived fields that aren't persisted */
97a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public String[] derivedMimeTypes;
98a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public int derivedIcon;
9955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    public @RootType int derivedType;
1005668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    // Currently, we are not persisting this and we should be asking Provider whether a Root
1015668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    // is in the process of eject. Provider does not have this available yet.
1025668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    public transient boolean ejecting;
103a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
104a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public RootInfo() {
105a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        reset();
106a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
107a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
108a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
109a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public void reset() {
110a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        authority = null;
111a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        rootId = null;
112a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        flags = 0;
113a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        icon = 0;
114a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        title = null;
115a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        summary = null;
116a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        documentId = null;
117a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        availableBytes = -1;
118a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        mimeTypes = null;
1195668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin        ejecting = false;
120a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
121a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        derivedMimeTypes = null;
122a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        derivedIcon = 0;
12385c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa        derivedType = 0;
124a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
125a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
126a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
127a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public void read(DataInputStream in) throws IOException {
128a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        final int version = in.readInt();
129a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        switch (version) {
1309dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            case VERSION_DROP_TYPE:
131a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                authority = DurableUtils.readNullableString(in);
132a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                rootId = DurableUtils.readNullableString(in);
133a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                flags = in.readInt();
134a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                icon = in.readInt();
135a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                title = DurableUtils.readNullableString(in);
136a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                summary = DurableUtils.readNullableString(in);
137a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                documentId = DurableUtils.readNullableString(in);
138a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                availableBytes = in.readLong();
139a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                mimeTypes = DurableUtils.readNullableString(in);
140a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                deriveFields();
141a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                break;
142a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            default:
143a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                throw new ProtocolException("Unknown version " + version);
144a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        }
145a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
146a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
147a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
148a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public void write(DataOutputStream out) throws IOException {
1499dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        out.writeInt(VERSION_DROP_TYPE);
150a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, authority);
151a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, rootId);
152a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        out.writeInt(flags);
153a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        out.writeInt(icon);
154a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, title);
155a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, summary);
156a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, documentId);
157a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        out.writeLong(availableBytes);
158a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeNullableString(out, mimeTypes);
159a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
160a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
161a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
162a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public int describeContents() {
163a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        return 0;
164a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
165a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
166a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    @Override
167a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public void writeToParcel(Parcel dest, int flags) {
168a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        DurableUtils.writeToParcel(dest, this);
169a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
170a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
171a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    public static final Creator<RootInfo> CREATOR = new Creator<RootInfo>() {
172a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        @Override
173a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        public RootInfo createFromParcel(Parcel in) {
174a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            final RootInfo root = new RootInfo();
175a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            DurableUtils.readFromParcel(in, root);
176a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            return root;
177a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        }
178a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey
179a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        @Override
180a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        public RootInfo[] newArray(int size) {
181a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey            return new RootInfo[size];
182a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        }
183a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    };
184724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey
185724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public static RootInfo fromRootsCursor(String authority, Cursor cursor) {
186724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        final RootInfo root = new RootInfo();
187724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.authority = authority;
188724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.rootId = getCursorString(cursor, Root.COLUMN_ROOT_ID);
189724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.flags = getCursorInt(cursor, Root.COLUMN_FLAGS);
190724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.icon = getCursorInt(cursor, Root.COLUMN_ICON);
191724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.title = getCursorString(cursor, Root.COLUMN_TITLE);
192724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.summary = getCursorString(cursor, Root.COLUMN_SUMMARY);
193724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.documentId = getCursorString(cursor, Root.COLUMN_DOCUMENT_ID);
194724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        root.availableBytes = getCursorLong(cursor, Root.COLUMN_AVAILABLE_BYTES);
195a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        root.mimeTypes = getCursorString(cursor, Root.COLUMN_MIME_TYPES);
196a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        root.deriveFields();
197a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        return root;
198a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
199e1a2ceef30fe9c514152c3fab3cedcb99bdb68dfJeff Sharkey
200a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    private void deriveFields() {
201a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        derivedMimeTypes = (mimeTypes != null) ? mimeTypes.split("\n") : null;
202e1a2ceef30fe9c514152c3fab3cedcb99bdb68dfJeff Sharkey
20312ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        if (isHome()) {
20412ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay            derivedType = TYPE_LOCAL;
2056695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_root_documents;
2066695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        } else if (isMtp()) {
2076695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedType = TYPE_MTP;
2086695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_usb_storage;
2096695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        } else if (isUsb()) {
2106695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedType = TYPE_USB;
2116695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_usb_storage;
2126695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        } else if (isSd()) {
2136695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedType = TYPE_SD;
2146695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_sd_storage;
21512ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        } else if (isExternalStorage()) {
21685c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_LOCAL;
2176695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_root_smartphone;
2189dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        } else if (isDownloads()) {
21985c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_DOWNLOADS;
2206695fdf0f06e13d500ebea00093185a864c384f8Steve McKay            derivedIcon = R.drawable.ic_root_download;
2219dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        } else if (isImages()) {
22285c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_IMAGES;
223fc84b34edff91524af63c82dcf8cc2e97ee76f75Ben Lin            derivedIcon = R.drawable.image_root_icon;
2249dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        } else if (isVideos()) {
22585c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_VIDEO;
226fc84b34edff91524af63c82dcf8cc2e97ee76f75Ben Lin            derivedIcon = R.drawable.video_root_icon;
2279dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        } else if (isAudio()) {
22885c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_AUDIO;
229fc84b34edff91524af63c82dcf8cc2e97ee76f75Ben Lin            derivedIcon = R.drawable.audio_root_icon;
23085c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa        } else if (isRecents()) {
23185c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa            derivedType = TYPE_RECENTS;
23285c8cdd2e79e96f719932db64b61d3c51d4aeefcBen Kwa        } else {
23312ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay            derivedType = TYPE_OTHER;
23406c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey        }
2356695fdf0f06e13d500ebea00093185a864c384f8Steve McKay
23630535bce902104c97bbf70783d684ee673cb7637Steve McKay        if (VERBOSE) Log.v(TAG, "Derived fields: " + this);
2379dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2389dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
23931e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    public Uri getUri() {
24031e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay        return DocumentsContract.buildRootUri(authority, rootId);
24131e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    }
24231e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay
2439dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isRecents() {
2449dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        return authority == null && rootId == null;
2459dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2469dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
24712ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay    public boolean isHome() {
24812ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        // Note that "home" is the expected root id for the auto-created
24912ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        // user home directory on external storage. The "home" value should
25012ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        // match ExternalStorageProvider.ROOT_ID_HOME.
25112ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay        return isExternalStorage() && "home".equals(rootId);
25212ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay    }
25312ef53e81e604a0668bc09747577c1686c90d2fbSteve McKay
2549dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isExternalStorage() {
2558659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay        return Providers.AUTHORITY_STORAGE.equals(authority);
2569dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2579dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
2589dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isDownloads() {
2598659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay        return Providers.AUTHORITY_DOWNLOADS.equals(authority);
2609dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2619dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
2629dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isImages() {
2638659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay        return Providers.AUTHORITY_MEDIA.equals(authority)
2648659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay                && Providers.ROOT_ID_IMAGES.equals(rootId);
2659dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2669dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
2679dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isVideos() {
2688659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay        return Providers.AUTHORITY_MEDIA.equals(authority)
2698659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay                && Providers.ROOT_ID_VIDEOS.equals(rootId);
2709dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2719dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
2729dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    public boolean isAudio() {
2738659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay        return Providers.AUTHORITY_MEDIA.equals(authority)
2748659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay                && Providers.ROOT_ID_AUDIO.equals(rootId);
275a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey    }
27606c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey
2779fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    public boolean isMtp() {
2788659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay        return Providers.AUTHORITY_MTP.equals(authority);
2799fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    }
2809fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono
2819fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    public boolean isLibrary() {
2821aeb3955403a44ef58082de11c26890ca98070e7Steve McKay        return derivedType == TYPE_IMAGES
2831aeb3955403a44ef58082de11c26890ca98070e7Steve McKay                || derivedType == TYPE_VIDEO
2841aeb3955403a44ef58082de11c26890ca98070e7Steve McKay                || derivedType == TYPE_AUDIO
2851aeb3955403a44ef58082de11c26890ca98070e7Steve McKay                || derivedType == TYPE_RECENTS;
2869fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono    }
2879fb33890e10dac56ced4559b4d325ba1a7470dc6Daichi Hirono
28836787540589e768fce222629a75e951904383250Steve McKay    public boolean hasSettings() {
28936787540589e768fce222629a75e951904383250Steve McKay        return (flags & Root.FLAG_HAS_SETTINGS) != 0;
29036787540589e768fce222629a75e951904383250Steve McKay    }
29136787540589e768fce222629a75e951904383250Steve McKay
292323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    public boolean supportsChildren() {
293323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay        return (flags & Root.FLAG_SUPPORTS_IS_CHILD) != 0;
294323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    }
295323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay
296323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    public boolean supportsCreate() {
297323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay        return (flags & Root.FLAG_SUPPORTS_CREATE) != 0;
298323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    }
299323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay
3001aeb3955403a44ef58082de11c26890ca98070e7Steve McKay    public boolean supportsRecents() {
3011aeb3955403a44ef58082de11c26890ca98070e7Steve McKay        return (flags & Root.FLAG_SUPPORTS_RECENTS) != 0;
3021aeb3955403a44ef58082de11c26890ca98070e7Steve McKay    }
3031aeb3955403a44ef58082de11c26890ca98070e7Steve McKay
3041aeb3955403a44ef58082de11c26890ca98070e7Steve McKay    public boolean supportsSearch() {
3051aeb3955403a44ef58082de11c26890ca98070e7Steve McKay        return (flags & Root.FLAG_SUPPORTS_SEARCH) != 0;
3061aeb3955403a44ef58082de11c26890ca98070e7Steve McKay    }
3071aeb3955403a44ef58082de11c26890ca98070e7Steve McKay
3085668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    public boolean supportsEject() {
3095668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin        return (flags & Root.FLAG_SUPPORTS_EJECT) != 0;
3105668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    }
3115668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin
312bffe6601327a4cb2eb79c8d8e2bf08cabcb8e56bAga Wronska    public boolean isAdvanced() {
313bffe6601327a4cb2eb79c8d8e2bf08cabcb8e56bAga Wronska        return (flags & Root.FLAG_ADVANCED) != 0;
314bffe6601327a4cb2eb79c8d8e2bf08cabcb8e56bAga Wronska    }
315bffe6601327a4cb2eb79c8d8e2bf08cabcb8e56bAga Wronska
316323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    public boolean isLocalOnly() {
317323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay        return (flags & Root.FLAG_LOCAL_ONLY) != 0;
318323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    }
319323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay
320323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    public boolean isEmpty() {
321323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay        return (flags & Root.FLAG_EMPTY) != 0;
322323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay    }
323323dffb4cffde781d325ddd3a36da9ed7b5bfec6Steve McKay
3246695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public boolean isSd() {
3256695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        return (flags & Root.FLAG_REMOVABLE_SD) != 0;
3266695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    }
3276695fdf0f06e13d500ebea00093185a864c384f8Steve McKay
3286695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    public boolean isUsb() {
3296695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        return (flags & Root.FLAG_REMOVABLE_USB) != 0;
3306695fdf0f06e13d500ebea00093185a864c384f8Steve McKay    }
3316695fdf0f06e13d500ebea00093185a864c384f8Steve McKay
332724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public Drawable loadIcon(Context context) {
333a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        if (derivedIcon != 0) {
33461791445af80ab126478e4bc956fe5d44086cf38Alan Viverette            return context.getDrawable(derivedIcon);
33506c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey        } else {
33606c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey            return IconUtils.loadPackageIcon(context, authority, icon);
33706c4187080497dffbcdb438aa45b262eb37706b1Jeff Sharkey        }
338724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    }
339d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey
3407e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey    public Drawable loadDrawerIcon(Context context) {
3417e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey        if (derivedIcon != 0) {
3427e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey            return IconUtils.applyTintColor(context, derivedIcon, R.color.item_root_icon);
3437e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey        } else {
3447e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey            return IconUtils.loadPackageIcon(context, authority, icon);
3457e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey        }
3467e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey    }
3477e544619f6518dd5eeed8262604edfc08942471fJeff Sharkey
3485668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    public Drawable loadEjectIcon(Context context) {
3495668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin        return IconUtils.applyTintColor(context, R.drawable.ic_eject, R.color.item_eject_icon);
3505668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin    }
3515668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin
352d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    @Override
353d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    public boolean equals(Object o) {
354405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        if (o == null) {
355d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey            return false;
356d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey        }
357405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay
358405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        if (this == o) {
359405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay            return true;
360405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        }
361405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay
362405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        if (o instanceof RootInfo) {
363405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay            RootInfo other = (RootInfo) o;
364405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay            return Objects.equals(authority, other.authority)
365405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay                    && Objects.equals(rootId, other.rootId);
366405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        }
367405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay
368405142a83f58ccf9c2c3ba66951aa714075b3932Steve McKay        return false;
369d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    }
370d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey
371d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    @Override
372d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    public int hashCode() {
373d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey        return Objects.hash(authority, rootId);
374d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    }
375d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey
37631e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    @Override
37755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    public int compareTo(RootInfo other) {
37855c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        // Sort by root type, then title, then summary.
37955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        int score = derivedType - other.derivedType;
38055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        if (score != 0) {
38155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            return score;
38255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        }
38355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay
38455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        score = compareToIgnoreCaseNullable(title, other.title);
38555c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        if (score != 0) {
38655c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay            return score;
38755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        }
38855c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay
38955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay        return compareToIgnoreCaseNullable(summary, other.summary);
39055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    }
39155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay
39255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay    @Override
39331e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    public String toString() {
3946695fdf0f06e13d500ebea00093185a864c384f8Steve McKay        return "Root{"
3956695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + "authority=" + authority
3966695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", rootId=" + rootId
3976695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", title=" + title
3986695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", isUsb=" + isUsb()
3996695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", isSd=" + isSd()
4006695fdf0f06e13d500ebea00093185a864c384f8Steve McKay                + ", isMtp=" + isMtp()
4018659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay                + "} @ "
4028659cbccc6fbab79fb6855abe9cb31ee8171b37eSteve McKay                + getUri();
40331e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay    }
40431e104f83db7dae9e8620ef1d3151f9a580e6dcbSteve McKay
4056a0a5688a3c250f18c895ab80af5e6093e7d38d1Steve McKay    public String toDebugString() {
4066a0a5688a3c250f18c895ab80af5e6093e7d38d1Steve McKay        return (TextUtils.isEmpty(summary))
4076a0a5688a3c250f18c895ab80af5e6093e7d38d1Steve McKay                ? "\"" + title + "\" @ " + getUri()
4086a0a5688a3c250f18c895ab80af5e6093e7d38d1Steve McKay                : "\"" + title + " (" + summary + ")\" @ " + getUri();
4096a0a5688a3c250f18c895ab80af5e6093e7d38d1Steve McKay    }
4106a0a5688a3c250f18c895ab80af5e6093e7d38d1Steve McKay
411d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    public String getDirectoryString() {
412a35ac2dd16a64014a524d1441fb20d5a02b40836Jeff Sharkey        return !TextUtils.isEmpty(summary) ? summary : title;
413d82b26b58a0950a0dd3522e630bd87fe85290ab2Jeff Sharkey    }
414724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey}
415