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

Commit e5fdc96a authored by Jeff DeCew's avatar Jeff DeCew
Browse files

Add ExecutorContentObserver.

This allows creating a ContentObserver with an Executor instead of a Handler.

This is currently done by creating an awkward constructor on ContentObserver that takes an Executor and an unused int to avoid breaking source compatibility. It is marked with @hide because it is really awkward.
ExecutorContentObserver, which is less weird, is also marked @hide. This could theoretically be unhidden, but will be valuable to platform source even as-is.

Change-Id: Ie3a0f200abcf1834cbf969186dc3a5aa11efb8a4
Fixes: 232409779
parent ca834953
Loading
Loading
Loading
Loading
+24 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.os.UserHandle;

import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.Executor;

/**
 * Receives call backs for changes to content.
@@ -54,6 +55,7 @@ public abstract class ContentObserver {
    private Transport mTransport; // guarded by mLock

    Handler mHandler;
    private final Executor mExecutor;

    /**
     * Creates a content observer.
@@ -62,6 +64,18 @@ public abstract class ContentObserver {
     */
    public ContentObserver(Handler handler) {
        mHandler = handler;
        mExecutor = null;
    }

    /**
     * @hide
     * Creates a content observer with an executor.
     *
     * @param executor The executor to run {@link #onChange} on, or null if none.
     * @param unused a second argument to avoid source incompatibility.
     */
    public ContentObserver(@Nullable Executor executor, int unused) {
        mExecutor = executor;
    }

    /**
@@ -306,12 +320,19 @@ public abstract class ContentObserver {
    /** @hide */
    public final void dispatchChange(boolean selfChange, @NonNull Collection<Uri> uris,
            @NotifyFlags int flags, @UserIdInt int userId) {
        if (mHandler == null) {
        if (mExecutor != null) {
            mExecutor.execute(() -> {
                onChange(selfChange, uris, flags, userId);
        } else {
            });
        } else if (mHandler != null) {
            // Supporting Handler directly rather than wrapping in a HandlerExecutor
            //  avoids introducing a RejectedExecutionException for legacy code when
            //  the post fails.
            mHandler.post(() -> {
                onChange(selfChange, uris, flags, userId);
            });
        } else {
            onChange(selfChange, uris, flags, userId);
        }
    }

+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.annotation.Nullable;

import java.util.concurrent.Executor;

/**
 * @hide
 *
 * Receives callbacks for changes to content.
 * Must be implemented by objects which are added to a {@link ContentObservable}.
 */
public abstract class ExecutorContentObserver extends ContentObserver {
    /**
     * Creates a content observer that uses an executor for change handling.
     *
     * @param executor The executor to run {@link #onChange} on, or null if none.
     */
    public ExecutorContentObserver(@Nullable Executor executor) {
        super(executor, 0);
    }
}