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

Commit 0bde9c1c authored by Fabian Kozynski's avatar Fabian Kozynski
Browse files

Changes to API

ControlTemplate and ControlAction serialize to Bundle. That way,
unserializing can always be done (maybe to UNKNOWN or NONE).

Also ControlState does not have a control anymore and now it just has
optional fields for overrides.

Test: atest

Change-Id: I1ce23c786a1b377d306e7785f9249b55b56d4c9f
parent c4b27ab6
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.service.controls;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;

/**
@@ -26,6 +27,8 @@ import android.os.Parcel;
 */
public final class BooleanAction extends ControlAction {

    private static final String KEY_NEW_STATE = "key_new_state";

    private final boolean mNewState;

    /**
@@ -49,9 +52,9 @@ public final class BooleanAction extends ControlAction {
        mNewState = newValue;
    }

    BooleanAction(Parcel in) {
        super(in);
        mNewState = in.readByte() == 1;
    BooleanAction(Bundle b) {
        super(b);
        mNewState = b.getBoolean(KEY_NEW_STATE);
    }

    /**
@@ -72,17 +75,17 @@ public final class BooleanAction extends ControlAction {
        return ControlAction.TYPE_BOOLEAN;
    }


    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeByte(mNewState ? (byte) 1 : (byte) 0);
    protected Bundle getDataBundle() {
        Bundle b =  super.getDataBundle();
        b.putBoolean(KEY_NEW_STATE, mNewState);
        return b;
    }

    public static final @NonNull Creator<BooleanAction> CREATOR = new Creator<BooleanAction>() {
        @Override
        public BooleanAction createFromParcel(Parcel source) {
            return new BooleanAction(source);
            return new BooleanAction(source.readBundle());
        }

        @Override
+11 −9
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.service.controls;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.drawable.Icon;
@@ -55,7 +56,7 @@ public class Control implements Parcelable {
    private final @NonNull Icon mIcon;
    private final @NonNull CharSequence mTitle;
    private final @Nullable ColorStateList mTintColor;
    private final @NonNull Intent mAppIntent;
    private final @NonNull PendingIntent mAppIntent;
    private final @ControlTemplate.TemplateType int mPrimaryType;

    /**
@@ -64,14 +65,15 @@ public class Control implements Parcelable {
     * @param title the user facing name of this control (e.g. "Bedroom thermostat").
     * @param tintColor the color to tint parts of the element UI. If {@code null} is passed, the
     *                  system accent color will be used.
     * @param appIntent an intent linking to a page to interact with the corresponding device.
     * @param appIntent a {@link PendingIntent} linking to a page to interact with the
     *                  corresponding device.
     * @param primaryType the primary template for this type.
     */
    public Control(@NonNull String controlId,
            @NonNull Icon icon,
            @NonNull CharSequence title,
            @Nullable ColorStateList tintColor,
            @NonNull Intent appIntent,
            @NonNull PendingIntent appIntent,
            int primaryType) {
        Preconditions.checkNotNull(controlId);
        Preconditions.checkNotNull(icon);
@@ -94,7 +96,7 @@ public class Control implements Parcelable {
        } else {
            mTintColor = null;
        }
        mAppIntent = Intent.CREATOR.createFromParcel(in);
        mAppIntent = PendingIntent.CREATOR.createFromParcel(in);
        mPrimaryType = in.readInt();
    }

@@ -119,7 +121,7 @@ public class Control implements Parcelable {
    }

    @NonNull
    public Intent getAppIntent() {
    public PendingIntent getAppIntent() {
        return mAppIntent;
    }

@@ -175,17 +177,17 @@ public class Control implements Parcelable {
        private Icon mIcon;
        private CharSequence mTitle = "";
        private ColorStateList mTintColor;
        private @Nullable Intent mAppIntent;
        private @Nullable PendingIntent mAppIntent;
        private @ControlTemplate.TemplateType int mPrimaryType = ControlTemplate.TYPE_NONE;

        /**
         * @param controlId the identifier for the {@link Control}.
         * @param icon the icon for the {@link Control}.
         * @param appIntent the intent linking to the device Activity.
         * @param appIntent the pending intent linking to the device Activity.
         */
        public Builder(@NonNull String controlId,
                @NonNull Icon icon,
                @NonNull Intent appIntent) {
                @NonNull PendingIntent appIntent) {
            Preconditions.checkNotNull(controlId);
            Preconditions.checkNotNull(icon);
            Preconditions.checkNotNull(appIntent);
@@ -256,7 +258,7 @@ public class Control implements Parcelable {
         * @return {@code this}
         */
        @NonNull
        public Builder setAppIntent(@NonNull Intent appIntent) {
        public Builder setAppIntent(@NonNull PendingIntent appIntent) {
            Preconditions.checkNotNull(appIntent);
            mAppIntent = appIntent;
            return this;
+40 −18
Original line number Diff line number Diff line
@@ -16,9 +16,11 @@

package android.service.controls;

import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

@@ -36,25 +38,38 @@ import java.lang.annotation.RetentionPolicy;
 */
public abstract class ControlAction implements Parcelable {

    private static final String KEY_TEMPLATE_ID = "key_template_id";
    private static final String KEY_CHALLENGE_VALUE = "key_challenge_value";

    public static final ControlAction UNKNOWN_ACTION = new ControlAction() {

        @Override
        public int getActionType() {
            return TYPE_UNKNOWN;
        }
    };

    /**
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
            TYPE_UNKNOWN,
            TYPE_BOOLEAN,
            TYPE_FLOAT
    })
    public @interface ActionType {};

    public static final @ActionType int TYPE_UNKNOWN = 0;
    /**
     * The identifier of {@link BooleanAction}.
     */
    public static final @ActionType int TYPE_BOOLEAN = 0;
    public static final @ActionType int TYPE_BOOLEAN = 1;

    /**
     * The identifier of {@link FloatAction}.
     */
    public static final @ActionType int TYPE_FLOAT = 1;
    public static final @ActionType int TYPE_FLOAT = 2;

    /**
     * @hide
@@ -120,13 +135,9 @@ public abstract class ControlAction implements Parcelable {
    /**
     * @hide
     */
    ControlAction(Parcel in) {
        mTemplateId = in.readString();
        if (in.readByte() == 1) {
            mChallengeValue = in.readString();
        } else {
            mChallengeValue = null;
        }
    ControlAction(Bundle b) {
        mTemplateId = b.getString(KEY_TEMPLATE_ID);
        mChallengeValue = b.getString(KEY_CHALLENGE_VALUE);
    }

    /**
@@ -151,15 +162,24 @@ public abstract class ControlAction implements Parcelable {
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
    public final void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(getActionType());
        dest.writeString(mTemplateId);
        if (mChallengeValue != null) {
            dest.writeByte((byte) 1);
            dest.writeString(mChallengeValue);
        } else {
            dest.writeByte((byte) 0);
        dest.writeBundle(getDataBundle());
    }

    /**
     * Obtain a {@link Bundle} describing this object populated with data.
     *
     * Implementations in subclasses should populate the {@link Bundle} returned by
     * {@link ControlAction}.
     * @return a {@link Bundle} containing the data that represents this object.
     */
    @CallSuper
    protected Bundle getDataBundle() {
        Bundle b = new Bundle();
        b.putString(KEY_TEMPLATE_ID, mTemplateId);
        b.putString(KEY_CHALLENGE_VALUE, mChallengeValue);
        return b;
    }

    public static final @NonNull Creator<ControlAction> CREATOR = new Creator<ControlAction>() {
@@ -175,6 +195,7 @@ public abstract class ControlAction implements Parcelable {
        }
    };


    private static ControlAction createActionFromType(@ActionType int type, Parcel source) {
        switch(type) {
            case TYPE_BOOLEAN:
@@ -182,7 +203,8 @@ public abstract class ControlAction implements Parcelable {
            case TYPE_FLOAT:
                return FloatAction.CREATOR.createFromParcel(source);
            default:
                return null;
                source.readBundle();
                return UNKNOWN_ACTION;
        }
    }

+9 −9
Original line number Diff line number Diff line
@@ -29,29 +29,29 @@ import com.android.internal.util.Preconditions;
 */
public class ControlButton implements Parcelable {

    private final boolean mActive;
    private final boolean mChecked;
    private final @NonNull Icon mIcon;
    private final @NonNull CharSequence mContentDescription;

    /**
     * @param active true if the button should be rendered as active.
     * @param checked true if the button should be rendered as active.
     * @param icon icon to display in the button.
     * @param contentDescription content description for the button.
     */
    public ControlButton(boolean active, @NonNull Icon icon,
    public ControlButton(boolean checked, @NonNull Icon icon,
            @NonNull CharSequence contentDescription) {
        Preconditions.checkNotNull(icon);
        Preconditions.checkNotNull(contentDescription);
        mActive = active;
        mChecked = checked;
        mIcon = icon;
        mContentDescription = contentDescription;
    }

    /**
     * Whether the button should be rendered in its active state.
     * Whether the button should be rendered in a checked state.
     */
    public boolean isActive() {
        return mActive;
    public boolean isChecked() {
        return mChecked;
    }

    /**
@@ -78,13 +78,13 @@ public class ControlButton implements Parcelable {

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeByte(mActive ? (byte) 1 : (byte) 0);
        dest.writeByte(mChecked ? (byte) 1 : (byte) 0);
        mIcon.writeToParcel(dest, flags);
        dest.writeCharSequence(mContentDescription);
    }

    ControlButton(Parcel in) {
        mActive = in.readByte() != 0;
        mChecked = in.readByte() != 0;
        mIcon = Icon.CREATOR.createFromParcel(in);
        mContentDescription = in.readCharSequence();
    }
+144 −73
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.service.controls;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.res.ColorStateList;
import android.graphics.drawable.Icon;
import android.os.Parcel;
@@ -33,11 +34,11 @@ import java.lang.annotation.RetentionPolicy;
 * Current state for a {@link Control}.
 *
 * Collects information to render the current state of a {@link Control} as well as possible action
 * that can be performed on it. Some of the information may temporarily override the defaults
 * provided by the corresponding {@link Control}, while this state is being displayed.
 *
 * Additionally, this can be used to modify information related to the corresponding
 * {@link Control}.
 * that can be performed on it.
 * <p>
 * Additionally, this object is used to modify elements from the {@link Control} such as icons,
 * colors, names and intents. This information will last until it is again modified by a
 * {@link ControlState}.
 * @hide
 */
public final class ControlState implements Parcelable {
@@ -74,58 +75,81 @@ public final class ControlState implements Parcelable {
     */
    public static final int STATUS_DISABLED = 3;

    private final @NonNull Control mControl;
    private final @NonNull String mControlId;
    private final @Status int mStatus;
    private final @NonNull ControlTemplate mControlTemplate;
    private final @NonNull CharSequence mStatusText;
    private final @Nullable Icon mOverrideIcon;
    private final @Nullable ColorStateList mOverrideTint;
    private final @Nullable CharSequence mTitle;
    private final @Nullable PendingIntent mAppIntent;
    private final @Nullable Icon mIcon;
    private final @Nullable ColorStateList mTint;

    /**
     * @param control the {@link Control} this state should be applied to. Can be used to
     *                       update information about the {@link Control}
     * @param controlId the identifier of the {@link Control} this object refers to.
     * @param status the current status of the {@link Control}.
     * @param controlTemplate the template to be used to render the {@link Control}.
     * @param statusText the text describing the current status.
     * @param overrideIcon the icon to temporarily override the one provided in
     *                     {@link Control#getIcon()}. Pass {@code null} to use the icon in
     *                     {@link Control#getIcon()}.
     * @param overrideTint the colors to temporarily override those provided in
     *                            {@link Control#getTint()}. Pass {@code null} to use the colors in
     *                            {@link Control#getTint()}.
     * @param controlTemplate the template to be used to render the {@link Control}. This can be
     *                        of a different
     *                        {@link android.service.controls.ControlTemplate.TemplateType} than the
     *                        one defined in {@link Control#getPrimaryType}
     * @param statusText the user facing text describing the current status.
     * @param title the title to replace the one set in the {@link Control} or set in the
     *              last {@link ControlState}. Pass {@code null} to use the last value set for this
     *              {@link Control}
     * @param appIntent the {@link PendingIntent} to replace the one set in the {@link Control} or
     *                  set in the last {@link ControlState}. Pass {@code null} to use the last
     *                  value set for this {@link Control}.
     * @param icon the icon to replace the one set in the {@link Control} or set in the last
     *             {@link ControlState}. Pass {@code null} to use the last value set for this
     *             {@link Control}.
     * @param tint the colors to replace those set in the {@link Control} or set in the last
     *             {@link ControlState}. Pass {@code null} to use the last value set for this
     *             {@link Control}.
     */
    public ControlState(@NonNull Control control,
    public ControlState(@NonNull String controlId,
            int status,
            @NonNull ControlTemplate controlTemplate,
            @NonNull CharSequence statusText,
            @Nullable Icon overrideIcon,
            @Nullable ColorStateList overrideTint) {
        Preconditions.checkNotNull(control);
            @Nullable CharSequence title,
            @Nullable PendingIntent appIntent,
            @Nullable Icon icon,
            @Nullable ColorStateList tint) {
        Preconditions.checkNotNull(controlId);
        Preconditions.checkNotNull(controlTemplate);
        Preconditions.checkNotNull(statusText);

        mControl = control;
        mControlId = controlId;
        mStatus = status;
        mControlTemplate = controlTemplate;
        mOverrideIcon = overrideIcon;
        mStatusText = statusText;
        mOverrideTint = overrideTint;
        mTitle = title;
        mAppIntent = appIntent;
        mIcon = icon;
        mTint = tint;
    }

    ControlState(Parcel in) {
        mControl = Control.CREATOR.createFromParcel(in);
        mControlId = in.readString();
        mStatus = in.readInt();
        mControlTemplate = ControlTemplate.CREATOR.createFromParcel(in);
        mStatusText = in.readCharSequence();
        if (in.readByte() == 1) {
            mOverrideIcon = Icon.CREATOR.createFromParcel(in);
            mTitle = in.readCharSequence();
        } else {
            mTitle = null;
        }
        if (in.readByte() == 1) {
            mAppIntent = PendingIntent.CREATOR.createFromParcel(in);
        } else {
            mAppIntent = null;
        }
        if (in.readByte() == 1) {
            mIcon = Icon.CREATOR.createFromParcel(in);
        } else {
            mOverrideIcon = null;
            mIcon = null;
        }
        if (in.readByte() == 1) {
            mOverrideTint = ColorStateList.CREATOR.createFromParcel(in);
            mTint = ColorStateList.CREATOR.createFromParcel(in);
        } else {
            mOverrideTint = null;
            mTint = null;
        }
    }

@@ -134,6 +158,21 @@ public final class ControlState implements Parcelable {
        return 0;
    }

    @NonNull
    public String getControlId() {
        return mControlId;
    }

    @Nullable
    public CharSequence getTitle() {
        return mTitle;
    }

    @Nullable
    public PendingIntent getAppIntent() {
        return mAppIntent;
    }

    @Status
    public int getStatus() {
        return mStatus;
@@ -145,8 +184,8 @@ public final class ControlState implements Parcelable {
    }

    @Nullable
    public Icon getOverrideIcon() {
        return mOverrideIcon;
    public Icon getIcon() {
        return mIcon;
    }

    @NonNull
@@ -155,35 +194,35 @@ public final class ControlState implements Parcelable {
    }

    @Nullable
    public ColorStateList getOverrideTint() {
        return mOverrideTint;
    }

    @NonNull
    public Control getControl() {
        return mControl;
    }

    @NonNull
    public String getControlId() {
        return mControl.getControlId();
    public ColorStateList getTint() {
        return mTint;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        mControl.writeToParcel(dest, flags);
        dest.writeString(mControlId);
        dest.writeInt(mStatus);
        mControlTemplate.writeToParcel(dest, flags);
        dest.writeCharSequence(mStatusText);
        if (mOverrideIcon != null) {
        if (mTitle != null) {
            dest.writeByte((byte) 1);
            dest.writeCharSequence(mTitle);
        } else {
            dest.writeByte((byte) 0);
        }
        if (mAppIntent != null) {
            dest.writeByte((byte) 1);
            mAppIntent.writeToParcel(dest, flags);
        }
        if (mIcon != null) {
            dest.writeByte((byte) 1);
            mOverrideIcon.writeToParcel(dest, flags);
            mIcon.writeToParcel(dest, flags);
        } else {
            dest.writeByte((byte) 0);
        }
        if (mOverrideTint != null) {
        if (mTint != null) {
            dest.writeByte((byte) 1);
            mOverrideTint.writeToParcel(dest, flags);
            mTint.writeToParcel(dest, flags);
        } else {
            dest.writeByte((byte) 0);
        }
@@ -213,19 +252,22 @@ public final class ControlState implements Parcelable {
     * </ul>
     */
    public static class Builder {
        private @NonNull Control mControl;
        private @NonNull String mControlId;
        private @Status int mStatus = STATUS_OK;
        private @NonNull ControlTemplate mControlTemplate = ControlTemplate.NO_TEMPLATE;
        private @NonNull CharSequence mStatusText = "";
        private @Nullable Icon mOverrideIcon;
        private @Nullable ColorStateList mOverrideTint;
        private @Nullable CharSequence mTitle;
        private @Nullable PendingIntent mAppIntent;
        private @Nullable Icon mIcon;
        private @Nullable ColorStateList mTint;

        /**
         * @param control the {@link Control} that the resulting {@link ControlState} refers to.
         * @param controlId the identifier of the {@link Control} that the resulting
         *                  {@link ControlState} refers to.
         */
        public Builder(@NonNull Control control) {
            Preconditions.checkNotNull(control);
            mControl = control;
        public Builder(@NonNull String controlId) {
            Preconditions.checkNotNull(controlId);
            mControlId = controlId;
        }

        /**
@@ -234,21 +276,24 @@ public final class ControlState implements Parcelable {
         */
        public Builder(@NonNull ControlState controlState) {
            Preconditions.checkNotNull(controlState);
            mControl = controlState.mControl;
            mControlId = controlState.mControlId;
            mStatus = controlState.mStatus;
            mControlTemplate = controlState.mControlTemplate;
            mOverrideIcon = controlState.mOverrideIcon;
            mStatusText = controlState.mStatusText;
            mOverrideTint = controlState.mOverrideTint;
            mTitle = controlState.mTitle;
            mAppIntent = controlState.mAppIntent;
            mIcon = controlState.mIcon;
            mTint = controlState.mTint;
        }


        /**
         * @param control the updated {@link Control} information.
         * @param controlId the identifier of the {@link Control} for the resulting object.
         * @return {@code this}
         */
        @NonNull
        public Builder setControl(@NonNull Control control) {
            mControl = control;
        public Builder setControlId(@NonNull String controlId) {
            mControlId = controlId;
            return this;
        }

@@ -285,24 +330,50 @@ public final class ControlState implements Parcelable {
        }

        /**
         * @param overrideIcon the icon to override the one defined in the corresponding
         *                            {@code Control}. Pass {@code null} to remove the override.
         * @param title the title to replace the one defined in the corresponding {@link Control} or
         *              set by the last {@link ControlState}. Pass {@code null} to keep the last
         *              value.
         * @return {@code this}
         */
        @NonNull
        public Builder setTitle(@Nullable CharSequence title) {
            mTitle = title;
            return this;
        }

        /**
         * @param appIntent the Pending Intent to replace the one defined in the corresponding
         *                  {@link Control} or set by the last {@link ControlState}. Pass
         *                  {@code null} to keep the last value.
         * @return {@code this}
         */
        @NonNull
        public Builder setAppIntent(@Nullable PendingIntent appIntent) {
            mAppIntent = appIntent;
            return this;
        }

        /**
         * @param icon the title to replace the one defined in the corresponding {@link Control} or
         *             set by the last {@link ControlState}. Pass {@code null} to keep the last
         *             value.
         * @return {@code this}
         */
        @NonNull
        public Builder setOverrideIcon(@Nullable Icon overrideIcon) {
            mOverrideIcon = overrideIcon;
        public Builder setIcon(@Nullable Icon icon) {
            mIcon = icon;
            return this;
        }

        /**
         * @param overrideTint the colors to override the ones defined in the corresponding
         *                            {@code Control}. Pass {@code null} to remove the override.
         * @param tint the title to replace the one defined in the corresponding {@link Control} or
         *             set by the last {@link ControlState}. Pass {@code null} to keep the last
         *             value.
         * @return {@code this}
         */
        @NonNull
        public Builder setOverrideTint(@Nullable ColorStateList overrideTint) {
            mOverrideTint = overrideTint;
        public Builder setTint(@Nullable ColorStateList tint) {
            mTint = tint;
            return this;
        }

@@ -310,8 +381,8 @@ public final class ControlState implements Parcelable {
         * @return a new {@link ControlState}
         */
        public ControlState build() {
            return new ControlState(mControl, mStatus, mControlTemplate, mStatusText,
                    mOverrideIcon, mOverrideTint);
            return new ControlState(mControlId, mStatus, mControlTemplate, mStatusText,
                    mTitle, mAppIntent, mIcon, mTint);
        }
    }
}
Loading