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