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