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