Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03263747 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Allow sending of bulk Uri change notifications."

parents 532431d1 1307f428
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -9650,8 +9650,9 @@ package android.content {
    method public static boolean isSyncPending(android.accounts.Account, String);
    method @NonNull public android.graphics.Bitmap loadThumbnail(@NonNull android.net.Uri, @NonNull android.util.Size, @Nullable android.os.CancellationSignal) throws java.io.IOException;
    method public void notifyChange(@NonNull android.net.Uri, @Nullable android.database.ContentObserver);
    method public void notifyChange(@NonNull android.net.Uri, @Nullable android.database.ContentObserver, boolean);
    method @Deprecated public void notifyChange(@NonNull android.net.Uri, @Nullable android.database.ContentObserver, boolean);
    method public void notifyChange(@NonNull android.net.Uri, @Nullable android.database.ContentObserver, int);
    method public void notifyChange(@NonNull Iterable<android.net.Uri>, @Nullable android.database.ContentObserver, int);
    method @Nullable public final android.content.res.AssetFileDescriptor openAssetFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;
    method @Nullable public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(@NonNull android.net.Uri, @NonNull String) throws java.io.FileNotFoundException;
    method @Nullable public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;
+72 −21
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
import android.util.Size;
import android.util.SparseArray;

import com.android.internal.util.MimeIconUtils;
import com.android.internal.util.Preconditions;
@@ -2381,15 +2382,15 @@ public abstract class ContentResolver implements ContentInterface {
     *            true.
     * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
     * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
     * @deprecated callers should consider migrating to
     *             {@link #notifyChange(Uri, ContentObserver, int)}, as it
     *             offers support for many more options than just
     *             {@link #NOTIFY_SYNC_TO_NETWORK}.
     */
    @Deprecated
    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
            boolean syncToNetwork) {
        Preconditions.checkNotNull(uri, "uri");
        notifyChange(
                ContentProvider.getUriWithoutUserId(uri),
                observer,
                syncToNetwork,
                ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
        notifyChange(uri, observer, syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0);
    }

    /**
@@ -2398,10 +2399,10 @@ public abstract class ContentResolver implements ContentInterface {
     * To observe events sent through this call, use
     * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
     * <p>
     * If syncToNetwork is true, this will attempt to schedule a local sync
     * using the sync adapter that's registered for the authority of the
     * provided uri. No account will be passed to the sync adapter, so all
     * matching accounts will be synchronized.
     * If {@link #NOTIFY_SYNC_TO_NETWORK} is set, this will attempt to schedule
     * a local sync using the sync adapter that's registered for the authority
     * of the provided uri. No account will be passed to the sync adapter, so
     * all matching accounts will be synchronized.
     * <p>
     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
     * notifications must be backed by a valid {@link ContentProvider}.
@@ -2426,22 +2427,72 @@ public abstract class ContentResolver implements ContentInterface {
                ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
    }

    /**
     * Notify registered observers that several rows have been updated.
     * <p>
     * To observe events sent through this call, use
     * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
     * <p>
     * If {@link #NOTIFY_SYNC_TO_NETWORK} is set, this will attempt to schedule
     * a local sync using the sync adapter that's registered for the authority
     * of the provided uri. No account will be passed to the sync adapter, so
     * all matching accounts will be synchronized.
     * <p>
     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
     * notifications must be backed by a valid {@link ContentProvider}.
     *
     * @param uris The uris of the content that was changed.
     * @param observer The observer that originated the change, may be
     *            <code>null</null>. The observer that originated the change
     *            will only receive the notification if it has requested to
     *            receive self-change notifications by implementing
     *            {@link ContentObserver#deliverSelfNotifications()} to return
     *            true.
     * @param flags Flags such as {@link #NOTIFY_SYNC_TO_NETWORK} or
     *            {@link #NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS}.
     */
    public void notifyChange(@NonNull Iterable<Uri> uris, @Nullable ContentObserver observer,
            @NotifyFlags int flags) {
        Preconditions.checkNotNull(uris, "uris");

        // Cluster based on user ID
        final SparseArray<ArrayList<Uri>> clusteredByUser = new SparseArray<>();
        for (Uri uri : uris) {
            final int userId = ContentProvider.getUserIdFromUri(uri, mContext.getUserId());
            ArrayList<Uri> list = clusteredByUser.get(userId);
            if (list == null) {
                list = new ArrayList<>();
                clusteredByUser.put(userId, list);
            }
            list.add(ContentProvider.getUriWithoutUserId(uri));
        }

        for (int i = 0; i < clusteredByUser.size(); i++) {
            final int userId = clusteredByUser.keyAt(i);
            final ArrayList<Uri> list = clusteredByUser.valueAt(i);
            notifyChange(list.toArray(new Uri[list.size()]), observer, flags, userId);
        }
    }

    /**
     * Notify registered observers within the designated user(s) that a row was updated.
     *
     * @deprecated callers should consider migrating to
     *             {@link #notifyChange(Uri, ContentObserver, int)}, as it
     *             offers support for many more options than just
     *             {@link #NOTIFY_SYNC_TO_NETWORK}.
     * @hide
     */
    @Deprecated
    public void notifyChange(@NonNull Uri uri, ContentObserver observer, boolean syncToNetwork,
            @UserIdInt int userHandle) {
        try {
            getContentService().notifyChange(
                    uri, observer == null ? null : observer.getContentObserver(),
                    observer != null && observer.deliverSelfNotifications(),
                    syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
                    userHandle, mTargetSdkVersion, mContext.getPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        notifyChange(uri, observer, syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0, userHandle);
    }

    /** {@hide} */
    public void notifyChange(@NonNull Uri uri, ContentObserver observer, @NotifyFlags int flags,
            @UserIdInt int userHandle) {
        notifyChange(new Uri[] { uri }, observer, flags, userHandle);
    }

    /**
@@ -2449,11 +2500,11 @@ public abstract class ContentResolver implements ContentInterface {
     *
     * @hide
     */
    public void notifyChange(@NonNull Uri uri, ContentObserver observer, @NotifyFlags int flags,
    public void notifyChange(@NonNull Uri[] uris, ContentObserver observer, @NotifyFlags int flags,
            @UserIdInt int userHandle) {
        try {
            getContentService().notifyChange(
                    uri, observer == null ? null : observer.getContentObserver(),
                    uris, observer == null ? null : observer.getContentObserver(),
                    observer != null && observer.deliverSelfNotifications(), flags,
                    userHandle, mTargetSdkVersion, mContext.getPackageName());
        } catch (RemoteException e) {
+1 −1
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ interface IContentService {
     *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL
     *     USER_CURRENT are properly interpreted.
     */
    void notifyChange(in Uri uri, IContentObserver observer,
    void notifyChange(in Uri[] uris, IContentObserver observer,
            boolean observerWantsSelfNotifications, int flags,
            int userHandle, int targetSdkVersion, String callingPackage);

+9 −0
Original line number Diff line number Diff line
@@ -394,6 +394,15 @@ public final class ContentService extends IContentService.Stub {
     *     allowed.
     */
    @Override
    public void notifyChange(Uri[] uris, IContentObserver observer,
            boolean observerWantsSelfNotifications, int flags, int userHandle,
            int targetSdkVersion, String callingPackage) {
        for (Uri uri : uris) {
            notifyChange(uri, observer, observerWantsSelfNotifications, flags, userHandle,
                    targetSdkVersion, callingPackage);
        }
    }

    public void notifyChange(Uri uri, IContentObserver observer,
            boolean observerWantsSelfNotifications, int flags, int userHandle,
            int targetSdkVersion, String callingPackage) {
+40 −8
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.test.mock;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -130,17 +132,47 @@ public class MockContentResolver extends ContentResolver {
    }

    /**
     * Overrides {@link android.content.ContentResolver#notifyChange(Uri, ContentObserver, boolean)
     * ContentResolver.notifChange(Uri, ContentObserver, boolean)}. All parameters are ignored.
     * The method hides providers linked to MockContentResolver from other observers in the system.
     * Overrides the behavior from the parent class to completely ignore any
     * content notifications sent to this object. This effectively hides clients
     * from observers elsewhere in the system.
     */
    @Override
    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
    }

    /**
     * Overrides the behavior from the parent class to completely ignore any
     * content notifications sent to this object. This effectively hides clients
     * from observers elsewhere in the system.
     *
     * @param uri (Ignored) The uri of the content provider.
     * @param observer (Ignored) The observer that originated the change.
     * @param syncToNetwork (Ignored) If true, attempt to sync the change to the network.
     * @deprecated callers should consider migrating to
     *             {@link #notifyChange(Uri, ContentObserver, int)}, as it
     *             offers support for many more options than just
     *             {@link #NOTIFY_SYNC_TO_NETWORK}.
     */
    @Override
    public void notifyChange(Uri uri,
            ContentObserver observer,
    @Deprecated
    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
            boolean syncToNetwork) {
    }

    /**
     * Overrides the behavior from the parent class to completely ignore any
     * content notifications sent to this object. This effectively hides clients
     * from observers elsewhere in the system.
     */
    @Override
    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
            @NotifyFlags int flags) {
    }

    /**
     * Overrides the behavior from the parent class to completely ignore any
     * content notifications sent to this object. This effectively hides clients
     * from observers elsewhere in the system.
     */
    @Override
    public void notifyChange(@NonNull Iterable<Uri> uris, @Nullable ContentObserver observer,
            @NotifyFlags int flags) {
    }
}