Merge "Add a CrossProcessCursorWrapper. Bug: 5220669"

This commit is contained in:
Jeff Brown
2011-10-14 21:06:22 -07:00
committed by Android (Google) Code Review
6 changed files with 138 additions and 16 deletions

View File

@@ -6782,6 +6782,13 @@ package android.database {
method public abstract boolean onMove(int, int); method public abstract boolean onMove(int, int);
} }
public class CrossProcessCursorWrapper extends android.database.CursorWrapper implements android.database.CrossProcessCursor {
ctor public CrossProcessCursorWrapper(android.database.Cursor);
method public void fillWindow(int, android.database.CursorWindow);
method public android.database.CursorWindow getWindow();
method public boolean onMove(int, int);
}
public abstract interface Cursor { public abstract interface Cursor {
method public abstract void close(); method public abstract void close();
method public abstract void copyStringToBuffer(int, android.database.CharArrayBuffer); method public abstract void copyStringToBuffer(int, android.database.CharArrayBuffer);

View File

@@ -26,6 +26,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.CrossProcessCursorWrapper;
import android.database.Cursor; import android.database.Cursor;
import android.database.CursorWrapper; import android.database.CursorWrapper;
import android.database.IContentObserver; import android.database.IContentObserver;
@@ -1568,7 +1569,7 @@ public abstract class ContentResolver {
samplePercent); samplePercent);
} }
private final class CursorWrapperInner extends CursorWrapper { private final class CursorWrapperInner extends CrossProcessCursorWrapper {
private final IContentProvider mContentProvider; private final IContentProvider mContentProvider;
public static final String TAG="CursorWrapperInner"; public static final String TAG="CursorWrapperInner";

View File

@@ -16,27 +16,63 @@
package android.database; package android.database;
/**
* A cross process cursor is an extension of a {@link Cursor} that also supports
* usage from remote processes.
* <p>
* The contents of a cross process cursor are marshalled to the remote process by
* filling {@link CursorWindow} objects using {@link #fillWindow}. As an optimization,
* the cursor can provide a pre-filled window to use via {@link #getWindow} thereby
* obviating the need to copy the data to yet another cursor window.
*/
public interface CrossProcessCursor extends Cursor { public interface CrossProcessCursor extends Cursor {
/** /**
* returns a pre-filled window, return NULL if no such window * Returns a pre-filled window that contains the data within this cursor.
* <p>
* In particular, the window contains the row indicated by {@link Cursor#getPosition}.
* The window's contents are automatically scrolled whenever the current
* row moved outside the range covered by the window.
* </p>
*
* @return The pre-filled window, or null if none.
*/ */
CursorWindow getWindow(); CursorWindow getWindow();
/** /**
* copies cursor data into the window start at pos * Copies cursor data into the window.
* <p>
* Clears the window and fills it with data beginning at the requested
* row position until all of the data in the cursor is exhausted
* or the window runs out of space.
* </p><p>
* The filled window uses the same row indices as the original cursor.
* For example, if you fill a window starting from row 5 from the cursor,
* you can query the contents of row 5 from the window just by asking it
* for row 5 because there is a direct correspondence between the row indices
* used by the cursor and the window.
* </p><p>
* The current position of the cursor, as returned by {@link #getPosition},
* is not changed by this method.
* </p>
*
* @param position The zero-based index of the first row to copy into the window.
* @param window The window to fill.
*/ */
void fillWindow(int pos, CursorWindow winow); void fillWindow(int position, CursorWindow window);
/** /**
* This function is called every time the cursor is successfully scrolled * This function is called every time the cursor is successfully scrolled
* to a new position, giving the subclass a chance to update any state it * to a new position, giving the subclass a chance to update any state it
* may have. If it returns false the move function will also do so and the * may have. If it returns false the move function will also do so and the
* cursor will scroll to the beforeFirst position. * cursor will scroll to the beforeFirst position.
* <p>
* This function should be called by methods such as {@link #moveToPosition(int)},
* so it will typically not be called from outside of the cursor class itself.
* </p>
* *
* @param oldPosition the position that we're moving from * @param oldPosition The position that we're moving from.
* @param newPosition the position that we're moving to * @param newPosition The position that we're moving to.
* @return true if the move is successful, false otherwise * @return True if the move is successful, false otherwise.
*/ */
boolean onMove(int oldPosition, int newPosition); boolean onMove(int oldPosition, int newPosition);
} }

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.database;
import android.database.CrossProcessCursor;
import android.database.Cursor;
import android.database.CursorWindow;
import android.database.CursorWrapper;
/**
* Cursor wrapper that implements {@link CrossProcessCursor}.
* <p>
* If the wrapper cursor implemented {@link CrossProcessCursor}, then delegates
* {@link #fillWindow}, {@link #getWindow()} and {@link #onMove} to it. Otherwise,
* provides default implementations of these methods that traverse the contents
* of the cursor similar to {@link AbstractCursor#fillWindow}.
* </p><p>
* This wrapper can be used to adapt an ordinary {@link Cursor} into a
* {@link CrossProcessCursor}.
* </p>
*/
public class CrossProcessCursorWrapper extends CursorWrapper implements CrossProcessCursor {
/**
* Creates a cross process cursor wrapper.
* @param cursor The underlying cursor to wrap.
*/
public CrossProcessCursorWrapper(Cursor cursor) {
super(cursor);
}
@Override
public void fillWindow(int position, CursorWindow window) {
if (mCursor instanceof CrossProcessCursor) {
final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor;
crossProcessCursor.fillWindow(position, window);
return;
}
DatabaseUtils.cursorFillWindow(mCursor, position, window);
}
@Override
public CursorWindow getWindow() {
if (mCursor instanceof CrossProcessCursor) {
final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor;
return crossProcessCursor.getWindow();
}
return null;
}
@Override
public boolean onMove(int oldPosition, int newPosition) {
if (mCursor instanceof CrossProcessCursor) {
final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor;
return crossProcessCursor.onMove(oldPosition, newPosition);
}
return true;
}
}

View File

@@ -89,11 +89,10 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative
public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer, public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer,
String providerName) { String providerName) {
try { if (cursor instanceof CrossProcessCursor) {
mCursor = (CrossProcessCursor) cursor; mCursor = (CrossProcessCursor)cursor;
} catch (ClassCastException e) { } else {
throw new UnsupportedOperationException( mCursor = new CrossProcessCursorWrapper(cursor);
"Only CrossProcessCursor cursors are supported across process for now", e);
} }
mProviderName = providerName; mProviderName = providerName;

View File

@@ -25,9 +25,13 @@ import android.os.Bundle;
* use for this class is to extend a cursor while overriding only a subset of its methods. * use for this class is to extend a cursor while overriding only a subset of its methods.
*/ */
public class CursorWrapper implements Cursor { public class CursorWrapper implements Cursor {
/** @hide */
protected final Cursor mCursor;
private final Cursor mCursor; /**
* Creates a cursor wrapper.
* @param cursor The underlying cursor to wrap.
*/
public CursorWrapper(Cursor cursor) { public CursorWrapper(Cursor cursor) {
mCursor = cursor; mCursor = cursor;
} }