Home | History | Annotate | Download | only in database
      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.database;
     18 
     19 import android.os.Binder;
     20 import android.os.Bundle;
     21 import android.os.IBinder;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 import android.os.RemoteException;
     25 
     26 /**
     27  * Native implementation of the bulk cursor. This is only for use in implementing
     28  * IPC, application code should use the Cursor interface.
     29  *
     30  * {@hide}
     31  */
     32 public abstract class BulkCursorNative extends Binder implements IBulkCursor
     33 {
     34     public BulkCursorNative()
     35     {
     36         attachInterface(this, descriptor);
     37     }
     38 
     39     /**
     40      * Cast a Binder object into a content resolver interface, generating
     41      * a proxy if needed.
     42      */
     43     static public IBulkCursor asInterface(IBinder obj)
     44     {
     45         if (obj == null) {
     46             return null;
     47         }
     48         IBulkCursor in = (IBulkCursor)obj.queryLocalInterface(descriptor);
     49         if (in != null) {
     50             return in;
     51         }
     52 
     53         return new BulkCursorProxy(obj);
     54     }
     55 
     56     @Override
     57     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
     58             throws RemoteException {
     59         try {
     60             switch (code) {
     61                 case GET_CURSOR_WINDOW_TRANSACTION: {
     62                     data.enforceInterface(IBulkCursor.descriptor);
     63                     int startPos = data.readInt();
     64                     CursorWindow window = getWindow(startPos);
     65                     reply.writeNoException();
     66                     if (window == null) {
     67                         reply.writeInt(0);
     68                     } else {
     69                         reply.writeInt(1);
     70                         window.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
     71                     }
     72                     return true;
     73                 }
     74 
     75                 case DEACTIVATE_TRANSACTION: {
     76                     data.enforceInterface(IBulkCursor.descriptor);
     77                     deactivate();
     78                     reply.writeNoException();
     79                     return true;
     80                 }
     81 
     82                 case CLOSE_TRANSACTION: {
     83                     data.enforceInterface(IBulkCursor.descriptor);
     84                     close();
     85                     reply.writeNoException();
     86                     return true;
     87                 }
     88 
     89                 case REQUERY_TRANSACTION: {
     90                     data.enforceInterface(IBulkCursor.descriptor);
     91                     IContentObserver observer =
     92                             IContentObserver.Stub.asInterface(data.readStrongBinder());
     93                     int count = requery(observer);
     94                     reply.writeNoException();
     95                     reply.writeInt(count);
     96                     reply.writeBundle(getExtras());
     97                     return true;
     98                 }
     99 
    100                 case ON_MOVE_TRANSACTION: {
    101                     data.enforceInterface(IBulkCursor.descriptor);
    102                     int position = data.readInt();
    103                     onMove(position);
    104                     reply.writeNoException();
    105                     return true;
    106                 }
    107 
    108                 case GET_EXTRAS_TRANSACTION: {
    109                     data.enforceInterface(IBulkCursor.descriptor);
    110                     Bundle extras = getExtras();
    111                     reply.writeNoException();
    112                     reply.writeBundle(extras);
    113                     return true;
    114                 }
    115 
    116                 case RESPOND_TRANSACTION: {
    117                     data.enforceInterface(IBulkCursor.descriptor);
    118                     Bundle extras = data.readBundle();
    119                     Bundle returnExtras = respond(extras);
    120                     reply.writeNoException();
    121                     reply.writeBundle(returnExtras);
    122                     return true;
    123                 }
    124             }
    125         } catch (Exception e) {
    126             DatabaseUtils.writeExceptionToParcel(reply, e);
    127             return true;
    128         }
    129 
    130         return super.onTransact(code, data, reply, flags);
    131     }
    132 
    133     public IBinder asBinder()
    134     {
    135         return this;
    136     }
    137 }
    138 
    139 
    140 final class BulkCursorProxy implements IBulkCursor {
    141     private IBinder mRemote;
    142     private Bundle mExtras;
    143 
    144     public BulkCursorProxy(IBinder remote)
    145     {
    146         mRemote = remote;
    147         mExtras = null;
    148     }
    149 
    150     public IBinder asBinder()
    151     {
    152         return mRemote;
    153     }
    154 
    155     public CursorWindow getWindow(int position) throws RemoteException
    156     {
    157         Parcel data = Parcel.obtain();
    158         Parcel reply = Parcel.obtain();
    159         try {
    160             data.writeInterfaceToken(IBulkCursor.descriptor);
    161             data.writeInt(position);
    162 
    163             mRemote.transact(GET_CURSOR_WINDOW_TRANSACTION, data, reply, 0);
    164             DatabaseUtils.readExceptionFromParcel(reply);
    165 
    166             CursorWindow window = null;
    167             if (reply.readInt() == 1) {
    168                 window = CursorWindow.newFromParcel(reply);
    169             }
    170             return window;
    171         } finally {
    172             data.recycle();
    173             reply.recycle();
    174         }
    175     }
    176 
    177     public void onMove(int position) throws RemoteException {
    178         Parcel data = Parcel.obtain();
    179         Parcel reply = Parcel.obtain();
    180         try {
    181             data.writeInterfaceToken(IBulkCursor.descriptor);
    182             data.writeInt(position);
    183 
    184             mRemote.transact(ON_MOVE_TRANSACTION, data, reply, 0);
    185             DatabaseUtils.readExceptionFromParcel(reply);
    186         } finally {
    187             data.recycle();
    188             reply.recycle();
    189         }
    190     }
    191 
    192     public void deactivate() throws RemoteException
    193     {
    194         Parcel data = Parcel.obtain();
    195         Parcel reply = Parcel.obtain();
    196         try {
    197             data.writeInterfaceToken(IBulkCursor.descriptor);
    198 
    199             mRemote.transact(DEACTIVATE_TRANSACTION, data, reply, 0);
    200             DatabaseUtils.readExceptionFromParcel(reply);
    201         } finally {
    202             data.recycle();
    203             reply.recycle();
    204         }
    205     }
    206 
    207     public void close() throws RemoteException
    208     {
    209         Parcel data = Parcel.obtain();
    210         Parcel reply = Parcel.obtain();
    211         try {
    212             data.writeInterfaceToken(IBulkCursor.descriptor);
    213 
    214             mRemote.transact(CLOSE_TRANSACTION, data, reply, 0);
    215             DatabaseUtils.readExceptionFromParcel(reply);
    216         } finally {
    217             data.recycle();
    218             reply.recycle();
    219         }
    220     }
    221 
    222     public int requery(IContentObserver observer) throws RemoteException {
    223         Parcel data = Parcel.obtain();
    224         Parcel reply = Parcel.obtain();
    225         try {
    226             data.writeInterfaceToken(IBulkCursor.descriptor);
    227             data.writeStrongInterface(observer);
    228 
    229             boolean result = mRemote.transact(REQUERY_TRANSACTION, data, reply, 0);
    230             DatabaseUtils.readExceptionFromParcel(reply);
    231 
    232             int count;
    233             if (!result) {
    234                 count = -1;
    235             } else {
    236                 count = reply.readInt();
    237                 mExtras = reply.readBundle();
    238             }
    239             return count;
    240         } finally {
    241             data.recycle();
    242             reply.recycle();
    243         }
    244     }
    245 
    246     public Bundle getExtras() throws RemoteException {
    247         if (mExtras == null) {
    248             Parcel data = Parcel.obtain();
    249             Parcel reply = Parcel.obtain();
    250             try {
    251                 data.writeInterfaceToken(IBulkCursor.descriptor);
    252 
    253                 mRemote.transact(GET_EXTRAS_TRANSACTION, data, reply, 0);
    254                 DatabaseUtils.readExceptionFromParcel(reply);
    255 
    256                 mExtras = reply.readBundle();
    257             } finally {
    258                 data.recycle();
    259                 reply.recycle();
    260             }
    261         }
    262         return mExtras;
    263     }
    264 
    265     public Bundle respond(Bundle extras) throws RemoteException {
    266         Parcel data = Parcel.obtain();
    267         Parcel reply = Parcel.obtain();
    268         try {
    269             data.writeInterfaceToken(IBulkCursor.descriptor);
    270             data.writeBundle(extras);
    271 
    272             mRemote.transact(RESPOND_TRANSACTION, data, reply, 0);
    273             DatabaseUtils.readExceptionFromParcel(reply);
    274 
    275             Bundle returnExtras = reply.readBundle();
    276             return returnExtras;
    277         } finally {
    278             data.recycle();
    279             reply.recycle();
    280         }
    281     }
    282 }
    283 
    284