1220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown/*
2220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Copyright (C) 2013 The Android Open Source Project
3220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown *
4220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * you may not use this file except in compliance with the License.
6220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * You may obtain a copy of the License at
7220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown *
8220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown *
10220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Unless required by applicable law or agreed to in writing, software
11220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * See the License for the specific language governing permissions and
14220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * limitations under the License.
15220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */
16220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown
17220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownpackage android.support.v4.content;
18220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown
19b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikasimport static android.os.Build.VERSION.SDK_INT;
20b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas
21220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.content.ContentResolver;
22220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.database.Cursor;
23220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.net.Uri;
24220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.support.v4.os.CancellationSignal;
25220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.support.v4.os.OperationCanceledException;
26220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown
27220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown/**
28b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas * Helper for accessing features in {@link android.content.ContentResolver} in a backwards
29b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas * compatible fashion.
30220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */
31c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class ContentResolverCompat {
32220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown    private ContentResolverCompat() {
33220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown        /* Hide constructor */
34220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown    }
35220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown
36220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown    /**
37220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * Query the given URI, returning a {@link Cursor} over the result set
38220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * with optional support for cancellation.
39220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * <p>
40220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * For best performance, the caller should follow these guidelines:
41220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * <ul>
42220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * <li>Provide an explicit projection, to prevent
43220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * reading data from storage that aren't going to be used.</li>
44220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * <li>Use question mark parameter markers such as 'phone=?' instead of
45220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * explicit values in the {@code selection} parameter, so that queries
46220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * that differ only by those values will be recognized as the same
47220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * for caching purposes.</li>
48220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * </ul>
49220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * </p>
50220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     *
51220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * @param uri The URI, using the content:// scheme, for the content to
52220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     *         retrieve.
53220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * @param projection A list of which columns to return. Passing null will
54220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     *         return all columns, which is inefficient.
55220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * @param selection A filter declaring which rows to return, formatted as an
56220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     *         SQL WHERE clause (excluding the WHERE itself). Passing null will
57220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     *         return all rows for the given URI.
58220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * @param selectionArgs You may include ?s in selection, which will be
59220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     *         replaced by the values from selectionArgs, in the order that they
60220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     *         appear in the selection. The values will be bound as Strings.
61220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
62220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     *         clause (excluding the ORDER BY itself). Passing null will use the
63220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     *         default sort order, which may be unordered.
64220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
65220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * If the operation is canceled, then {@link OperationCanceledException} will be thrown
66220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * when the query is executed.
67220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * @return A Cursor object, which is positioned before the first entry, or null
68220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     * @see Cursor
69220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown     */
70220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown    public static Cursor query(ContentResolver resolver,
71220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown            Uri uri, String[] projection, String selection, String[] selectionArgs,
72220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown            String sortOrder, CancellationSignal cancellationSignal) {
73b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas        if (SDK_INT >= 16) {
74b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas            try {
75b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                final android.os.CancellationSignal cancellationSignalObj =
76b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                        (android.os.CancellationSignal)
77b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                                (cancellationSignal != null
78b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                                        ? cancellationSignal.getCancellationSignalObject()
79b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                                        : null);
80b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                return resolver.query(uri, projection, selection, selectionArgs, sortOrder,
81b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                        cancellationSignalObj);
82b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas            } catch (Exception e) {
83b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                if (e instanceof android.os.OperationCanceledException) {
84b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                    // query() can throw a framework OperationCanceledException if it has been
85b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                    // canceled. We catch that and throw the support version instead.
86b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                    throw new OperationCanceledException();
87b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                } else {
88b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                    // If it's not a framework OperationCanceledException, re-throw the exception
89b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                    throw e;
90b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                }
91b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas            }
92b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas        } else {
93b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas            // Note that the cancellation signal cannot cancel the query in progress
94b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas            // prior to Jellybean so we cancel it preemptively here if needed.
95b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas            if (cancellationSignal != null) {
96b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas                cancellationSignal.throwIfCanceled();
97b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas            }
98b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas            return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
99b9bc12cd1b9694ce7ef467f5b6156b7d8dc39f57Aurimas Liutikas        }
100220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown    }
101220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown}
102