975 lines
36 KiB
Java
975 lines
36 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2006 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package android.content;
|
||
|
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.compat.annotation.UnsupportedAppUsage;
|
||
|
import android.content.res.AssetFileDescriptor;
|
||
|
import android.database.BulkCursorDescriptor;
|
||
|
import android.database.BulkCursorToCursorAdaptor;
|
||
|
import android.database.Cursor;
|
||
|
import android.database.CursorToBulkCursorAdaptor;
|
||
|
import android.database.DatabaseUtils;
|
||
|
import android.database.IContentObserver;
|
||
|
import android.net.Uri;
|
||
|
import android.os.Binder;
|
||
|
import android.os.Bundle;
|
||
|
import android.os.IBinder;
|
||
|
import android.os.ICancellationSignal;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.ParcelFileDescriptor;
|
||
|
import android.os.Parcelable;
|
||
|
import android.os.RemoteCallback;
|
||
|
import android.os.RemoteException;
|
||
|
|
||
|
import java.io.FileNotFoundException;
|
||
|
import java.util.ArrayList;
|
||
|
|
||
|
/**
|
||
|
* {@hide}
|
||
|
*/
|
||
|
abstract public class ContentProviderNative extends Binder implements IContentProvider {
|
||
|
public ContentProviderNative()
|
||
|
{
|
||
|
attachInterface(this, descriptor);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Cast a Binder object into a content resolver interface, generating
|
||
|
* a proxy if needed.
|
||
|
*/
|
||
|
@UnsupportedAppUsage
|
||
|
static public IContentProvider asInterface(IBinder obj)
|
||
|
{
|
||
|
if (obj == null) {
|
||
|
return null;
|
||
|
}
|
||
|
IContentProvider in =
|
||
|
(IContentProvider)obj.queryLocalInterface(descriptor);
|
||
|
if (in != null) {
|
||
|
return in;
|
||
|
}
|
||
|
|
||
|
return new ContentProviderProxy(obj);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the name of the content provider.
|
||
|
* Should probably be part of the {@link IContentProvider} interface.
|
||
|
* @return The content provider name.
|
||
|
*/
|
||
|
public abstract String getProviderName();
|
||
|
|
||
|
@Override
|
||
|
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
|
||
|
throws RemoteException {
|
||
|
try {
|
||
|
switch (code) {
|
||
|
case QUERY_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
|
||
|
// String[] projection
|
||
|
int num = data.readInt();
|
||
|
String[] projection = null;
|
||
|
if (num > 0) {
|
||
|
projection = new String[num];
|
||
|
for (int i = 0; i < num; i++) {
|
||
|
projection[i] = data.readString();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Bundle queryArgs = data.readBundle();
|
||
|
IContentObserver observer = IContentObserver.Stub.asInterface(
|
||
|
data.readStrongBinder());
|
||
|
ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
|
||
|
data.readStrongBinder());
|
||
|
|
||
|
Cursor cursor = query(attributionSource, url, projection, queryArgs,
|
||
|
cancellationSignal);
|
||
|
if (cursor != null) {
|
||
|
CursorToBulkCursorAdaptor adaptor = null;
|
||
|
|
||
|
try {
|
||
|
adaptor = new CursorToBulkCursorAdaptor(cursor, observer,
|
||
|
getProviderName());
|
||
|
cursor = null;
|
||
|
|
||
|
BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor();
|
||
|
adaptor = null;
|
||
|
|
||
|
reply.writeNoException();
|
||
|
reply.writeInt(1);
|
||
|
d.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
|
||
|
} finally {
|
||
|
// Close cursor if an exception was thrown while constructing the adaptor.
|
||
|
if (adaptor != null) {
|
||
|
adaptor.close();
|
||
|
}
|
||
|
if (cursor != null) {
|
||
|
cursor.close();
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
reply.writeNoException();
|
||
|
reply.writeInt(0);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case GET_TYPE_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
String type = getType(attributionSource, url);
|
||
|
reply.writeNoException();
|
||
|
reply.writeString(type);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case GET_TYPE_ASYNC_TRANSACTION: {
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
|
||
|
getTypeAsync(attributionSource, url, callback);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case GET_TYPE_ANONYMOUS_ASYNC_TRANSACTION: {
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
|
||
|
getTypeAnonymousAsync(url, callback);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case INSERT_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
|
||
|
Bundle extras = data.readBundle();
|
||
|
|
||
|
Uri out = insert(attributionSource, url, values, extras);
|
||
|
reply.writeNoException();
|
||
|
Uri.writeToParcel(reply, out);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case BULK_INSERT_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
ContentValues[] values = data.createTypedArray(ContentValues.CREATOR);
|
||
|
|
||
|
int count = bulkInsert(attributionSource, url, values);
|
||
|
reply.writeNoException();
|
||
|
reply.writeInt(count);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case APPLY_BATCH_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
String authority = data.readString();
|
||
|
final int numOperations = data.readInt();
|
||
|
final ArrayList<ContentProviderOperation> operations =
|
||
|
new ArrayList<>(numOperations);
|
||
|
for (int i = 0; i < numOperations; i++) {
|
||
|
operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
|
||
|
}
|
||
|
final ContentProviderResult[] results = applyBatch(attributionSource,
|
||
|
authority, operations);
|
||
|
reply.writeNoException();
|
||
|
reply.writeTypedArray(results, 0);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case DELETE_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
Bundle extras = data.readBundle();
|
||
|
|
||
|
int count = delete(attributionSource, url, extras);
|
||
|
|
||
|
reply.writeNoException();
|
||
|
reply.writeInt(count);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case UPDATE_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
|
||
|
Bundle extras = data.readBundle();
|
||
|
|
||
|
int count = update(attributionSource, url, values, extras);
|
||
|
|
||
|
reply.writeNoException();
|
||
|
reply.writeInt(count);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case OPEN_FILE_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
String mode = data.readString();
|
||
|
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
|
||
|
data.readStrongBinder());
|
||
|
|
||
|
ParcelFileDescriptor fd;
|
||
|
fd = openFile(attributionSource, url, mode, signal);
|
||
|
reply.writeNoException();
|
||
|
if (fd != null) {
|
||
|
reply.writeInt(1);
|
||
|
fd.writeToParcel(reply,
|
||
|
Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
|
||
|
} else {
|
||
|
reply.writeInt(0);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case OPEN_ASSET_FILE_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
String mode = data.readString();
|
||
|
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
|
||
|
data.readStrongBinder());
|
||
|
|
||
|
AssetFileDescriptor fd;
|
||
|
fd = openAssetFile(attributionSource, url, mode, signal);
|
||
|
reply.writeNoException();
|
||
|
if (fd != null) {
|
||
|
reply.writeInt(1);
|
||
|
fd.writeToParcel(reply,
|
||
|
Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
|
||
|
} else {
|
||
|
reply.writeInt(0);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case CALL_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
String authority = data.readString();
|
||
|
String method = data.readString();
|
||
|
String stringArg = data.readString();
|
||
|
Bundle extras = data.readBundle();
|
||
|
|
||
|
Bundle responseBundle = call(attributionSource, authority, method,
|
||
|
stringArg, extras);
|
||
|
|
||
|
reply.writeNoException();
|
||
|
reply.writeBundle(responseBundle);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case GET_STREAM_TYPES_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
String mimeTypeFilter = data.readString();
|
||
|
String[] types = getStreamTypes(attributionSource, url, mimeTypeFilter);
|
||
|
reply.writeNoException();
|
||
|
reply.writeStringArray(types);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case OPEN_TYPED_ASSET_FILE_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
String mimeType = data.readString();
|
||
|
Bundle opts = data.readBundle();
|
||
|
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
|
||
|
data.readStrongBinder());
|
||
|
|
||
|
AssetFileDescriptor fd;
|
||
|
fd = openTypedAssetFile(attributionSource, url, mimeType, opts, signal);
|
||
|
reply.writeNoException();
|
||
|
if (fd != null) {
|
||
|
reply.writeInt(1);
|
||
|
fd.writeToParcel(reply,
|
||
|
Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
|
||
|
} else {
|
||
|
reply.writeInt(0);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case CREATE_CANCELATION_SIGNAL_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
|
||
|
ICancellationSignal cancellationSignal = createCancellationSignal();
|
||
|
reply.writeNoException();
|
||
|
reply.writeStrongBinder(cancellationSignal.asBinder());
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case CANONICALIZE_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
|
||
|
Uri out = canonicalize(attributionSource, url);
|
||
|
reply.writeNoException();
|
||
|
Uri.writeToParcel(reply, out);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case CANONICALIZE_ASYNC_TRANSACTION: {
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri uri = Uri.CREATOR.createFromParcel(data);
|
||
|
RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
|
||
|
canonicalizeAsync(attributionSource, uri, callback);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case UNCANONICALIZE_TRANSACTION:
|
||
|
{
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
|
||
|
Uri out = uncanonicalize(attributionSource, url);
|
||
|
reply.writeNoException();
|
||
|
Uri.writeToParcel(reply, out);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case UNCANONICALIZE_ASYNC_TRANSACTION: {
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri uri = Uri.CREATOR.createFromParcel(data);
|
||
|
RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
|
||
|
uncanonicalizeAsync(attributionSource, uri, callback);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case REFRESH_TRANSACTION: {
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri url = Uri.CREATOR.createFromParcel(data);
|
||
|
Bundle extras = data.readBundle();
|
||
|
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
|
||
|
data.readStrongBinder());
|
||
|
|
||
|
boolean out = refresh(attributionSource, url, extras, signal);
|
||
|
reply.writeNoException();
|
||
|
reply.writeInt(out ? 0 : -1);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case CHECK_URI_PERMISSION_TRANSACTION: {
|
||
|
data.enforceInterface(IContentProvider.descriptor);
|
||
|
AttributionSource attributionSource = AttributionSource.CREATOR
|
||
|
.createFromParcel(data);
|
||
|
Uri uri = Uri.CREATOR.createFromParcel(data);
|
||
|
int uid = data.readInt();
|
||
|
int modeFlags = data.readInt();
|
||
|
|
||
|
int out = checkUriPermission(attributionSource, uri, uid, modeFlags);
|
||
|
reply.writeNoException();
|
||
|
reply.writeInt(out);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
} catch (Exception e) {
|
||
|
DatabaseUtils.writeExceptionToParcel(reply, e);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return super.onTransact(code, data, reply, flags);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public IBinder asBinder()
|
||
|
{
|
||
|
return this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
final class ContentProviderProxy implements IContentProvider
|
||
|
{
|
||
|
public ContentProviderProxy(IBinder remote)
|
||
|
{
|
||
|
mRemote = remote;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public IBinder asBinder()
|
||
|
{
|
||
|
return mRemote;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Cursor query(@NonNull AttributionSource attributionSource, Uri url,
|
||
|
@Nullable String[] projection, @Nullable Bundle queryArgs,
|
||
|
@Nullable ICancellationSignal cancellationSignal)
|
||
|
throws RemoteException {
|
||
|
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
int length = 0;
|
||
|
if (projection != null) {
|
||
|
length = projection.length;
|
||
|
}
|
||
|
data.writeInt(length);
|
||
|
for (int i = 0; i < length; i++) {
|
||
|
data.writeString(projection[i]);
|
||
|
}
|
||
|
data.writeBundle(queryArgs);
|
||
|
data.writeStrongBinder(adaptor.getObserver().asBinder());
|
||
|
data.writeStrongBinder(
|
||
|
cancellationSignal != null ? cancellationSignal.asBinder() : null);
|
||
|
|
||
|
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
|
||
|
if (reply.readInt() != 0) {
|
||
|
BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
|
||
|
Binder.copyAllowBlocking(mRemote, (d.cursor != null) ? d.cursor.asBinder() : null);
|
||
|
adaptor.initialize(d);
|
||
|
} else {
|
||
|
adaptor.close();
|
||
|
adaptor = null;
|
||
|
}
|
||
|
return adaptor;
|
||
|
} catch (RemoteException ex) {
|
||
|
adaptor.close();
|
||
|
throw ex;
|
||
|
} catch (RuntimeException ex) {
|
||
|
adaptor.close();
|
||
|
throw ex;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public String getType(AttributionSource attributionSource, Uri url) throws RemoteException
|
||
|
{
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
|
||
|
mRemote.transact(IContentProvider.GET_TYPE_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
String out = reply.readString();
|
||
|
return out;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
/* oneway */ public void getTypeAsync(AttributionSource attributionSource,
|
||
|
Uri uri, RemoteCallback callback) throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
uri.writeToParcel(data, 0);
|
||
|
callback.writeToParcel(data, 0);
|
||
|
|
||
|
mRemote.transact(IContentProvider.GET_TYPE_ASYNC_TRANSACTION, data, null,
|
||
|
IBinder.FLAG_ONEWAY);
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
/* oneway */ public void getTypeAnonymousAsync(Uri uri, RemoteCallback callback)
|
||
|
throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
uri.writeToParcel(data, 0);
|
||
|
callback.writeToParcel(data, 0);
|
||
|
|
||
|
mRemote.transact(IContentProvider.GET_TYPE_ANONYMOUS_ASYNC_TRANSACTION, data, null,
|
||
|
IBinder.FLAG_ONEWAY);
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
|
||
|
ContentValues values, Bundle extras) throws RemoteException
|
||
|
{
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
values.writeToParcel(data, 0);
|
||
|
data.writeBundle(extras);
|
||
|
|
||
|
mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
Uri out = Uri.CREATOR.createFromParcel(reply);
|
||
|
return out;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int bulkInsert(@NonNull AttributionSource attributionSource, Uri url,
|
||
|
ContentValues[] values) throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
data.writeTypedArray(values, 0);
|
||
|
|
||
|
mRemote.transact(IContentProvider.BULK_INSERT_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
int count = reply.readInt();
|
||
|
return count;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public ContentProviderResult[] applyBatch(@NonNull AttributionSource attributionSource,
|
||
|
String authority, ArrayList<ContentProviderOperation> operations)
|
||
|
throws RemoteException, OperationApplicationException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
data.writeString(authority);
|
||
|
data.writeInt(operations.size());
|
||
|
for (ContentProviderOperation operation : operations) {
|
||
|
operation.writeToParcel(data, 0);
|
||
|
}
|
||
|
mRemote.transact(IContentProvider.APPLY_BATCH_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionWithOperationApplicationExceptionFromParcel(reply);
|
||
|
final ContentProviderResult[] results =
|
||
|
reply.createTypedArray(ContentProviderResult.CREATOR);
|
||
|
return results;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int delete(@NonNull AttributionSource attributionSource, Uri url, Bundle extras)
|
||
|
throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
data.writeBundle(extras);
|
||
|
|
||
|
mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
int count = reply.readInt();
|
||
|
return count;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int update(@NonNull AttributionSource attributionSource, Uri url,
|
||
|
ContentValues values, Bundle extras) throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
values.writeToParcel(data, 0);
|
||
|
data.writeBundle(extras);
|
||
|
|
||
|
mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
int count = reply.readInt();
|
||
|
return count;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public ParcelFileDescriptor openFile(@NonNull AttributionSource attributionSource, Uri url,
|
||
|
String mode, ICancellationSignal signal)
|
||
|
throws RemoteException, FileNotFoundException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
data.writeString(mode);
|
||
|
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
|
||
|
|
||
|
mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
|
||
|
int has = reply.readInt();
|
||
|
ParcelFileDescriptor fd = has != 0 ? ParcelFileDescriptor.CREATOR
|
||
|
.createFromParcel(reply) : null;
|
||
|
return fd;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public AssetFileDescriptor openAssetFile(@NonNull AttributionSource attributionSource,
|
||
|
Uri url, String mode, ICancellationSignal signal)
|
||
|
throws RemoteException, FileNotFoundException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
data.writeString(mode);
|
||
|
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
|
||
|
|
||
|
mRemote.transact(IContentProvider.OPEN_ASSET_FILE_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
|
||
|
int has = reply.readInt();
|
||
|
AssetFileDescriptor fd = has != 0
|
||
|
? AssetFileDescriptor.CREATOR.createFromParcel(reply) : null;
|
||
|
return fd;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Bundle call(@NonNull AttributionSource attributionSource, String authority,
|
||
|
String method, String request, Bundle extras) throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
data.writeString(authority);
|
||
|
data.writeString(method);
|
||
|
data.writeString(request);
|
||
|
data.writeBundle(extras);
|
||
|
|
||
|
mRemote.transact(IContentProvider.CALL_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
Bundle bundle = reply.readBundle();
|
||
|
return bundle;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public String[] getStreamTypes(AttributionSource attributionSource,
|
||
|
Uri url, String mimeTypeFilter) throws RemoteException
|
||
|
{
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
|
||
|
url.writeToParcel(data, 0);
|
||
|
data.writeString(mimeTypeFilter);
|
||
|
|
||
|
mRemote.transact(IContentProvider.GET_STREAM_TYPES_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
String[] out = reply.createStringArray();
|
||
|
return out;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public AssetFileDescriptor openTypedAssetFile(@NonNull AttributionSource attributionSource,
|
||
|
Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
|
||
|
throws RemoteException, FileNotFoundException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
data.writeString(mimeType);
|
||
|
data.writeBundle(opts);
|
||
|
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
|
||
|
|
||
|
mRemote.transact(IContentProvider.OPEN_TYPED_ASSET_FILE_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
|
||
|
int has = reply.readInt();
|
||
|
AssetFileDescriptor fd = has != 0
|
||
|
? AssetFileDescriptor.CREATOR.createFromParcel(reply) : null;
|
||
|
return fd;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public ICancellationSignal createCancellationSignal() throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
mRemote.transact(IContentProvider.CREATE_CANCELATION_SIGNAL_TRANSACTION,
|
||
|
data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
|
||
|
reply.readStrongBinder());
|
||
|
return cancellationSignal;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Uri canonicalize(@NonNull AttributionSource attributionSource, Uri url)
|
||
|
throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
|
||
|
mRemote.transact(IContentProvider.CANONICALIZE_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
Uri out = Uri.CREATOR.createFromParcel(reply);
|
||
|
return out;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
/* oneway */ public void canonicalizeAsync(@NonNull AttributionSource attributionSource,
|
||
|
Uri uri, RemoteCallback callback) throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
uri.writeToParcel(data, 0);
|
||
|
callback.writeToParcel(data, 0);
|
||
|
|
||
|
mRemote.transact(IContentProvider.CANONICALIZE_ASYNC_TRANSACTION, data, null,
|
||
|
Binder.FLAG_ONEWAY);
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Uri uncanonicalize(@NonNull AttributionSource attributionSource, Uri url)
|
||
|
throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
|
||
|
mRemote.transact(IContentProvider.UNCANONICALIZE_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
Uri out = Uri.CREATOR.createFromParcel(reply);
|
||
|
return out;
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
/* oneway */ public void uncanonicalizeAsync(@NonNull AttributionSource attributionSource,
|
||
|
Uri uri, RemoteCallback callback) throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
uri.writeToParcel(data, 0);
|
||
|
callback.writeToParcel(data, 0);
|
||
|
|
||
|
mRemote.transact(IContentProvider.UNCANONICALIZE_ASYNC_TRANSACTION, data, null,
|
||
|
Binder.FLAG_ONEWAY);
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean refresh(@NonNull AttributionSource attributionSource, Uri url, Bundle extras,
|
||
|
ICancellationSignal signal) throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
data.writeBundle(extras);
|
||
|
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
|
||
|
|
||
|
mRemote.transact(IContentProvider.REFRESH_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
int success = reply.readInt();
|
||
|
return (success == 0);
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri url, int uid,
|
||
|
int modeFlags) throws RemoteException {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
Parcel reply = Parcel.obtain();
|
||
|
try {
|
||
|
data.writeInterfaceToken(IContentProvider.descriptor);
|
||
|
|
||
|
attributionSource.writeToParcel(data, 0);
|
||
|
url.writeToParcel(data, 0);
|
||
|
data.writeInt(uid);
|
||
|
data.writeInt(modeFlags);
|
||
|
|
||
|
mRemote.transact(IContentProvider.CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0);
|
||
|
|
||
|
DatabaseUtils.readExceptionFromParcel(reply);
|
||
|
return reply.readInt();
|
||
|
} finally {
|
||
|
data.recycle();
|
||
|
reply.recycle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@UnsupportedAppUsage
|
||
|
private IBinder mRemote;
|
||
|
}
|