1b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio/*
2b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Copyright (C) 2014 The Android Open Source Project
3b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *
4b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License");
5b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * you may not use this file except in compliance with the License.
6b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * You may obtain a copy of the License at
7b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *
8b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *      http://www.apache.org/licenses/LICENSE-2.0
9b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *
10b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Unless required by applicable law or agreed to in writing, software
11b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS,
12b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * See the License for the specific language governing permissions and
14b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * limitations under the License.
15b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */
16b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
17b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Megliopackage android.provider;
18b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
1927e13347344276f337d4289e3197f8ab7d5c74d2Fabrice Di Meglioimport android.annotation.SystemApi;
20b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.ContentProvider;
21b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.ContentValues;
22b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.Context;
23b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.UriMatcher;
24b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.pm.ProviderInfo;
25b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.database.Cursor;
26b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.net.Uri;
27b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
28b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio/**
29b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Base class for a search indexable provider. Such provider offers data to be indexed either
30b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * as a reference to an XML file (like a {@link android.preference.PreferenceScreen}) or either
31b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * as some raw data.
32b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *
33b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @see SearchIndexableResource
34b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @see SearchIndexableData
35b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @see SearchIndexablesContract
36b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *
37b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * To create a search indexables provider, extend this class, then implement the abstract methods,
38b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * and add it to your manifest like this:
39b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *
40b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <pre class="prettyprint">&lt;manifest&gt;
41b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *    ...
42b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *    &lt;application&gt;
43b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *        ...
44b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *        &lt;provider
45b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *            android:name="com.example.MyIndexablesProvider"
46b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *            android:authorities="com.example.myindexablesprovider"
47b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *            android:exported="true"
48b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *            android:grantUriPermissions="true"
49b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *            android:permission="android.permission.READ_SEARCH_INDEXABLES"
50b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *            &lt;intent-filter&gt;
51b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *                &lt;action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" /&gt;
52b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *            &lt;/intent-filter&gt;
53b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *        &lt;/provider&gt;
54b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *        ...
55b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *    &lt;/application&gt;
56b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *&lt;/manifest&gt;</pre>
57b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <p>
58b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * When defining your provider, you must protect it with
59b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * {@link android.Manifest.permission#READ_SEARCH_INDEXABLES}, which is a permission only the system
60b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * can obtain.
61b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * </p>
62b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *
63b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @hide
64b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */
6527e13347344276f337d4289e3197f8ab7d5c74d2Fabrice Di Meglio@SystemApi
66b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Megliopublic abstract class SearchIndexablesProvider extends ContentProvider {
67b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    private static final String TAG = "IndexablesProvider";
68b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
69b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    private String mAuthority;
70b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    private UriMatcher mMatcher;
71b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
72b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    private static final int MATCH_RES_CODE = 1;
73b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    private static final int MATCH_RAW_CODE = 2;
7497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio    private static final int MATCH_NON_INDEXABLE_KEYS_CODE = 3;
75b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
76b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    /**
77b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     * Implementation is provided by the parent class.
78b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     */
79b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    @Override
80b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    public void attachInfo(Context context, ProviderInfo info) {
81b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        mAuthority = info.authority;
82b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
83b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
84b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        mMatcher.addURI(mAuthority, SearchIndexablesContract.INDEXABLES_XML_RES_PATH,
85b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio                MATCH_RES_CODE);
86b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        mMatcher.addURI(mAuthority, SearchIndexablesContract.INDEXABLES_RAW_PATH,
87b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio                MATCH_RAW_CODE);
8897babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio        mMatcher.addURI(mAuthority, SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH,
8997babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio                MATCH_NON_INDEXABLE_KEYS_CODE);
90b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
91b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        // Sanity check our setup
92b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        if (!info.exported) {
93b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            throw new SecurityException("Provider must be exported");
94b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        }
95b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        if (!info.grantUriPermissions) {
96b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            throw new SecurityException("Provider must grantUriPermissions");
97b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        }
98b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        if (!android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(info.readPermission)) {
99b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            throw new SecurityException("Provider must be protected by READ_SEARCH_INDEXABLES");
100b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        }
101b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
102b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        super.attachInfo(context, info);
103b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    }
104b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
105b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    @Override
106b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
107b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio                        String sortOrder) {
108b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        switch (mMatcher.match(uri)) {
109b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            case MATCH_RES_CODE:
110b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio                return queryXmlResources(null);
111b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            case MATCH_RAW_CODE:
112b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio                return queryRawData(null);
11397babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio            case MATCH_NON_INDEXABLE_KEYS_CODE:
11497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio                return queryNonIndexableKeys(null);
115b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            default:
116b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio                throw new UnsupportedOperationException("Unknown Uri " + uri);
117b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        }
118b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    }
119b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
120b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    /**
121b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     * Returns all {@link android.provider.SearchIndexablesContract.XmlResource}.
122b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     *
12397babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     * Those are Xml resource IDs to some {@link android.preference.PreferenceScreen}.
124b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     *
125b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     * @param projection list of {@link android.provider.SearchIndexablesContract.XmlResource}
126b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     *                   columns to put into the cursor. If {@code null} all supported columns
127b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     *                   should be included.
128b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     */
129b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    public abstract Cursor queryXmlResources(String[] projection);
130b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
131b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    /**
132b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     * Returns all {@link android.provider.SearchIndexablesContract.RawData}.
133b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     *
13497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     * Those are the raw indexable data.
135b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     *
136b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     * @param projection list of {@link android.provider.SearchIndexablesContract.RawData} columns
137b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     *                   to put into the cursor. If {@code null} all supported columns should be
138b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     *                   included.
139b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     */
140b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    public abstract Cursor queryRawData(String[] projection);
141b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
14297babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio    /**
14397babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     * Returns all {@link android.provider.SearchIndexablesContract.NonIndexableKey}.
14497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     *
14597babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     * Those are the non indexable data keys.
14697babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     *
14797babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     * @param projection list of {@link android.provider.SearchIndexablesContract.NonIndexableKey}
14897babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     *                   columns to put into the cursor. If {@code null} all supported columns
14997babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     *                   should be included.
15097babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     */
15197babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio    public abstract Cursor queryNonIndexableKeys(String[] projection);
15297babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio
153b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    @Override
154b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    public String getType(Uri uri) {
155b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        switch (mMatcher.match(uri)) {
156b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            case MATCH_RES_CODE:
157b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio                return SearchIndexablesContract.XmlResource.MIME_TYPE;
158b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            case MATCH_RAW_CODE:
159b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio                return SearchIndexablesContract.RawData.MIME_TYPE;
16097babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio            case MATCH_NON_INDEXABLE_KEYS_CODE:
16197babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio                return SearchIndexablesContract.NonIndexableKey.MIME_TYPE;
162b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            default:
163b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio                throw new IllegalArgumentException("Unknown URI " + uri);
164b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        }
165b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    }
166b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
167b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    /**
16897babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
169b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     */
170b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    @Override
171b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    public final Uri insert(Uri uri, ContentValues values) {
172b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        throw new UnsupportedOperationException("Insert not supported");
173b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    }
174b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
175b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    /**
17697babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
177b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     */
178b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    @Override
179b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    public final int delete(Uri uri, String selection, String[] selectionArgs) {
180b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        throw new UnsupportedOperationException("Delete not supported");
181b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    }
182b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio
183b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    /**
18497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
185b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio     */
186b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    @Override
187b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    public final int update(
188b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio            Uri uri, ContentValues values, String selection, String[] selectionArgs) {
189b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio        throw new UnsupportedOperationException("Update not supported");
190b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio    }
191b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio}
192