DocumentsProvider.java revision 911d7f411f36f2279aae44c89ff1d33a29140046
1aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey/*
2aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Copyright (C) 2013 The Android Open Source Project
3aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey *
4aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * you may not use this file except in compliance with the License.
6aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * You may obtain a copy of the License at
7aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey *
8aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey *
10aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * See the License for the specific language governing permissions and
14aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * limitations under the License.
15aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey */
16aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
17aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeypackage android.provider;
18aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
19aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport static android.provider.DocumentsContract.EXTRA_THUMBNAIL_SIZE;
20aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport static android.provider.DocumentsContract.METHOD_CREATE_DOCUMENT;
21aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport static android.provider.DocumentsContract.METHOD_DELETE_DOCUMENT;
22ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport static android.provider.DocumentsContract.getDocumentId;
23ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport static android.provider.DocumentsContract.getRootId;
24ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport static android.provider.DocumentsContract.getSearchDocumentsQuery;
25aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
26aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.content.ContentProvider;
27aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.content.ContentValues;
28aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.content.Context;
29aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.content.Intent;
30aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.content.UriMatcher;
31e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkeyimport android.content.pm.PackageManager;
32aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.content.pm.ProviderInfo;
33aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.content.res.AssetFileDescriptor;
34aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.database.Cursor;
35aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.graphics.Point;
36aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.net.Uri;
37aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.os.Bundle;
38aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.os.CancellationSignal;
39aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.os.ParcelFileDescriptor;
40aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.os.ParcelFileDescriptor.OnCloseListener;
41ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport android.provider.DocumentsContract.Document;
42aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.util.Log;
43aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
44aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport libcore.io.IoUtils;
45aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
46aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport java.io.FileNotFoundException;
47aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
48aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey/**
49aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Base class for a document provider. A document provider should extend this
50aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * class and implement the abstract methods.
51aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * <p>
52aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Each document provider expresses one or more "roots" which each serve as the
53aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * top-level of a tree. For example, a root could represent an account, or a
54aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * physical storage device. Under each root, documents are referenced by
55ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Document#COLUMN_DOCUMENT_ID}, which must not change once returned.
56aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * <p>
57aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Documents can be either an openable file (with a specific MIME type), or a
58aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * directory containing additional documents (with the
59ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Document#MIME_TYPE_DIR} MIME type). Each document can have different
60ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * capabilities, as described by {@link Document#COLUMN_FLAGS}. The same
61ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey * {@link Document#COLUMN_DOCUMENT_ID} can be included in multiple directories.
62aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * <p>
63aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Document providers must be protected with the
64aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * {@link android.Manifest.permission#MANAGE_DOCUMENTS} permission, which can
65aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * only be requested by the system. The system-provided UI then issues narrow
66aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * Uri permission grants for individual documents when the user explicitly picks
67aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * documents.
68aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey *
69aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * @see Intent#ACTION_OPEN_DOCUMENT
70aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey * @see Intent#ACTION_CREATE_DOCUMENT
71aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey */
72aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeypublic abstract class DocumentsProvider extends ContentProvider {
73aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    private static final String TAG = "DocumentsProvider";
74aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
75a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey    private static final int MATCH_ROOTS = 1;
76a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey    private static final int MATCH_ROOT = 2;
77a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey    private static final int MATCH_RECENT = 3;
78a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey    private static final int MATCH_DOCUMENT = 4;
79a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey    private static final int MATCH_CHILDREN = 5;
80a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey    private static final int MATCH_SEARCH = 6;
81aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
82aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    private String mAuthority;
83aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
84aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    private UriMatcher mMatcher;
85aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
86ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
87ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class.
88ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
89aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
90aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public void attachInfo(Context context, ProviderInfo info) {
91aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        mAuthority = info.authority;
92aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
93aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
94a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey        mMatcher.addURI(mAuthority, "root", MATCH_ROOTS);
95a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey        mMatcher.addURI(mAuthority, "root/*", MATCH_ROOT);
96ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        mMatcher.addURI(mAuthority, "root/*/recent", MATCH_RECENT);
97ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        mMatcher.addURI(mAuthority, "document/*", MATCH_DOCUMENT);
98ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        mMatcher.addURI(mAuthority, "document/*/children", MATCH_CHILDREN);
99ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        mMatcher.addURI(mAuthority, "document/*/search", MATCH_SEARCH);
100aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
101aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        // Sanity check our setup
102aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        if (!info.exported) {
103aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            throw new SecurityException("Provider must be exported");
104aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
105aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        if (!info.grantUriPermissions) {
106aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            throw new SecurityException("Provider must grantUriPermissions");
107aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
108aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        if (!android.Manifest.permission.MANAGE_DOCUMENTS.equals(info.readPermission)
109aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                || !android.Manifest.permission.MANAGE_DOCUMENTS.equals(info.writePermission)) {
110aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            throw new SecurityException("Provider must be protected by MANAGE_DOCUMENTS");
111aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
112aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
113aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        super.attachInfo(context, info);
114aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
115aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
116aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    /**
117ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Create a new document and return its {@link Document#COLUMN_DOCUMENT_ID}.
118ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * A provider must allocate a new {@link Document#COLUMN_DOCUMENT_ID} to
119ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * represent the document, which must not change once returned.
120aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *
121ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @param documentId the parent directory to create the new document under.
122aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @param mimeType the MIME type associated with the new document.
123aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @param displayName the display name of the new document.
124aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     */
125aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @SuppressWarnings("unused")
126ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public String createDocument(String documentId, String mimeType, String displayName)
127aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            throws FileNotFoundException {
128aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        throw new UnsupportedOperationException("Create not supported");
129aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
130aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
131aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    /**
132ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Delete the given document. Upon returning, any Uri permission grants for
133ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * the given document will be revoked. If additional documents were deleted
134ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * as a side effect of this call, such as documents inside a directory, the
135ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * implementor is responsible for revoking those permissions.
136aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *
137ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @param documentId the document to delete.
138aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     */
139aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @SuppressWarnings("unused")
140ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public void deleteDocument(String documentId) throws FileNotFoundException {
141ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        throw new UnsupportedOperationException("Delete not supported");
142aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
143aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
144ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public abstract Cursor queryRoots(String[] projection) throws FileNotFoundException;
145ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey
146aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @SuppressWarnings("unused")
147ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public Cursor queryRecentDocuments(String rootId, String[] projection)
148ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            throws FileNotFoundException {
149ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        throw new UnsupportedOperationException("Recent not supported");
150aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
151aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
152aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    /**
153aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * Return metadata for the given document. A provider should avoid making
154aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * network requests to keep this request fast.
155aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *
156ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @param documentId the document to return.
157aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     */
158ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public abstract Cursor queryDocument(String documentId, String[] projection)
159ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            throws FileNotFoundException;
160aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
161aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    /**
162aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * Return the children of the given document which is a directory.
163aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *
164ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @param parentDocumentId the directory to return children for.
165aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     */
166ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public abstract Cursor queryChildDocuments(
167ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            String parentDocumentId, String[] projection, String sortOrder)
168ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            throws FileNotFoundException;
169aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
170aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    /**
171aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * Return documents that that match the given query, starting the search at
172aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * the given directory.
173aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *
174ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @param parentDocumentId the directory to start search at.
175aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     */
176aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @SuppressWarnings("unused")
177ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public Cursor querySearchDocuments(String parentDocumentId, String query, String[] projection)
178ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            throws FileNotFoundException {
179aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        throw new UnsupportedOperationException("Search not supported");
180aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
181aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
182aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    /**
183aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * Return MIME type for the given document. Must match the value of
184ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * {@link Document#COLUMN_MIME_TYPE} for this document.
185aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     */
186ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public String getDocumentType(String documentId) throws FileNotFoundException {
187ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        final Cursor cursor = queryDocument(documentId, null);
188aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        try {
189aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            if (cursor.moveToFirst()) {
190ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                return cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE));
191aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            } else {
192aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                return null;
193aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            }
194aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        } finally {
195aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            IoUtils.closeQuietly(cursor);
196aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
197aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
198aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
199aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    /**
200aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * Open and return the requested document. A provider should return a
201aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * reliable {@link ParcelFileDescriptor} to detect when the remote caller
202aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * has finished reading or writing the document. A provider may return a
203aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * pipe or socket pair if the mode is exclusively
204aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * {@link ParcelFileDescriptor#MODE_READ_ONLY} or
205aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * {@link ParcelFileDescriptor#MODE_WRITE_ONLY}, but complex modes like
206aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * {@link ParcelFileDescriptor#MODE_READ_WRITE} require a normal file on
207aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * disk. If a provider blocks while downloading content, it should
208aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * periodically check {@link CancellationSignal#isCanceled()} to abort
209aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * abandoned open requests.
210aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *
211aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @param docId the document to return.
212aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @param mode the mode to open with, such as 'r', 'w', or 'rw'.
213aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @param signal used by the caller to signal if the request should be
214aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *            cancelled.
215aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @see ParcelFileDescriptor#open(java.io.File, int, android.os.Handler,
216aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *      OnCloseListener)
217aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @see ParcelFileDescriptor#createReliablePipe()
218aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @see ParcelFileDescriptor#createReliableSocketPair()
219aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     */
220aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public abstract ParcelFileDescriptor openDocument(
221aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            String docId, String mode, CancellationSignal signal) throws FileNotFoundException;
222aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
223aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    /**
224aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * Open and return a thumbnail of the requested document. A provider should
225aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * return a thumbnail closely matching the hinted size, attempting to serve
226aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * from a local cache if possible. A provider should never return images
227aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * more than double the hinted size. If a provider performs expensive
228aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * operations to download or generate a thumbnail, it should periodically
229aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * check {@link CancellationSignal#isCanceled()} to abort abandoned
230aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * thumbnail requests.
231aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *
232aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @param docId the document to return.
233aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @param sizeHint hint of the optimal thumbnail dimensions.
234aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     * @param signal used by the caller to signal if the request should be
235aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     *            cancelled.
236ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see Document#FLAG_SUPPORTS_THUMBNAIL
237aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey     */
238aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @SuppressWarnings("unused")
239aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public AssetFileDescriptor openDocumentThumbnail(
240aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            String docId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
241aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        throw new UnsupportedOperationException("Thumbnails not supported");
242aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
243aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
244ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
245ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class. Cannot be overriden.
246ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     *
247ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #queryRoots(String[])
248ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #queryRecentDocuments(String, String[])
249ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #queryDocument(String, String[])
250ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #queryChildDocuments(String, String[], String)
251ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #querySearchDocuments(String, String, String[])
252ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
253aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
254ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public final Cursor query(Uri uri, String[] projection, String selection,
255ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            String[] selectionArgs, String sortOrder) {
256aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        try {
257aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            switch (mMatcher.match(uri)) {
258a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                case MATCH_ROOTS:
259ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                    return queryRoots(projection);
260ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                case MATCH_RECENT:
261ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                    return queryRecentDocuments(getRootId(uri), projection);
262aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                case MATCH_DOCUMENT:
263ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                    return queryDocument(getDocumentId(uri), projection);
264aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                case MATCH_CHILDREN:
265ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                    return queryChildDocuments(getDocumentId(uri), projection, sortOrder);
266aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                case MATCH_SEARCH:
267ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                    return querySearchDocuments(
268ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                            getDocumentId(uri), getSearchDocumentsQuery(uri), projection);
269aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                default:
270aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                    throw new UnsupportedOperationException("Unsupported Uri " + uri);
271aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            }
272aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        } catch (FileNotFoundException e) {
273aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            Log.w(TAG, "Failed during query", e);
274aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            return null;
275aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
276aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
277aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
278ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
279ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class. Cannot be overriden.
280ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     *
281ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #getDocumentType(String)
282ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
283aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
284aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public final String getType(Uri uri) {
285aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        try {
286aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            switch (mMatcher.match(uri)) {
287a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                case MATCH_ROOT:
288a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                    return DocumentsContract.Root.MIME_TYPE_ITEM;
289aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                case MATCH_DOCUMENT:
290ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                    return getDocumentType(getDocumentId(uri));
291aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                default:
292aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                    return null;
293aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            }
294aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        } catch (FileNotFoundException e) {
295aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            Log.w(TAG, "Failed during getType", e);
296aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            return null;
297aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
298aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
299aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
300ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
301ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class. Throws by default, and
302ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * cannot be overriden.
303ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     *
304ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #createDocument(String, String, String)
305ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
306aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
307aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public final Uri insert(Uri uri, ContentValues values) {
308aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        throw new UnsupportedOperationException("Insert not supported");
309aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
310aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
311ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
312ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class. Throws by default, and
313ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * cannot be overriden.
314ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     *
315ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #deleteDocument(String)
316ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
317aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
318aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public final int delete(Uri uri, String selection, String[] selectionArgs) {
319aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        throw new UnsupportedOperationException("Delete not supported");
320aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
321aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
322ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
323ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class. Throws by default, and
324ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * cannot be overriden.
325ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
326aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
327aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public final int update(
328aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            Uri uri, ContentValues values, String selection, String[] selectionArgs) {
329aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        throw new UnsupportedOperationException("Update not supported");
330aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
331aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
332911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey    /**
333911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey     * Implementation is provided by the parent class. Can be overridden to
334911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey     * provide additional functionality, but subclasses <em>must</em> always
335911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey     * call the superclass. If the superclass returns {@code null}, the subclass
336911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey     * may implement custom behavior.
337911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey     *
338911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey     * @see #openDocument(String, String, CancellationSignal)
339911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey     * @see #deleteDocument(String)
340911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey     */
341aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
342911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey    public Bundle call(String method, String arg, Bundle extras) {
343e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey        final Context context = getContext();
344e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey
345aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        if (!method.startsWith("android:")) {
346aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            // Let non-platform methods pass through
347911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey            return super.call(method, arg, extras);
348aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
349aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
350ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        final String documentId = extras.getString(Document.COLUMN_DOCUMENT_ID);
351ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        final Uri documentUri = DocumentsContract.buildDocumentUri(mAuthority, documentId);
352e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey
353e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey        // Require that caller can manage given document
354e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey        final boolean callerHasManage =
355e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                context.checkCallingOrSelfPermission(android.Manifest.permission.MANAGE_DOCUMENTS)
356e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                == PackageManager.PERMISSION_GRANTED;
357e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey        if (!callerHasManage) {
358e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey            getContext().enforceCallingOrSelfUriPermission(
359e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                    documentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, method);
360e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey        }
361aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
362aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        final Bundle out = new Bundle();
363aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        try {
364ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            if (METHOD_CREATE_DOCUMENT.equals(method)) {
365ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
366ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
367aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
368ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                final String newDocumentId = createDocument(documentId, mimeType, displayName);
369ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey                out.putString(Document.COLUMN_DOCUMENT_ID, newDocumentId);
370aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
371e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                // Extend permission grant towards caller if needed
372e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                if (!callerHasManage) {
373e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                    final Uri newDocumentUri = DocumentsContract.buildDocumentUri(
374e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                            mAuthority, newDocumentId);
375911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey                    context.grantUriPermission(getCallingPackage(), newDocumentUri,
376e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                            Intent.FLAG_GRANT_READ_URI_PERMISSION
377e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
378e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                            | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION);
379e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                }
380e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey
381aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            } else if (METHOD_DELETE_DOCUMENT.equals(method)) {
382e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                deleteDocument(documentId);
383e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey
384e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                // Document no longer exists, clean up any grants
385e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                context.revokeUriPermission(documentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
386e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
387e37ea6123d1aa3cd3e8804988886b1f6046d79d6Jeff Sharkey                        | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION);
388aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
389aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            } else {
390aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey                throw new UnsupportedOperationException("Method not supported " + method);
391aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            }
392aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        } catch (FileNotFoundException e) {
393aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            throw new IllegalStateException("Failed call " + method, e);
394aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
395aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        return out;
396aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
397aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
398ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
399ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class.
400ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     *
401ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #openDocument(String, String, CancellationSignal)
402ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
403aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
404aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public final ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
405ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        return openDocument(getDocumentId(uri), mode, null);
406aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
407aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
408ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
409ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class.
410ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     *
411ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #openDocument(String, String, CancellationSignal)
412ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
413aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
414aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public final ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal)
415aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            throws FileNotFoundException {
416ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        return openDocument(getDocumentId(uri), mode, signal);
417aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
418aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
419ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
420ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class.
421ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     *
422ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #openDocumentThumbnail(String, Point, CancellationSignal)
423ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
424aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
425aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public final AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
426aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            throws FileNotFoundException {
427aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) {
428aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE);
429ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            return openDocumentThumbnail(getDocumentId(uri), sizeHint, null);
430aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        } else {
431aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            return super.openTypedAssetFile(uri, mimeTypeFilter, opts);
432aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
433aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
434aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey
435ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    /**
436ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * Implementation is provided by the parent class.
437ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     *
438ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     * @see #openDocumentThumbnail(String, Point, CancellationSignal)
439ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey     */
440aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    @Override
441aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    public final AssetFileDescriptor openTypedAssetFile(
442aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
443aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            throws FileNotFoundException {
444aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) {
445aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE);
446ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            return openDocumentThumbnail(getDocumentId(uri), sizeHint, signal);
447aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        } else {
448aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            return super.openTypedAssetFile(uri, mimeTypeFilter, opts, signal);
449aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        }
450aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey    }
451aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey}
452