/core/java/android/content/ContentProviderNative.java
Java | 572 lines | 423 code | 116 blank | 33 comment | 39 complexity | c9cde0018332a23952d92655e7fa5d90 MD5 | raw file
- /*
- * 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.content.res.AssetFileDescriptor;
- import android.database.BulkCursorNative;
- import android.database.BulkCursorToCursorAdaptor;
- import android.database.Cursor;
- import android.database.CursorWindow;
- import android.database.DatabaseUtils;
- import android.database.IBulkCursor;
- import android.database.IContentObserver;
- import android.net.Uri;
- import android.os.Binder;
- import android.os.Bundle;
- import android.os.RemoteException;
- import android.os.IBinder;
- import android.os.Parcel;
- import android.os.ParcelFileDescriptor;
- import android.os.Parcelable;
- import java.io.FileNotFoundException;
- import java.util.ArrayList;
- /**
- * {@hide}
- */
- abstract public class ContentProviderNative extends Binder implements IContentProvider {
- private static final String TAG = "ContentProvider";
- public ContentProviderNative()
- {
- attachInterface(this, descriptor);
- }
- /**
- * Cast a Binder object into a content resolver interface, generating
- * a proxy if needed.
- */
- 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);
- }
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- try {
- switch (code) {
- case QUERY_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- 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();
- }
- }
- // String selection, String[] selectionArgs...
- String selection = data.readString();
- num = data.readInt();
- String[] selectionArgs = null;
- if (num > 0) {
- selectionArgs = new String[num];
- for (int i = 0; i < num; i++) {
- selectionArgs[i] = data.readString();
- }
- }
- String sortOrder = data.readString();
- IContentObserver observer = IContentObserver.Stub.
- asInterface(data.readStrongBinder());
- CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);
- // Flag for whether caller wants the number of
- // rows in the cursor and the position of the
- // "_id" column index (or -1 if non-existent)
- // Only to be returned if binder != null.
- boolean wantsCursorMetadata = data.readInt() != 0;
- IBulkCursor bulkCursor = bulkQuery(url, projection, selection,
- selectionArgs, sortOrder, observer, window);
- reply.writeNoException();
- if (bulkCursor != null) {
- reply.writeStrongBinder(bulkCursor.asBinder());
- if (wantsCursorMetadata) {
- reply.writeInt(bulkCursor.count());
- reply.writeInt(BulkCursorToCursorAdaptor.findRowIdColumnIndex(
- bulkCursor.getColumnNames()));
- }
- } else {
- reply.writeStrongBinder(null);
- }
- return true;
- }
- case GET_TYPE_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- String type = getType(url);
- reply.writeNoException();
- reply.writeString(type);
- return true;
- }
- case INSERT_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- ContentValues values = ContentValues.CREATOR.createFromParcel(data);
- Uri out = insert(url, values);
- reply.writeNoException();
- Uri.writeToParcel(reply, out);
- return true;
- }
- case BULK_INSERT_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- ContentValues[] values = data.createTypedArray(ContentValues.CREATOR);
- int count = bulkInsert(url, values);
- reply.writeNoException();
- reply.writeInt(count);
- return true;
- }
- case APPLY_BATCH_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- final int numOperations = data.readInt();
- final ArrayList<ContentProviderOperation> operations =
- new ArrayList<ContentProviderOperation>(numOperations);
- for (int i = 0; i < numOperations; i++) {
- operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
- }
- final ContentProviderResult[] results = applyBatch(operations);
- reply.writeNoException();
- reply.writeTypedArray(results, 0);
- return true;
- }
- case DELETE_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- String selection = data.readString();
- String[] selectionArgs = data.readStringArray();
- int count = delete(url, selection, selectionArgs);
- reply.writeNoException();
- reply.writeInt(count);
- return true;
- }
- case UPDATE_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- ContentValues values = ContentValues.CREATOR.createFromParcel(data);
- String selection = data.readString();
- String[] selectionArgs = data.readStringArray();
- int count = update(url, values, selection, selectionArgs);
- reply.writeNoException();
- reply.writeInt(count);
- return true;
- }
- case OPEN_FILE_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- String mode = data.readString();
- ParcelFileDescriptor fd;
- fd = openFile(url, mode);
- 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);
- Uri url = Uri.CREATOR.createFromParcel(data);
- String mode = data.readString();
- AssetFileDescriptor fd;
- fd = openAssetFile(url, mode);
- 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);
- String method = data.readString();
- String stringArg = data.readString();
- Bundle args = data.readBundle();
- Bundle responseBundle = call(method, stringArg, args);
- reply.writeNoException();
- reply.writeBundle(responseBundle);
- return true;
- }
- }
- } catch (Exception e) {
- DatabaseUtils.writeExceptionToParcel(reply, e);
- return true;
- }
- return super.onTransact(code, data, reply, flags);
- }
- public IBinder asBinder()
- {
- return this;
- }
- }
- final class ContentProviderProxy implements IContentProvider
- {
- public ContentProviderProxy(IBinder remote)
- {
- mRemote = remote;
- }
- public IBinder asBinder()
- {
- return mRemote;
- }
- // Like bulkQuery() but sets up provided 'adaptor' if not null.
- private IBulkCursor bulkQueryInternal(
- Uri url, String[] projection,
- String selection, String[] selectionArgs, String sortOrder,
- IContentObserver observer, CursorWindow window,
- BulkCursorToCursorAdaptor adaptor) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- 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.writeString(selection);
- if (selectionArgs != null) {
- length = selectionArgs.length;
- } else {
- length = 0;
- }
- data.writeInt(length);
- for (int i = 0; i < length; i++) {
- data.writeString(selectionArgs[i]);
- }
- data.writeString(sortOrder);
- data.writeStrongBinder(observer.asBinder());
- window.writeToParcel(data, 0);
- // Flag for whether or not we want the number of rows in the
- // cursor and the position of the "_id" column index (or -1 if
- // non-existent). Only to be returned if binder != null.
- final boolean wantsCursorMetadata = (adaptor != null);
- data.writeInt(wantsCursorMetadata ? 1 : 0);
- mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
- IBulkCursor bulkCursor = null;
- IBinder bulkCursorBinder = reply.readStrongBinder();
- if (bulkCursorBinder != null) {
- bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder);
- if (wantsCursorMetadata) {
- int rowCount = reply.readInt();
- int idColumnPosition = reply.readInt();
- if (bulkCursor != null) {
- adaptor.set(bulkCursor, rowCount, idColumnPosition);
- }
- }
- }
- data.recycle();
- reply.recycle();
- return bulkCursor;
- }
- public IBulkCursor bulkQuery(Uri url, String[] projection,
- String selection, String[] selectionArgs, String sortOrder, IContentObserver observer,
- CursorWindow window) throws RemoteException {
- return bulkQueryInternal(
- url, projection, selection, selectionArgs, sortOrder,
- observer, window,
- null /* BulkCursorToCursorAdaptor */);
- }
- public Cursor query(Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) throws RemoteException {
- //TODO make a pool of windows so we can reuse memory dealers
- CursorWindow window = new CursorWindow(false /* window will be used remotely */);
- BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
- IBulkCursor bulkCursor = bulkQueryInternal(
- url, projection, selection, selectionArgs, sortOrder,
- adaptor.getObserver(), window,
- adaptor);
- if (bulkCursor == null) {
- return null;
- }
- return adaptor;
- }
- public String getType(Uri url) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- url.writeToParcel(data, 0);
- mRemote.transact(IContentProvider.GET_TYPE_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
- String out = reply.readString();
- data.recycle();
- reply.recycle();
- return out;
- }
- public Uri insert(Uri url, ContentValues values) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- url.writeToParcel(data, 0);
- values.writeToParcel(data, 0);
- mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
- Uri out = Uri.CREATOR.createFromParcel(reply);
- data.recycle();
- reply.recycle();
- return out;
- }
- public int bulkInsert(Uri url, ContentValues[] values) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- url.writeToParcel(data, 0);
- data.writeTypedArray(values, 0);
- mRemote.transact(IContentProvider.BULK_INSERT_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
- int count = reply.readInt();
- data.recycle();
- reply.recycle();
- return count;
- }
- public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
- throws RemoteException, OperationApplicationException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- 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);
- data.recycle();
- reply.recycle();
- return results;
- }
- public int delete(Uri url, String selection, String[] selectionArgs)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- url.writeToParcel(data, 0);
- data.writeString(selection);
- data.writeStringArray(selectionArgs);
- mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
- int count = reply.readInt();
- data.recycle();
- reply.recycle();
- return count;
- }
- public int update(Uri url, ContentValues values, String selection,
- String[] selectionArgs) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- url.writeToParcel(data, 0);
- values.writeToParcel(data, 0);
- data.writeString(selection);
- data.writeStringArray(selectionArgs);
- mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
- int count = reply.readInt();
- data.recycle();
- reply.recycle();
- return count;
- }
- public ParcelFileDescriptor openFile(Uri url, String mode)
- throws RemoteException, FileNotFoundException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- url.writeToParcel(data, 0);
- data.writeString(mode);
- mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
- int has = reply.readInt();
- ParcelFileDescriptor fd = has != 0 ? reply.readFileDescriptor() : null;
- data.recycle();
- reply.recycle();
- return fd;
- }
- public AssetFileDescriptor openAssetFile(Uri url, String mode)
- throws RemoteException, FileNotFoundException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- url.writeToParcel(data, 0);
- data.writeString(mode);
- 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;
- data.recycle();
- reply.recycle();
- return fd;
- }
- public Bundle call(String method, String request, Bundle args)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IContentProvider.descriptor);
- data.writeString(method);
- data.writeString(request);
- data.writeBundle(args);
- mRemote.transact(IContentProvider.CALL_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
- Bundle bundle = reply.readBundle();
- data.recycle();
- reply.recycle();
- return bundle;
- }
- private IBinder mRemote;
- }