1/*
2 * Copyright (C) 2006 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 android.content;
18
19import static android.Manifest.permission.INTERACT_ACROSS_USERS;
20import static android.app.AppOpsManager.MODE_ALLOWED;
21import static android.app.AppOpsManager.MODE_ERRORED;
22import static android.app.AppOpsManager.MODE_IGNORED;
23import static android.content.pm.PackageManager.PERMISSION_GRANTED;
24
25import android.annotation.NonNull;
26import android.annotation.Nullable;
27import android.app.AppOpsManager;
28import android.content.pm.PathPermission;
29import android.content.pm.ProviderInfo;
30import android.content.res.AssetFileDescriptor;
31import android.content.res.Configuration;
32import android.database.Cursor;
33import android.database.MatrixCursor;
34import android.database.SQLException;
35import android.net.Uri;
36import android.os.AsyncTask;
37import android.os.Binder;
38import android.os.Bundle;
39import android.os.CancellationSignal;
40import android.os.IBinder;
41import android.os.ICancellationSignal;
42import android.os.OperationCanceledException;
43import android.os.ParcelFileDescriptor;
44import android.os.Process;
45import android.os.UserHandle;
46import android.text.TextUtils;
47import android.util.Log;
48
49import java.io.File;
50import java.io.FileDescriptor;
51import java.io.FileNotFoundException;
52import java.io.IOException;
53import java.io.PrintWriter;
54import java.util.ArrayList;
55
56/**
57 * Content providers are one of the primary building blocks of Android applications, providing
58 * content to applications. They encapsulate data and provide it to applications through the single
59 * {@link ContentResolver} interface. A content provider is only required if you need to share
60 * data between multiple applications. For example, the contacts data is used by multiple
61 * applications and must be stored in a content provider. If you don't need to share data amongst
62 * multiple applications you can use a database directly via
63 * {@link android.database.sqlite.SQLiteDatabase}.
64 *
65 * <p>When a request is made via
66 * a {@link ContentResolver} the system inspects the authority of the given URI and passes the
67 * request to the content provider registered with the authority. The content provider can interpret
68 * the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing
69 * URIs.</p>
70 *
71 * <p>The primary methods that need to be implemented are:
72 * <ul>
73 *   <li>{@link #onCreate} which is called to initialize the provider</li>
74 *   <li>{@link #query} which returns data to the caller</li>
75 *   <li>{@link #insert} which inserts new data into the content provider</li>
76 *   <li>{@link #update} which updates existing data in the content provider</li>
77 *   <li>{@link #delete} which deletes data from the content provider</li>
78 *   <li>{@link #getType} which returns the MIME type of data in the content provider</li>
79 * </ul></p>
80 *
81 * <p class="caution">Data access methods (such as {@link #insert} and
82 * {@link #update}) may be called from many threads at once, and must be thread-safe.
83 * Other methods (such as {@link #onCreate}) are only called from the application
84 * main thread, and must avoid performing lengthy operations.  See the method
85 * descriptions for their expected thread behavior.</p>
86 *
87 * <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate
88 * ContentProvider instance, so subclasses don't have to worry about the details of
89 * cross-process calls.</p>
90 *
91 * <div class="special reference">
92 * <h3>Developer Guides</h3>
93 * <p>For more information about using content providers, read the
94 * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
95 * developer guide.</p>
96 */
97public abstract class ContentProvider implements ComponentCallbacks2 {
98    private static final String TAG = "ContentProvider";
99
100    /*
101     * Note: if you add methods to ContentProvider, you must add similar methods to
102     *       MockContentProvider.
103     */
104
105    private Context mContext = null;
106    private int mMyUid;
107
108    // Since most Providers have only one authority, we keep both a String and a String[] to improve
109    // performance.
110    private String mAuthority;
111    private String[] mAuthorities;
112    private String mReadPermission;
113    private String mWritePermission;
114    private PathPermission[] mPathPermissions;
115    private boolean mExported;
116    private boolean mNoPerms;
117    private boolean mSingleUser;
118
119    private final ThreadLocal<String> mCallingPackage = new ThreadLocal<String>();
120
121    private Transport mTransport = new Transport();
122
123    /**
124     * Construct a ContentProvider instance.  Content providers must be
125     * <a href="{@docRoot}guide/topics/manifest/provider-element.html">declared
126     * in the manifest</a>, accessed with {@link ContentResolver}, and created
127     * automatically by the system, so applications usually do not create
128     * ContentProvider instances directly.
129     *
130     * <p>At construction time, the object is uninitialized, and most fields and
131     * methods are unavailable.  Subclasses should initialize themselves in
132     * {@link #onCreate}, not the constructor.
133     *
134     * <p>Content providers are created on the application main thread at
135     * application launch time.  The constructor must not perform lengthy
136     * operations, or application startup will be delayed.
137     */
138    public ContentProvider() {
139    }
140
141    /**
142     * Constructor just for mocking.
143     *
144     * @param context A Context object which should be some mock instance (like the
145     * instance of {@link android.test.mock.MockContext}).
146     * @param readPermission The read permision you want this instance should have in the
147     * test, which is available via {@link #getReadPermission()}.
148     * @param writePermission The write permission you want this instance should have
149     * in the test, which is available via {@link #getWritePermission()}.
150     * @param pathPermissions The PathPermissions you want this instance should have
151     * in the test, which is available via {@link #getPathPermissions()}.
152     * @hide
153     */
154    public ContentProvider(
155            Context context,
156            String readPermission,
157            String writePermission,
158            PathPermission[] pathPermissions) {
159        mContext = context;
160        mReadPermission = readPermission;
161        mWritePermission = writePermission;
162        mPathPermissions = pathPermissions;
163    }
164
165    /**
166     * Given an IContentProvider, try to coerce it back to the real
167     * ContentProvider object if it is running in the local process.  This can
168     * be used if you know you are running in the same process as a provider,
169     * and want to get direct access to its implementation details.  Most
170     * clients should not nor have a reason to use it.
171     *
172     * @param abstractInterface The ContentProvider interface that is to be
173     *              coerced.
174     * @return If the IContentProvider is non-{@code null} and local, returns its actual
175     * ContentProvider instance.  Otherwise returns {@code null}.
176     * @hide
177     */
178    public static ContentProvider coerceToLocalContentProvider(
179            IContentProvider abstractInterface) {
180        if (abstractInterface instanceof Transport) {
181            return ((Transport)abstractInterface).getContentProvider();
182        }
183        return null;
184    }
185
186    /**
187     * Binder object that deals with remoting.
188     *
189     * @hide
190     */
191    class Transport extends ContentProviderNative {
192        AppOpsManager mAppOpsManager = null;
193        int mReadOp = AppOpsManager.OP_NONE;
194        int mWriteOp = AppOpsManager.OP_NONE;
195
196        ContentProvider getContentProvider() {
197            return ContentProvider.this;
198        }
199
200        @Override
201        public String getProviderName() {
202            return getContentProvider().getClass().getName();
203        }
204
205        @Override
206        public Cursor query(String callingPkg, Uri uri, String[] projection,
207                String selection, String[] selectionArgs, String sortOrder,
208                ICancellationSignal cancellationSignal) {
209            validateIncomingUri(uri);
210            uri = getUriWithoutUserId(uri);
211            if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
212                // The caller has no access to the data, so return an empty cursor with
213                // the columns in the requested order. The caller may ask for an invalid
214                // column and we would not catch that but this is not a problem in practice.
215                // We do not call ContentProvider#query with a modified where clause since
216                // the implementation is not guaranteed to be backed by a SQL database, hence
217                // it may not handle properly the tautology where clause we would have created.
218                if (projection != null) {
219                    return new MatrixCursor(projection, 0);
220                }
221
222                // Null projection means all columns but we have no idea which they are.
223                // However, the caller may be expecting to access them my index. Hence,
224                // we have to execute the query as if allowed to get a cursor with the
225                // columns. We then use the column names to return an empty cursor.
226                Cursor cursor = ContentProvider.this.query(uri, projection, selection,
227                        selectionArgs, sortOrder, CancellationSignal.fromTransport(
228                                cancellationSignal));
229                if (cursor == null) {
230                    return null;
231                }
232
233                // Return an empty cursor for all columns.
234                return new MatrixCursor(cursor.getColumnNames(), 0);
235            }
236            final String original = setCallingPackage(callingPkg);
237            try {
238                return ContentProvider.this.query(
239                        uri, projection, selection, selectionArgs, sortOrder,
240                        CancellationSignal.fromTransport(cancellationSignal));
241            } finally {
242                setCallingPackage(original);
243            }
244        }
245
246        @Override
247        public String getType(Uri uri) {
248            validateIncomingUri(uri);
249            uri = getUriWithoutUserId(uri);
250            return ContentProvider.this.getType(uri);
251        }
252
253        @Override
254        public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
255            validateIncomingUri(uri);
256            int userId = getUserIdFromUri(uri);
257            uri = getUriWithoutUserId(uri);
258            if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
259                return rejectInsert(uri, initialValues);
260            }
261            final String original = setCallingPackage(callingPkg);
262            try {
263                return maybeAddUserId(ContentProvider.this.insert(uri, initialValues), userId);
264            } finally {
265                setCallingPackage(original);
266            }
267        }
268
269        @Override
270        public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
271            validateIncomingUri(uri);
272            uri = getUriWithoutUserId(uri);
273            if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
274                return 0;
275            }
276            final String original = setCallingPackage(callingPkg);
277            try {
278                return ContentProvider.this.bulkInsert(uri, initialValues);
279            } finally {
280                setCallingPackage(original);
281            }
282        }
283
284        @Override
285        public ContentProviderResult[] applyBatch(String callingPkg,
286                ArrayList<ContentProviderOperation> operations)
287                throws OperationApplicationException {
288            int numOperations = operations.size();
289            final int[] userIds = new int[numOperations];
290            for (int i = 0; i < numOperations; i++) {
291                ContentProviderOperation operation = operations.get(i);
292                Uri uri = operation.getUri();
293                validateIncomingUri(uri);
294                userIds[i] = getUserIdFromUri(uri);
295                if (userIds[i] != UserHandle.USER_CURRENT) {
296                    // Removing the user id from the uri.
297                    operation = new ContentProviderOperation(operation, true);
298                    operations.set(i, operation);
299                }
300                if (operation.isReadOperation()) {
301                    if (enforceReadPermission(callingPkg, uri, null)
302                            != AppOpsManager.MODE_ALLOWED) {
303                        throw new OperationApplicationException("App op not allowed", 0);
304                    }
305                }
306                if (operation.isWriteOperation()) {
307                    if (enforceWritePermission(callingPkg, uri, null)
308                            != AppOpsManager.MODE_ALLOWED) {
309                        throw new OperationApplicationException("App op not allowed", 0);
310                    }
311                }
312            }
313            final String original = setCallingPackage(callingPkg);
314            try {
315                ContentProviderResult[] results = ContentProvider.this.applyBatch(operations);
316                if (results != null) {
317                    for (int i = 0; i < results.length ; i++) {
318                        if (userIds[i] != UserHandle.USER_CURRENT) {
319                            // Adding the userId to the uri.
320                            results[i] = new ContentProviderResult(results[i], userIds[i]);
321                        }
322                    }
323                }
324                return results;
325            } finally {
326                setCallingPackage(original);
327            }
328        }
329
330        @Override
331        public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
332            validateIncomingUri(uri);
333            uri = getUriWithoutUserId(uri);
334            if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
335                return 0;
336            }
337            final String original = setCallingPackage(callingPkg);
338            try {
339                return ContentProvider.this.delete(uri, selection, selectionArgs);
340            } finally {
341                setCallingPackage(original);
342            }
343        }
344
345        @Override
346        public int update(String callingPkg, Uri uri, ContentValues values, String selection,
347                String[] selectionArgs) {
348            validateIncomingUri(uri);
349            uri = getUriWithoutUserId(uri);
350            if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
351                return 0;
352            }
353            final String original = setCallingPackage(callingPkg);
354            try {
355                return ContentProvider.this.update(uri, values, selection, selectionArgs);
356            } finally {
357                setCallingPackage(original);
358            }
359        }
360
361        @Override
362        public ParcelFileDescriptor openFile(
363                String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal,
364                IBinder callerToken) throws FileNotFoundException {
365            validateIncomingUri(uri);
366            uri = getUriWithoutUserId(uri);
367            enforceFilePermission(callingPkg, uri, mode, callerToken);
368            final String original = setCallingPackage(callingPkg);
369            try {
370                return ContentProvider.this.openFile(
371                        uri, mode, CancellationSignal.fromTransport(cancellationSignal));
372            } finally {
373                setCallingPackage(original);
374            }
375        }
376
377        @Override
378        public AssetFileDescriptor openAssetFile(
379                String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
380                throws FileNotFoundException {
381            validateIncomingUri(uri);
382            uri = getUriWithoutUserId(uri);
383            enforceFilePermission(callingPkg, uri, mode, null);
384            final String original = setCallingPackage(callingPkg);
385            try {
386                return ContentProvider.this.openAssetFile(
387                        uri, mode, CancellationSignal.fromTransport(cancellationSignal));
388            } finally {
389                setCallingPackage(original);
390            }
391        }
392
393        @Override
394        public Bundle call(
395                String callingPkg, String method, @Nullable String arg, @Nullable Bundle extras) {
396            final String original = setCallingPackage(callingPkg);
397            try {
398                return ContentProvider.this.call(method, arg, extras);
399            } finally {
400                setCallingPackage(original);
401            }
402        }
403
404        @Override
405        public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
406            validateIncomingUri(uri);
407            uri = getUriWithoutUserId(uri);
408            return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
409        }
410
411        @Override
412        public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
413                Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
414            validateIncomingUri(uri);
415            uri = getUriWithoutUserId(uri);
416            enforceFilePermission(callingPkg, uri, "r", null);
417            final String original = setCallingPackage(callingPkg);
418            try {
419                return ContentProvider.this.openTypedAssetFile(
420                        uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal));
421            } finally {
422                setCallingPackage(original);
423            }
424        }
425
426        @Override
427        public ICancellationSignal createCancellationSignal() {
428            return CancellationSignal.createTransport();
429        }
430
431        @Override
432        public Uri canonicalize(String callingPkg, Uri uri) {
433            validateIncomingUri(uri);
434            int userId = getUserIdFromUri(uri);
435            uri = getUriWithoutUserId(uri);
436            if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
437                return null;
438            }
439            final String original = setCallingPackage(callingPkg);
440            try {
441                return maybeAddUserId(ContentProvider.this.canonicalize(uri), userId);
442            } finally {
443                setCallingPackage(original);
444            }
445        }
446
447        @Override
448        public Uri uncanonicalize(String callingPkg, Uri uri) {
449            validateIncomingUri(uri);
450            int userId = getUserIdFromUri(uri);
451            uri = getUriWithoutUserId(uri);
452            if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
453                return null;
454            }
455            final String original = setCallingPackage(callingPkg);
456            try {
457                return maybeAddUserId(ContentProvider.this.uncanonicalize(uri), userId);
458            } finally {
459                setCallingPackage(original);
460            }
461        }
462
463        private void enforceFilePermission(String callingPkg, Uri uri, String mode,
464                IBinder callerToken) throws FileNotFoundException, SecurityException {
465            if (mode != null && mode.indexOf('w') != -1) {
466                if (enforceWritePermission(callingPkg, uri, callerToken)
467                        != AppOpsManager.MODE_ALLOWED) {
468                    throw new FileNotFoundException("App op not allowed");
469                }
470            } else {
471                if (enforceReadPermission(callingPkg, uri, callerToken)
472                        != AppOpsManager.MODE_ALLOWED) {
473                    throw new FileNotFoundException("App op not allowed");
474                }
475            }
476        }
477
478        private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken)
479                throws SecurityException {
480            final int mode = enforceReadPermissionInner(uri, callingPkg, callerToken);
481            if (mode != MODE_ALLOWED) {
482                return mode;
483            }
484
485            if (mReadOp != AppOpsManager.OP_NONE) {
486                return mAppOpsManager.noteProxyOp(mReadOp, callingPkg);
487            }
488
489            return AppOpsManager.MODE_ALLOWED;
490        }
491
492        private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken)
493                throws SecurityException {
494            final int mode = enforceWritePermissionInner(uri, callingPkg, callerToken);
495            if (mode != MODE_ALLOWED) {
496                return mode;
497            }
498
499            if (mWriteOp != AppOpsManager.OP_NONE) {
500                return mAppOpsManager.noteProxyOp(mWriteOp, callingPkg);
501            }
502
503            return AppOpsManager.MODE_ALLOWED;
504        }
505    }
506
507    boolean checkUser(int pid, int uid, Context context) {
508        return UserHandle.getUserId(uid) == context.getUserId()
509                || mSingleUser
510                || context.checkPermission(INTERACT_ACROSS_USERS, pid, uid)
511                == PERMISSION_GRANTED;
512    }
513
514    /**
515     * Verify that calling app holds both the given permission and any app-op
516     * associated with that permission.
517     */
518    private int checkPermissionAndAppOp(String permission, String callingPkg,
519            IBinder callerToken) {
520        if (getContext().checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid(),
521                callerToken) != PERMISSION_GRANTED) {
522            return MODE_ERRORED;
523        }
524
525        final int permOp = AppOpsManager.permissionToOpCode(permission);
526        if (permOp != AppOpsManager.OP_NONE) {
527            return mTransport.mAppOpsManager.noteProxyOp(permOp, callingPkg);
528        }
529
530        return MODE_ALLOWED;
531    }
532
533    /** {@hide} */
534    protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken)
535            throws SecurityException {
536        final Context context = getContext();
537        final int pid = Binder.getCallingPid();
538        final int uid = Binder.getCallingUid();
539        String missingPerm = null;
540        int strongestMode = MODE_ALLOWED;
541
542        if (UserHandle.isSameApp(uid, mMyUid)) {
543            return MODE_ALLOWED;
544        }
545
546        if (mExported && checkUser(pid, uid, context)) {
547            final String componentPerm = getReadPermission();
548            if (componentPerm != null) {
549                final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken);
550                if (mode == MODE_ALLOWED) {
551                    return MODE_ALLOWED;
552                } else {
553                    missingPerm = componentPerm;
554                    strongestMode = Math.max(strongestMode, mode);
555                }
556            }
557
558            // track if unprotected read is allowed; any denied
559            // <path-permission> below removes this ability
560            boolean allowDefaultRead = (componentPerm == null);
561
562            final PathPermission[] pps = getPathPermissions();
563            if (pps != null) {
564                final String path = uri.getPath();
565                for (PathPermission pp : pps) {
566                    final String pathPerm = pp.getReadPermission();
567                    if (pathPerm != null && pp.match(path)) {
568                        final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken);
569                        if (mode == MODE_ALLOWED) {
570                            return MODE_ALLOWED;
571                        } else {
572                            // any denied <path-permission> means we lose
573                            // default <provider> access.
574                            allowDefaultRead = false;
575                            missingPerm = pathPerm;
576                            strongestMode = Math.max(strongestMode, mode);
577                        }
578                    }
579                }
580            }
581
582            // if we passed <path-permission> checks above, and no default
583            // <provider> permission, then allow access.
584            if (allowDefaultRead) return MODE_ALLOWED;
585        }
586
587        // last chance, check against any uri grants
588        final int callingUserId = UserHandle.getUserId(uid);
589        final Uri userUri = (mSingleUser && !UserHandle.isSameUser(mMyUid, uid))
590                ? maybeAddUserId(uri, callingUserId) : uri;
591        if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION,
592                callerToken) == PERMISSION_GRANTED) {
593            return MODE_ALLOWED;
594        }
595
596        // If the worst denial we found above was ignored, then pass that
597        // ignored through; otherwise we assume it should be a real error below.
598        if (strongestMode == MODE_IGNORED) {
599            return MODE_IGNORED;
600        }
601
602        final String failReason = mExported
603                ? " requires " + missingPerm + ", or grantUriPermission()"
604                : " requires the provider be exported, or grantUriPermission()";
605        throw new SecurityException("Permission Denial: reading "
606                + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
607                + ", uid=" + uid + failReason);
608    }
609
610    /** {@hide} */
611    protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken)
612            throws SecurityException {
613        final Context context = getContext();
614        final int pid = Binder.getCallingPid();
615        final int uid = Binder.getCallingUid();
616        String missingPerm = null;
617        int strongestMode = MODE_ALLOWED;
618
619        if (UserHandle.isSameApp(uid, mMyUid)) {
620            return MODE_ALLOWED;
621        }
622
623        if (mExported && checkUser(pid, uid, context)) {
624            final String componentPerm = getWritePermission();
625            if (componentPerm != null) {
626                final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken);
627                if (mode == MODE_ALLOWED) {
628                    return MODE_ALLOWED;
629                } else {
630                    missingPerm = componentPerm;
631                    strongestMode = Math.max(strongestMode, mode);
632                }
633            }
634
635            // track if unprotected write is allowed; any denied
636            // <path-permission> below removes this ability
637            boolean allowDefaultWrite = (componentPerm == null);
638
639            final PathPermission[] pps = getPathPermissions();
640            if (pps != null) {
641                final String path = uri.getPath();
642                for (PathPermission pp : pps) {
643                    final String pathPerm = pp.getWritePermission();
644                    if (pathPerm != null && pp.match(path)) {
645                        final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken);
646                        if (mode == MODE_ALLOWED) {
647                            return MODE_ALLOWED;
648                        } else {
649                            // any denied <path-permission> means we lose
650                            // default <provider> access.
651                            allowDefaultWrite = false;
652                            missingPerm = pathPerm;
653                            strongestMode = Math.max(strongestMode, mode);
654                        }
655                    }
656                }
657            }
658
659            // if we passed <path-permission> checks above, and no default
660            // <provider> permission, then allow access.
661            if (allowDefaultWrite) return MODE_ALLOWED;
662        }
663
664        // last chance, check against any uri grants
665        if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
666                callerToken) == PERMISSION_GRANTED) {
667            return MODE_ALLOWED;
668        }
669
670        // If the worst denial we found above was ignored, then pass that
671        // ignored through; otherwise we assume it should be a real error below.
672        if (strongestMode == MODE_IGNORED) {
673            return MODE_IGNORED;
674        }
675
676        final String failReason = mExported
677                ? " requires " + missingPerm + ", or grantUriPermission()"
678                : " requires the provider be exported, or grantUriPermission()";
679        throw new SecurityException("Permission Denial: writing "
680                + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid
681                + ", uid=" + uid + failReason);
682    }
683
684    /**
685     * Retrieves the Context this provider is running in.  Only available once
686     * {@link #onCreate} has been called -- this will return {@code null} in the
687     * constructor.
688     */
689    public final @Nullable Context getContext() {
690        return mContext;
691    }
692
693    /**
694     * Set the calling package, returning the current value (or {@code null})
695     * which can be used later to restore the previous state.
696     */
697    private String setCallingPackage(String callingPackage) {
698        final String original = mCallingPackage.get();
699        mCallingPackage.set(callingPackage);
700        return original;
701    }
702
703    /**
704     * Return the package name of the caller that initiated the request being
705     * processed on the current thread. The returned package will have been
706     * verified to belong to the calling UID. Returns {@code null} if not
707     * currently processing a request.
708     * <p>
709     * This will always return {@code null} when processing
710     * {@link #getType(Uri)} or {@link #getStreamTypes(Uri, String)} requests.
711     *
712     * @see Binder#getCallingUid()
713     * @see Context#grantUriPermission(String, Uri, int)
714     * @throws SecurityException if the calling package doesn't belong to the
715     *             calling UID.
716     */
717    public final @Nullable String getCallingPackage() {
718        final String pkg = mCallingPackage.get();
719        if (pkg != null) {
720            mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
721        }
722        return pkg;
723    }
724
725    /**
726     * Change the authorities of the ContentProvider.
727     * This is normally set for you from its manifest information when the provider is first
728     * created.
729     * @hide
730     * @param authorities the semi-colon separated authorities of the ContentProvider.
731     */
732    protected final void setAuthorities(String authorities) {
733        if (authorities != null) {
734            if (authorities.indexOf(';') == -1) {
735                mAuthority = authorities;
736                mAuthorities = null;
737            } else {
738                mAuthority = null;
739                mAuthorities = authorities.split(";");
740            }
741        }
742    }
743
744    /** @hide */
745    protected final boolean matchesOurAuthorities(String authority) {
746        if (mAuthority != null) {
747            return mAuthority.equals(authority);
748        }
749        if (mAuthorities != null) {
750            int length = mAuthorities.length;
751            for (int i = 0; i < length; i++) {
752                if (mAuthorities[i].equals(authority)) return true;
753            }
754        }
755        return false;
756    }
757
758
759    /**
760     * Change the permission required to read data from the content
761     * provider.  This is normally set for you from its manifest information
762     * when the provider is first created.
763     *
764     * @param permission Name of the permission required for read-only access.
765     */
766    protected final void setReadPermission(@Nullable String permission) {
767        mReadPermission = permission;
768    }
769
770    /**
771     * Return the name of the permission required for read-only access to
772     * this content provider.  This method can be called from multiple
773     * threads, as described in
774     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
775     * and Threads</a>.
776     */
777    public final @Nullable String getReadPermission() {
778        return mReadPermission;
779    }
780
781    /**
782     * Change the permission required to read and write data in the content
783     * provider.  This is normally set for you from its manifest information
784     * when the provider is first created.
785     *
786     * @param permission Name of the permission required for read/write access.
787     */
788    protected final void setWritePermission(@Nullable String permission) {
789        mWritePermission = permission;
790    }
791
792    /**
793     * Return the name of the permission required for read/write access to
794     * this content provider.  This method can be called from multiple
795     * threads, as described in
796     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
797     * and Threads</a>.
798     */
799    public final @Nullable String getWritePermission() {
800        return mWritePermission;
801    }
802
803    /**
804     * Change the path-based permission required to read and/or write data in
805     * the content provider.  This is normally set for you from its manifest
806     * information when the provider is first created.
807     *
808     * @param permissions Array of path permission descriptions.
809     */
810    protected final void setPathPermissions(@Nullable PathPermission[] permissions) {
811        mPathPermissions = permissions;
812    }
813
814    /**
815     * Return the path-based permissions required for read and/or write access to
816     * this content provider.  This method can be called from multiple
817     * threads, as described in
818     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
819     * and Threads</a>.
820     */
821    public final @Nullable PathPermission[] getPathPermissions() {
822        return mPathPermissions;
823    }
824
825    /** @hide */
826    public final void setAppOps(int readOp, int writeOp) {
827        if (!mNoPerms) {
828            mTransport.mReadOp = readOp;
829            mTransport.mWriteOp = writeOp;
830        }
831    }
832
833    /** @hide */
834    public AppOpsManager getAppOpsManager() {
835        return mTransport.mAppOpsManager;
836    }
837
838    /**
839     * Implement this to initialize your content provider on startup.
840     * This method is called for all registered content providers on the
841     * application main thread at application launch time.  It must not perform
842     * lengthy operations, or application startup will be delayed.
843     *
844     * <p>You should defer nontrivial initialization (such as opening,
845     * upgrading, and scanning databases) until the content provider is used
846     * (via {@link #query}, {@link #insert}, etc).  Deferred initialization
847     * keeps application startup fast, avoids unnecessary work if the provider
848     * turns out not to be needed, and stops database errors (such as a full
849     * disk) from halting application launch.
850     *
851     * <p>If you use SQLite, {@link android.database.sqlite.SQLiteOpenHelper}
852     * is a helpful utility class that makes it easy to manage databases,
853     * and will automatically defer opening until first use.  If you do use
854     * SQLiteOpenHelper, make sure to avoid calling
855     * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or
856     * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase}
857     * from this method.  (Instead, override
858     * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the
859     * database when it is first opened.)
860     *
861     * @return true if the provider was successfully loaded, false otherwise
862     */
863    public abstract boolean onCreate();
864
865    /**
866     * {@inheritDoc}
867     * This method is always called on the application main thread, and must
868     * not perform lengthy operations.
869     *
870     * <p>The default content provider implementation does nothing.
871     * Override this method to take appropriate action.
872     * (Content providers do not usually care about things like screen
873     * orientation, but may want to know about locale changes.)
874     */
875    public void onConfigurationChanged(Configuration newConfig) {
876    }
877
878    /**
879     * {@inheritDoc}
880     * This method is always called on the application main thread, and must
881     * not perform lengthy operations.
882     *
883     * <p>The default content provider implementation does nothing.
884     * Subclasses may override this method to take appropriate action.
885     */
886    public void onLowMemory() {
887    }
888
889    public void onTrimMemory(int level) {
890    }
891
892    /**
893     * Implement this to handle query requests from clients.
894     * This method can be called from multiple threads, as described in
895     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
896     * and Threads</a>.
897     * <p>
898     * Example client call:<p>
899     * <pre>// Request a specific record.
900     * Cursor managedCursor = managedQuery(
901                ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
902                projection,    // Which columns to return.
903                null,          // WHERE clause.
904                null,          // WHERE clause value substitution
905                People.NAME + " ASC");   // Sort order.</pre>
906     * Example implementation:<p>
907     * <pre>// SQLiteQueryBuilder is a helper class that creates the
908        // proper SQL syntax for us.
909        SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
910
911        // Set the table we're querying.
912        qBuilder.setTables(DATABASE_TABLE_NAME);
913
914        // If the query ends in a specific record number, we're
915        // being asked for a specific record, so set the
916        // WHERE clause in our query.
917        if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
918            qBuilder.appendWhere("_id=" + uri.getPathLeafId());
919        }
920
921        // Make the query.
922        Cursor c = qBuilder.query(mDb,
923                projection,
924                selection,
925                selectionArgs,
926                groupBy,
927                having,
928                sortOrder);
929        c.setNotificationUri(getContext().getContentResolver(), uri);
930        return c;</pre>
931     *
932     * @param uri The URI to query. This will be the full URI sent by the client;
933     *      if the client is requesting a specific record, the URI will end in a record number
934     *      that the implementation should parse and add to a WHERE or HAVING clause, specifying
935     *      that _id value.
936     * @param projection The list of columns to put into the cursor. If
937     *      {@code null} all columns are included.
938     * @param selection A selection criteria to apply when filtering rows.
939     *      If {@code null} then all rows are included.
940     * @param selectionArgs You may include ?s in selection, which will be replaced by
941     *      the values from selectionArgs, in order that they appear in the selection.
942     *      The values will be bound as Strings.
943     * @param sortOrder How the rows in the cursor should be sorted.
944     *      If {@code null} then the provider is free to define the sort order.
945     * @return a Cursor or {@code null}.
946     */
947    public abstract @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
948            @Nullable String selection, @Nullable String[] selectionArgs,
949            @Nullable String sortOrder);
950
951    /**
952     * Implement this to handle query requests from clients with support for cancellation.
953     * This method can be called from multiple threads, as described in
954     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
955     * and Threads</a>.
956     * <p>
957     * Example client call:<p>
958     * <pre>// Request a specific record.
959     * Cursor managedCursor = managedQuery(
960                ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
961                projection,    // Which columns to return.
962                null,          // WHERE clause.
963                null,          // WHERE clause value substitution
964                People.NAME + " ASC");   // Sort order.</pre>
965     * Example implementation:<p>
966     * <pre>// SQLiteQueryBuilder is a helper class that creates the
967        // proper SQL syntax for us.
968        SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
969
970        // Set the table we're querying.
971        qBuilder.setTables(DATABASE_TABLE_NAME);
972
973        // If the query ends in a specific record number, we're
974        // being asked for a specific record, so set the
975        // WHERE clause in our query.
976        if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
977            qBuilder.appendWhere("_id=" + uri.getPathLeafId());
978        }
979
980        // Make the query.
981        Cursor c = qBuilder.query(mDb,
982                projection,
983                selection,
984                selectionArgs,
985                groupBy,
986                having,
987                sortOrder);
988        c.setNotificationUri(getContext().getContentResolver(), uri);
989        return c;</pre>
990     * <p>
991     * If you implement this method then you must also implement the version of
992     * {@link #query(Uri, String[], String, String[], String)} that does not take a cancellation
993     * signal to ensure correct operation on older versions of the Android Framework in
994     * which the cancellation signal overload was not available.
995     *
996     * @param uri The URI to query. This will be the full URI sent by the client;
997     *      if the client is requesting a specific record, the URI will end in a record number
998     *      that the implementation should parse and add to a WHERE or HAVING clause, specifying
999     *      that _id value.
1000     * @param projection The list of columns to put into the cursor. If
1001     *      {@code null} all columns are included.
1002     * @param selection A selection criteria to apply when filtering rows.
1003     *      If {@code null} then all rows are included.
1004     * @param selectionArgs You may include ?s in selection, which will be replaced by
1005     *      the values from selectionArgs, in order that they appear in the selection.
1006     *      The values will be bound as Strings.
1007     * @param sortOrder How the rows in the cursor should be sorted.
1008     *      If {@code null} then the provider is free to define the sort order.
1009     * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if none.
1010     * If the operation is canceled, then {@link OperationCanceledException} will be thrown
1011     * when the query is executed.
1012     * @return a Cursor or {@code null}.
1013     */
1014    public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
1015            @Nullable String selection, @Nullable String[] selectionArgs,
1016            @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) {
1017        return query(uri, projection, selection, selectionArgs, sortOrder);
1018    }
1019
1020    /**
1021     * Implement this to handle requests for the MIME type of the data at the
1022     * given URI.  The returned MIME type should start with
1023     * <code>vnd.android.cursor.item</code> for a single record,
1024     * or <code>vnd.android.cursor.dir/</code> for multiple items.
1025     * This method can be called from multiple threads, as described in
1026     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1027     * and Threads</a>.
1028     *
1029     * <p>Note that there are no permissions needed for an application to
1030     * access this information; if your content provider requires read and/or
1031     * write permissions, or is not exported, all applications can still call
1032     * this method regardless of their access permissions.  This allows them
1033     * to retrieve the MIME type for a URI when dispatching intents.
1034     *
1035     * @param uri the URI to query.
1036     * @return a MIME type string, or {@code null} if there is no type.
1037     */
1038    public abstract @Nullable String getType(@NonNull Uri uri);
1039
1040    /**
1041     * Implement this to support canonicalization of URIs that refer to your
1042     * content provider.  A canonical URI is one that can be transported across
1043     * devices, backup/restore, and other contexts, and still be able to refer
1044     * to the same data item.  Typically this is implemented by adding query
1045     * params to the URI allowing the content provider to verify that an incoming
1046     * canonical URI references the same data as it was originally intended for and,
1047     * if it doesn't, to find that data (if it exists) in the current environment.
1048     *
1049     * <p>For example, if the content provider holds people and a normal URI in it
1050     * is created with a row index into that people database, the cananical representation
1051     * may have an additional query param at the end which specifies the name of the
1052     * person it is intended for.  Later calls into the provider with that URI will look
1053     * up the row of that URI's base index and, if it doesn't match or its entry's
1054     * name doesn't match the name in the query param, perform a query on its database
1055     * to find the correct row to operate on.</p>
1056     *
1057     * <p>If you implement support for canonical URIs, <b>all</b> incoming calls with
1058     * URIs (including this one) must perform this verification and recovery of any
1059     * canonical URIs they receive.  In addition, you must also implement
1060     * {@link #uncanonicalize} to strip the canonicalization of any of these URIs.</p>
1061     *
1062     * <p>The default implementation of this method returns null, indicating that
1063     * canonical URIs are not supported.</p>
1064     *
1065     * @param url The Uri to canonicalize.
1066     *
1067     * @return Return the canonical representation of <var>url</var>, or null if
1068     * canonicalization of that Uri is not supported.
1069     */
1070    public @Nullable Uri canonicalize(@NonNull Uri url) {
1071        return null;
1072    }
1073
1074    /**
1075     * Remove canonicalization from canonical URIs previously returned by
1076     * {@link #canonicalize}.  For example, if your implementation is to add
1077     * a query param to canonicalize a URI, this method can simply trip any
1078     * query params on the URI.  The default implementation always returns the
1079     * same <var>url</var> that was passed in.
1080     *
1081     * @param url The Uri to remove any canonicalization from.
1082     *
1083     * @return Return the non-canonical representation of <var>url</var>, return
1084     * the <var>url</var> as-is if there is nothing to do, or return null if
1085     * the data identified by the canonical representation can not be found in
1086     * the current environment.
1087     */
1088    public @Nullable Uri uncanonicalize(@NonNull Uri url) {
1089        return url;
1090    }
1091
1092    /**
1093     * @hide
1094     * Implementation when a caller has performed an insert on the content
1095     * provider, but that call has been rejected for the operation given
1096     * to {@link #setAppOps(int, int)}.  The default implementation simply
1097     * returns a dummy URI that is the base URI with a 0 path element
1098     * appended.
1099     */
1100    public Uri rejectInsert(Uri uri, ContentValues values) {
1101        // If not allowed, we need to return some reasonable URI.  Maybe the
1102        // content provider should be responsible for this, but for now we
1103        // will just return the base URI with a dummy '0' tagged on to it.
1104        // You shouldn't be able to read if you can't write, anyway, so it
1105        // shouldn't matter much what is returned.
1106        return uri.buildUpon().appendPath("0").build();
1107    }
1108
1109    /**
1110     * Implement this to handle requests to insert a new row.
1111     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
1112     * after inserting.
1113     * This method can be called from multiple threads, as described in
1114     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1115     * and Threads</a>.
1116     * @param uri The content:// URI of the insertion request. This must not be {@code null}.
1117     * @param values A set of column_name/value pairs to add to the database.
1118     *     This must not be {@code null}.
1119     * @return The URI for the newly inserted item.
1120     */
1121    public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values);
1122
1123    /**
1124     * Override this to handle requests to insert a set of new rows, or the
1125     * default implementation will iterate over the values and call
1126     * {@link #insert} on each of them.
1127     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
1128     * after inserting.
1129     * This method can be called from multiple threads, as described in
1130     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1131     * and Threads</a>.
1132     *
1133     * @param uri The content:// URI of the insertion request.
1134     * @param values An array of sets of column_name/value pairs to add to the database.
1135     *    This must not be {@code null}.
1136     * @return The number of values that were inserted.
1137     */
1138    public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
1139        int numValues = values.length;
1140        for (int i = 0; i < numValues; i++) {
1141            insert(uri, values[i]);
1142        }
1143        return numValues;
1144    }
1145
1146    /**
1147     * Implement this to handle requests to delete one or more rows.
1148     * The implementation should apply the selection clause when performing
1149     * deletion, allowing the operation to affect multiple rows in a directory.
1150     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
1151     * after deleting.
1152     * This method can be called from multiple threads, as described in
1153     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1154     * and Threads</a>.
1155     *
1156     * <p>The implementation is responsible for parsing out a row ID at the end
1157     * of the URI, if a specific row is being deleted. That is, the client would
1158     * pass in <code>content://contacts/people/22</code> and the implementation is
1159     * responsible for parsing the record number (22) when creating a SQL statement.
1160     *
1161     * @param uri The full URI to query, including a row ID (if a specific record is requested).
1162     * @param selection An optional restriction to apply to rows when deleting.
1163     * @return The number of rows affected.
1164     * @throws SQLException
1165     */
1166    public abstract int delete(@NonNull Uri uri, @Nullable String selection,
1167            @Nullable String[] selectionArgs);
1168
1169    /**
1170     * Implement this to handle requests to update one or more rows.
1171     * The implementation should update all rows matching the selection
1172     * to set the columns according to the provided values map.
1173     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
1174     * after updating.
1175     * This method can be called from multiple threads, as described in
1176     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1177     * and Threads</a>.
1178     *
1179     * @param uri The URI to query. This can potentially have a record ID if this
1180     * is an update request for a specific record.
1181     * @param values A set of column_name/value pairs to update in the database.
1182     *     This must not be {@code null}.
1183     * @param selection An optional filter to match rows to update.
1184     * @return the number of rows affected.
1185     */
1186    public abstract int update(@NonNull Uri uri, @Nullable ContentValues values,
1187            @Nullable String selection, @Nullable String[] selectionArgs);
1188
1189    /**
1190     * Override this to handle requests to open a file blob.
1191     * The default implementation always throws {@link FileNotFoundException}.
1192     * This method can be called from multiple threads, as described in
1193     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1194     * and Threads</a>.
1195     *
1196     * <p>This method returns a ParcelFileDescriptor, which is returned directly
1197     * to the caller.  This way large data (such as images and documents) can be
1198     * returned without copying the content.
1199     *
1200     * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
1201     * their responsibility to close it when done.  That is, the implementation
1202     * of this method should create a new ParcelFileDescriptor for each call.
1203     * <p>
1204     * If opened with the exclusive "r" or "w" modes, the returned
1205     * ParcelFileDescriptor can be a pipe or socket pair to enable streaming
1206     * of data. Opening with the "rw" or "rwt" modes implies a file on disk that
1207     * supports seeking.
1208     * <p>
1209     * If you need to detect when the returned ParcelFileDescriptor has been
1210     * closed, or if the remote process has crashed or encountered some other
1211     * error, you can use {@link ParcelFileDescriptor#open(File, int,
1212     * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)},
1213     * {@link ParcelFileDescriptor#createReliablePipe()}, or
1214     * {@link ParcelFileDescriptor#createReliableSocketPair()}.
1215     *
1216     * <p class="note">For use in Intents, you will want to implement {@link #getType}
1217     * to return the appropriate MIME type for the data returned here with
1218     * the same URI.  This will allow intent resolution to automatically determine the data MIME
1219     * type and select the appropriate matching targets as part of its operation.</p>
1220     *
1221     * <p class="note">For better interoperability with other applications, it is recommended
1222     * that for any URIs that can be opened, you also support queries on them
1223     * containing at least the columns specified by {@link android.provider.OpenableColumns}.
1224     * You may also want to support other common columns if you have additional meta-data
1225     * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
1226     * in {@link android.provider.MediaStore.MediaColumns}.</p>
1227     *
1228     * @param uri The URI whose file is to be opened.
1229     * @param mode Access mode for the file.  May be "r" for read-only access,
1230     * "rw" for read and write access, or "rwt" for read and write access
1231     * that truncates any existing file.
1232     *
1233     * @return Returns a new ParcelFileDescriptor which you can use to access
1234     * the file.
1235     *
1236     * @throws FileNotFoundException Throws FileNotFoundException if there is
1237     * no file associated with the given URI or the mode is invalid.
1238     * @throws SecurityException Throws SecurityException if the caller does
1239     * not have permission to access the file.
1240     *
1241     * @see #openAssetFile(Uri, String)
1242     * @see #openFileHelper(Uri, String)
1243     * @see #getType(android.net.Uri)
1244     * @see ParcelFileDescriptor#parseMode(String)
1245     */
1246    public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode)
1247            throws FileNotFoundException {
1248        throw new FileNotFoundException("No files supported by provider at "
1249                + uri);
1250    }
1251
1252    /**
1253     * Override this to handle requests to open a file blob.
1254     * The default implementation always throws {@link FileNotFoundException}.
1255     * This method can be called from multiple threads, as described in
1256     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1257     * and Threads</a>.
1258     *
1259     * <p>This method returns a ParcelFileDescriptor, which is returned directly
1260     * to the caller.  This way large data (such as images and documents) can be
1261     * returned without copying the content.
1262     *
1263     * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
1264     * their responsibility to close it when done.  That is, the implementation
1265     * of this method should create a new ParcelFileDescriptor for each call.
1266     * <p>
1267     * If opened with the exclusive "r" or "w" modes, the returned
1268     * ParcelFileDescriptor can be a pipe or socket pair to enable streaming
1269     * of data. Opening with the "rw" or "rwt" modes implies a file on disk that
1270     * supports seeking.
1271     * <p>
1272     * If you need to detect when the returned ParcelFileDescriptor has been
1273     * closed, or if the remote process has crashed or encountered some other
1274     * error, you can use {@link ParcelFileDescriptor#open(File, int,
1275     * android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener)},
1276     * {@link ParcelFileDescriptor#createReliablePipe()}, or
1277     * {@link ParcelFileDescriptor#createReliableSocketPair()}.
1278     *
1279     * <p class="note">For use in Intents, you will want to implement {@link #getType}
1280     * to return the appropriate MIME type for the data returned here with
1281     * the same URI.  This will allow intent resolution to automatically determine the data MIME
1282     * type and select the appropriate matching targets as part of its operation.</p>
1283     *
1284     * <p class="note">For better interoperability with other applications, it is recommended
1285     * that for any URIs that can be opened, you also support queries on them
1286     * containing at least the columns specified by {@link android.provider.OpenableColumns}.
1287     * You may also want to support other common columns if you have additional meta-data
1288     * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
1289     * in {@link android.provider.MediaStore.MediaColumns}.</p>
1290     *
1291     * @param uri The URI whose file is to be opened.
1292     * @param mode Access mode for the file. May be "r" for read-only access,
1293     *            "w" for write-only access, "rw" for read and write access, or
1294     *            "rwt" for read and write access that truncates any existing
1295     *            file.
1296     * @param signal A signal to cancel the operation in progress, or
1297     *            {@code null} if none. For example, if you are downloading a
1298     *            file from the network to service a "rw" mode request, you
1299     *            should periodically call
1300     *            {@link CancellationSignal#throwIfCanceled()} to check whether
1301     *            the client has canceled the request and abort the download.
1302     *
1303     * @return Returns a new ParcelFileDescriptor which you can use to access
1304     * the file.
1305     *
1306     * @throws FileNotFoundException Throws FileNotFoundException if there is
1307     * no file associated with the given URI or the mode is invalid.
1308     * @throws SecurityException Throws SecurityException if the caller does
1309     * not have permission to access the file.
1310     *
1311     * @see #openAssetFile(Uri, String)
1312     * @see #openFileHelper(Uri, String)
1313     * @see #getType(android.net.Uri)
1314     * @see ParcelFileDescriptor#parseMode(String)
1315     */
1316    public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
1317            @Nullable CancellationSignal signal) throws FileNotFoundException {
1318        return openFile(uri, mode);
1319    }
1320
1321    /**
1322     * This is like {@link #openFile}, but can be implemented by providers
1323     * that need to be able to return sub-sections of files, often assets
1324     * inside of their .apk.
1325     * This method can be called from multiple threads, as described in
1326     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1327     * and Threads</a>.
1328     *
1329     * <p>If you implement this, your clients must be able to deal with such
1330     * file slices, either directly with
1331     * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level
1332     * {@link ContentResolver#openInputStream ContentResolver.openInputStream}
1333     * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream}
1334     * methods.
1335     * <p>
1336     * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1337     * streaming of data.
1338     *
1339     * <p class="note">If you are implementing this to return a full file, you
1340     * should create the AssetFileDescriptor with
1341     * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with
1342     * applications that cannot handle sub-sections of files.</p>
1343     *
1344     * <p class="note">For use in Intents, you will want to implement {@link #getType}
1345     * to return the appropriate MIME type for the data returned here with
1346     * the same URI.  This will allow intent resolution to automatically determine the data MIME
1347     * type and select the appropriate matching targets as part of its operation.</p>
1348     *
1349     * <p class="note">For better interoperability with other applications, it is recommended
1350     * that for any URIs that can be opened, you also support queries on them
1351     * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p>
1352     *
1353     * @param uri The URI whose file is to be opened.
1354     * @param mode Access mode for the file.  May be "r" for read-only access,
1355     * "w" for write-only access (erasing whatever data is currently in
1356     * the file), "wa" for write-only access to append to any existing data,
1357     * "rw" for read and write access on any existing data, and "rwt" for read
1358     * and write access that truncates any existing file.
1359     *
1360     * @return Returns a new AssetFileDescriptor which you can use to access
1361     * the file.
1362     *
1363     * @throws FileNotFoundException Throws FileNotFoundException if there is
1364     * no file associated with the given URI or the mode is invalid.
1365     * @throws SecurityException Throws SecurityException if the caller does
1366     * not have permission to access the file.
1367     *
1368     * @see #openFile(Uri, String)
1369     * @see #openFileHelper(Uri, String)
1370     * @see #getType(android.net.Uri)
1371     */
1372    public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode)
1373            throws FileNotFoundException {
1374        ParcelFileDescriptor fd = openFile(uri, mode);
1375        return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
1376    }
1377
1378    /**
1379     * This is like {@link #openFile}, but can be implemented by providers
1380     * that need to be able to return sub-sections of files, often assets
1381     * inside of their .apk.
1382     * This method can be called from multiple threads, as described in
1383     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1384     * and Threads</a>.
1385     *
1386     * <p>If you implement this, your clients must be able to deal with such
1387     * file slices, either directly with
1388     * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level
1389     * {@link ContentResolver#openInputStream ContentResolver.openInputStream}
1390     * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream}
1391     * methods.
1392     * <p>
1393     * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1394     * streaming of data.
1395     *
1396     * <p class="note">If you are implementing this to return a full file, you
1397     * should create the AssetFileDescriptor with
1398     * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with
1399     * applications that cannot handle sub-sections of files.</p>
1400     *
1401     * <p class="note">For use in Intents, you will want to implement {@link #getType}
1402     * to return the appropriate MIME type for the data returned here with
1403     * the same URI.  This will allow intent resolution to automatically determine the data MIME
1404     * type and select the appropriate matching targets as part of its operation.</p>
1405     *
1406     * <p class="note">For better interoperability with other applications, it is recommended
1407     * that for any URIs that can be opened, you also support queries on them
1408     * containing at least the columns specified by {@link android.provider.OpenableColumns}.</p>
1409     *
1410     * @param uri The URI whose file is to be opened.
1411     * @param mode Access mode for the file.  May be "r" for read-only access,
1412     * "w" for write-only access (erasing whatever data is currently in
1413     * the file), "wa" for write-only access to append to any existing data,
1414     * "rw" for read and write access on any existing data, and "rwt" for read
1415     * and write access that truncates any existing file.
1416     * @param signal A signal to cancel the operation in progress, or
1417     *            {@code null} if none. For example, if you are downloading a
1418     *            file from the network to service a "rw" mode request, you
1419     *            should periodically call
1420     *            {@link CancellationSignal#throwIfCanceled()} to check whether
1421     *            the client has canceled the request and abort the download.
1422     *
1423     * @return Returns a new AssetFileDescriptor which you can use to access
1424     * the file.
1425     *
1426     * @throws FileNotFoundException Throws FileNotFoundException if there is
1427     * no file associated with the given URI or the mode is invalid.
1428     * @throws SecurityException Throws SecurityException if the caller does
1429     * not have permission to access the file.
1430     *
1431     * @see #openFile(Uri, String)
1432     * @see #openFileHelper(Uri, String)
1433     * @see #getType(android.net.Uri)
1434     */
1435    public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
1436            @Nullable CancellationSignal signal) throws FileNotFoundException {
1437        return openAssetFile(uri, mode);
1438    }
1439
1440    /**
1441     * Convenience for subclasses that wish to implement {@link #openFile}
1442     * by looking up a column named "_data" at the given URI.
1443     *
1444     * @param uri The URI to be opened.
1445     * @param mode The file mode.  May be "r" for read-only access,
1446     * "w" for write-only access (erasing whatever data is currently in
1447     * the file), "wa" for write-only access to append to any existing data,
1448     * "rw" for read and write access on any existing data, and "rwt" for read
1449     * and write access that truncates any existing file.
1450     *
1451     * @return Returns a new ParcelFileDescriptor that can be used by the
1452     * client to access the file.
1453     */
1454    protected final @NonNull ParcelFileDescriptor openFileHelper(@NonNull Uri uri,
1455            @NonNull String mode) throws FileNotFoundException {
1456        Cursor c = query(uri, new String[]{"_data"}, null, null, null);
1457        int count = (c != null) ? c.getCount() : 0;
1458        if (count != 1) {
1459            // If there is not exactly one result, throw an appropriate
1460            // exception.
1461            if (c != null) {
1462                c.close();
1463            }
1464            if (count == 0) {
1465                throw new FileNotFoundException("No entry for " + uri);
1466            }
1467            throw new FileNotFoundException("Multiple items at " + uri);
1468        }
1469
1470        c.moveToFirst();
1471        int i = c.getColumnIndex("_data");
1472        String path = (i >= 0 ? c.getString(i) : null);
1473        c.close();
1474        if (path == null) {
1475            throw new FileNotFoundException("Column _data not found.");
1476        }
1477
1478        int modeBits = ParcelFileDescriptor.parseMode(mode);
1479        return ParcelFileDescriptor.open(new File(path), modeBits);
1480    }
1481
1482    /**
1483     * Called by a client to determine the types of data streams that this
1484     * content provider supports for the given URI.  The default implementation
1485     * returns {@code null}, meaning no types.  If your content provider stores data
1486     * of a particular type, return that MIME type if it matches the given
1487     * mimeTypeFilter.  If it can perform type conversions, return an array
1488     * of all supported MIME types that match mimeTypeFilter.
1489     *
1490     * @param uri The data in the content provider being queried.
1491     * @param mimeTypeFilter The type of data the client desires.  May be
1492     * a pattern, such as *&#47;* to retrieve all possible data types.
1493     * @return Returns {@code null} if there are no possible data streams for the
1494     * given mimeTypeFilter.  Otherwise returns an array of all available
1495     * concrete MIME types.
1496     *
1497     * @see #getType(Uri)
1498     * @see #openTypedAssetFile(Uri, String, Bundle)
1499     * @see ClipDescription#compareMimeTypes(String, String)
1500     */
1501    public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter) {
1502        return null;
1503    }
1504
1505    /**
1506     * Called by a client to open a read-only stream containing data of a
1507     * particular MIME type.  This is like {@link #openAssetFile(Uri, String)},
1508     * except the file can only be read-only and the content provider may
1509     * perform data conversions to generate data of the desired type.
1510     *
1511     * <p>The default implementation compares the given mimeType against the
1512     * result of {@link #getType(Uri)} and, if they match, simply calls
1513     * {@link #openAssetFile(Uri, String)}.
1514     *
1515     * <p>See {@link ClipData} for examples of the use and implementation
1516     * of this method.
1517     * <p>
1518     * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1519     * streaming of data.
1520     *
1521     * <p class="note">For better interoperability with other applications, it is recommended
1522     * that for any URIs that can be opened, you also support queries on them
1523     * containing at least the columns specified by {@link android.provider.OpenableColumns}.
1524     * You may also want to support other common columns if you have additional meta-data
1525     * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
1526     * in {@link android.provider.MediaStore.MediaColumns}.</p>
1527     *
1528     * @param uri The data in the content provider being queried.
1529     * @param mimeTypeFilter The type of data the client desires.  May be
1530     * a pattern, such as *&#47;*, if the caller does not have specific type
1531     * requirements; in this case the content provider will pick its best
1532     * type matching the pattern.
1533     * @param opts Additional options from the client.  The definitions of
1534     * these are specific to the content provider being called.
1535     *
1536     * @return Returns a new AssetFileDescriptor from which the client can
1537     * read data of the desired type.
1538     *
1539     * @throws FileNotFoundException Throws FileNotFoundException if there is
1540     * no file associated with the given URI or the mode is invalid.
1541     * @throws SecurityException Throws SecurityException if the caller does
1542     * not have permission to access the data.
1543     * @throws IllegalArgumentException Throws IllegalArgumentException if the
1544     * content provider does not support the requested MIME type.
1545     *
1546     * @see #getStreamTypes(Uri, String)
1547     * @see #openAssetFile(Uri, String)
1548     * @see ClipDescription#compareMimeTypes(String, String)
1549     */
1550    public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
1551            @NonNull String mimeTypeFilter, @Nullable Bundle opts) throws FileNotFoundException {
1552        if ("*/*".equals(mimeTypeFilter)) {
1553            // If they can take anything, the untyped open call is good enough.
1554            return openAssetFile(uri, "r");
1555        }
1556        String baseType = getType(uri);
1557        if (baseType != null && ClipDescription.compareMimeTypes(baseType, mimeTypeFilter)) {
1558            // Use old untyped open call if this provider has a type for this
1559            // URI and it matches the request.
1560            return openAssetFile(uri, "r");
1561        }
1562        throw new FileNotFoundException("Can't open " + uri + " as type " + mimeTypeFilter);
1563    }
1564
1565
1566    /**
1567     * Called by a client to open a read-only stream containing data of a
1568     * particular MIME type.  This is like {@link #openAssetFile(Uri, String)},
1569     * except the file can only be read-only and the content provider may
1570     * perform data conversions to generate data of the desired type.
1571     *
1572     * <p>The default implementation compares the given mimeType against the
1573     * result of {@link #getType(Uri)} and, if they match, simply calls
1574     * {@link #openAssetFile(Uri, String)}.
1575     *
1576     * <p>See {@link ClipData} for examples of the use and implementation
1577     * of this method.
1578     * <p>
1579     * The returned AssetFileDescriptor can be a pipe or socket pair to enable
1580     * streaming of data.
1581     *
1582     * <p class="note">For better interoperability with other applications, it is recommended
1583     * that for any URIs that can be opened, you also support queries on them
1584     * containing at least the columns specified by {@link android.provider.OpenableColumns}.
1585     * You may also want to support other common columns if you have additional meta-data
1586     * to supply, such as {@link android.provider.MediaStore.MediaColumns#DATE_ADDED}
1587     * in {@link android.provider.MediaStore.MediaColumns}.</p>
1588     *
1589     * @param uri The data in the content provider being queried.
1590     * @param mimeTypeFilter The type of data the client desires.  May be
1591     * a pattern, such as *&#47;*, if the caller does not have specific type
1592     * requirements; in this case the content provider will pick its best
1593     * type matching the pattern.
1594     * @param opts Additional options from the client.  The definitions of
1595     * these are specific to the content provider being called.
1596     * @param signal A signal to cancel the operation in progress, or
1597     *            {@code null} if none. For example, if you are downloading a
1598     *            file from the network to service a "rw" mode request, you
1599     *            should periodically call
1600     *            {@link CancellationSignal#throwIfCanceled()} to check whether
1601     *            the client has canceled the request and abort the download.
1602     *
1603     * @return Returns a new AssetFileDescriptor from which the client can
1604     * read data of the desired type.
1605     *
1606     * @throws FileNotFoundException Throws FileNotFoundException if there is
1607     * no file associated with the given URI or the mode is invalid.
1608     * @throws SecurityException Throws SecurityException if the caller does
1609     * not have permission to access the data.
1610     * @throws IllegalArgumentException Throws IllegalArgumentException if the
1611     * content provider does not support the requested MIME type.
1612     *
1613     * @see #getStreamTypes(Uri, String)
1614     * @see #openAssetFile(Uri, String)
1615     * @see ClipDescription#compareMimeTypes(String, String)
1616     */
1617    public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
1618            @NonNull String mimeTypeFilter, @Nullable Bundle opts,
1619            @Nullable CancellationSignal signal) throws FileNotFoundException {
1620        return openTypedAssetFile(uri, mimeTypeFilter, opts);
1621    }
1622
1623    /**
1624     * Interface to write a stream of data to a pipe.  Use with
1625     * {@link ContentProvider#openPipeHelper}.
1626     */
1627    public interface PipeDataWriter<T> {
1628        /**
1629         * Called from a background thread to stream data out to a pipe.
1630         * Note that the pipe is blocking, so this thread can block on
1631         * writes for an arbitrary amount of time if the client is slow
1632         * at reading.
1633         *
1634         * @param output The pipe where data should be written.  This will be
1635         * closed for you upon returning from this function.
1636         * @param uri The URI whose data is to be written.
1637         * @param mimeType The desired type of data to be written.
1638         * @param opts Options supplied by caller.
1639         * @param args Your own custom arguments.
1640         */
1641        public void writeDataToPipe(@NonNull ParcelFileDescriptor output, @NonNull Uri uri,
1642                @NonNull String mimeType, @Nullable Bundle opts, @Nullable T args);
1643    }
1644
1645    /**
1646     * A helper function for implementing {@link #openTypedAssetFile}, for
1647     * creating a data pipe and background thread allowing you to stream
1648     * generated data back to the client.  This function returns a new
1649     * ParcelFileDescriptor that should be returned to the caller (the caller
1650     * is responsible for closing it).
1651     *
1652     * @param uri The URI whose data is to be written.
1653     * @param mimeType The desired type of data to be written.
1654     * @param opts Options supplied by caller.
1655     * @param args Your own custom arguments.
1656     * @param func Interface implementing the function that will actually
1657     * stream the data.
1658     * @return Returns a new ParcelFileDescriptor holding the read side of
1659     * the pipe.  This should be returned to the caller for reading; the caller
1660     * is responsible for closing it when done.
1661     */
1662    public @NonNull <T> ParcelFileDescriptor openPipeHelper(final @NonNull Uri uri,
1663            final @NonNull String mimeType, final @Nullable Bundle opts, final @Nullable T args,
1664            final @NonNull PipeDataWriter<T> func) throws FileNotFoundException {
1665        try {
1666            final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
1667
1668            AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() {
1669                @Override
1670                protected Object doInBackground(Object... params) {
1671                    func.writeDataToPipe(fds[1], uri, mimeType, opts, args);
1672                    try {
1673                        fds[1].close();
1674                    } catch (IOException e) {
1675                        Log.w(TAG, "Failure closing pipe", e);
1676                    }
1677                    return null;
1678                }
1679            };
1680            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null);
1681
1682            return fds[0];
1683        } catch (IOException e) {
1684            throw new FileNotFoundException("failure making pipe");
1685        }
1686    }
1687
1688    /**
1689     * Returns true if this instance is a temporary content provider.
1690     * @return true if this instance is a temporary content provider
1691     */
1692    protected boolean isTemporary() {
1693        return false;
1694    }
1695
1696    /**
1697     * Returns the Binder object for this provider.
1698     *
1699     * @return the Binder object for this provider
1700     * @hide
1701     */
1702    public IContentProvider getIContentProvider() {
1703        return mTransport;
1704    }
1705
1706    /**
1707     * Like {@link #attachInfo(Context, android.content.pm.ProviderInfo)}, but for use
1708     * when directly instantiating the provider for testing.
1709     * @hide
1710     */
1711    public void attachInfoForTesting(Context context, ProviderInfo info) {
1712        attachInfo(context, info, true);
1713    }
1714
1715    /**
1716     * After being instantiated, this is called to tell the content provider
1717     * about itself.
1718     *
1719     * @param context The context this provider is running in
1720     * @param info Registered information about this content provider
1721     */
1722    public void attachInfo(Context context, ProviderInfo info) {
1723        attachInfo(context, info, false);
1724    }
1725
1726    private void attachInfo(Context context, ProviderInfo info, boolean testing) {
1727        mNoPerms = testing;
1728
1729        /*
1730         * Only allow it to be set once, so after the content service gives
1731         * this to us clients can't change it.
1732         */
1733        if (mContext == null) {
1734            mContext = context;
1735            if (context != null) {
1736                mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
1737                        Context.APP_OPS_SERVICE);
1738            }
1739            mMyUid = Process.myUid();
1740            if (info != null) {
1741                setReadPermission(info.readPermission);
1742                setWritePermission(info.writePermission);
1743                setPathPermissions(info.pathPermissions);
1744                mExported = info.exported;
1745                mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0;
1746                setAuthorities(info.authority);
1747            }
1748            ContentProvider.this.onCreate();
1749        }
1750    }
1751
1752    /**
1753     * Override this to handle requests to perform a batch of operations, or the
1754     * default implementation will iterate over the operations and call
1755     * {@link ContentProviderOperation#apply} on each of them.
1756     * If all calls to {@link ContentProviderOperation#apply} succeed
1757     * then a {@link ContentProviderResult} array with as many
1758     * elements as there were operations will be returned.  If any of the calls
1759     * fail, it is up to the implementation how many of the others take effect.
1760     * This method can be called from multiple threads, as described in
1761     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
1762     * and Threads</a>.
1763     *
1764     * @param operations the operations to apply
1765     * @return the results of the applications
1766     * @throws OperationApplicationException thrown if any operation fails.
1767     * @see ContentProviderOperation#apply
1768     */
1769    public @NonNull ContentProviderResult[] applyBatch(
1770            @NonNull ArrayList<ContentProviderOperation> operations)
1771                    throws OperationApplicationException {
1772        final int numOperations = operations.size();
1773        final ContentProviderResult[] results = new ContentProviderResult[numOperations];
1774        for (int i = 0; i < numOperations; i++) {
1775            results[i] = operations.get(i).apply(this, results, i);
1776        }
1777        return results;
1778    }
1779
1780    /**
1781     * Call a provider-defined method.  This can be used to implement
1782     * interfaces that are cheaper and/or unnatural for a table-like
1783     * model.
1784     *
1785     * <p class="note"><strong>WARNING:</strong> The framework does no permission checking
1786     * on this entry into the content provider besides the basic ability for the application
1787     * to get access to the provider at all.  For example, it has no idea whether the call
1788     * being executed may read or write data in the provider, so can't enforce those
1789     * individual permissions.  Any implementation of this method <strong>must</strong>
1790     * do its own permission checks on incoming calls to make sure they are allowed.</p>
1791     *
1792     * @param method method name to call.  Opaque to framework, but should not be {@code null}.
1793     * @param arg provider-defined String argument.  May be {@code null}.
1794     * @param extras provider-defined Bundle argument.  May be {@code null}.
1795     * @return provider-defined return value.  May be {@code null}, which is also
1796     *   the default for providers which don't implement any call methods.
1797     */
1798    public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
1799            @Nullable Bundle extras) {
1800        return null;
1801    }
1802
1803    /**
1804     * Implement this to shut down the ContentProvider instance. You can then
1805     * invoke this method in unit tests.
1806     *
1807     * <p>
1808     * Android normally handles ContentProvider startup and shutdown
1809     * automatically. You do not need to start up or shut down a
1810     * ContentProvider. When you invoke a test method on a ContentProvider,
1811     * however, a ContentProvider instance is started and keeps running after
1812     * the test finishes, even if a succeeding test instantiates another
1813     * ContentProvider. A conflict develops because the two instances are
1814     * usually running against the same underlying data source (for example, an
1815     * sqlite database).
1816     * </p>
1817     * <p>
1818     * Implementing shutDown() avoids this conflict by providing a way to
1819     * terminate the ContentProvider. This method can also prevent memory leaks
1820     * from multiple instantiations of the ContentProvider, and it can ensure
1821     * unit test isolation by allowing you to completely clean up the test
1822     * fixture before moving on to the next test.
1823     * </p>
1824     */
1825    public void shutdown() {
1826        Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " +
1827                "connections are gracefully shutdown");
1828    }
1829
1830    /**
1831     * Print the Provider's state into the given stream.  This gets invoked if
1832     * you run "adb shell dumpsys activity provider &lt;provider_component_name&gt;".
1833     *
1834     * @param fd The raw file descriptor that the dump is being sent to.
1835     * @param writer The PrintWriter to which you should dump your state.  This will be
1836     * closed for you after you return.
1837     * @param args additional arguments to the dump request.
1838     */
1839    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1840        writer.println("nothing to dump");
1841    }
1842
1843    /** @hide */
1844    private void validateIncomingUri(Uri uri) throws SecurityException {
1845        String auth = uri.getAuthority();
1846        int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
1847        if (userId != UserHandle.USER_CURRENT && userId != mContext.getUserId()) {
1848            throw new SecurityException("trying to query a ContentProvider in user "
1849                    + mContext.getUserId() + " with a uri belonging to user " + userId);
1850        }
1851        if (!matchesOurAuthorities(getAuthorityWithoutUserId(auth))) {
1852            String message = "The authority of the uri " + uri + " does not match the one of the "
1853                    + "contentProvider: ";
1854            if (mAuthority != null) {
1855                message += mAuthority;
1856            } else {
1857                message += mAuthorities;
1858            }
1859            throw new SecurityException(message);
1860        }
1861    }
1862
1863    /** @hide */
1864    public static int getUserIdFromAuthority(String auth, int defaultUserId) {
1865        if (auth == null) return defaultUserId;
1866        int end = auth.lastIndexOf('@');
1867        if (end == -1) return defaultUserId;
1868        String userIdString = auth.substring(0, end);
1869        try {
1870            return Integer.parseInt(userIdString);
1871        } catch (NumberFormatException e) {
1872            Log.w(TAG, "Error parsing userId.", e);
1873            return UserHandle.USER_NULL;
1874        }
1875    }
1876
1877    /** @hide */
1878    public static int getUserIdFromAuthority(String auth) {
1879        return getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
1880    }
1881
1882    /** @hide */
1883    public static int getUserIdFromUri(Uri uri, int defaultUserId) {
1884        if (uri == null) return defaultUserId;
1885        return getUserIdFromAuthority(uri.getAuthority(), defaultUserId);
1886    }
1887
1888    /** @hide */
1889    public static int getUserIdFromUri(Uri uri) {
1890        return getUserIdFromUri(uri, UserHandle.USER_CURRENT);
1891    }
1892
1893    /**
1894     * Removes userId part from authority string. Expects format:
1895     * userId@some.authority
1896     * If there is no userId in the authority, it symply returns the argument
1897     * @hide
1898     */
1899    public static String getAuthorityWithoutUserId(String auth) {
1900        if (auth == null) return null;
1901        int end = auth.lastIndexOf('@');
1902        return auth.substring(end+1);
1903    }
1904
1905    /** @hide */
1906    public static Uri getUriWithoutUserId(Uri uri) {
1907        if (uri == null) return null;
1908        Uri.Builder builder = uri.buildUpon();
1909        builder.authority(getAuthorityWithoutUserId(uri.getAuthority()));
1910        return builder.build();
1911    }
1912
1913    /** @hide */
1914    public static boolean uriHasUserId(Uri uri) {
1915        if (uri == null) return false;
1916        return !TextUtils.isEmpty(uri.getUserInfo());
1917    }
1918
1919    /** @hide */
1920    public static Uri maybeAddUserId(Uri uri, int userId) {
1921        if (uri == null) return null;
1922        if (userId != UserHandle.USER_CURRENT
1923                && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
1924            if (!uriHasUserId(uri)) {
1925                //We don't add the user Id if there's already one
1926                Uri.Builder builder = uri.buildUpon();
1927                builder.encodedAuthority("" + userId + "@" + uri.getEncodedAuthority());
1928                return builder.build();
1929            }
1930        }
1931        return uri;
1932    }
1933}
1934