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 
17 package android.content;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.compat.annotation.UnsupportedAppUsage;
22 import android.content.res.AssetFileDescriptor;
23 import android.database.BulkCursorDescriptor;
24 import android.database.BulkCursorToCursorAdaptor;
25 import android.database.Cursor;
26 import android.database.CursorToBulkCursorAdaptor;
27 import android.database.DatabaseUtils;
28 import android.database.IContentObserver;
29 import android.net.Uri;
30 import android.os.Binder;
31 import android.os.Bundle;
32 import android.os.IBinder;
33 import android.os.ICancellationSignal;
34 import android.os.Parcel;
35 import android.os.ParcelFileDescriptor;
36 import android.os.Parcelable;
37 import android.os.RemoteCallback;
38 import android.os.RemoteException;
39 
40 import java.io.FileNotFoundException;
41 import java.util.ArrayList;
42 
43 /**
44  * {@hide}
45  */
46 abstract public class ContentProviderNative extends Binder implements IContentProvider {
ContentProviderNative()47     public ContentProviderNative()
48     {
49         attachInterface(this, descriptor);
50     }
51 
52     /**
53      * Cast a Binder object into a content resolver interface, generating
54      * a proxy if needed.
55      */
56     @UnsupportedAppUsage
asInterface(IBinder obj)57     static public IContentProvider asInterface(IBinder obj)
58     {
59         if (obj == null) {
60             return null;
61         }
62         IContentProvider in =
63             (IContentProvider)obj.queryLocalInterface(descriptor);
64         if (in != null) {
65             return in;
66         }
67 
68         return new ContentProviderProxy(obj);
69     }
70 
71     /**
72      * Gets the name of the content provider.
73      * Should probably be part of the {@link IContentProvider} interface.
74      * @return The content provider name.
75      */
getProviderName()76     public abstract String getProviderName();
77 
78     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)79     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
80             throws RemoteException {
81         try {
82             switch (code) {
83                 case QUERY_TRANSACTION:
84                 {
85                     data.enforceInterface(IContentProvider.descriptor);
86 
87                     AttributionSource attributionSource = AttributionSource.CREATOR
88                             .createFromParcel(data);
89                     Uri url = Uri.CREATOR.createFromParcel(data);
90 
91                     // String[] projection
92                     int num = data.readInt();
93                     String[] projection = null;
94                     if (num > 0) {
95                         projection = new String[num];
96                         for (int i = 0; i < num; i++) {
97                             projection[i] = data.readString();
98                         }
99                     }
100 
101                     Bundle queryArgs = data.readBundle();
102                     IContentObserver observer = IContentObserver.Stub.asInterface(
103                             data.readStrongBinder());
104                     ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
105                             data.readStrongBinder());
106 
107                     Cursor cursor = query(attributionSource, url, projection, queryArgs,
108                             cancellationSignal);
109                     if (cursor != null) {
110                         CursorToBulkCursorAdaptor adaptor = null;
111 
112                         try {
113                             adaptor = new CursorToBulkCursorAdaptor(cursor, observer,
114                                     getProviderName());
115                             cursor = null;
116 
117                             BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor();
118                             adaptor = null;
119 
120                             reply.writeNoException();
121                             reply.writeInt(1);
122                             d.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
123                         } finally {
124                             // Close cursor if an exception was thrown while constructing the adaptor.
125                             if (adaptor != null) {
126                                 adaptor.close();
127                             }
128                             if (cursor != null) {
129                                 cursor.close();
130                             }
131                         }
132                     } else {
133                         reply.writeNoException();
134                         reply.writeInt(0);
135                     }
136 
137                     return true;
138                 }
139 
140                 case GET_TYPE_TRANSACTION:
141                 {
142                     data.enforceInterface(IContentProvider.descriptor);
143                     Uri url = Uri.CREATOR.createFromParcel(data);
144                     String type = getType(url);
145                     reply.writeNoException();
146                     reply.writeString(type);
147 
148                     return true;
149                 }
150 
151                 case GET_TYPE_ASYNC_TRANSACTION: {
152                     data.enforceInterface(IContentProvider.descriptor);
153                     Uri url = Uri.CREATOR.createFromParcel(data);
154                     RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
155                     getTypeAsync(url, callback);
156                     return true;
157                 }
158 
159                 case INSERT_TRANSACTION:
160                 {
161                     data.enforceInterface(IContentProvider.descriptor);
162                     AttributionSource attributionSource = AttributionSource.CREATOR
163                             .createFromParcel(data);
164                     Uri url = Uri.CREATOR.createFromParcel(data);
165                     ContentValues values = ContentValues.CREATOR.createFromParcel(data);
166                     Bundle extras = data.readBundle();
167 
168                     Uri out = insert(attributionSource, url, values, extras);
169                     reply.writeNoException();
170                     Uri.writeToParcel(reply, out);
171                     return true;
172                 }
173 
174                 case BULK_INSERT_TRANSACTION:
175                 {
176                     data.enforceInterface(IContentProvider.descriptor);
177                     AttributionSource attributionSource = AttributionSource.CREATOR
178                             .createFromParcel(data);
179                     Uri url = Uri.CREATOR.createFromParcel(data);
180                     ContentValues[] values = data.createTypedArray(ContentValues.CREATOR);
181 
182                     int count = bulkInsert(attributionSource, url, values);
183                     reply.writeNoException();
184                     reply.writeInt(count);
185                     return true;
186                 }
187 
188                 case APPLY_BATCH_TRANSACTION:
189                 {
190                     data.enforceInterface(IContentProvider.descriptor);
191                     AttributionSource attributionSource = AttributionSource.CREATOR
192                             .createFromParcel(data);
193                     String authority = data.readString();
194                     final int numOperations = data.readInt();
195                     final ArrayList<ContentProviderOperation> operations =
196                             new ArrayList<>(numOperations);
197                     for (int i = 0; i < numOperations; i++) {
198                         operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
199                     }
200                     final ContentProviderResult[] results = applyBatch(attributionSource,
201                             authority, operations);
202                     reply.writeNoException();
203                     reply.writeTypedArray(results, 0);
204                     return true;
205                 }
206 
207                 case DELETE_TRANSACTION:
208                 {
209                     data.enforceInterface(IContentProvider.descriptor);
210                     AttributionSource attributionSource = AttributionSource.CREATOR
211                             .createFromParcel(data);
212                     Uri url = Uri.CREATOR.createFromParcel(data);
213                     Bundle extras = data.readBundle();
214 
215                     int count = delete(attributionSource, url, extras);
216 
217                     reply.writeNoException();
218                     reply.writeInt(count);
219                     return true;
220                 }
221 
222                 case UPDATE_TRANSACTION:
223                 {
224                     data.enforceInterface(IContentProvider.descriptor);
225                     AttributionSource attributionSource = AttributionSource.CREATOR
226                             .createFromParcel(data);
227                     Uri url = Uri.CREATOR.createFromParcel(data);
228                     ContentValues values = ContentValues.CREATOR.createFromParcel(data);
229                     Bundle extras = data.readBundle();
230 
231                     int count = update(attributionSource, url, values, extras);
232 
233                     reply.writeNoException();
234                     reply.writeInt(count);
235                     return true;
236                 }
237 
238                 case OPEN_FILE_TRANSACTION:
239                 {
240                     data.enforceInterface(IContentProvider.descriptor);
241                     AttributionSource attributionSource = AttributionSource.CREATOR
242                             .createFromParcel(data);
243                     Uri url = Uri.CREATOR.createFromParcel(data);
244                     String mode = data.readString();
245                     ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
246                             data.readStrongBinder());
247 
248                     ParcelFileDescriptor fd;
249                     fd = openFile(attributionSource, url, mode, signal);
250                     reply.writeNoException();
251                     if (fd != null) {
252                         reply.writeInt(1);
253                         fd.writeToParcel(reply,
254                                 Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
255                     } else {
256                         reply.writeInt(0);
257                     }
258                     return true;
259                 }
260 
261                 case OPEN_ASSET_FILE_TRANSACTION:
262                 {
263                     data.enforceInterface(IContentProvider.descriptor);
264                     AttributionSource attributionSource = AttributionSource.CREATOR
265                             .createFromParcel(data);
266                     Uri url = Uri.CREATOR.createFromParcel(data);
267                     String mode = data.readString();
268                     ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
269                             data.readStrongBinder());
270 
271                     AssetFileDescriptor fd;
272                     fd = openAssetFile(attributionSource, url, mode, signal);
273                     reply.writeNoException();
274                     if (fd != null) {
275                         reply.writeInt(1);
276                         fd.writeToParcel(reply,
277                                 Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
278                     } else {
279                         reply.writeInt(0);
280                     }
281                     return true;
282                 }
283 
284                 case CALL_TRANSACTION:
285                 {
286                     data.enforceInterface(IContentProvider.descriptor);
287 
288                     AttributionSource attributionSource = AttributionSource.CREATOR
289                             .createFromParcel(data);
290                     String authority = data.readString();
291                     String method = data.readString();
292                     String stringArg = data.readString();
293                     Bundle extras = data.readBundle();
294 
295                     Bundle responseBundle = call(attributionSource, authority, method,
296                             stringArg, extras);
297 
298                     reply.writeNoException();
299                     reply.writeBundle(responseBundle);
300                     return true;
301                 }
302 
303                 case GET_STREAM_TYPES_TRANSACTION:
304                 {
305                     data.enforceInterface(IContentProvider.descriptor);
306                     Uri url = Uri.CREATOR.createFromParcel(data);
307                     String mimeTypeFilter = data.readString();
308                     String[] types = getStreamTypes(url, mimeTypeFilter);
309                     reply.writeNoException();
310                     reply.writeStringArray(types);
311 
312                     return true;
313                 }
314 
315                 case OPEN_TYPED_ASSET_FILE_TRANSACTION:
316                 {
317                     data.enforceInterface(IContentProvider.descriptor);
318                     AttributionSource attributionSource = AttributionSource.CREATOR
319                             .createFromParcel(data);
320                     Uri url = Uri.CREATOR.createFromParcel(data);
321                     String mimeType = data.readString();
322                     Bundle opts = data.readBundle();
323                     ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
324                             data.readStrongBinder());
325 
326                     AssetFileDescriptor fd;
327                     fd = openTypedAssetFile(attributionSource, url, mimeType, opts, signal);
328                     reply.writeNoException();
329                     if (fd != null) {
330                         reply.writeInt(1);
331                         fd.writeToParcel(reply,
332                                 Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
333                     } else {
334                         reply.writeInt(0);
335                     }
336                     return true;
337                 }
338 
339                 case CREATE_CANCELATION_SIGNAL_TRANSACTION:
340                 {
341                     data.enforceInterface(IContentProvider.descriptor);
342 
343                     ICancellationSignal cancellationSignal = createCancellationSignal();
344                     reply.writeNoException();
345                     reply.writeStrongBinder(cancellationSignal.asBinder());
346                     return true;
347                 }
348 
349                 case CANONICALIZE_TRANSACTION:
350                 {
351                     data.enforceInterface(IContentProvider.descriptor);
352                     AttributionSource attributionSource = AttributionSource.CREATOR
353                             .createFromParcel(data);
354                     Uri url = Uri.CREATOR.createFromParcel(data);
355 
356                     Uri out = canonicalize(attributionSource, url);
357                     reply.writeNoException();
358                     Uri.writeToParcel(reply, out);
359                     return true;
360                 }
361 
362                 case CANONICALIZE_ASYNC_TRANSACTION: {
363                     data.enforceInterface(IContentProvider.descriptor);
364                     AttributionSource attributionSource = AttributionSource.CREATOR
365                             .createFromParcel(data);
366                     Uri uri = Uri.CREATOR.createFromParcel(data);
367                     RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
368                     canonicalizeAsync(attributionSource, uri, callback);
369                     return true;
370                 }
371 
372                 case UNCANONICALIZE_TRANSACTION:
373                 {
374                     data.enforceInterface(IContentProvider.descriptor);
375                     AttributionSource attributionSource = AttributionSource.CREATOR
376                             .createFromParcel(data);
377                     Uri url = Uri.CREATOR.createFromParcel(data);
378 
379                     Uri out = uncanonicalize(attributionSource, url);
380                     reply.writeNoException();
381                     Uri.writeToParcel(reply, out);
382                     return true;
383                 }
384 
385                 case UNCANONICALIZE_ASYNC_TRANSACTION: {
386                     data.enforceInterface(IContentProvider.descriptor);
387                     AttributionSource attributionSource = AttributionSource.CREATOR
388                             .createFromParcel(data);
389                     Uri uri = Uri.CREATOR.createFromParcel(data);
390                     RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
391                     uncanonicalizeAsync(attributionSource, uri, callback);
392                     return true;
393                 }
394 
395                 case REFRESH_TRANSACTION: {
396                     data.enforceInterface(IContentProvider.descriptor);
397                     AttributionSource attributionSource = AttributionSource.CREATOR
398                             .createFromParcel(data);
399                     Uri url = Uri.CREATOR.createFromParcel(data);
400                     Bundle extras = data.readBundle();
401                     ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
402                             data.readStrongBinder());
403 
404                     boolean out = refresh(attributionSource, url, extras, signal);
405                     reply.writeNoException();
406                     reply.writeInt(out ? 0 : -1);
407                     return true;
408                 }
409 
410                 case CHECK_URI_PERMISSION_TRANSACTION: {
411                     data.enforceInterface(IContentProvider.descriptor);
412                     AttributionSource attributionSource = AttributionSource.CREATOR
413                             .createFromParcel(data);
414                     Uri uri = Uri.CREATOR.createFromParcel(data);
415                     int uid = data.readInt();
416                     int modeFlags = data.readInt();
417 
418                     int out = checkUriPermission(attributionSource, uri, uid, modeFlags);
419                     reply.writeNoException();
420                     reply.writeInt(out);
421                     return true;
422                 }
423             }
424         } catch (Exception e) {
425             DatabaseUtils.writeExceptionToParcel(reply, e);
426             return true;
427         }
428 
429         return super.onTransact(code, data, reply, flags);
430     }
431 
432     @Override
asBinder()433     public IBinder asBinder()
434     {
435         return this;
436     }
437 }
438 
439 
440 final class ContentProviderProxy implements IContentProvider
441 {
ContentProviderProxy(IBinder remote)442     public ContentProviderProxy(IBinder remote)
443     {
444         mRemote = remote;
445     }
446 
447     @Override
asBinder()448     public IBinder asBinder()
449     {
450         return mRemote;
451     }
452 
453     @Override
query(@onNull AttributionSource attributionSource, Uri url, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)454     public Cursor query(@NonNull AttributionSource attributionSource, Uri url,
455             @Nullable String[] projection, @Nullable Bundle queryArgs,
456             @Nullable ICancellationSignal cancellationSignal)
457             throws RemoteException {
458         BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
459         Parcel data = Parcel.obtain();
460         Parcel reply = Parcel.obtain();
461         try {
462             data.writeInterfaceToken(IContentProvider.descriptor);
463 
464             attributionSource.writeToParcel(data, 0);
465             url.writeToParcel(data, 0);
466             int length = 0;
467             if (projection != null) {
468                 length = projection.length;
469             }
470             data.writeInt(length);
471             for (int i = 0; i < length; i++) {
472                 data.writeString(projection[i]);
473             }
474             data.writeBundle(queryArgs);
475             data.writeStrongBinder(adaptor.getObserver().asBinder());
476             data.writeStrongBinder(
477                     cancellationSignal != null ? cancellationSignal.asBinder() : null);
478 
479             mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
480 
481             DatabaseUtils.readExceptionFromParcel(reply);
482 
483             if (reply.readInt() != 0) {
484                 BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
485                 Binder.copyAllowBlocking(mRemote, (d.cursor != null) ? d.cursor.asBinder() : null);
486                 adaptor.initialize(d);
487             } else {
488                 adaptor.close();
489                 adaptor = null;
490             }
491             return adaptor;
492         } catch (RemoteException ex) {
493             adaptor.close();
494             throw ex;
495         } catch (RuntimeException ex) {
496             adaptor.close();
497             throw ex;
498         } finally {
499             data.recycle();
500             reply.recycle();
501         }
502     }
503 
504     @Override
getType(Uri url)505     public String getType(Uri url) throws RemoteException
506     {
507         Parcel data = Parcel.obtain();
508         Parcel reply = Parcel.obtain();
509         try {
510             data.writeInterfaceToken(IContentProvider.descriptor);
511 
512             url.writeToParcel(data, 0);
513 
514             mRemote.transact(IContentProvider.GET_TYPE_TRANSACTION, data, reply, 0);
515 
516             DatabaseUtils.readExceptionFromParcel(reply);
517             String out = reply.readString();
518             return out;
519         } finally {
520             data.recycle();
521             reply.recycle();
522         }
523     }
524 
525     @Override
getTypeAsync(Uri uri, RemoteCallback callback)526     /* oneway */ public void getTypeAsync(Uri uri, RemoteCallback callback) throws RemoteException {
527         Parcel data = Parcel.obtain();
528         try {
529             data.writeInterfaceToken(IContentProvider.descriptor);
530 
531             uri.writeToParcel(data, 0);
532             callback.writeToParcel(data, 0);
533 
534             mRemote.transact(IContentProvider.GET_TYPE_ASYNC_TRANSACTION, data, null,
535                     IBinder.FLAG_ONEWAY);
536         } finally {
537             data.recycle();
538         }
539     }
540 
541     @Override
insert(@onNull AttributionSource attributionSource, Uri url, ContentValues values, Bundle extras)542     public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
543             ContentValues values, Bundle extras) throws RemoteException
544     {
545         Parcel data = Parcel.obtain();
546         Parcel reply = Parcel.obtain();
547         try {
548             data.writeInterfaceToken(IContentProvider.descriptor);
549 
550             attributionSource.writeToParcel(data, 0);
551             url.writeToParcel(data, 0);
552             values.writeToParcel(data, 0);
553             data.writeBundle(extras);
554 
555             mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
556 
557             DatabaseUtils.readExceptionFromParcel(reply);
558             Uri out = Uri.CREATOR.createFromParcel(reply);
559             return out;
560         } finally {
561             data.recycle();
562             reply.recycle();
563         }
564     }
565 
566     @Override
bulkInsert(@onNull AttributionSource attributionSource, Uri url, ContentValues[] values)567     public int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
568             ContentValues[] values) throws RemoteException {
569         Parcel data = Parcel.obtain();
570         Parcel reply = Parcel.obtain();
571         try {
572             data.writeInterfaceToken(IContentProvider.descriptor);
573 
574             attributionSource.writeToParcel(data, 0);
575             url.writeToParcel(data, 0);
576             data.writeTypedArray(values, 0);
577 
578             mRemote.transact(IContentProvider.BULK_INSERT_TRANSACTION, data, reply, 0);
579 
580             DatabaseUtils.readExceptionFromParcel(reply);
581             int count = reply.readInt();
582             return count;
583         } finally {
584             data.recycle();
585             reply.recycle();
586         }
587     }
588 
589     @Override
applyBatch(@onNull AttributionSource attributionSource, String authority, ArrayList<ContentProviderOperation> operations)590     public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
591             String authority, ArrayList<ContentProviderOperation> operations)
592             throws RemoteException, OperationApplicationException {
593         Parcel data = Parcel.obtain();
594         Parcel reply = Parcel.obtain();
595         try {
596             data.writeInterfaceToken(IContentProvider.descriptor);
597             attributionSource.writeToParcel(data, 0);
598             data.writeString(authority);
599             data.writeInt(operations.size());
600             for (ContentProviderOperation operation : operations) {
601                 operation.writeToParcel(data, 0);
602             }
603             mRemote.transact(IContentProvider.APPLY_BATCH_TRANSACTION, data, reply, 0);
604 
605             DatabaseUtils.readExceptionWithOperationApplicationExceptionFromParcel(reply);
606             final ContentProviderResult[] results =
607                     reply.createTypedArray(ContentProviderResult.CREATOR);
608             return results;
609         } finally {
610             data.recycle();
611             reply.recycle();
612         }
613     }
614 
615     @Override
delete(@onNull AttributionSource attributionSource, Uri url, Bundle extras)616     public int delete(@NonNull AttributionSource attributionSource, Uri url, Bundle extras)
617             throws RemoteException {
618         Parcel data = Parcel.obtain();
619         Parcel reply = Parcel.obtain();
620         try {
621             data.writeInterfaceToken(IContentProvider.descriptor);
622 
623             attributionSource.writeToParcel(data, 0);
624             url.writeToParcel(data, 0);
625             data.writeBundle(extras);
626 
627             mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
628 
629             DatabaseUtils.readExceptionFromParcel(reply);
630             int count = reply.readInt();
631             return count;
632         } finally {
633             data.recycle();
634             reply.recycle();
635         }
636     }
637 
638     @Override
update(@onNull AttributionSource attributionSource, Uri url, ContentValues values, Bundle extras)639     public int update(@NonNull AttributionSource attributionSource, Uri url,
640             ContentValues values, Bundle extras) throws RemoteException {
641         Parcel data = Parcel.obtain();
642         Parcel reply = Parcel.obtain();
643         try {
644             data.writeInterfaceToken(IContentProvider.descriptor);
645 
646             attributionSource.writeToParcel(data, 0);
647             url.writeToParcel(data, 0);
648             values.writeToParcel(data, 0);
649             data.writeBundle(extras);
650 
651             mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
652 
653             DatabaseUtils.readExceptionFromParcel(reply);
654             int count = reply.readInt();
655             return count;
656         } finally {
657             data.recycle();
658             reply.recycle();
659         }
660     }
661 
662     @Override
openFile(@onNull AttributionSource attributionSource, Uri url, String mode, ICancellationSignal signal)663     public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource, Uri url,
664             String mode, ICancellationSignal signal)
665             throws RemoteException, FileNotFoundException {
666         Parcel data = Parcel.obtain();
667         Parcel reply = Parcel.obtain();
668         try {
669             data.writeInterfaceToken(IContentProvider.descriptor);
670 
671             attributionSource.writeToParcel(data, 0);
672             url.writeToParcel(data, 0);
673             data.writeString(mode);
674             data.writeStrongBinder(signal != null ? signal.asBinder() : null);
675 
676             mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
677 
678             DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
679             int has = reply.readInt();
680             ParcelFileDescriptor fd = has != 0 ? ParcelFileDescriptor.CREATOR
681                     .createFromParcel(reply) : null;
682             return fd;
683         } finally {
684             data.recycle();
685             reply.recycle();
686         }
687     }
688 
689     @Override
openAssetFile(@onNull AttributionSource attributionSource, Uri url, String mode, ICancellationSignal signal)690     public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
691             Uri url, String mode, ICancellationSignal signal)
692             throws RemoteException, FileNotFoundException {
693         Parcel data = Parcel.obtain();
694         Parcel reply = Parcel.obtain();
695         try {
696             data.writeInterfaceToken(IContentProvider.descriptor);
697 
698             attributionSource.writeToParcel(data, 0);
699             url.writeToParcel(data, 0);
700             data.writeString(mode);
701             data.writeStrongBinder(signal != null ? signal.asBinder() : null);
702 
703             mRemote.transact(IContentProvider.OPEN_ASSET_FILE_TRANSACTION, data, reply, 0);
704 
705             DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
706             int has = reply.readInt();
707             AssetFileDescriptor fd = has != 0
708                     ? AssetFileDescriptor.CREATOR.createFromParcel(reply) : null;
709             return fd;
710         } finally {
711             data.recycle();
712             reply.recycle();
713         }
714     }
715 
716     @Override
call(@onNull AttributionSource attributionSource, String authority, String method, String request, Bundle extras)717     public Bundle call(@NonNull AttributionSource attributionSource, String authority,
718             String method, String request, Bundle extras) throws RemoteException {
719         Parcel data = Parcel.obtain();
720         Parcel reply = Parcel.obtain();
721         try {
722             data.writeInterfaceToken(IContentProvider.descriptor);
723 
724             attributionSource.writeToParcel(data, 0);
725             data.writeString(authority);
726             data.writeString(method);
727             data.writeString(request);
728             data.writeBundle(extras);
729 
730             mRemote.transact(IContentProvider.CALL_TRANSACTION, data, reply, 0);
731 
732             DatabaseUtils.readExceptionFromParcel(reply);
733             Bundle bundle = reply.readBundle();
734             return bundle;
735         } finally {
736             data.recycle();
737             reply.recycle();
738         }
739     }
740 
741     @Override
getStreamTypes(Uri url, String mimeTypeFilter)742     public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException
743     {
744         Parcel data = Parcel.obtain();
745         Parcel reply = Parcel.obtain();
746         try {
747             data.writeInterfaceToken(IContentProvider.descriptor);
748 
749             url.writeToParcel(data, 0);
750             data.writeString(mimeTypeFilter);
751 
752             mRemote.transact(IContentProvider.GET_STREAM_TYPES_TRANSACTION, data, reply, 0);
753 
754             DatabaseUtils.readExceptionFromParcel(reply);
755             String[] out = reply.createStringArray();
756             return out;
757         } finally {
758             data.recycle();
759             reply.recycle();
760         }
761     }
762 
763     @Override
openTypedAssetFile(@onNull AttributionSource attributionSource, Uri url, String mimeType, Bundle opts, ICancellationSignal signal)764     public AssetFileDescriptor openTypedAssetFile(@NonNull AttributionSource attributionSource,
765             Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
766             throws RemoteException, FileNotFoundException {
767         Parcel data = Parcel.obtain();
768         Parcel reply = Parcel.obtain();
769         try {
770             data.writeInterfaceToken(IContentProvider.descriptor);
771 
772             attributionSource.writeToParcel(data, 0);
773             url.writeToParcel(data, 0);
774             data.writeString(mimeType);
775             data.writeBundle(opts);
776             data.writeStrongBinder(signal != null ? signal.asBinder() : null);
777 
778             mRemote.transact(IContentProvider.OPEN_TYPED_ASSET_FILE_TRANSACTION, data, reply, 0);
779 
780             DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
781             int has = reply.readInt();
782             AssetFileDescriptor fd = has != 0
783                     ? AssetFileDescriptor.CREATOR.createFromParcel(reply) : null;
784             return fd;
785         } finally {
786             data.recycle();
787             reply.recycle();
788         }
789     }
790 
791     @Override
createCancellationSignal()792     public ICancellationSignal createCancellationSignal() throws RemoteException {
793         Parcel data = Parcel.obtain();
794         Parcel reply = Parcel.obtain();
795         try {
796             data.writeInterfaceToken(IContentProvider.descriptor);
797 
798             mRemote.transact(IContentProvider.CREATE_CANCELATION_SIGNAL_TRANSACTION,
799                     data, reply, 0);
800 
801             DatabaseUtils.readExceptionFromParcel(reply);
802             ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
803                     reply.readStrongBinder());
804             return cancellationSignal;
805         } finally {
806             data.recycle();
807             reply.recycle();
808         }
809     }
810 
811     @Override
canonicalize(@onNull AttributionSource attributionSource, Uri url)812     public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri url)
813             throws RemoteException {
814         Parcel data = Parcel.obtain();
815         Parcel reply = Parcel.obtain();
816         try {
817             data.writeInterfaceToken(IContentProvider.descriptor);
818 
819             attributionSource.writeToParcel(data, 0);
820             url.writeToParcel(data, 0);
821 
822             mRemote.transact(IContentProvider.CANONICALIZE_TRANSACTION, data, reply, 0);
823 
824             DatabaseUtils.readExceptionFromParcel(reply);
825             Uri out = Uri.CREATOR.createFromParcel(reply);
826             return out;
827         } finally {
828             data.recycle();
829             reply.recycle();
830         }
831     }
832 
833     @Override
canonicalizeAsync(@onNull AttributionSource attributionSource, Uri uri, RemoteCallback callback)834     /* oneway */ public void canonicalizeAsync(@NonNull AttributionSource attributionSource,
835             Uri uri, RemoteCallback callback) throws RemoteException {
836         Parcel data = Parcel.obtain();
837         try {
838             data.writeInterfaceToken(IContentProvider.descriptor);
839 
840             attributionSource.writeToParcel(data, 0);
841             uri.writeToParcel(data, 0);
842             callback.writeToParcel(data, 0);
843 
844             mRemote.transact(IContentProvider.CANONICALIZE_ASYNC_TRANSACTION, data, null,
845                     Binder.FLAG_ONEWAY);
846         } finally {
847             data.recycle();
848         }
849     }
850 
851     @Override
uncanonicalize(@onNull AttributionSource attributionSource, Uri url)852     public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri url)
853             throws RemoteException {
854         Parcel data = Parcel.obtain();
855         Parcel reply = Parcel.obtain();
856         try {
857             data.writeInterfaceToken(IContentProvider.descriptor);
858 
859             attributionSource.writeToParcel(data, 0);
860             url.writeToParcel(data, 0);
861 
862             mRemote.transact(IContentProvider.UNCANONICALIZE_TRANSACTION, data, reply, 0);
863 
864             DatabaseUtils.readExceptionFromParcel(reply);
865             Uri out = Uri.CREATOR.createFromParcel(reply);
866             return out;
867         } finally {
868             data.recycle();
869             reply.recycle();
870         }
871     }
872 
873     @Override
uncanonicalizeAsync(@onNull AttributionSource attributionSource, Uri uri, RemoteCallback callback)874     /* oneway */ public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource,
875             Uri uri, RemoteCallback callback) throws RemoteException {
876         Parcel data = Parcel.obtain();
877         try {
878             data.writeInterfaceToken(IContentProvider.descriptor);
879 
880             attributionSource.writeToParcel(data, 0);
881             uri.writeToParcel(data, 0);
882             callback.writeToParcel(data, 0);
883 
884             mRemote.transact(IContentProvider.UNCANONICALIZE_ASYNC_TRANSACTION, data, null,
885                     Binder.FLAG_ONEWAY);
886         } finally {
887             data.recycle();
888         }
889     }
890 
891     @Override
refresh(@onNull AttributionSource attributionSource, Uri url, Bundle extras, ICancellationSignal signal)892     public boolean refresh(@NonNull AttributionSource attributionSource, Uri url, Bundle extras,
893             ICancellationSignal signal) throws RemoteException {
894         Parcel data = Parcel.obtain();
895         Parcel reply = Parcel.obtain();
896         try {
897             data.writeInterfaceToken(IContentProvider.descriptor);
898 
899             attributionSource.writeToParcel(data, 0);
900             url.writeToParcel(data, 0);
901             data.writeBundle(extras);
902             data.writeStrongBinder(signal != null ? signal.asBinder() : null);
903 
904             mRemote.transact(IContentProvider.REFRESH_TRANSACTION, data, reply, 0);
905 
906             DatabaseUtils.readExceptionFromParcel(reply);
907             int success = reply.readInt();
908             return (success == 0);
909         } finally {
910             data.recycle();
911             reply.recycle();
912         }
913     }
914 
915     @Override
checkUriPermission(@onNull AttributionSource attributionSource, Uri url, int uid, int modeFlags)916     public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri url, int uid,
917             int modeFlags) throws RemoteException {
918         Parcel data = Parcel.obtain();
919         Parcel reply = Parcel.obtain();
920         try {
921             data.writeInterfaceToken(IContentProvider.descriptor);
922 
923             attributionSource.writeToParcel(data, 0);
924             url.writeToParcel(data, 0);
925             data.writeInt(uid);
926             data.writeInt(modeFlags);
927 
928             mRemote.transact(IContentProvider.CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0);
929 
930             DatabaseUtils.readExceptionFromParcel(reply);
931             return reply.readInt();
932         } finally {
933             data.recycle();
934             reply.recycle();
935         }
936     }
937 
938     @UnsupportedAppUsage
939     private IBinder mRemote;
940 }
941