diff options
| author | Fabian Kozynski <kozynski@google.com> | 2020-01-02 15:19:13 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-01-02 15:19:13 +0000 |
| commit | 49fe4569a8a9e7b9f6193abaeee0cf78f93ebaee (patch) | |
| tree | 2fe9264bebef05ea7b37c74ef810c0355462f1f1 /core/java/android | |
| parent | 695ee8cd8d4c711b4c09ee6f40283e3d8a5e4232 (diff) | |
| parent | ee57f49c7d8ab4d6c22608ae8de224b356f5b94e (diff) | |
Merge "Merge ControlState into Control"
Diffstat (limited to 'core/java/android')
8 files changed, 313 insertions, 430 deletions
diff --git a/core/java/android/service/controls/Control.java b/core/java/android/service/controls/Control.java index df18eb626c5e..43a308cf82cb 100644 --- a/core/java/android/service/controls/Control.java +++ b/core/java/android/service/controls/Control.java @@ -16,6 +16,7 @@ package android.service.controls; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.PendingIntent; @@ -28,28 +29,26 @@ import android.util.Log; import com.android.internal.util.Preconditions; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Represents a physical object that can be represented by a {@link ControlTemplate} and whose * properties may be modified through a {@link ControlAction}. * - * The information is provided by a {@link ControlProviderService} and represents static + * The information is provided by a {@link ControlsProviderService} and represents static * information (not current status) about the device. * <p> * Each control needs a unique (per provider) identifier that is persistent across reboots of the * system. * <p> * Each {@link Control} will have a name, a subtitle and will optionally belong to a structure - * and zone. Some of these values are defined by the user and/or the {@link ControlProviderService} + * and zone. Some of these values are defined by the user and/or the {@link ControlsProviderService} * and will be used to display the control as well as group them for management. * <p> * Each object will have an associated {@link DeviceTypes.DeviceType}. This will determine the icons and colors * used to display it. * <p> - * The {@link ControlTemplate.TemplateType} provided will be used as a hint when displaying this in - * non-interactive situations (for example when there's no state to display). This template is not - * the one that will be shown with the current state and provide interactions. That template is set - * using {@link ControlState}. - * <p> * An {@link Intent} linking to the provider Activity that expands on this {@link Control} and * allows for further actions should be provided. * @hide @@ -57,17 +56,52 @@ import com.android.internal.util.Preconditions; public class Control implements Parcelable { private static final String TAG = "Control"; - ; + private static final int NUM_STATUS = 5; + /** + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + STATUS_UNKNOWN, + STATUS_OK, + STATUS_NOT_FOUND, + STATUS_ERROR, + STATUS_DISABLED, + }) + public @interface Status {}; + + public static final int STATUS_UNKNOWN = 0; + + /** + * The device corresponding to the {@link Control} is responding correctly. + */ + public static final int STATUS_OK = 1; + + /** + * The device corresponding to the {@link Control} cannot be found or was removed. + */ + public static final int STATUS_NOT_FOUND = 2; + + /** + * The device corresponding to the {@link Control} is in an error state. + */ + public static final int STATUS_ERROR = 3; + + /** + * The {@link Control} is currently disabled. + */ + public static final int STATUS_DISABLED = 4; private final @NonNull String mControlId; - private final @DeviceTypes.DeviceType - int mDeviceType; + private final @DeviceTypes.DeviceType int mDeviceType; private final @NonNull CharSequence mTitle; private final @NonNull CharSequence mSubtitle; private final @Nullable CharSequence mStructure; private final @Nullable CharSequence mZone; private final @NonNull PendingIntent mAppIntent; - private final @ControlTemplate.TemplateType int mPrimaryType; + private final @Status int mStatus; + private final @NonNull ControlTemplate mControlTemplate; + private final @NonNull CharSequence mStatusText; /** * @param controlId the unique persistent identifier for this object. @@ -79,7 +113,6 @@ public class Control implements Parcelable { * @param zone * @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, @DeviceTypes.DeviceType int deviceType, @@ -88,11 +121,15 @@ public class Control implements Parcelable { @Nullable CharSequence structure, @Nullable CharSequence zone, @NonNull PendingIntent appIntent, - int primaryType) { + @Status int status, + @NonNull ControlTemplate controlTemplate, + @NonNull CharSequence statusText) { Preconditions.checkNotNull(controlId); Preconditions.checkNotNull(title); Preconditions.checkNotNull(subtitle); Preconditions.checkNotNull(appIntent); + Preconditions.checkNotNull(controlTemplate); + Preconditions.checkNotNull(statusText); mControlId = controlId; if (!DeviceTypes.validDeviceType(deviceType)) { Log.e(TAG, "Invalid device type:" + deviceType); @@ -105,7 +142,14 @@ public class Control implements Parcelable { mStructure = structure; mZone = zone; mAppIntent = appIntent; - mPrimaryType = primaryType; + if (status < 0 || status >= NUM_STATUS) { + mStatus = STATUS_UNKNOWN; + Log.e(TAG, "Status unknown:" + status); + } else { + mStatus = status; + } + mControlTemplate = controlTemplate; + mStatusText = statusText; } public Control(Parcel in) { @@ -124,7 +168,9 @@ public class Control implements Parcelable { mZone = null; } mAppIntent = PendingIntent.CREATOR.createFromParcel(in); - mPrimaryType = in.readInt(); + mStatus = in.readInt(); + mControlTemplate = ControlTemplate.CREATOR.createFromParcel(in); + mStatusText = in.readCharSequence(); } @NonNull @@ -162,9 +208,19 @@ public class Control implements Parcelable { return mAppIntent; } - @android.service.controls.templates.ControlTemplate.TemplateType - public int getPrimaryType() { - return mPrimaryType; + @Status + public int getStatus() { + return mStatus; + } + + @NonNull + public ControlTemplate getControlTemplate() { + return mControlTemplate; + } + + @NonNull + public CharSequence getStatusText() { + return mStatusText; } @Override @@ -191,7 +247,9 @@ public class Control implements Parcelable { dest.writeByte((byte) 0); } mAppIntent.writeToParcel(dest, flags); - dest.writeInt(mPrimaryType); + dest.writeInt(mStatus); + mControlTemplate.writeToParcel(dest, flags); + dest.writeCharSequence(mStatusText); } public static final Creator<Control> CREATOR = new Creator<Control>() { @@ -209,32 +267,39 @@ public class Control implements Parcelable { /** * Builder class for {@link Control}. * - * This class facilitates the creation of {@link Control}. It provides the following - * defaults for non-optional parameters: + * This class facilitates the creation of {@link Control} with no state. + * It provides the following defaults for non-optional parameters: * <ul> * <li> Device type: {@link DeviceTypes#TYPE_UNKNOWN} * <li> Title: {@code ""} * <li> Subtitle: {@code ""} - * <li> Primary template: {@link ControlTemplate#TYPE_NONE} + * </ul> + * This fixes the values relating to state of the {@link Control} as required by + * {@link ControlsProviderService#onLoad}: + * <ul> + * <li> Status: {@link Status#STATUS_UNKNOWN} + * <li> Control template: {@link ControlTemplate#NO_TEMPLATE} + * <li> Status text: {@code ""} * </ul> */ - public static class Builder { - private static final String TAG = "Control.Builder"; - private @NonNull String mControlId; - private @DeviceTypes.DeviceType - int mDeviceType = DeviceTypes.TYPE_UNKNOWN; - private @NonNull CharSequence mTitle = ""; - private @NonNull CharSequence mSubtitle = ""; - private @Nullable CharSequence mStructure; - private @Nullable CharSequence mZone; - private @NonNull PendingIntent mAppIntent; - private @ControlTemplate.TemplateType int mPrimaryType = ControlTemplate.TYPE_NONE; + public static class StatelessBuilder { + private static final String TAG = "StatelessBuilder"; + protected @NonNull String mControlId; + protected @DeviceTypes.DeviceType int mDeviceType = DeviceTypes.TYPE_UNKNOWN; + protected @NonNull CharSequence mTitle = ""; + protected @NonNull CharSequence mSubtitle = ""; + protected @Nullable CharSequence mStructure; + protected @Nullable CharSequence mZone; + protected @NonNull PendingIntent mAppIntent; + protected @Status int mStatus = STATUS_UNKNOWN; + protected @NonNull ControlTemplate mControlTemplate = ControlTemplate.NO_TEMPLATE; + protected @NonNull CharSequence mStatusText = ""; /** * @param controlId the identifier for the {@link Control}. * @param appIntent the pending intent linking to the device Activity. */ - public Builder(@NonNull String controlId, + public StatelessBuilder(@NonNull String controlId, @NonNull PendingIntent appIntent) { Preconditions.checkNotNull(controlId); Preconditions.checkNotNull(appIntent); @@ -243,10 +308,10 @@ public class Control implements Parcelable { } /** - * Creates a {@link Builder} using an existing {@link Control} as a base. + * Creates a {@link StatelessBuilder} using an existing {@link Control} as a base. * @param control base for the builder. */ - public Builder(@NonNull Control control) { + public StatelessBuilder(@NonNull Control control) { Preconditions.checkNotNull(control); mControlId = control.mControlId; mDeviceType = control.mDeviceType; @@ -255,7 +320,6 @@ public class Control implements Parcelable { mStructure = control.mStructure; mZone = control.mZone; mAppIntent = control.mAppIntent; - mPrimaryType = control.mPrimaryType; } /** @@ -263,14 +327,14 @@ public class Control implements Parcelable { * @return {@code this} */ @NonNull - public Builder setControlId(@NonNull String controlId) { + public StatelessBuilder setControlId(@NonNull String controlId) { Preconditions.checkNotNull(controlId); mControlId = controlId; return this; } @NonNull - public Builder setDeviceType(@DeviceTypes.DeviceType int deviceType) { + public StatelessBuilder setDeviceType(@DeviceTypes.DeviceType int deviceType) { if (!DeviceTypes.validDeviceType(deviceType)) { Log.e(TAG, "Invalid device type:" + deviceType); mDeviceType = DeviceTypes.TYPE_UNKNOWN; @@ -285,27 +349,27 @@ public class Control implements Parcelable { * @return {@code this} */ @NonNull - public Builder setTitle(@NonNull CharSequence title) { + public StatelessBuilder setTitle(@NonNull CharSequence title) { Preconditions.checkNotNull(title); mTitle = title; return this; } @NonNull - public Builder setSubtitle(@NonNull CharSequence subtitle) { + public StatelessBuilder setSubtitle(@NonNull CharSequence subtitle) { Preconditions.checkNotNull(subtitle); mSubtitle = subtitle; return this; } @NonNull - public Builder setStructure(@Nullable CharSequence structure) { + public StatelessBuilder setStructure(@Nullable CharSequence structure) { mStructure = structure; return this; } @NonNull - public Builder setZone(@Nullable CharSequence zone) { + public StatelessBuilder setZone(@Nullable CharSequence zone) { mZone = zone; return this; } @@ -315,23 +379,13 @@ public class Control implements Parcelable { * @return {@code this} */ @NonNull - public Builder setAppIntent(@NonNull PendingIntent appIntent) { + public StatelessBuilder setAppIntent(@NonNull PendingIntent appIntent) { Preconditions.checkNotNull(appIntent); mAppIntent = appIntent; return this; } /** - * @param type type to use as default in the {@link Control} - * @return {@code this} - */ - @NonNull - public Builder setPrimaryType(@ControlTemplate.TemplateType int type) { - mPrimaryType = type; - return this; - } - - /** * Build a {@link Control} * @return a valid {@link Control} */ @@ -344,7 +398,108 @@ public class Control implements Parcelable { mStructure, mZone, mAppIntent, - mPrimaryType); + mStatus, + mControlTemplate, + mStatusText); + } + } + + public static class StatefulBuilder extends StatelessBuilder { + private static final String TAG = "StatefulBuilder"; + + /** + * @param controlId the identifier for the {@link Control}. + * @param appIntent the pending intent linking to the device Activity. + */ + public StatefulBuilder(@NonNull String controlId, + @NonNull PendingIntent appIntent) { + super(controlId, appIntent); + } + + public StatefulBuilder(@NonNull Control control) { + super(control); + mStatus = control.mStatus; + mControlTemplate = control.mControlTemplate; + mStatusText = control.mStatusText; + } + + /** + * @param controlId the identifier for the {@link Control}. + * @return {@code this} + */ + @NonNull + public StatefulBuilder setControlId(@NonNull String controlId) { + super.setControlId(controlId); + return this; + } + + @NonNull + public StatefulBuilder setDeviceType(@DeviceTypes.DeviceType int deviceType) { + super.setDeviceType(deviceType); + return this; + } + + /** + * @param title the user facing name of the {@link Control} + * @return {@code this} + */ + @NonNull + public StatefulBuilder setTitle(@NonNull CharSequence title) { + super.setTitle(title); + return this; + } + + @NonNull + public StatefulBuilder setSubtitle(@NonNull CharSequence subtitle) { + super.setSubtitle(subtitle); + return this; + } + + @NonNull + public StatefulBuilder setStructure(@Nullable CharSequence structure) { + super.setStructure(structure); + return this; + } + + @NonNull + public StatefulBuilder setZone(@Nullable CharSequence zone) { + super.setZone(zone); + return this; + } + + /** + * @param appIntent an {@link Intent} linking to an Activity for the {@link Control} + * @return {@code this} + */ + @NonNull + public StatefulBuilder setAppIntent(@NonNull PendingIntent appIntent) { + super.setAppIntent(appIntent); + return this; + } + + @NonNull + public StatefulBuilder setStatus(@Status int status) { + if (status < 0 || status >= NUM_STATUS) { + mStatus = STATUS_UNKNOWN; + Log.e(TAG, "Status unknown:" + status); + } else { + mStatus = status; + } + return this; + } + + @NonNull + public StatefulBuilder setControlTemplate(@NonNull ControlTemplate controlTemplate) { + Preconditions.checkNotNull(controlTemplate); + mControlTemplate = controlTemplate; + return this; + } + + @NonNull + public StatefulBuilder setStatusText(@NonNull CharSequence statusText) { + Preconditions.checkNotNull(statusText); + mStatusText = statusText; + return this; } } } diff --git a/core/java/android/service/controls/ControlState.aidl b/core/java/android/service/controls/ControlState.aidl deleted file mode 100644 index 520d85b47d3e..000000000000 --- a/core/java/android/service/controls/ControlState.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2019, 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.service.controls; - -parcelable ControlState;
\ No newline at end of file diff --git a/core/java/android/service/controls/ControlState.java b/core/java/android/service/controls/ControlState.java deleted file mode 100644 index 998fb54613ba..000000000000 --- a/core/java/android/service/controls/ControlState.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2019 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.service.controls; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.PendingIntent; -import android.os.Parcel; -import android.os.Parcelable; -import android.service.controls.templates.ControlTemplate; -import android.util.Log; - -import com.android.internal.util.Preconditions; - -import java.lang.annotation.Retention; -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. - * <p> - * Additionally, this object is used to modify elements from the {@link Control} such as device - * type, and intents. This information will last until it is again modified by a - * {@link ControlState}. - * @hide - */ -public final class ControlState implements Parcelable { - - private static final String TAG = "ControlState"; - - /** - * @hide - */ - @Retention(RetentionPolicy.SOURCE) - @IntDef({ - STATUS_OK, - STATUS_NOT_FOUND, - STATUS_ERROR, - STATUS_DISABLED, - }) - public @interface Status {}; - - /** - * The device corresponding to the {@link Control} is responding correctly. - */ - public static final int STATUS_OK = 0; - - /** - * The device corresponding to the {@link Control} cannot be found or was removed. - */ - public static final int STATUS_NOT_FOUND = 1; - - /** - * The device corresponding to the {@link Control} is in an error state. - */ - public static final int STATUS_ERROR = 2; - - /** - * The {@link Control} is currently disabled. - */ - public static final int STATUS_DISABLED = 3; - - private final @NonNull String mControlId; - private final @DeviceTypes.DeviceType int mDeviceType; - private final @Status int mStatus; - private final @NonNull ControlTemplate mControlTemplate; - private final @NonNull CharSequence mStatusText; - private final @Nullable PendingIntent mAppIntent; - - /** - * @param controlId the identifier of the {@link Control} this object refers to. - * @param status the current status of the {@link Control}. - * @param deviceType the {@link DeviceTypes.DeviceType} to replace the one set in the - * {@link Control} or set in the last {@link ControlState}. In order to keep - * the current device type for this {@link Control}, the old value must be - * passed. - * @param controlTemplate the template to be used to render the {@link Control}. This can be - * of a different {@link ControlTemplate.TemplateType} than the - * one defined in {@link Control#getPrimaryType} - * @param statusText the user facing text describing the current status. - * @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}. - */ - public ControlState(@NonNull String controlId, - @DeviceTypes.DeviceType int deviceType, - @Status int status, - @NonNull ControlTemplate controlTemplate, - @NonNull CharSequence statusText, - @Nullable PendingIntent appIntent) { - Preconditions.checkNotNull(controlId); - Preconditions.checkNotNull(controlTemplate); - Preconditions.checkNotNull(statusText); - mControlId = controlId; - if (!DeviceTypes.validDeviceType(deviceType)) { - Log.e(TAG, "Invalid device type:" + deviceType); - mDeviceType = DeviceTypes.TYPE_UNKNOWN; - } else { - mDeviceType = deviceType; - } - mStatus = status; - mControlTemplate = controlTemplate; - mStatusText = statusText; - mAppIntent = appIntent; - } - - ControlState(Parcel in) { - mControlId = in.readString(); - mDeviceType = in.readInt(); - mStatus = in.readInt(); - mControlTemplate = ControlTemplate.CREATOR.createFromParcel(in); - mStatusText = in.readCharSequence(); - if (in.readByte() == 1) { - mAppIntent = PendingIntent.CREATOR.createFromParcel(in); - } else { - mAppIntent = null; - } - } - - @Override - public int describeContents() { - return 0; - } - - @NonNull - public String getControlId() { - return mControlId; - } - - @DeviceTypes.DeviceType - public int getDeviceType() { - return mDeviceType; - } - - @Nullable - public PendingIntent getAppIntent() { - return mAppIntent; - } - - @Status - public int getStatus() { - return mStatus; - } - - @NonNull - public ControlTemplate getControlTemplate() { - return mControlTemplate; - } - - @NonNull - public CharSequence getStatusText() { - return mStatusText; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mControlId); - dest.writeInt(mDeviceType); - dest.writeInt(mStatus); - mControlTemplate.writeToParcel(dest, flags); - dest.writeCharSequence(mStatusText); - if (mAppIntent != null) { - dest.writeByte((byte) 1); - mAppIntent.writeToParcel(dest, flags); - } else { - dest.writeByte((byte) 0); - } - } - - public static final Creator<ControlState> CREATOR = new Creator<ControlState>() { - @Override - public ControlState createFromParcel(Parcel source) { - return new ControlState(source); - } - - @Override - public ControlState[] newArray(int size) { - return new ControlState[size]; - } - }; - - /** - * Builder class for {@link ControlState}. - * - * This class facilitates the creation of {@link ControlState}. It provides the following - * defaults for non-optional parameters: - * <ul> - * <li> Device type: {@link DeviceTypes#TYPE_UNKNOWN} - * <li> Status: {@link ControlState#STATUS_OK} - * <li> Control template: {@link ControlTemplate#NO_TEMPLATE} - * <li> Status text: {@code ""} - * </ul> - */ - public static class Builder { - private static final String TAG = "ControlState.Builder"; - - private @NonNull String mControlId; - private @DeviceTypes.DeviceType - int mDeviceType = DeviceTypes.TYPE_UNKNOWN; - private @Status int mStatus = STATUS_OK; - private @NonNull ControlTemplate mControlTemplate = ControlTemplate.NO_TEMPLATE; - private @NonNull CharSequence mStatusText = ""; - private @Nullable PendingIntent mAppIntent; - - /** - * @param controlId the identifier of the {@link Control} that the resulting - * {@link ControlState} refers to. - */ - public Builder(@NonNull String controlId) { - Preconditions.checkNotNull(controlId); - mControlId = controlId; - } - - /** - * Creates a {@link Builder} using an existing {@link ControlState} as a base. - * @param controlState base for the builder. - */ - public Builder(@NonNull ControlState controlState) { - Preconditions.checkNotNull(controlState); - mControlId = controlState.mControlId; - mDeviceType = controlState.mDeviceType; - mStatus = controlState.mStatus; - mControlTemplate = controlState.mControlTemplate; - mStatusText = controlState.mStatusText; - mAppIntent = controlState.mAppIntent; - } - - - /** - * @param controlId the identifier of the {@link Control} for the resulting object. - * @return {@code this} - */ - @NonNull - public Builder setControlId(@NonNull String controlId) { - mControlId = controlId; - return this; - } - - /** - * @param deviceType the device type of the {@link Control}. - * @return {@code this} - */ - @NonNull - public Builder setDeviceType(@DeviceTypes.DeviceType int deviceType) { - if (!DeviceTypes.validDeviceType(deviceType)) { - Log.e(TAG, "Invalid device type:" + deviceType); - mDeviceType = DeviceTypes.TYPE_UNKNOWN; - } else { - mDeviceType = deviceType; - } - return this; - } - - /** - * @param status the current status of the {@link Control} - * @return {@code this} - */ - @NonNull - public Builder setStatus(@Status int status) { - mStatus = status; - return this; - } - - /** - * @param controlTemplate the template to use when rendering the {@code Control}. - * @return {@code this} - */ - @NonNull - public Builder setControlTemplate(@NonNull ControlTemplate controlTemplate) { - Preconditions.checkNotNull(controlTemplate); - mControlTemplate = controlTemplate; - return this; - } - - /** - * @param statusText the user-visible description of the status. - * @return {@code this} - */ - @NonNull - public Builder setStatusText(@NonNull CharSequence statusText) { - Preconditions.checkNotNull(statusText); - mStatusText = statusText; - 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; - } - - /** - * @return a new {@link ControlState} - */ - public ControlState build() { - return new ControlState(mControlId, mDeviceType, mStatus, mControlTemplate, mStatusText, - mAppIntent); - } - - /** - * Creates a new {@link ControlState.Builder} for the given {@link Control}. - * - * This will set the corresponding identifier as well as the device type. - * @param control the {@link Control} to create a state for. - * @return a {@link ControlState.Builder} for a {@link Control} - */ - public static Builder createForControl(Control control) { - return new Builder(control.getControlId()).setDeviceType(control.getDeviceType()); - } - } -} - diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java index 8a95f4d0f566..2fd51a1578f6 100644 --- a/core/java/android/service/controls/ControlsProviderService.java +++ b/core/java/android/service/controls/ControlsProviderService.java @@ -20,13 +20,21 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; import android.content.Intent; +import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.RemoteException; import android.service.controls.actions.ControlAction; +import android.service.controls.templates.ControlTemplate; +import android.text.TextUtils; +import android.util.Log; +import com.android.internal.util.Preconditions; + +import java.util.ArrayList; import java.util.List; /** @@ -38,8 +46,14 @@ public abstract class ControlsProviderService extends Service { @SdkConstant(SdkConstantType.SERVICE_ACTION) public static final String CONTROLS_ACTION = "android.service.controls.ControlsProviderService"; + public static final String CALLBACK_BUNDLE = "CALLBACK_BUNDLE"; + public static final String CALLBACK_BINDER = "CALLBACK_BINDER"; + public static final String CALLBACK_TOKEN = "CALLBACK_TOKEN"; + + public final String TAG = getClass().getSimpleName(); private IControlsProviderCallback mCallback; + private IBinder mToken; private RequestHandler mHandler; /** @@ -67,16 +81,80 @@ public abstract class ControlsProviderService extends Service { */ public abstract void onAction(@NonNull String controlId, @NonNull ControlAction action); - protected IControlsProviderCallback getControlsProviderCallback() { - return mCallback; + /** + * Sends a list of the controls available from this service. + * + * The items in the list must not have state information (as created by + * {@link Control.StatelessBuilder}). + * @param controls + */ + public void onLoad(@NonNull List<Control> controls) { + Preconditions.checkNotNull(controls); + List<Control> list = new ArrayList<>(); + for (Control control: controls) { + if (control == null) { + Log.e(TAG, "onLoad: null control."); + } + if (isStateless(control)) { + list.add(control); + } else { + Log.w(TAG, "onLoad: control is not stateless."); + list.add(new Control.StatelessBuilder(control).build()); + } + } + try { + mCallback.onLoad(mToken, list); + } catch (RemoteException ex) { + ex.rethrowAsRuntimeException(); + } + } + + /** + * Sends a list of the controls requested by {@link ControlsProviderService#subscribe} with + * their state. + * @param statefulControls + */ + public void onRefreshState(@NonNull List<Control> statefulControls) { + Preconditions.checkNotNull(statefulControls); + try { + mCallback.onRefreshState(mToken, statefulControls); + } catch (RemoteException ex) { + ex.rethrowAsRuntimeException(); + } + } + + /** + * Sends the response of a command in the specified {@link Control}. + * @param controlId + * @param response + */ + public void onControlActionResponse( + @NonNull String controlId, @ControlAction.ResponseResult int response) { + Preconditions.checkNotNull(controlId); + if (!ControlAction.isValidResponse(response)) { + Log.e(TAG, "Not valid response result: " + response); + response = ControlAction.RESPONSE_UNKNOWN; + } + try { + mCallback.onControlActionResponse(mToken, controlId, response); + } catch (RemoteException ex) { + ex.rethrowAsRuntimeException(); + } + } + + private boolean isStateless(Control control) { + return (control.getStatus() == Control.STATUS_UNKNOWN + && control.getControlTemplate().getTemplateType() == ControlTemplate.TYPE_NONE + && TextUtils.isEmpty(control.getStatusText())); } @Override public IBinder onBind(Intent intent) { mHandler = new RequestHandler(Looper.getMainLooper()); - Bundle bundle = intent.getBundleExtra("CALLBACK_BUNDLE"); - IBinder callbackBinder = bundle.getBinder("CALLBACK_BINDER"); + Bundle bundle = intent.getBundleExtra(CALLBACK_BUNDLE); + IBinder callbackBinder = bundle.getBinder(CALLBACK_BINDER); + mToken = bundle.getBinder(CALLBACK_TOKEN); mCallback = IControlsProviderCallback.Stub.asInterface(callbackBinder); return new IControlsProvider.Stub() { diff --git a/core/java/android/service/controls/IControlsProviderCallback.aidl b/core/java/android/service/controls/IControlsProviderCallback.aidl index 3dbb68c1c7f0..91f6a7980ce6 100644 --- a/core/java/android/service/controls/IControlsProviderCallback.aidl +++ b/core/java/android/service/controls/IControlsProviderCallback.aidl @@ -17,13 +17,12 @@ package android.service.controls; import android.service.controls.Control; -import android.service.controls.ControlState; /** @hide */ oneway interface IControlsProviderCallback { - void onLoad(in List<Control> controls); + void onLoad(in IBinder token, in List<Control> controls); - void onRefreshState(in List<ControlState> controlStates); + void onRefreshState(in IBinder token, in List<Control> statefulControls); - void onControlActionResponse(in String controlId, int response); + void onControlActionResponse(in IBinder token, in String controlId, int response); }
\ No newline at end of file diff --git a/core/java/android/service/controls/actions/ControlAction.java b/core/java/android/service/controls/actions/ControlAction.java index 63ae9bd6810f..83d1cf824f1f 100644 --- a/core/java/android/service/controls/actions/ControlAction.java +++ b/core/java/android/service/controls/actions/ControlAction.java @@ -23,8 +23,8 @@ import android.annotation.Nullable; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.service.controls.templates.ControlTemplate; import android.service.controls.IControlsProviderCallback; +import android.service.controls.templates.ControlTemplate; import com.android.internal.util.Preconditions; @@ -82,11 +82,17 @@ public abstract class ControlAction implements Parcelable { public static final @ActionType int TYPE_COMMAND = 5; + + public static final boolean isValidResponse(@ResponseResult int response) { + return (response >= 0 && response < NUM_RESPONSE_TYPES); + } + private static final int NUM_RESPONSE_TYPES = 6; /** * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({ + RESPONSE_UNKNOWN, RESPONSE_OK, RESPONSE_FAIL, RESPONSE_CHALLENGE_ACK, @@ -95,31 +101,33 @@ public abstract class ControlAction implements Parcelable { }) public @interface ResponseResult {}; + public static final @ResponseResult int RESPONSE_UNKNOWN = 0; + /** * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that * the action has been performed. The action may still fail later and the state may not change. */ - public static final @ResponseResult int RESPONSE_OK = 0; + public static final @ResponseResult int RESPONSE_OK = 1; /** * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that * the action has failed. */ - public static final @ResponseResult int RESPONSE_FAIL = 1; + public static final @ResponseResult int RESPONSE_FAIL = 2; /** * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that * in order for the action to be performed, acknowledgment from the user is required. */ - public static final @ResponseResult int RESPONSE_CHALLENGE_ACK = 2; + public static final @ResponseResult int RESPONSE_CHALLENGE_ACK = 3; /** * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that * in order for the action to be performed, a PIN is required. */ - public static final @ResponseResult int RESPONSE_CHALLENGE_PIN = 3; + public static final @ResponseResult int RESPONSE_CHALLENGE_PIN = 4; /** * Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that * in order for the action to be performed, an alphanumeric passphrase is required. */ - public static final @ResponseResult int RESPONSE_CHALLENGE_PASSPHRASE = 4; + public static final @ResponseResult int RESPONSE_CHALLENGE_PASSPHRASE = 5; /** * The {@link ActionType} associated with this class. diff --git a/core/java/android/service/controls/templates/ControlTemplate.java b/core/java/android/service/controls/templates/ControlTemplate.java index f39b26efee49..bf194f8efcda 100644 --- a/core/java/android/service/controls/templates/ControlTemplate.java +++ b/core/java/android/service/controls/templates/ControlTemplate.java @@ -23,7 +23,6 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.service.controls.Control; -import android.service.controls.ControlState; import android.service.controls.actions.ControlAction; import com.android.internal.util.Preconditions; @@ -34,12 +33,11 @@ import java.lang.annotation.RetentionPolicy; /** * An abstract input template for a {@link Control}. * - * Specifies what layout is presented to the user when a {@link ControlState} is assigned to a - * particular {@link Control}. + * Specifies what layout is presented to the user for a given {@link Control}. * <p> * Some instances of {@link Control} can originate actions (via user interaction) to modify its - * associated state. The actions available to a given {@link Control} in a particular - * {@link ControlState} are determined by its {@link ControlTemplate}. + * associated state. The actions available to a given {@link Control} are determined by its + * {@link ControlTemplate}. * @see ControlAction * @hide */ diff --git a/core/java/android/service/controls/templates/RangeTemplate.java b/core/java/android/service/controls/templates/RangeTemplate.java index 5624f88b16a3..bb79d83b1825 100644 --- a/core/java/android/service/controls/templates/RangeTemplate.java +++ b/core/java/android/service/controls/templates/RangeTemplate.java @@ -21,7 +21,6 @@ import android.annotation.Nullable; import android.os.Bundle; import android.os.Parcel; import android.service.controls.Control; -import android.service.controls.ControlState; import android.service.controls.actions.FloatAction; /** @@ -61,7 +60,7 @@ public final class RangeTemplate extends ControlTemplate { * @param templateId the identifier for this template object * @param minValue minimum value for the input * @param maxValue maximum value for the input - * @param currentValue the current value of the {@link ControlState} containing this object. + * @param currentValue the current value of the {@link Control} containing this object. * @param stepValue minimum value of increments/decrements when interacting with this control. * @param formatString a formatting string as per {@link String#format} used to display the * {@code currentValue}. If {@code null} is passed, the "%.1f" is used. |
