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