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.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 { ContentProviderNative()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 asInterface(IBinder obj)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 */ getProviderName()74 public abstract String getProviderName(); 75 76 @Override onTransact(int code, Parcel data, Parcel reply, int flags)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 asBinder()376 public IBinder asBinder() 377 { 378 return this; 379 } 380 } 381 382 383 final class ContentProviderProxy implements IContentProvider 384 { ContentProviderProxy(IBinder remote)385 public ContentProviderProxy(IBinder remote) 386 { 387 mRemote = remote; 388 } 389 390 @Override asBinder()391 public IBinder asBinder() 392 { 393 return mRemote; 394 } 395 396 @Override query(String callingPkg, Uri url, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)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 getType(Uri url)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 insert(String callingPkg, Uri url, ContentValues values)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 bulkInsert(String callingPkg, Uri url, ContentValues[] values)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 applyBatch(String callingPkg, String authority, ArrayList<ContentProviderOperation> operations)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 delete(String callingPkg, Uri url, String selection, String[] selectionArgs)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 update(String callingPkg, Uri url, ContentValues values, String selection, String[] selectionArgs)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 openFile( String callingPkg, Uri url, String mode, ICancellationSignal signal, IBinder token)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 openAssetFile( String callingPkg, Uri url, String mode, ICancellationSignal signal)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 call(String callingPkg, String authority, String method, String request, Bundle args)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 getStreamTypes(Uri url, String mimeTypeFilter)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 openTypedAssetFile(String callingPkg, Uri url, String mimeType, Bundle opts, ICancellationSignal signal)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 createCancellationSignal()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 canonicalize(String callingPkg, Uri url)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 uncanonicalize(String callingPkg, Uri url)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 refresh(String callingPkg, Uri url, Bundle args, ICancellationSignal signal)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