Merge "Add Cursor.{set,get}NotificationUris."

This commit is contained in:
Sudheer Shanka
2019-01-27 23:00:13 +00:00
committed by Android (Google) Code Review
5 changed files with 108 additions and 9 deletions

View File

@@ -12512,6 +12512,7 @@ package android.database {
method public int getInt(int);
method public long getLong(int);
method public android.net.Uri getNotificationUri();
method public default java.util.List<android.net.Uri> getNotificationUris();
method public int getPosition();
method public short getShort(int);
method public String getString(int);
@@ -12535,6 +12536,7 @@ package android.database {
method public android.os.Bundle respond(android.os.Bundle);
method public void setExtras(android.os.Bundle);
method public void setNotificationUri(android.content.ContentResolver, android.net.Uri);
method public default void setNotificationUris(@NonNull android.content.ContentResolver, @NonNull java.util.List<android.net.Uri>);
method public void unregisterContentObserver(android.database.ContentObserver);
method public void unregisterDataSetObserver(android.database.DataSetObserver);
field public static final int FIELD_TYPE_BLOB = 4; // 0x4

View File

@@ -16,17 +16,20 @@
package android.database;
import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
import com.android.internal.util.Preconditions;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -72,6 +75,7 @@ public abstract class AbstractCursor implements CrossProcessCursor {
@UnsupportedAppUsage
private Uri mNotifyUri;
private List<Uri> mNotifyUris;
private final Object mSelfObserverLock = new Object();
private ContentObserver mSelfObserver;
@@ -155,7 +159,11 @@ public abstract class AbstractCursor implements CrossProcessCursor {
@Override
public boolean requery() {
if (mSelfObserver != null && mSelfObserverRegistered == false) {
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
final int size = mNotifyUris.size();
for (int i = 0; i < size; ++i) {
final Uri notifyUri = mNotifyUris.get(i);
mContentResolver.registerContentObserver(notifyUri, true, mSelfObserver);
}
mSelfObserverRegistered = true;
}
mDataSetObservable.notifyChanged();
@@ -384,8 +392,12 @@ public abstract class AbstractCursor implements CrossProcessCursor {
protected void onChange(boolean selfChange) {
synchronized (mSelfObserverLock) {
mContentObservable.dispatchChange(selfChange, null);
if (mNotifyUri != null && selfChange) {
mContentResolver.notifyChange(mNotifyUri, mSelfObserver);
if (mNotifyUris != null && selfChange) {
final int size = mNotifyUris.size();
for (int i = 0; i < size; ++i) {
final Uri notifyUri = mNotifyUris.get(i);
mContentResolver.notifyChange(notifyUri, mSelfObserver);
}
}
}
}
@@ -399,19 +411,33 @@ public abstract class AbstractCursor implements CrossProcessCursor {
*/
@Override
public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
setNotificationUri(cr, notifyUri, cr.getUserId());
setNotificationUris(cr, Arrays.asList(notifyUri));
}
@Override
public void setNotificationUris(@NonNull ContentResolver cr, @NonNull List<Uri> notifyUris) {
Preconditions.checkNotNull(cr);
Preconditions.checkNotNull(notifyUris);
setNotificationUris(cr, notifyUris, cr.getUserId());
}
/** @hide - set the notification uri but with an observer for a particular user's view */
public void setNotificationUri(ContentResolver cr, Uri notifyUri, int userHandle) {
public void setNotificationUris(ContentResolver cr, List<Uri> notifyUris, int userHandle) {
synchronized (mSelfObserverLock) {
mNotifyUri = notifyUri;
mNotifyUris = notifyUris;
mNotifyUri = mNotifyUris.get(0);
mContentResolver = cr;
if (mSelfObserver != null) {
mContentResolver.unregisterContentObserver(mSelfObserver);
}
mSelfObserver = new SelfContentObserver(this);
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver, userHandle);
final int size = mNotifyUris.size();
for (int i = 0; i < size; ++i) {
final Uri notifyUri = mNotifyUris.get(i);
mContentResolver.registerContentObserver(
notifyUri, true, mSelfObserver, userHandle);
}
mSelfObserverRegistered = true;
}
}
@@ -423,6 +449,13 @@ public abstract class AbstractCursor implements CrossProcessCursor {
}
}
@Override
public List<Uri> getNotificationUris() {
synchronized (mSelfObserverLock) {
return mNotifyUris;
}
}
@Override
public boolean getWantsAllOnMoveCalls() {
return false;

View File

@@ -16,11 +16,14 @@
package android.database;
import android.annotation.NonNull;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.Bundle;
import java.io.Closeable;
import java.util.Arrays;
import java.util.List;
/**
* This interface provides random read-write access to the result set returned
@@ -421,13 +424,34 @@ public interface Cursor extends Closeable {
/**
* Register to watch a content URI for changes. This can be the URI of a specific data row (for
* example, "content://my_provider_type/23"), or a a generic URI for a content type.
*
*
* <p>Calling this overrides any previous call to
* {@link #setNotificationUris(ContentResolver, List)}.
*
* @param cr The content resolver from the caller's context. The listener attached to
* this resolver will be notified.
* @param uri The content URI to watch.
*/
void setNotificationUri(ContentResolver cr, Uri uri);
/**
* Similar to {@link #setNotificationUri(ContentResolver, Uri)}, except this version allows
* to watch multiple content URIs for changes.
*
* <p>If this is not implemented, this is equivalent to calling
* {@link #setNotificationUri(ContentResolver, Uri)} with the first URI in {@code uris}.
*
* <p>Calling this overrides any previous call to
* {@link #setNotificationUri(ContentResolver, Uri)}.
*
* @param cr The content resolver from the caller's context. The listener attached to
* this resolver will be notified.
* @param uris The content URIs to watch.
*/
default void setNotificationUris(@NonNull ContentResolver cr, @NonNull List<Uri> uris) {
setNotificationUri(cr, uris.get(0));
}
/**
* Return the URI at which notifications of changes in this Cursor's data
* will be delivered, as previously set by {@link #setNotificationUri}.
@@ -438,6 +462,22 @@ public interface Cursor extends Closeable {
*/
Uri getNotificationUri();
/**
* Return the URIs at which notifications of changes in this Cursor's data
* will be delivered, as previously set by {@link #setNotificationUris}.
*
* <p>If this is not implemented, this is equivalent to calling {@link #getNotificationUri()}.
*
* @return Returns URIs that can be used with
* {@link ContentResolver#registerContentObserver(android.net.Uri, boolean, ContentObserver)
* ContentResolver.registerContentObserver} to find out about changes to this Cursor's
* data. May be null if no notification URI has been set.
*/
default List<Uri> getNotificationUris() {
final Uri notifyUri = getNotificationUri();
return notifyUri == null ? null : Arrays.asList(notifyUri);
}
/**
* onMove() will only be called across processes if this method returns true.
* @return whether all cursor movement should result in a call to onMove().

View File

@@ -21,6 +21,8 @@ import android.content.ContentResolver;
import android.net.Uri;
import android.os.Bundle;
import java.util.List;
/**
* Wrapper class for Cursor that delegates all calls to the actual cursor object. The primary
* use for this class is to extend a cursor while overriding only a subset of its methods.
@@ -240,11 +242,21 @@ public class CursorWrapper implements Cursor {
mCursor.setNotificationUri(cr, uri);
}
@Override
public void setNotificationUris(ContentResolver cr, List<Uri> uris) {
mCursor.setNotificationUris(cr, uris);
}
@Override
public Uri getNotificationUri() {
return mCursor.getNotificationUri();
}
@Override
public List<Uri> getNotificationUris() {
return mCursor.getNotificationUris();
}
@Override
public void unregisterContentObserver(ContentObserver observer) {
mCursor.unregisterContentObserver(observer);

View File

@@ -24,6 +24,8 @@ import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Bundle;
import java.util.List;
/**
* A mock {@link android.database.Cursor} class that isolates the test code from real
* Cursor implementation.
@@ -225,11 +227,21 @@ public class MockCursor implements Cursor {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
public void setNotificationUris(ContentResolver cr, List<Uri> uris) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
public Uri getNotificationUri() {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
public List<Uri> getNotificationUris() {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
public void unregisterContentObserver(ContentObserver observer) {
throw new UnsupportedOperationException("unimplemented mock method");