CursorToBulkCursorAdaptor.java revision 825c5132bff21e72c1448241f4c6868563c8d624
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.database;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Wraps a BulkCursor around an existing Cursor making it remotable.
27d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown * <p>
28b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown * If the wrapped cursor returns non-null from {@link CrossProcessCursor#getWindow}
29b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown * then it is assumed to own the window.  Otherwise, the adaptor provides a
30b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown * window to be filled and ensures it gets closed as needed during deactivation
31d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown * and requeries.
32d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown * </p>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class CursorToBulkCursorAdaptor extends BulkCursorNative
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements IBinder.DeathRecipient {
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "Cursor";
39d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
40d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private final Object mLock = new Object();
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final String mProviderName;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ContentObserverProxy mObserver;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
44d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    /**
45d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown     * The cursor that is being adapted.
46d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown     * This field is set to null when the cursor is closed.
47d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown     */
48d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private CrossProcessCursor mCursor;
49d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
50d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    /**
51b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown     * The cursor window that was filled by the cross process cursor in the
52b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown     * case where the cursor does not support getWindow.
53b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown     * This field is only ever non-null when the window has actually be filled.
54d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown     */
55b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown    private CursorWindow mFilledWindow;
56d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
57d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private static final class ContentObserverProxy extends ContentObserver {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected IContentObserver mRemote;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ContentObserverProxy(IContentObserver remoteObserver, DeathRecipient recipient) {
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(null);
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRemote = remoteObserver;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                remoteObserver.asBinder().linkToDeath(recipient, 0);
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Do nothing, the far side is dead
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean unlinkToDeath(DeathRecipient recipient) {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mRemote.asBinder().unlinkToDeath(recipient, 0);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean deliverSelfNotifications() {
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The far side handles the self notifications.
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onChange(boolean selfChange) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRemote.onChange(selfChange);
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException ex) {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Do nothing, the far side is dead
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
900cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer,
910cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            String providerName) {
92825c5132bff21e72c1448241f4c6868563c8d624Jeff Brown        if (cursor instanceof CrossProcessCursor) {
93825c5132bff21e72c1448241f4c6868563c8d624Jeff Brown            mCursor = (CrossProcessCursor)cursor;
94825c5132bff21e72c1448241f4c6868563c8d624Jeff Brown        } else {
95825c5132bff21e72c1448241f4c6868563c8d624Jeff Brown            mCursor = new CrossProcessCursorWrapper(cursor);
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProviderName = providerName;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
100d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            createAndRegisterObserverProxyLocked(observer);
101d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
103d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
104b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown    private void closeFilledWindowLocked() {
105b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown        if (mFilledWindow != null) {
106b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            mFilledWindow.close();
107b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            mFilledWindow = null;
1080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        }
1090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
1100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
1110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    private void disposeLocked() {
112d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        if (mCursor != null) {
113d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            unregisterObserverProxyLocked();
114d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            mCursor.close();
115d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            mCursor = null;
116d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
117d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
118b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown        closeFilledWindowLocked();
119d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    }
120d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
121d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private void throwIfCursorIsClosed() {
122d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        if (mCursor == null) {
123d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throw new StaleDataException("Attempted to access a cursor after it has been closed.");
124d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
125d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    }
126d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
127d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void binderDied() {
129d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
1300cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            disposeLocked();
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
133d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
134d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CursorWindow getWindow(int startPos) {
136d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
137d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
138d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
139b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            if (!mCursor.moveToPosition(startPos)) {
140b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                closeFilledWindowLocked();
141b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                return null;
142b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            }
1430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
144b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            CursorWindow window = mCursor.getWindow();
145b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            if (window != null) {
146b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                closeFilledWindowLocked();
147d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            } else {
148b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                window = mFilledWindow;
1490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                if (window == null) {
150b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                    mFilledWindow = new CursorWindow(mProviderName);
151b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                    window = mFilledWindow;
152b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                    mCursor.fillWindow(startPos, window);
153b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                } else if (startPos < window.getStartPosition()
1540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                        || startPos >= window.getStartPosition() + window.getNumRows()) {
155b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                    window.clear();
156d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                    mCursor.fillWindow(startPos, window);
157d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                }
158d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            }
159d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
160d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            // Acquire a reference before returning from this RPC.
161d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            // The Binder proxy will decrement the reference count again as part of writing
162d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            // the CursorWindow to the reply parcel as a return value.
163d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            if (window != null) {
164d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                window.acquireReference();
165d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            }
166d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return window;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
170d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onMove(int position) {
172d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
173d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
174d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
175d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            mCursor.onMove(mCursor.getPosition(), position);
176d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int count() {
181d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
182d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
183d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
184d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return mCursor.getCount();
185d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
188d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] getColumnNames() {
190d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
191d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
192d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
193d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return mCursor.getColumnNames();
194d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
197d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void deactivate() {
199d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
200d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            if (mCursor != null) {
201d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                unregisterObserverProxyLocked();
202d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                mCursor.deactivate();
203d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            }
2040cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
205b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            closeFilledWindowLocked();
206d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
209d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void close() {
211d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
2120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            disposeLocked();
213d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
216d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
2170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    public int requery(IContentObserver observer) {
218d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
219d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
220d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
221b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            closeFilledWindowLocked();
222d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
223d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            try {
224d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                if (!mCursor.requery()) {
225d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                    return -1;
226d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                }
227d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            } catch (IllegalStateException e) {
228d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                IllegalStateException leakProgram = new IllegalStateException(
229d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                        mProviderName + " Requery misuse db, mCursor isClosed:" +
230d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                        mCursor.isClosed(), e);
231d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                throw leakProgram;
232d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            }
233d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
234d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            unregisterObserverProxyLocked();
235d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            createAndRegisterObserverProxyLocked(observer);
236d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return mCursor.getCount();
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
240d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getWantsAllOnMoveCalls() {
242d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
243d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
244d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
245d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return mCursor.getWantsAllOnMoveCalls();
246d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a ContentObserver from the observer and register it as an observer on the
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * underlying cursor.
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param observer the IContentObserver that wants to monitor the cursor
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException if an observer is already registered
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
255d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private void createAndRegisterObserverProxyLocked(IContentObserver observer) {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mObserver != null) {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("an observer is already registered");
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mObserver = new ContentObserverProxy(observer, this);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCursor.registerContentObserver(mObserver);
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Unregister the observer if it is already registered. */
264d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private void unregisterObserverProxyLocked() {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mObserver != null) {
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCursor.unregisterContentObserver(mObserver);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mObserver.unlinkToDeath(this);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mObserver = null;
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
272d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Bundle getExtras() {
274d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
275d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
276d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
277d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return mCursor.getExtras();
278d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
281d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Bundle respond(Bundle extras) {
283d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
284d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
285d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
286d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return mCursor.respond(extras);
287d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
290