Merge "Use flags to indicate reason for Uri changes." into rvc-dev

This commit is contained in:
Jeff Sharkey
2020-03-06 00:04:24 +00:00
committed by Android (Google) Code Review
7 changed files with 358 additions and 143 deletions

View File

@@ -629,7 +629,10 @@ public abstract class ContentResolver implements ContentInterface {
/** @hide */
@IntDef(flag = true, prefix = { "NOTIFY_" }, value = {
NOTIFY_SYNC_TO_NETWORK,
NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS
NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS,
NOTIFY_INSERT,
NOTIFY_UPDATE,
NOTIFY_DELETE
})
@Retention(RetentionPolicy.SOURCE)
public @interface NotifyFlags {}
@@ -650,6 +653,36 @@ public abstract class ContentResolver implements ContentInterface {
*/
public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 1<<1;
/**
* Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set
* by a {@link ContentProvider} to indicate that this notification is the
* result of an {@link ContentProvider#insert} call.
* <p>
* Sending these detailed flags are optional, but providers are strongly
* recommended to send them.
*/
public static final int NOTIFY_INSERT = 1 << 2;
/**
* Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set
* by a {@link ContentProvider} to indicate that this notification is the
* result of an {@link ContentProvider#update} call.
* <p>
* Sending these detailed flags are optional, but providers are strongly
* recommended to send them.
*/
public static final int NOTIFY_UPDATE = 1 << 3;
/**
* Flag for {@link #notifyChange(Uri, ContentObserver, int)}: typically set
* by a {@link ContentProvider} to indicate that this notification is the
* result of a {@link ContentProvider#delete} call.
* <p>
* Sending these detailed flags are optional, but providers are strongly
* recommended to send them.
*/
public static final int NOTIFY_DELETE = 1 << 4;
/**
* No exception, throttled by app standby normally.
* @hide

View File

@@ -16,11 +16,17 @@
package android.database;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver.NotifyFlags;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import java.util.Arrays;
/**
* Receives call backs for changes to content.
* Must be implemented by objects which are added to a {@link ContentObservable}.
@@ -101,12 +107,10 @@ public abstract class ContentObserver {
* This method is called when a content change occurs.
* Includes the changed content Uri when available.
* <p>
* Subclasses should override this method to handle content changes.
* To ensure correct operation on older versions of the framework that
* did not provide a Uri argument, applications should also implement
* the {@link #onChange(boolean)} overload of this method whenever they
* implement the {@link #onChange(boolean, Uri)} overload.
* </p><p>
* Subclasses should override this method to handle content changes. To
* ensure correct operation on older versions of the framework that did not
* provide richer arguments, applications should implement all overloads.
* <p>
* Example implementation:
* <pre><code>
* // Implement the onChange(boolean) method to delegate the change notification to
@@ -126,38 +130,63 @@ public abstract class ContentObserver {
* </p>
*
* @param selfChange True if this is a self-change notification.
* @param uri The Uri of the changed content, or null if unknown.
* @param uri The Uri of the changed content.
*/
public void onChange(boolean selfChange, Uri uri) {
public void onChange(boolean selfChange, @Nullable Uri uri) {
onChange(selfChange);
}
/**
* Dispatches a change notification to the observer. Includes the changed
* content Uri when available and also the user whose content changed.
* This method is called when a content change occurs. Includes the changed
* content Uri when available.
* <p>
* Subclasses should override this method to handle content changes. To
* ensure correct operation on older versions of the framework that did not
* provide richer arguments, applications should implement all overloads.
*
* @param selfChange True if this is a self-change notification.
* @param uri The Uri of the changed content, or null if unknown.
* @param userId The user whose content changed. Can be either a specific
* user or {@link UserHandle#USER_ALL}.
*
* @hide
* @param uri The Uri of the changed content.
* @param flags Flags indicating details about this change.
*/
public void onChange(boolean selfChange, Uri uri, int userId) {
public void onChange(boolean selfChange, @Nullable Uri uri, @NotifyFlags int flags) {
onChange(selfChange, uri);
}
/**
* This method is called when a content change occurs. Includes the changed
* content Uris when available.
* <p>
* Subclasses should override this method to handle content changes. To
* ensure correct operation on older versions of the framework that did not
* provide richer arguments, applications should implement all overloads.
*
* @param selfChange True if this is a self-change notification.
* @param uris The Uris of the changed content.
* @param flags Flags indicating details about this change.
*/
public void onChange(boolean selfChange, @NonNull Iterable<Uri> uris, @NotifyFlags int flags) {
for (Uri uri : uris) {
onChange(selfChange, uri, flags);
}
}
/** @hide */
public void onChange(boolean selfChange, @NonNull Iterable<Uri> uris, @NotifyFlags int flags,
@UserIdInt int userId) {
onChange(selfChange, uris, flags);
}
/**
* Dispatches a change notification to the observer.
* <p>
* If a {@link Handler} was supplied to the {@link ContentObserver} constructor,
* then a call to the {@link #onChange} method is posted to the handler's message queue.
* Otherwise, the {@link #onChange} method is invoked immediately on this thread.
* </p>
* If a {@link Handler} was supplied to the {@link ContentObserver}
* constructor, then a call to the {@link #onChange} method is posted to the
* handler's message queue. Otherwise, the {@link #onChange} method is
* invoked immediately on this thread.
*
* @param selfChange True if this is a self-change notification.
*
* @deprecated Use {@link #dispatchChange(boolean, Uri)} instead.
* @deprecated Callers should migrate towards using a richer overload that
* provides more details about the change, such as
* {@link #dispatchChange(boolean, Iterable, int)}.
*/
@Deprecated
public final void dispatchChange(boolean selfChange) {
@@ -165,57 +194,66 @@ public abstract class ContentObserver {
}
/**
* Dispatches a change notification to the observer.
* Includes the changed content Uri when available.
* Dispatches a change notification to the observer. Includes the changed
* content Uri when available.
* <p>
* If a {@link Handler} was supplied to the {@link ContentObserver} constructor,
* then a call to the {@link #onChange} method is posted to the handler's message queue.
* Otherwise, the {@link #onChange} method is invoked immediately on this thread.
* </p>
* If a {@link Handler} was supplied to the {@link ContentObserver}
* constructor, then a call to the {@link #onChange} method is posted to the
* handler's message queue. Otherwise, the {@link #onChange} method is
* invoked immediately on this thread.
*
* @param selfChange True if this is a self-change notification.
* @param uri The Uri of the changed content, or null if unknown.
* @param uri The Uri of the changed content.
*/
public final void dispatchChange(boolean selfChange, Uri uri) {
dispatchChange(selfChange, uri, UserHandle.getCallingUserId());
public final void dispatchChange(boolean selfChange, @Nullable Uri uri) {
dispatchChange(selfChange, Arrays.asList(uri), 0, UserHandle.getCallingUserId());
}
/**
* Dispatches a change notification to the observer. Includes the changed
* content Uri when available and also the user whose content changed.
* content Uri when available.
* <p>
* If a {@link Handler} was supplied to the {@link ContentObserver} constructor,
* then a call to the {@link #onChange} method is posted to the handler's message queue.
* Otherwise, the {@link #onChange} method is invoked immediately on this thread.
* </p>
* If a {@link Handler} was supplied to the {@link ContentObserver}
* constructor, then a call to the {@link #onChange} method is posted to the
* handler's message queue. Otherwise, the {@link #onChange} method is
* invoked immediately on this thread.
*
* @param selfChange True if this is a self-change notification.
* @param uri The Uri of the changed content, or null if unknown.
* @param userId The user whose content changed.
* @param uri The Uri of the changed content.
* @param flags Flags indicating details about this change.
*/
private void dispatchChange(boolean selfChange, Uri uri, int userId) {
if (mHandler == null) {
onChange(selfChange, uri, userId);
} else {
mHandler.post(new NotificationRunnable(selfChange, uri, userId));
}
public final void dispatchChange(boolean selfChange, @Nullable Uri uri,
@NotifyFlags int flags) {
dispatchChange(selfChange, Arrays.asList(uri), flags, UserHandle.getCallingUserId());
}
/**
* Dispatches a change notification to the observer. Includes the changed
* content Uris when available.
* <p>
* If a {@link Handler} was supplied to the {@link ContentObserver}
* constructor, then a call to the {@link #onChange} method is posted to the
* handler's message queue. Otherwise, the {@link #onChange} method is
* invoked immediately on this thread.
*
* @param selfChange True if this is a self-change notification.
* @param uris The Uri of the changed content.
* @param flags Flags indicating details about this change.
*/
public final void dispatchChange(boolean selfChange, @NonNull Iterable<Uri> uris,
@NotifyFlags int flags) {
dispatchChange(selfChange, uris, flags, UserHandle.getCallingUserId());
}
private final class NotificationRunnable implements Runnable {
private final boolean mSelfChange;
private final Uri mUri;
private final int mUserId;
public NotificationRunnable(boolean selfChange, Uri uri, int userId) {
mSelfChange = selfChange;
mUri = uri;
mUserId = userId;
}
@Override
public void run() {
ContentObserver.this.onChange(mSelfChange, mUri, mUserId);
/** @hide */
public final void dispatchChange(boolean selfChange, @NonNull Iterable<Uri> uris,
@NotifyFlags int flags, @UserIdInt int userId) {
if (mHandler == null) {
onChange(selfChange, uris, flags, userId);
} else {
mHandler.post(() -> {
onChange(selfChange, uris, flags, userId);
});
}
}
@@ -228,9 +266,16 @@ public abstract class ContentObserver {
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
// This is kept intact purely for apps using hidden APIs, to
// redirect to the updated implementation
onChangeEtc(selfChange, new Uri[] { uri }, 0, userId);
}
@Override
public void onChangeEtc(boolean selfChange, Uri[] uris, int flags, int userId) {
ContentObserver contentObserver = mContentObserver;
if (contentObserver != null) {
contentObserver.dispatchChange(selfChange, uri, userId);
contentObserver.dispatchChange(selfChange, Arrays.asList(uris), flags, userId);
}
}

View File

@@ -16,9 +16,14 @@
package android.database;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.ContentResolver.NotifyFlags;
import android.net.Uri;
import android.os.*;
import java.util.ArrayList;
/**
* Wraps a BulkCursor around an existing Cursor making it remotable.
@@ -76,9 +81,18 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative
}
@Override
public void onChange(boolean selfChange, Uri uri) {
public void onChange(boolean selfChange, @NonNull Iterable<Uri> uris,
@NotifyFlags int flags, @UserIdInt int userId) {
// Since we deliver changes from the most-specific to least-specific
// overloads, we only need to redirect from the most-specific local
// method to the most-specific remote method
final ArrayList<Uri> asList = new ArrayList<>();
uris.forEach(asList::add);
final Uri[] asArray = asList.toArray(new Uri[asList.size()]);
try {
mRemote.onChange(selfChange, uri, android.os.Process.myUid());
mRemote.onChangeEtc(selfChange, asArray, flags, userId);
} catch (RemoteException ex) {
// Do nothing, the far side is dead
}

View File

@@ -22,8 +22,7 @@ import android.net.Uri;
/**
* @hide
*/
interface IContentObserver
{
interface IContentObserver {
/**
* This method is called when an update occurs to the cursor that is being
* observed. selfUpdate is true if the update was caused by a call to
@@ -31,4 +30,11 @@ interface IContentObserver
*/
@UnsupportedAppUsage
oneway void onChange(boolean selfUpdate, in Uri uri, int userId);
/**
* This method is called when an update occurs to the cursor that is being
* observed. selfUpdate is true if the update was caused by a call to
* commit on the cursor that is being observed.
*/
oneway void onChangeEtc(boolean selfUpdate, in Uri[] uri, int flags, int userId);
}