diff options
author | Sudheer Shanka <sudheersai@google.com> | 2019-01-26 10:40:42 -0800 |
---|---|---|
committer | Sudheer Shanka <sudheersai@google.com> | 2019-01-26 11:19:34 -0800 |
commit | a07b052eb4e210329a9f81e6783baed66533143f (patch) | |
tree | 8c3b2883e0ace6a6af4ff2a77c777ef4faeb57bf | |
parent | 2bfd202ec50bff7e94d178a63e35b77009ea915b (diff) |
Add Cursor.{set,get}NotificationUris.
Bug: 120879205
Test: manual
Test: atest cts/tests/tests/database/src/android/database/cts/AbstractCursorTest.java
Change-Id: If3be228dc6b08ea58d24c9209822f9d8c2348082
-rw-r--r-- | api/current.txt | 2 | ||||
-rw-r--r-- | core/java/android/database/AbstractCursor.java | 49 | ||||
-rw-r--r-- | core/java/android/database/Cursor.java | 42 | ||||
-rw-r--r-- | core/java/android/database/CursorWrapper.java | 12 | ||||
-rw-r--r-- | test-mock/src/android/test/mock/MockCursor.java | 12 |
5 files changed, 108 insertions, 9 deletions
diff --git a/api/current.txt b/api/current.txt index bb6dbeba2e7a..e397d3da8463 100644 --- a/api/current.txt +++ b/api/current.txt @@ -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 diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java index 8bcaa4526fa7..b44458a7d449 100644 --- a/core/java/android/database/AbstractCursor.java +++ b/core/java/android/database/AbstractCursor.java @@ -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; } } @@ -424,6 +450,13 @@ public abstract class AbstractCursor implements CrossProcessCursor { } @Override + public List<Uri> getNotificationUris() { + synchronized (mSelfObserverLock) { + return mNotifyUris; + } + } + + @Override public boolean getWantsAllOnMoveCalls() { return false; } diff --git a/core/java/android/database/Cursor.java b/core/java/android/database/Cursor.java index 5a4280e997cd..1379138b37c0 100644 --- a/core/java/android/database/Cursor.java +++ b/core/java/android/database/Cursor.java @@ -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,7 +424,10 @@ 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. @@ -429,6 +435,24 @@ public interface Cursor extends Closeable { 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}. * @return Returns a URI that can be used with @@ -439,6 +463,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(). */ diff --git a/core/java/android/database/CursorWrapper.java b/core/java/android/database/CursorWrapper.java index 0d27dfb872f0..c9cafafe4041 100644 --- a/core/java/android/database/CursorWrapper.java +++ b/core/java/android/database/CursorWrapper.java @@ -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. @@ -241,11 +243,21 @@ public class CursorWrapper implements Cursor { } @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); } diff --git a/test-mock/src/android/test/mock/MockCursor.java b/test-mock/src/android/test/mock/MockCursor.java index 576f24ad6384..f69db2c84111 100644 --- a/test-mock/src/android/test/mock/MockCursor.java +++ b/test-mock/src/android/test/mock/MockCursor.java @@ -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. @@ -226,11 +228,21 @@ public class MockCursor implements Cursor { } @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"); } |