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