blob: beb7e5c841025e4f5f0fc6beba495e56557ff538 [file] [log] [blame]
Steve McKay99bcc6a2015-10-26 17:03:55 -07001/*
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 com.android.documentsui;
18
Steve McKaybbeba522016-01-13 17:17:39 -080019import static android.provider.DocumentsContract.buildChildDocumentsUri;
20import static android.provider.DocumentsContract.buildDocumentUri;
21import static android.provider.DocumentsContract.buildRootsUri;
Steve McKayd0805062016-09-15 14:30:38 -070022import static com.android.documentsui.base.DocumentInfo.getCursorString;
Steve McKay22797f52016-01-25 16:31:35 -080023import static com.android.internal.util.Preconditions.checkArgument;
Steve McKaybbeba522016-01-13 17:17:39 -080024import static junit.framework.Assert.assertEquals;
25import static junit.framework.Assert.assertNotNull;
26import static junit.framework.Assert.fail;
Steve McKay99bcc6a2015-10-26 17:03:55 -070027
28import android.content.ContentProviderClient;
29import android.database.Cursor;
30import android.net.Uri;
Steve McKaybbeba522016-01-13 17:17:39 -080031import android.os.Bundle;
32import android.os.ParcelFileDescriptor;
33import android.os.ParcelFileDescriptor.AutoCloseInputStream;
34import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
Steve McKay99bcc6a2015-10-26 17:03:55 -070035import android.os.RemoteException;
36import android.provider.DocumentsContract;
37import android.provider.DocumentsContract.Document;
38import android.provider.DocumentsContract.Root;
Steve McKaybbeba522016-01-13 17:17:39 -080039import android.support.annotation.Nullable;
40import android.test.MoreAsserts;
Steve McKay22797f52016-01-25 16:31:35 -080041import android.text.TextUtils;
Steve McKay99bcc6a2015-10-26 17:03:55 -070042
Steve McKayd0805062016-09-15 14:30:38 -070043import com.android.documentsui.base.DocumentInfo;
44import com.android.documentsui.base.RootInfo;
Steve McKayd9caa6a2016-09-15 16:36:45 -070045import com.android.documentsui.roots.RootCursorWrapper;
Steve McKay99bcc6a2015-10-26 17:03:55 -070046
Steve McKaybbeba522016-01-13 17:17:39 -080047import com.google.android.collect.Lists;
48
Steve McKay99bcc6a2015-10-26 17:03:55 -070049import libcore.io.IoUtils;
Steve McKaybbeba522016-01-13 17:17:39 -080050import libcore.io.Streams;
51
52import java.io.IOException;
53import java.util.ArrayList;
54import java.util.List;
Steve McKay99bcc6a2015-10-26 17:03:55 -070055
56/**
57 * Provides support for creation of documents in a test settings.
58 */
59public class DocumentsProviderHelper {
60
Steve McKay99bcc6a2015-10-26 17:03:55 -070061 private final String mAuthority;
Steve McKaybbeba522016-01-13 17:17:39 -080062 private final ContentProviderClient mClient;
Steve McKay99bcc6a2015-10-26 17:03:55 -070063
64 public DocumentsProviderHelper(String authority, ContentProviderClient client) {
Steve McKay22797f52016-01-25 16:31:35 -080065 checkArgument(!TextUtils.isEmpty(authority));
Steve McKay99bcc6a2015-10-26 17:03:55 -070066 mAuthority = authority;
Steve McKaybbeba522016-01-13 17:17:39 -080067 mClient = client;
Steve McKay99bcc6a2015-10-26 17:03:55 -070068 }
69
Steve McKaybbeba522016-01-13 17:17:39 -080070 public RootInfo getRoot(String documentId) throws RemoteException {
71 final Uri rootsUri = buildRootsUri(mAuthority);
Steve McKay99bcc6a2015-10-26 17:03:55 -070072 Cursor cursor = null;
73 try {
74 cursor = mClient.query(rootsUri, null, null, null, null);
75 while (cursor.moveToNext()) {
Steve McKaybbeba522016-01-13 17:17:39 -080076 if (documentId.equals(getCursorString(cursor, Root.COLUMN_ROOT_ID))) {
Steve McKay99bcc6a2015-10-26 17:03:55 -070077 return RootInfo.fromRootsCursor(mAuthority, cursor);
78 }
79 }
Steve McKaybbeba522016-01-13 17:17:39 -080080 throw new IllegalArgumentException("Can't find matching root for id=" + documentId);
Steve McKay99bcc6a2015-10-26 17:03:55 -070081 } catch (Exception e) {
Steve McKaybbeba522016-01-13 17:17:39 -080082 throw new RuntimeException("Can't load root for id=" + documentId , e);
Steve McKay99bcc6a2015-10-26 17:03:55 -070083 } finally {
84 IoUtils.closeQuietly(cursor);
85 }
86 }
87
88 public Uri createDocument(Uri parentUri, String mimeType, String name) {
89 if (name.contains("/")) {
90 throw new IllegalArgumentException("Name and mimetype probably interposed.");
91 }
92 try {
Steve McKaybbeba522016-01-13 17:17:39 -080093 Uri uri = DocumentsContract.createDocument(mClient, parentUri, mimeType, name);
94 return uri;
Steve McKay99bcc6a2015-10-26 17:03:55 -070095 } catch (RemoteException e) {
Tomasz Mikolajewskia2ad8df2016-02-04 17:46:35 +090096 throw new RuntimeException("Couldn't create document: " + name + " with mimetype "
97 + mimeType, e);
Steve McKay99bcc6a2015-10-26 17:03:55 -070098 }
99 }
100
Steve McKaybbeba522016-01-13 17:17:39 -0800101 public Uri createDocument(String parentId, String mimeType, String name) {
102 Uri parentUri = buildDocumentUri(mAuthority, parentId);
103 return createDocument(parentUri, mimeType, name);
104 }
105
106 public Uri createDocument(RootInfo root, String mimeType, String name) {
107 return createDocument(root.documentId, mimeType, name);
108 }
109
Tomasz Mikolajewskife7f5362016-03-02 17:41:40 +0900110 public Uri createDocumentWithFlags(String documentId, String mimeType, String name, int flags,
111 String... streamTypes)
Aga Wronska18410b72016-01-26 14:06:29 -0800112 throws RemoteException {
113 Bundle in = new Bundle();
114 in.putInt(StubProvider.EXTRA_FLAGS, flags);
115 in.putString(StubProvider.EXTRA_PARENT_ID, documentId);
116 in.putString(Document.COLUMN_MIME_TYPE, mimeType);
117 in.putString(Document.COLUMN_DISPLAY_NAME, name);
Tomasz Mikolajewskife7f5362016-03-02 17:41:40 +0900118 in.putStringArrayList(StubProvider.EXTRA_STREAM_TYPES, Lists.newArrayList(streamTypes));
Aga Wronska18410b72016-01-26 14:06:29 -0800119
120 Bundle out = mClient.call("createDocumentWithFlags", null, in);
121 Uri uri = out.getParcelable(DocumentsContract.EXTRA_URI);
122 return uri;
123 }
124
Steve McKay99bcc6a2015-10-26 17:03:55 -0700125 public Uri createFolder(Uri parentUri, String name) {
126 return createDocument(parentUri, Document.MIME_TYPE_DIR, name);
127 }
128
Steve McKaybbeba522016-01-13 17:17:39 -0800129 public Uri createFolder(String parentId, String name) {
130 Uri parentUri = buildDocumentUri(mAuthority, parentId);
131 return createDocument(parentUri, Document.MIME_TYPE_DIR, name);
Steve McKay99bcc6a2015-10-26 17:03:55 -0700132 }
133
134 public Uri createFolder(RootInfo root, String name) {
135 return createDocument(root, Document.MIME_TYPE_DIR, name);
136 }
Steve McKaybbeba522016-01-13 17:17:39 -0800137
138 public void writeDocument(Uri documentUri, byte[] contents)
139 throws RemoteException, IOException {
140 ParcelFileDescriptor file = mClient.openFile(documentUri, "w", null);
141 try (AutoCloseOutputStream out = new AutoCloseOutputStream(file)) {
142 out.write(contents, 0, contents.length);
143 }
144 }
145
146 public byte[] readDocument(Uri documentUri) throws RemoteException, IOException {
Steve McKaybbeba522016-01-13 17:17:39 -0800147 ParcelFileDescriptor file = mClient.openFile(documentUri, "r", null);
148 byte[] buf = null;
149 try (AutoCloseInputStream in = new AutoCloseInputStream(file)) {
150 buf = Streams.readFully(in);
151 }
152 return buf;
153 }
154
155 public void assertChildCount(Uri parentUri, int expected) throws Exception {
156 List<DocumentInfo> children = listChildren(parentUri);
157 assertEquals("Incorrect file count after copy", expected, children.size());
158 }
159
160 public void assertChildCount(String parentId, int expected) throws Exception {
161 List<DocumentInfo> children = listChildren(parentId);
162 assertEquals("Incorrect file count after copy", expected, children.size());
163 }
164
165 public void assertChildCount(RootInfo root, int expected) throws Exception {
166 assertChildCount(root.documentId, expected);
167 }
168
169 public void assertHasFile(Uri parentUri, String name) throws Exception {
170 List<DocumentInfo> children = listChildren(parentUri);
171 for (DocumentInfo child : children) {
172 if (name.equals(child.displayName) && !child.isDirectory()) {
173 return;
174 }
175 }
176 fail("Could not find file named=" + name + " in children " + children);
177 }
178
179 public void assertHasFile(String parentId, String name) throws Exception {
180 Uri parentUri = buildDocumentUri(mAuthority, parentId);
181 assertHasFile(parentUri, name);
182 }
183
184 public void assertHasFile(RootInfo root, String name) throws Exception {
185 assertHasFile(root.documentId, name);
186 }
187
188 public void assertHasDirectory(Uri parentUri, String name) throws Exception {
189 List<DocumentInfo> children = listChildren(parentUri);
190 for (DocumentInfo child : children) {
191 if (name.equals(child.displayName) && child.isDirectory()) {
192 return;
193 }
194 }
195 fail("Could not find name=" + name + " in children " + children);
196 }
197
198 public void assertHasDirectory(String parentId, String name) throws Exception {
199 Uri parentUri = buildDocumentUri(mAuthority, parentId);
200 assertHasDirectory(parentUri, name);
201 }
202
203 public void assertHasDirectory(RootInfo root, String name) throws Exception {
204 assertHasDirectory(root.documentId, name);
205 }
206
207 public void assertDoesNotExist(Uri parentUri, String name) throws Exception {
208 List<DocumentInfo> children = listChildren(parentUri);
209 for (DocumentInfo child : children) {
210 if (name.equals(child.displayName)) {
211 fail("Found name=" + name + " in children " + children);
212 }
213 }
214 }
215
216 public void assertDoesNotExist(String parentId, String name) throws Exception {
217 Uri parentUri = buildDocumentUri(mAuthority, parentId);
218 assertDoesNotExist(parentUri, name);
219 }
220
221 public void assertDoesNotExist(RootInfo root, String name) throws Exception {
222 assertDoesNotExist(root.getUri(), name);
223 }
224
225 public @Nullable DocumentInfo findFile(String parentId, String name)
226 throws Exception {
227 List<DocumentInfo> children = listChildren(parentId);
228 for (DocumentInfo child : children) {
229 if (name.equals(child.displayName)) {
230 return child;
231 }
232 }
233 return null;
234 }
235
236 public DocumentInfo findDocument(String parentId, String name) throws Exception {
237 List<DocumentInfo> children = listChildren(parentId);
238 for (DocumentInfo child : children) {
239 if (name.equals(child.displayName)) {
240 return child;
241 }
242 }
243 return null;
244 }
245
246 public DocumentInfo findDocument(Uri parentUri, String name) throws Exception {
247 List<DocumentInfo> children = listChildren(parentUri);
248 for (DocumentInfo child : children) {
249 if (name.equals(child.displayName)) {
250 return child;
251 }
252 }
253 return null;
254 }
255
256 public List<DocumentInfo> listChildren(Uri parentUri) throws Exception {
257 String id = DocumentsContract.getDocumentId(parentUri);
258 return listChildren(id);
259 }
260
261 public List<DocumentInfo> listChildren(String documentId) throws Exception {
262 Uri uri = buildChildDocumentsUri(mAuthority, documentId);
263 List<DocumentInfo> children = new ArrayList<>();
264 try (Cursor cursor = mClient.query(uri, null, null, null, null, null)) {
Steve McKay22797f52016-01-25 16:31:35 -0800265 Cursor wrapper = new RootCursorWrapper(mAuthority, "totally-fake", cursor, 100);
266 while (wrapper.moveToNext()) {
267 children.add(DocumentInfo.fromDirectoryCursor(wrapper));
Steve McKaybbeba522016-01-13 17:17:39 -0800268 }
269 }
270 return children;
271 }
272
273 public void assertFileContents(Uri documentUri, byte[] expected) throws Exception {
Steve McKay22797f52016-01-25 16:31:35 -0800274 MoreAsserts.assertEquals(
275 "Copied file contents differ",
276 expected, readDocument(documentUri));
Steve McKaybbeba522016-01-13 17:17:39 -0800277 }
278
279 public void assertFileContents(String parentId, String fileName, byte[] expected)
280 throws Exception {
281 DocumentInfo file = findFile(parentId, fileName);
282 assertNotNull(file);
283 assertFileContents(file.derivedUri, expected);
284 }
285
286 /**
287 * A helper method for StubProvider only. Won't work with other providers.
288 * @throws RemoteException
289 */
290 public Uri createVirtualFile(
291 RootInfo root, String path, String mimeType, byte[] content, String... streamTypes)
292 throws RemoteException {
293
294 Bundle args = new Bundle();
295 args.putString(StubProvider.EXTRA_ROOT, root.rootId);
296 args.putString(StubProvider.EXTRA_PATH, path);
297 args.putString(Document.COLUMN_MIME_TYPE, mimeType);
298 args.putStringArrayList(StubProvider.EXTRA_STREAM_TYPES, Lists.newArrayList(streamTypes));
299 args.putByteArray(StubProvider.EXTRA_CONTENT, content);
300
301 Bundle result = mClient.call("createVirtualFile", null, args);
302 String documentId = result.getString(Document.COLUMN_DOCUMENT_ID);
303
304 return DocumentsContract.buildDocumentUri(mAuthority, documentId);
305 }
Aga Wronska18410b72016-01-26 14:06:29 -0800306
Steve McKay99bcc6a2015-10-26 17:03:55 -0700307}