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