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