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