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

Commit e4beb133 authored by Matt Pietal's avatar Matt Pietal Committed by Android (Google) Code Review
Browse files

Merge changes I7ac3a378,Id06a24d2 into rvc-dev

* changes:
  Controls API - Docs + method name change
  Controls API - Publisher change - Phase 2
parents 879f32b1 e44217b3
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -43448,12 +43448,12 @@ package android.service.controls {
  public abstract class ControlsProviderService extends android.app.Service {
    ctor public ControlsProviderService();
    method @Deprecated public void loadAvailableControls(@NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
    method @NonNull public abstract java.util.concurrent.Flow.Publisher<android.service.controls.Control> createPublisherFor(@NonNull java.util.List<java.lang.String>);
    method @NonNull public abstract java.util.concurrent.Flow.Publisher<android.service.controls.Control> createPublisherForAllAvailable();
    method @Nullable public java.util.concurrent.Flow.Publisher<android.service.controls.Control> createPublisherForSuggested();
    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
    method public final boolean onUnbind(@NonNull android.content.Intent);
    method public abstract void performControlAction(@NonNull String, @NonNull android.service.controls.actions.ControlAction, @NonNull java.util.function.Consumer<java.lang.Integer>);
    method @NonNull public abstract java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherFor(@NonNull java.util.List<java.lang.String>);
    method @Nullable public java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherForAllAvailable();
    method @Nullable public java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherForSuggested();
    method public static void requestAddControl(@NonNull android.content.Context, @NonNull android.content.ComponentName, @NonNull android.service.controls.Control);
    field public static final String SERVICE_CONTROLS = "android.service.controls.ControlsProviderService";
    field @NonNull public static final String TAG = "ControlsProviderService";
+126 −33
Original line number Diff line number Diff line
@@ -209,61 +209,116 @@ public final class Control implements Parcelable {
        mStatusText = in.readCharSequence();
    }

    /**
     * @return the identifier for the {@link Control}
     */
    @NonNull
    public String getControlId() {
        return mControlId;
    }


    /**
     * @return type of device represented by this {@link Control}, used to determine the default
     *         icon and color
     */
    @DeviceTypes.DeviceType
    public int getDeviceType() {
        return mDeviceType;
    }

    /**
     * @return the user facing name of the {@link Control}
     */
    @NonNull
    public CharSequence getTitle() {
        return mTitle;
    }

    /**
     * @return additional information about the {@link Control}, to appear underneath the title
     */
    @NonNull
    public CharSequence getSubtitle() {
        return mSubtitle;
    }

    /**
     * Optional top-level group to help define the {@link Control}'s location, visible to the user.
     * If not present, the application name will be used as the top-level group. A structure
     * contains zones which contains controls.
     *
     * @return name of the structure containing the control
     */
    @Nullable
    public CharSequence getStructure() {
        return mStructure;
    }

    /**
     * Optional group name to help define the {@link Control}'s location within a structure,
     * visible to the user. A structure contains zones which contains controls.
     *
     * @return name of the zone containing the control
     */
    @Nullable
    public CharSequence getZone() {
        return mZone;
    }

    /**
     * @return a {@link PendingIntent} linking to an Activity for the {@link Control}
     */
    @NonNull
    public PendingIntent getAppIntent() {
        return mAppIntent;
    }

    /**
     * Optional icon to be shown with the {@link Control}. It is highly recommended
     * to let the system default the icon unless the default icon is not suitable.
     *
     * @return icon to show
     */
    @Nullable
    public Icon getCustomIcon() {
        return mCustomIcon;
    }

    /**
     * Optional color to be shown with the {@link Control}. It is highly recommended
     * to let the system default the color unless the default is not suitable for the
     * application.
     *
     * @return background color to use
     */
    @Nullable
    public ColorStateList getCustomColor() {
        return mCustomColor;
    }

    /**
     * @return status of the {@link Control}, used to convey information about the attempt to
     *         fetch the current state
     */
    @Status
    public int getStatus() {
        return mStatus;
    }

    /**
     * @return instance of {@link ControlTemplate}, that defines how the {@link Control} will
     *         behave and what interactions are available to the user
     */
    @NonNull
    public ControlTemplate getControlTemplate() {
        return mControlTemplate;
    }

    /**
     * @return user-facing text description of the {@link Control}'s status, describing its current
     *         state
     */
    @NonNull
    public CharSequence getStatusText() {
        return mStatusText;
@@ -326,7 +381,10 @@ public final class Control implements Parcelable {
    /**
     * Builder class for {@link Control}.
     *
     * This class facilitates the creation of {@link Control} with no state.
     * This class facilitates the creation of {@link Control} with no state. Must be used to
     * provide controls for {@link ControlsProviderService#createPublisherForAllAvailable} and
     * {@link ControlsProviderService#createPublisherForSuggested}.
     *
     * It provides the following defaults for non-optional parameters:
     * <ul>
     *     <li> Device type: {@link DeviceTypes#TYPE_UNKNOWN}
@@ -334,7 +392,7 @@ public final class Control implements Parcelable {
     *     <li> Subtitle: {@code ""}
     * </ul>
     * This fixes the values relating to state of the {@link Control} as required by
     * {@link ControlsProviderService#loadAvailableControls}:
     * {@link ControlsProviderService#createPublisherForAllAvailable}:
     * <ul>
     *     <li> Status: {@link Status#STATUS_UNKNOWN}
     *     <li> Control template: {@link ControlTemplate#NO_TEMPLATE}
@@ -355,8 +413,8 @@ public final class Control implements Parcelable {
        private @Nullable ColorStateList mCustomColor;

        /**
         * @param controlId the identifier for the {@link Control}.
         * @param appIntent the pending intent linking to the device Activity.
         * @param controlId the identifier for the {@link Control}
         * @param appIntent the pending intent linking to the device Activity
         */
        public StatelessBuilder(@NonNull String controlId,
                @NonNull PendingIntent appIntent) {
@@ -368,6 +426,7 @@ public final class Control implements Parcelable {

        /**
         * Creates a {@link StatelessBuilder} using an existing {@link Control} as a base.
         *
         * @param control base for the builder.
         */
        public StatelessBuilder(@NonNull Control control) {
@@ -384,7 +443,7 @@ public final class Control implements Parcelable {
        }

        /**
         * @param controlId the identifier for the {@link Control}.
         * @param controlId the identifier for the {@link Control}
         * @return {@code this}
         */
        @NonNull
@@ -395,8 +454,8 @@ public final class Control implements Parcelable {
        }

        /**
         * @param deviceType the device type for the {@link Control}. Setting an invalid value not
         *                   in {@link DeviceTypes} will set it to {@link DeviceTypes#TYPE_UNKNOWN}.
         * @param deviceType type of device represented by this {@link Control}, used to
         *                   determine the default icon and color
         * @return {@code this}
         */
        @NonNull
@@ -422,7 +481,8 @@ public final class Control implements Parcelable {
        }

        /**
         * @param subtitle the user facing subtitle for the {@link Control}
         * @param subtitle additional information about the {@link Control}, to appear underneath
         *                 the title
         * @return {@code this}
         */
        @NonNull
@@ -433,8 +493,11 @@ public final class Control implements Parcelable {
        }

        /**
         * @param structure the user facing name of the structure for the {@link Control}.
         *                  {@code null} indicates that it's not associated with any structure.
         * Optional top-level group to help define the {@link Control}'s location, visible to the
         * user. If not present, the application name will be used as the top-level group. A
         * structure contains zones which contains controls.
         *
         * @param structure name of the structure containing the control
         * @return {@code this}
         */
        @NonNull
@@ -444,8 +507,10 @@ public final class Control implements Parcelable {
        }

        /**
         * @param zone the user facing name of the zone for the {@link Control}. {@code null}
         *             indicates that it's not associated with any zone.
         * Optional group name to help define the {@link Control}'s location within a structure,
         * visible to the user. A structure contains zones which contains controls.
         *
         * @param zone name of the zone containing the control
         * @return {@code this}
         */
        @NonNull
@@ -455,7 +520,7 @@ public final class Control implements Parcelable {
        }

        /**
         * @param appIntent an {@link Intent} linking to an Activity for the {@link Control}
         * @param appIntent a {@link PendingIntent} linking to an Activity for the {@link Control}
         * @return {@code this}
         */
        @NonNull
@@ -466,7 +531,10 @@ public final class Control implements Parcelable {
        }

        /**
         * @param customIcon an {@link Icon} to override the one determined by the device type.
         * Optional icon to be shown with the {@link Control}. It is highly recommended
         * to let the system default the icon unless the default icon is not suitable.
         *
         * @param customIcon icon to show
         * @return {@code this}
         */
        @NonNull
@@ -476,7 +544,11 @@ public final class Control implements Parcelable {
        }

        /**
         * @param customColor a list of colors to override the ones determined by the device type.
         * Optional color to be shown with the {@link Control}. It is highly recommended
         * to let the system default the color unless the default is not suitable for the
         * application.
         *
         * @param customColor background color to use
         * @return {@code this}
         */
        @NonNull
@@ -486,7 +558,6 @@ public final class Control implements Parcelable {
        }

        /**
         * Build a stateless {@link Control}
         * @return a valid {@link Control}
         */
        @NonNull
@@ -507,9 +578,15 @@ public final class Control implements Parcelable {
    }

    /**
     * Builder class for {@link Control}.
     * Builder class for {@link Control} that contains state information.
     *
     * State information is passed through an instance of a {@link ControlTemplate} and will
     * determine how the user can interact with the {@link Control}. User interactions will
     * be sent through the method call {@link ControlsProviderService#performControlAction}
     * with an instance of {@link ControlAction} to convey any potential new value.
     *
     * Must be used to provide controls for {@link ControlsProviderService#createPublisherFor}.
     *
     * This class facilitates the creation of {@link Control} with an associated state.
     * It provides the following defaults for non-optional parameters:
     * <ul>
     *     <li> Device type: {@link DeviceTypes#TYPE_UNKNOWN}
@@ -549,6 +626,7 @@ public final class Control implements Parcelable {

        /**
         * Creates a {@link StatelessBuilder} using an existing {@link Control} as a base.
         *
         * @param control base for the builder.
         */
        public StatefulBuilder(@NonNull Control control) {
@@ -579,8 +657,8 @@ public final class Control implements Parcelable {
        }

        /**
         * @param deviceType the device type for the {@link Control}. Setting an invalid value not
         *                   in {@link DeviceTypes} will set it to {@link DeviceTypes#TYPE_UNKNOWN}.
         * @param deviceType type of device represented by this {@link Control}, used to
         *                   determine the default icon and color
         * @return {@code this}
         */
        @NonNull
@@ -606,7 +684,8 @@ public final class Control implements Parcelable {
        }

        /**
         * @param subtitle the user facing subtitle for the {@link Control}
         * @param subtitle additional information about the {@link Control}, to appear underneath
         *                 the title
         * @return {@code this}
         */
        @NonNull
@@ -617,8 +696,11 @@ public final class Control implements Parcelable {
        }

        /**
         * @param structure the user facing name of the structure for the {@link Control}.
         *                  {@code null} indicates that it's not associated with any structure.
         * Optional top-level group to help define the {@link Control}'s location, visible to the
         * user. If not present, the application name will be used as the top-level group. A
         * structure contains zones which contains controls.
         *
         * @param structure name of the structure containing the control
         * @return {@code this}
         */
        @NonNull
@@ -628,8 +710,10 @@ public final class Control implements Parcelable {
        }

        /**
         * @param zone the user facing name of the zone for the {@link Control}. {@code null}
         *             indicates that it's not associated with any zone.
         * Optional group name to help define the {@link Control}'s location within a structure,
         * visible to the user. A structure contains zones which contains controls.
         *
         * @param zone name of the zone containing the control
         * @return {@code this}
         */
        @NonNull
@@ -639,7 +723,7 @@ public final class Control implements Parcelable {
        }

        /**
         * @param appIntent an {@link Intent} linking to an Activity for the {@link Control}
         * @param appIntent a {@link PendingIntent} linking to an Activity for the {@link Control}
         * @return {@code this}
         */
        @NonNull
@@ -650,7 +734,10 @@ public final class Control implements Parcelable {
        }

        /**
         * @param customIcon an {@link Icon} to override the one determined by the device type.
         * Optional icon to be shown with the {@link Control}. It is highly recommended
         * to let the system default the icon unless the default icon is not suitable.
         *
         * @param customIcon icon to show
         * @return {@code this}
         */
        @NonNull
@@ -660,7 +747,11 @@ public final class Control implements Parcelable {
        }

        /**
         * @param customColor a list of colors to override the ones determined by the device type.
         * Optional color to be shown with the {@link Control}. It is highly recommended
         * to let the system default the color unless the default is not suitable for the
         * application.
         *
         * @param customColor background color to use
         * @return {@code this}
         */
        @NonNull
@@ -670,8 +761,8 @@ public final class Control implements Parcelable {
        }

        /**
         * @param status the status of the {@link Control}. Setting an invalid value not in
         *               {@link Control} will set it to {@link Control#STATUS_UNKNOWN}.
         * @param status status of the {@link Control}, used to convey information about the
         *               attempt to fetch the current state
         * @return {@code this}
         */
        @NonNull
@@ -686,7 +777,9 @@ public final class Control implements Parcelable {
        }

        /**
         * @param controlTemplate a template for the {@link Control}
         * @param controlTemplate instance of {@link ControlTemplate}, that defines how the
         *                        {@link Control} will behave and what interactions are
         *                        available to the user
         * @return {@code this}
         */
        @NonNull
@@ -697,7 +790,8 @@ public final class Control implements Parcelable {
        }

        /**
         * @param statusText a user facing text representing the status of the {@link Control}.
         * @param statusText user-facing text description of the {@link Control}'s status,
         *                   describing its current state
         * @return {@code this}
         */
        @NonNull
@@ -708,7 +802,6 @@ public final class Control implements Parcelable {
        }

        /**
         * Build a stateless {@link Control}
         * @return a valid {@link Control}
         */
        @NonNull
+11 −63
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ import android.util.Log;

import com.android.internal.util.Preconditions;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.Flow.Publisher;
import java.util.concurrent.Flow.Subscriber;
@@ -83,19 +82,6 @@ public abstract class ControlsProviderService extends Service {
    private IBinder mToken;
    private RequestHandler mHandler;

    /**
     * Retrieve all available controls, using the stateless builder
     * {@link Control.StatelessBuilder} to build each Control, then use the
     * provided consumer to callback to the call originator.
     *
     * @deprecated Removing consumer-based load apis. Use publisherForAllAvailable() instead
     */
    @Deprecated
    public void loadAvailableControls(@NonNull Consumer<List<Control>> consumer) {
        // pending removal
        consumer.accept(Collections.emptyList());
    }

    /**
     * Publisher for all available controls
     *
@@ -104,11 +90,8 @@ public abstract class ControlsProviderService extends Service {
     * controls, or {@link Subscriber#onError} for error scenarios. Duplicate Controls will
     * replace the original.
     */
    @Nullable
    public Publisher<Control> publisherForAllAvailable() {
        // will be abstract and @nonnull when consumers are removed
        return null;
    }
    @NonNull
    public abstract Publisher<Control> createPublisherForAllAvailable();

    /**
     * (Optional) Publisher for suggested controls
@@ -120,7 +103,7 @@ public abstract class ControlsProviderService extends Service {
     * when done, or {@link Subscriber#onError} for error scenarios.
     */
    @Nullable
    public Publisher<Control> publisherForSuggested() {
    public Publisher<Control> createPublisherForSuggested() {
        return null;
    }

@@ -128,10 +111,11 @@ public abstract class ControlsProviderService extends Service {
     * Return a valid Publisher for the given controlIds. This publisher will be asked to provide
     * updates for the given list of controlIds as long as the {@link Subscription} is valid.
     * Calls to {@link Subscriber#onComplete} will not be expected. Instead, wait for the call from
     * {@link Subscription#cancel} to indicate that updates are no longer required.
     * {@link Subscription#cancel} to indicate that updates are no longer required. It is expected
     * that controls provided by this publisher were created using {@link Control.StatefulBuilder}.
     */
    @NonNull
    public abstract Publisher<Control> publisherFor(@NonNull List<String> controlIds);
    public abstract Publisher<Control> createPublisherFor(@NonNull List<String> controlIds);

    /**
     * The user has interacted with a Control. The action is dictated by the type of
@@ -177,7 +161,7 @@ public abstract class ControlsProviderService extends Service {
    }

    @Override
    public boolean onUnbind(@NonNull Intent intent) {
    public final boolean onUnbind(@NonNull Intent intent) {
        mHandler = null;
        return true;
    }
@@ -198,13 +182,7 @@ public abstract class ControlsProviderService extends Service {
                    final IControlsSubscriber cs = (IControlsSubscriber) msg.obj;
                    final SubscriberProxy proxy = new SubscriberProxy(true, mToken, cs);

                    Publisher<Control> publisher =
                            ControlsProviderService.this.publisherForAllAvailable();
                    if (publisher == null) {
                        ControlsProviderService.this.loadAvailableControls(consumerFor(proxy));
                    } else {
                        publisher.subscribe(proxy);
                    }
                    ControlsProviderService.this.createPublisherForAllAvailable().subscribe(proxy);
                    break;
                }

@@ -213,7 +191,7 @@ public abstract class ControlsProviderService extends Service {
                    final SubscriberProxy proxy = new SubscriberProxy(true, mToken, cs);

                    Publisher<Control> publisher =
                            ControlsProviderService.this.publisherForSuggested();
                            ControlsProviderService.this.createPublisherForSuggested();
                    if (publisher == null) {
                        Log.i(TAG, "No publisher provided for suggested controls");
                        proxy.onComplete();
@@ -228,7 +206,8 @@ public abstract class ControlsProviderService extends Service {
                    final SubscriberProxy proxy = new SubscriberProxy(false, mToken,
                            sMsg.mSubscriber);

                    ControlsProviderService.this.publisherFor(sMsg.mControlIds).subscribe(proxy);
                    ControlsProviderService.this.createPublisherFor(sMsg.mControlIds)
                            .subscribe(proxy);
                    break;
                }

@@ -256,37 +235,6 @@ public abstract class ControlsProviderService extends Service {
                }
            };
        }

        /**
         * Method will be removed during migration to publisher
         */
        private Consumer<List<Control>> consumerFor(final Subscriber<Control> subscriber) {
            return (@NonNull final List<Control> controls) -> {
                Preconditions.checkNotNull(controls);

                subscriber.onSubscribe(new Subscription() {
                        public void request(long n) {
                            for (Control control: controls) {
                                Control c;
                                if (control == null) {
                                    Log.e(TAG, "onLoad: null control.");
                                }
                                if (isStatelessControl(control)) {
                                    c = control;
                                } else {
                                    Log.w(TAG, "onLoad: control is not stateless.");
                                    c = new Control.StatelessBuilder(control).build();
                                }

                                subscriber.onNext(c);
                            }
                            subscriber.onComplete();
                        }

                        public void cancel() {}
                    });
            };
        }
    }

    private static boolean isStatelessControl(Control control) {
+8 −4
Original line number Diff line number Diff line
@@ -284,12 +284,16 @@ public class ControlProviderServiceTest {
        }

        @Override
        public void loadAvailableControls(Consumer<List<Control>> cb) {
            cb.accept(mControls);
        public Publisher<Control> createPublisherForAllAvailable() {
            return new Publisher<Control>() {
                public void subscribe(final Subscriber s) {
                    s.onSubscribe(createSubscription(s, mControls));
                }
            };
        }

        @Override
        public Publisher<Control> publisherFor(List<String> ids) {
        public Publisher<Control> createPublisherFor(List<String> ids) {
            return new Publisher<Control>() {
                public void subscribe(final Subscriber s) {
                    s.onSubscribe(createSubscription(s, mControls));
@@ -298,7 +302,7 @@ public class ControlProviderServiceTest {
        }

        @Override
        public Publisher<Control> publisherForSuggested() {
        public Publisher<Control> createPublisherForSuggested() {
            return new Publisher<Control>() {
                public void subscribe(final Subscriber s) {
                    s.onSubscribe(createSubscription(s, mControls));