blob: aa21457e74d576d6e7386864d4ad4569a27236b9 [file] [log] [blame]
Jeff Sharkey76112212013-08-06 11:26:10 -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;
18
19import static com.android.documentsui.DocumentsActivity.TAG;
20
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070021import android.content.ContentProviderClient;
22import android.content.ContentResolver;
Jeff Sharkey76112212013-08-06 11:26:10 -070023import android.content.Context;
24import android.content.Intent;
25import android.content.pm.PackageManager;
26import android.content.pm.ProviderInfo;
27import android.content.pm.ResolveInfo;
Jeff Sharkey76112212013-08-06 11:26:10 -070028import android.graphics.drawable.Drawable;
29import android.net.Uri;
30import android.provider.DocumentsContract;
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070031import android.provider.DocumentsContract.DocumentRoot;
Jeff Sharkeyf339f252013-08-15 16:17:41 -070032import android.provider.DocumentsContract.Documents;
Jeff Sharkey76112212013-08-06 11:26:10 -070033import android.util.Log;
Jeff Sharkey76112212013-08-06 11:26:10 -070034
Jeff Sharkey76112212013-08-06 11:26:10 -070035import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070036import com.android.internal.util.Objects;
Jeff Sharkey76112212013-08-06 11:26:10 -070037import com.google.android.collect.Lists;
Jeff Sharkey76112212013-08-06 11:26:10 -070038
Jeff Sharkey76112212013-08-06 11:26:10 -070039import java.util.List;
40
41/**
42 * Cache of known storage backends and their roots.
43 */
44public class RootsCache {
45
46 // TODO: cache roots in local provider to avoid spinning up backends
Jeff Sharkey873daa32013-08-18 17:38:20 -070047 // TODO: root updates should trigger UI refresh
Jeff Sharkey76112212013-08-06 11:26:10 -070048
Jeff Sharkey873daa32013-08-18 17:38:20 -070049 private final Context mContext;
Jeff Sharkey76112212013-08-06 11:26:10 -070050
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070051 public List<DocumentRoot> mRoots = Lists.newArrayList();
Jeff Sharkey76112212013-08-06 11:26:10 -070052
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070053 private DocumentRoot mRecentsRoot;
Jeff Sharkey873daa32013-08-18 17:38:20 -070054
55 public RootsCache(Context context) {
56 mContext = context;
57 update();
58 }
Jeff Sharkey76112212013-08-06 11:26:10 -070059
60 /**
61 * Gather roots from all known storage providers.
62 */
Jeff Sharkey873daa32013-08-18 17:38:20 -070063 @GuardedBy("ActivityThread")
64 public void update() {
Jeff Sharkey873daa32013-08-18 17:38:20 -070065 mRoots.clear();
Jeff Sharkey76112212013-08-06 11:26:10 -070066
67 {
68 // Create special root for recents
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070069 final DocumentRoot root = new DocumentRoot();
70 root.rootType = DocumentRoot.ROOT_TYPE_SHORTCUT;
71 root.docId = null;
72 root.icon = R.drawable.ic_dir;
73 root.title = mContext.getString(R.string.root_recent);
74 root.summary = null;
75 root.availableBytes = -1;
76
77 mRoots.add(root);
Jeff Sharkey873daa32013-08-18 17:38:20 -070078 mRecentsRoot = root;
Jeff Sharkey76112212013-08-06 11:26:10 -070079 }
80
81 // Query for other storage backends
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070082 final ContentResolver resolver = mContext.getContentResolver();
Jeff Sharkey873daa32013-08-18 17:38:20 -070083 final PackageManager pm = mContext.getPackageManager();
Jeff Sharkey76112212013-08-06 11:26:10 -070084 final List<ProviderInfo> providers = pm.queryContentProviders(
85 null, -1, PackageManager.GET_META_DATA);
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070086 for (ProviderInfo info : providers) {
87 if (info.metaData != null && info.metaData.containsKey(
Jeff Sharkey76112212013-08-06 11:26:10 -070088 DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
Jeff Sharkey76112212013-08-06 11:26:10 -070089
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070090 // TODO: remove deprecated customRoots flag
91 // TODO: populate roots on background thread, and cache results
92 final ContentProviderClient client = resolver
93 .acquireUnstableContentProviderClient(info.authority);
Jeff Sharkey76112212013-08-06 11:26:10 -070094 try {
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070095 final List<DocumentRoot> roots = DocumentsContract.getDocumentRoots(client);
96 for (DocumentRoot root : roots) {
97 root.authority = info.authority;
Jeff Sharkey76112212013-08-06 11:26:10 -070098 }
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -070099 mRoots.addAll(roots);
Jeff Sharkey1d890e02013-08-15 11:24:03 -0700100 } catch (Exception e) {
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -0700101 Log.w(TAG, "Failed to load some roots from " + info.authority + ": " + e);
102 } finally {
103 ContentProviderClient.closeQuietly(client);
Jeff Sharkey76112212013-08-06 11:26:10 -0700104 }
105 }
106 }
107 }
108
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -0700109 public DocumentRoot findRoot(Uri uri) {
110 final String authority = uri.getAuthority();
111 final String docId = DocumentsContract.getDocId(uri);
112 for (DocumentRoot root : mRoots) {
113 if (Objects.equal(root.authority, authority) && Objects.equal(root.docId, docId)) {
114 return root;
115 }
116 }
117 return null;
Jeff Sharkey76112212013-08-06 11:26:10 -0700118 }
119
120 @GuardedBy("ActivityThread")
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -0700121 public DocumentRoot getRecentsRoot() {
Jeff Sharkey873daa32013-08-18 17:38:20 -0700122 return mRecentsRoot;
Jeff Sharkey2e694f82013-08-06 16:26:14 -0700123 }
124
125 @GuardedBy("ActivityThread")
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -0700126 public boolean isRecentsRoot(DocumentRoot root) {
127 return mRecentsRoot == root;
Jeff Sharkey76112212013-08-06 11:26:10 -0700128 }
129
130 @GuardedBy("ActivityThread")
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -0700131 public List<DocumentRoot> getRoots() {
132 return mRoots;
133 }
Jeff Sharkey76112212013-08-06 11:26:10 -0700134
Jeff Sharkeyb6a7f2c2013-08-27 18:26:48 -0700135 @GuardedBy("ActivityThread")
136 public static Drawable resolveDocumentIcon(Context context, String mimeType) {
Jeff Sharkeyf339f252013-08-15 16:17:41 -0700137 if (Documents.MIME_TYPE_DIR.equals(mimeType)) {
Jeff Sharkey76112212013-08-06 11:26:10 -0700138 return context.getResources().getDrawable(R.drawable.ic_dir);
139 } else {
140 final PackageManager pm = context.getPackageManager();
141 final Intent intent = new Intent(Intent.ACTION_VIEW);
142 intent.setType(mimeType);
143
144 final ResolveInfo activityInfo = pm.resolveActivity(
145 intent, PackageManager.MATCH_DEFAULT_ONLY);
146 if (activityInfo != null) {
147 return activityInfo.loadIcon(pm);
148 } else {
149 return null;
150 }
151 }
152 }
153}