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 { BulkCursorNative()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 */ asInterface(IBinder obj)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 onTransact(int code, Parcel data, Parcel reply, int flags)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 asBinder()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 BulkCursorProxy(IBinder remote)144 public BulkCursorProxy(IBinder remote) 145 { 146 mRemote = remote; 147 mExtras = null; 148 } 149 asBinder()150 public IBinder asBinder() 151 { 152 return mRemote; 153 } 154 getWindow(int position)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 onMove(int position)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 deactivate()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 close()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 requery(IContentObserver observer)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 getExtras()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 respond(Bundle extras)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