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