BulkCursorNative.java revision 0cde89f5f025b7826be009ebb9673b970e180e32
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 17package android.database; 18 19import android.os.Binder; 20import android.os.Bundle; 21import android.os.IBinder; 22import android.os.Parcel; 23import android.os.Parcelable; 24import 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 */ 32public 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 COUNT_TRANSACTION: { 76 data.enforceInterface(IBulkCursor.descriptor); 77 int count = count(); 78 reply.writeNoException(); 79 reply.writeInt(count); 80 return true; 81 } 82 83 case GET_COLUMN_NAMES_TRANSACTION: { 84 data.enforceInterface(IBulkCursor.descriptor); 85 String[] columnNames = getColumnNames(); 86 reply.writeNoException(); 87 reply.writeInt(columnNames.length); 88 int length = columnNames.length; 89 for (int i = 0; i < length; i++) { 90 reply.writeString(columnNames[i]); 91 } 92 return true; 93 } 94 95 case DEACTIVATE_TRANSACTION: { 96 data.enforceInterface(IBulkCursor.descriptor); 97 deactivate(); 98 reply.writeNoException(); 99 return true; 100 } 101 102 case CLOSE_TRANSACTION: { 103 data.enforceInterface(IBulkCursor.descriptor); 104 close(); 105 reply.writeNoException(); 106 return true; 107 } 108 109 case REQUERY_TRANSACTION: { 110 data.enforceInterface(IBulkCursor.descriptor); 111 IContentObserver observer = 112 IContentObserver.Stub.asInterface(data.readStrongBinder()); 113 int count = requery(observer); 114 reply.writeNoException(); 115 reply.writeInt(count); 116 reply.writeBundle(getExtras()); 117 return true; 118 } 119 120 case ON_MOVE_TRANSACTION: { 121 data.enforceInterface(IBulkCursor.descriptor); 122 int position = data.readInt(); 123 onMove(position); 124 reply.writeNoException(); 125 return true; 126 } 127 128 case WANTS_ON_MOVE_TRANSACTION: { 129 data.enforceInterface(IBulkCursor.descriptor); 130 boolean result = getWantsAllOnMoveCalls(); 131 reply.writeNoException(); 132 reply.writeInt(result ? 1 : 0); 133 return true; 134 } 135 136 case GET_EXTRAS_TRANSACTION: { 137 data.enforceInterface(IBulkCursor.descriptor); 138 Bundle extras = getExtras(); 139 reply.writeNoException(); 140 reply.writeBundle(extras); 141 return true; 142 } 143 144 case RESPOND_TRANSACTION: { 145 data.enforceInterface(IBulkCursor.descriptor); 146 Bundle extras = data.readBundle(); 147 Bundle returnExtras = respond(extras); 148 reply.writeNoException(); 149 reply.writeBundle(returnExtras); 150 return true; 151 } 152 } 153 } catch (Exception e) { 154 DatabaseUtils.writeExceptionToParcel(reply, e); 155 return true; 156 } 157 158 return super.onTransact(code, data, reply, flags); 159 } 160 161 public IBinder asBinder() 162 { 163 return this; 164 } 165} 166 167 168final class BulkCursorProxy implements IBulkCursor { 169 private IBinder mRemote; 170 private Bundle mExtras; 171 172 public BulkCursorProxy(IBinder remote) 173 { 174 mRemote = remote; 175 mExtras = null; 176 } 177 178 public IBinder asBinder() 179 { 180 return mRemote; 181 } 182 183 public CursorWindow getWindow(int startPos) throws RemoteException 184 { 185 Parcel data = Parcel.obtain(); 186 Parcel reply = Parcel.obtain(); 187 try { 188 data.writeInterfaceToken(IBulkCursor.descriptor); 189 data.writeInt(startPos); 190 191 mRemote.transact(GET_CURSOR_WINDOW_TRANSACTION, data, reply, 0); 192 DatabaseUtils.readExceptionFromParcel(reply); 193 194 CursorWindow window = null; 195 if (reply.readInt() == 1) { 196 window = CursorWindow.newFromParcel(reply); 197 } 198 return window; 199 } finally { 200 data.recycle(); 201 reply.recycle(); 202 } 203 } 204 205 public void onMove(int position) throws RemoteException { 206 Parcel data = Parcel.obtain(); 207 Parcel reply = Parcel.obtain(); 208 try { 209 data.writeInterfaceToken(IBulkCursor.descriptor); 210 data.writeInt(position); 211 212 mRemote.transact(ON_MOVE_TRANSACTION, data, reply, 0); 213 DatabaseUtils.readExceptionFromParcel(reply); 214 } finally { 215 data.recycle(); 216 reply.recycle(); 217 } 218 } 219 220 public int count() throws RemoteException 221 { 222 Parcel data = Parcel.obtain(); 223 Parcel reply = Parcel.obtain(); 224 try { 225 data.writeInterfaceToken(IBulkCursor.descriptor); 226 227 boolean result = mRemote.transact(COUNT_TRANSACTION, data, reply, 0); 228 DatabaseUtils.readExceptionFromParcel(reply); 229 230 int count; 231 if (result == false) { 232 count = -1; 233 } else { 234 count = reply.readInt(); 235 } 236 return count; 237 } finally { 238 data.recycle(); 239 reply.recycle(); 240 } 241 } 242 243 public String[] getColumnNames() throws RemoteException 244 { 245 Parcel data = Parcel.obtain(); 246 Parcel reply = Parcel.obtain(); 247 try { 248 data.writeInterfaceToken(IBulkCursor.descriptor); 249 250 mRemote.transact(GET_COLUMN_NAMES_TRANSACTION, data, reply, 0); 251 DatabaseUtils.readExceptionFromParcel(reply); 252 253 String[] columnNames = null; 254 int numColumns = reply.readInt(); 255 columnNames = new String[numColumns]; 256 for (int i = 0; i < numColumns; i++) { 257 columnNames[i] = reply.readString(); 258 } 259 return columnNames; 260 } finally { 261 data.recycle(); 262 reply.recycle(); 263 } 264 } 265 266 public void deactivate() throws RemoteException 267 { 268 Parcel data = Parcel.obtain(); 269 Parcel reply = Parcel.obtain(); 270 try { 271 data.writeInterfaceToken(IBulkCursor.descriptor); 272 273 mRemote.transact(DEACTIVATE_TRANSACTION, data, reply, 0); 274 DatabaseUtils.readExceptionFromParcel(reply); 275 } finally { 276 data.recycle(); 277 reply.recycle(); 278 } 279 } 280 281 public void close() throws RemoteException 282 { 283 Parcel data = Parcel.obtain(); 284 Parcel reply = Parcel.obtain(); 285 try { 286 data.writeInterfaceToken(IBulkCursor.descriptor); 287 288 mRemote.transact(CLOSE_TRANSACTION, data, reply, 0); 289 DatabaseUtils.readExceptionFromParcel(reply); 290 } finally { 291 data.recycle(); 292 reply.recycle(); 293 } 294 } 295 296 public int requery(IContentObserver observer) throws RemoteException { 297 Parcel data = Parcel.obtain(); 298 Parcel reply = Parcel.obtain(); 299 try { 300 data.writeInterfaceToken(IBulkCursor.descriptor); 301 data.writeStrongInterface(observer); 302 303 boolean result = mRemote.transact(REQUERY_TRANSACTION, data, reply, 0); 304 DatabaseUtils.readExceptionFromParcel(reply); 305 306 int count; 307 if (!result) { 308 count = -1; 309 } else { 310 count = reply.readInt(); 311 mExtras = reply.readBundle(); 312 } 313 return count; 314 } finally { 315 data.recycle(); 316 reply.recycle(); 317 } 318 } 319 320 public boolean getWantsAllOnMoveCalls() throws RemoteException { 321 Parcel data = Parcel.obtain(); 322 Parcel reply = Parcel.obtain(); 323 try { 324 data.writeInterfaceToken(IBulkCursor.descriptor); 325 326 mRemote.transact(WANTS_ON_MOVE_TRANSACTION, data, reply, 0); 327 DatabaseUtils.readExceptionFromParcel(reply); 328 329 int result = reply.readInt(); 330 return result != 0; 331 } finally { 332 data.recycle(); 333 reply.recycle(); 334 } 335 } 336 337 public Bundle getExtras() throws RemoteException { 338 if (mExtras == null) { 339 Parcel data = Parcel.obtain(); 340 Parcel reply = Parcel.obtain(); 341 try { 342 data.writeInterfaceToken(IBulkCursor.descriptor); 343 344 mRemote.transact(GET_EXTRAS_TRANSACTION, data, reply, 0); 345 DatabaseUtils.readExceptionFromParcel(reply); 346 347 mExtras = reply.readBundle(); 348 } finally { 349 data.recycle(); 350 reply.recycle(); 351 } 352 } 353 return mExtras; 354 } 355 356 public Bundle respond(Bundle extras) throws RemoteException { 357 Parcel data = Parcel.obtain(); 358 Parcel reply = Parcel.obtain(); 359 try { 360 data.writeInterfaceToken(IBulkCursor.descriptor); 361 data.writeBundle(extras); 362 363 mRemote.transact(RESPOND_TRANSACTION, data, reply, 0); 364 DatabaseUtils.readExceptionFromParcel(reply); 365 366 Bundle returnExtras = reply.readBundle(); 367 return returnExtras; 368 } finally { 369 data.recycle(); 370 reply.recycle(); 371 } 372 } 373} 374 375