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