FileDocCategorySizeDatePackage
CursorToBulkCursorAdaptor.javaAPI DocAndroid 5.1 API8806Thu Mar 12 22:22:10 GMT 2015android.database

CursorToBulkCursorAdaptor

public final class CursorToBulkCursorAdaptor extends BulkCursorNative implements IBinder.DeathRecipient
Wraps a BulkCursor around an existing Cursor making it remotable.

If the wrapped cursor returns non-null from {@link CrossProcessCursor#getWindow} then it is assumed to own the window. Otherwise, the adaptor provides a window to be filled and ensures it gets closed as needed during deactivation and requeries.

{@hide}

Fields Summary
private static final String
TAG
private final Object
mLock
private final String
mProviderName
private ContentObserverProxy
mObserver
private CrossProcessCursor
mCursor
The cursor that is being adapted. This field is set to null when the cursor is closed.
private CursorWindow
mFilledWindow
The cursor window that was filled by the cross process cursor in the case where the cursor does not support getWindow. This field is only ever non-null when the window has actually be filled.
Constructors Summary
public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer, String providerName)

        if (cursor instanceof CrossProcessCursor) {
            mCursor = (CrossProcessCursor)cursor;
        } else {
            mCursor = new CrossProcessCursorWrapper(cursor);
        }
        mProviderName = providerName;

        synchronized (mLock) {
            createAndRegisterObserverProxyLocked(observer);
        }
    
Methods Summary
public voidbinderDied()

        synchronized (mLock) {
            disposeLocked();
        }
    
public voidclose()

        synchronized (mLock) {
            disposeLocked();
        }
    
private voidcloseFilledWindowLocked()

        if (mFilledWindow != null) {
            mFilledWindow.close();
            mFilledWindow = null;
        }
    
private voidcreateAndRegisterObserverProxyLocked(IContentObserver observer)
Create a ContentObserver from the observer and register it as an observer on the underlying cursor.

param
observer the IContentObserver that wants to monitor the cursor
throws
IllegalStateException if an observer is already registered

        if (mObserver != null) {
            throw new IllegalStateException("an observer is already registered");
        }
        mObserver = new ContentObserverProxy(observer, this);
        mCursor.registerContentObserver(mObserver);
    
public voiddeactivate()

        synchronized (mLock) {
            if (mCursor != null) {
                unregisterObserverProxyLocked();
                mCursor.deactivate();
            }

            closeFilledWindowLocked();
        }
    
private voiddisposeLocked()

        if (mCursor != null) {
            unregisterObserverProxyLocked();
            mCursor.close();
            mCursor = null;
        }

        closeFilledWindowLocked();
    
public BulkCursorDescriptorgetBulkCursorDescriptor()
Returns an object that contains sufficient metadata to reconstruct the cursor remotely. May throw if an error occurs when executing the query and obtaining the row count.

        synchronized (mLock) {
            throwIfCursorIsClosed();

            BulkCursorDescriptor d = new BulkCursorDescriptor();
            d.cursor = this;
            d.columnNames = mCursor.getColumnNames();
            d.wantsAllOnMoveCalls = mCursor.getWantsAllOnMoveCalls();
            d.count = mCursor.getCount();
            d.window = mCursor.getWindow();
            if (d.window != null) {
                // Acquire a reference to the window because its reference count will be
                // decremented when it is returned as part of the binder call reply parcel.
                d.window.acquireReference();
            }
            return d;
        }
    
public BundlegetExtras()

        synchronized (mLock) {
            throwIfCursorIsClosed();

            return mCursor.getExtras();
        }
    
public CursorWindowgetWindow(int position)

        synchronized (mLock) {
            throwIfCursorIsClosed();

            if (!mCursor.moveToPosition(position)) {
                closeFilledWindowLocked();
                return null;
            }

            CursorWindow window = mCursor.getWindow();
            if (window != null) {
                closeFilledWindowLocked();
            } else {
                window = mFilledWindow;
                if (window == null) {
                    mFilledWindow = new CursorWindow(mProviderName);
                    window = mFilledWindow;
                } else if (position < window.getStartPosition()
                        || position >= window.getStartPosition() + window.getNumRows()) {
                    window.clear();
                }
                mCursor.fillWindow(position, window);
            }

            if (window != null) {
                // Acquire a reference to the window because its reference count will be
                // decremented when it is returned as part of the binder call reply parcel.
                window.acquireReference();
            }
            return window;
        }
    
public voidonMove(int position)

        synchronized (mLock) {
            throwIfCursorIsClosed();

            mCursor.onMove(mCursor.getPosition(), position);
        }
    
public intrequery(IContentObserver observer)

        synchronized (mLock) {
            throwIfCursorIsClosed();

            closeFilledWindowLocked();

            try {
                if (!mCursor.requery()) {
                    return -1;
                }
            } catch (IllegalStateException e) {
                IllegalStateException leakProgram = new IllegalStateException(
                        mProviderName + " Requery misuse db, mCursor isClosed:" +
                        mCursor.isClosed(), e);
                throw leakProgram;
            }

            unregisterObserverProxyLocked();
            createAndRegisterObserverProxyLocked(observer);
            return mCursor.getCount();
        }
    
public Bundlerespond(Bundle extras)

        synchronized (mLock) {
            throwIfCursorIsClosed();

            return mCursor.respond(extras);
        }
    
private voidthrowIfCursorIsClosed()

        if (mCursor == null) {
            throw new StaleDataException("Attempted to access a cursor after it has been closed.");
        }
    
private voidunregisterObserverProxyLocked()
Unregister the observer if it is already registered.

        if (mObserver != null) {
            mCursor.unregisterContentObserver(mObserver);
            mObserver.unlinkToDeath(this);
            mObserver = null;
        }