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
19655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brownimport android.net.Uri;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Wraps a BulkCursor around an existing Cursor making it remotable.
28d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown * <p>
29b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown * If the wrapped cursor returns non-null from {@link CrossProcessCursor#getWindow}
30b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown * then it is assumed to own the window.  Otherwise, the adaptor provides a
31b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown * window to be filled and ensures it gets closed as needed during deactivation
32d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown * and requeries.
33d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown * </p>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class CursorToBulkCursorAdaptor extends BulkCursorNative
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements IBinder.DeathRecipient {
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "Cursor";
40d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
41d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private final Object mLock = new Object();
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final String mProviderName;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ContentObserverProxy mObserver;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
45d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    /**
46d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown     * The cursor that is being adapted.
47d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown     * This field is set to null when the cursor is closed.
48d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown     */
49d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private CrossProcessCursor mCursor;
50d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
51d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    /**
52b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown     * The cursor window that was filled by the cross process cursor in the
53b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown     * case where the cursor does not support getWindow.
54b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown     * This field is only ever non-null when the window has actually be filled.
55d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown     */
56b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown    private CursorWindow mFilledWindow;
57d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
58d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private static final class ContentObserverProxy extends ContentObserver {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        protected IContentObserver mRemote;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ContentObserverProxy(IContentObserver remoteObserver, DeathRecipient recipient) {
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(null);
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRemote = remoteObserver;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                remoteObserver.asBinder().linkToDeath(recipient, 0);
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Do nothing, the far side is dead
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean unlinkToDeath(DeathRecipient recipient) {
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mRemote.asBinder().unlinkToDeath(recipient, 0);
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean deliverSelfNotifications() {
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The far side handles the self notifications.
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
82655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown        public void onChange(boolean selfChange, Uri uri) {
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
84655e66bceba7595a2b80e7a328433e6ed5dc28a9Jeff Brown                mRemote.onChange(selfChange, uri);
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException ex) {
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Do nothing, the far side is dead
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
910cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer,
920cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            String providerName) {
93825c5132bff21e72c1448241f4c6868563c8d624Jeff Brown        if (cursor instanceof CrossProcessCursor) {
94825c5132bff21e72c1448241f4c6868563c8d624Jeff Brown            mCursor = (CrossProcessCursor)cursor;
95825c5132bff21e72c1448241f4c6868563c8d624Jeff Brown        } else {
96825c5132bff21e72c1448241f4c6868563c8d624Jeff Brown            mCursor = new CrossProcessCursorWrapper(cursor);
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProviderName = providerName;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
100d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
101d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            createAndRegisterObserverProxyLocked(observer);
102d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
104d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
105b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown    private void closeFilledWindowLocked() {
106b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown        if (mFilledWindow != null) {
107b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            mFilledWindow.close();
108b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            mFilledWindow = null;
1090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        }
1100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
1110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
1120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    private void disposeLocked() {
113d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        if (mCursor != null) {
114d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            unregisterObserverProxyLocked();
115d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            mCursor.close();
116d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            mCursor = null;
117d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
118d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
119b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown        closeFilledWindowLocked();
120d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    }
121d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
122d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private void throwIfCursorIsClosed() {
123d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        if (mCursor == null) {
124d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throw new StaleDataException("Attempted to access a cursor after it has been closed.");
125d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
126d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    }
127d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
128d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void binderDied() {
130d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
1310cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            disposeLocked();
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
134d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
135fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown    public BulkCursorDescriptor getBulkCursorDescriptor() {
136fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown        synchronized (mLock) {
137fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            throwIfCursorIsClosed();
138fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown
139fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            BulkCursorDescriptor d = new BulkCursorDescriptor();
140fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            d.cursor = this;
141fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            d.columnNames = mCursor.getColumnNames();
142fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            d.wantsAllOnMoveCalls = mCursor.getWantsAllOnMoveCalls();
143fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            d.count = mCursor.getCount();
144fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            d.window = mCursor.getWindow();
145fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            if (d.window != null) {
146fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown                // Acquire a reference to the window because its reference count will be
147fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown                // decremented when it is returned as part of the binder call reply parcel.
148fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown                d.window.acquireReference();
149fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            }
150fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown            return d;
151fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown        }
152fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown    }
153fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown
154d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
155650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown    public CursorWindow getWindow(int position) {
156d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
157d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
158d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
159650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown            if (!mCursor.moveToPosition(position)) {
160b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                closeFilledWindowLocked();
161b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                return null;
162b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            }
1630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
164b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            CursorWindow window = mCursor.getWindow();
165b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown            if (window != null) {
166b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                closeFilledWindowLocked();
167d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            } else {
168b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                window = mFilledWindow;
1690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                if (window == null) {
170b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                    mFilledWindow = new CursorWindow(mProviderName);
171b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                    window = mFilledWindow;
172650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown                } else if (position < window.getStartPosition()
173650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown                        || position >= window.getStartPosition() + window.getNumRows()) {
174b4009c73819e871bba369cdb7dbe56a55db23fc9Jeff Brown                    window.clear();
175d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                }
176650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown                mCursor.fillWindow(position, window);
177d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            }
178d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
179d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            if (window != null) {
180fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown                // Acquire a reference to the window because its reference count will be
181fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown                // decremented when it is returned as part of the binder call reply parcel.
182d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown                window.acquireReference();
183d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            }
184d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return window;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
188d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onMove(int position) {
190d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
191d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
192d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
193d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            mCursor.onMove(mCursor.getPosition(), position);
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
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a ContentObserver from the observer and register it as an observer on the
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * underlying cursor.
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param observer the IContentObserver that wants to monitor the cursor
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException if an observer is already registered
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
246d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private void createAndRegisterObserverProxyLocked(IContentObserver observer) {
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mObserver != null) {
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("an observer is already registered");
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mObserver = new ContentObserverProxy(observer, this);
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCursor.registerContentObserver(mObserver);
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Unregister the observer if it is already registered. */
255d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    private void unregisterObserverProxyLocked() {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mObserver != null) {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCursor.unregisterContentObserver(mObserver);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mObserver.unlinkToDeath(this);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mObserver = null;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
263d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Bundle getExtras() {
265d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
266d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
267d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
268d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return mCursor.getExtras();
269d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
272d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown    @Override
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Bundle respond(Bundle extras) {
274d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        synchronized (mLock) {
275d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            throwIfCursorIsClosed();
276d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown
277d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown            return mCursor.respond(extras);
278d2183654e03d589b120467f4e98da1b178ceeadbJeff Brown        }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
281