summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorFabian Kozynski <kozynski@google.com>2020-01-02 15:19:13 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-01-02 15:19:13 +0000
commit49fe4569a8a9e7b9f6193abaeee0cf78f93ebaee (patch)
tree2fe9264bebef05ea7b37c74ef810c0355462f1f1 /core/java/android
parent695ee8cd8d4c711b4c09ee6f40283e3d8a5e4232 (diff)
parentee57f49c7d8ab4d6c22608ae8de224b356f5b94e (diff)
Merge "Merge ControlState into Control"
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/service/controls/Control.java265
-rw-r--r--core/java/android/service/controls/ControlState.aidl19
-rw-r--r--core/java/android/service/controls/ControlState.java335
-rw-r--r--core/java/android/service/controls/ControlsProviderService.java86
-rw-r--r--core/java/android/service/controls/IControlsProviderCallback.aidl7
-rw-r--r--core/java/android/service/controls/actions/ControlAction.java20
-rw-r--r--core/java/android/service/controls/templates/ControlTemplate.java8
-rw-r--r--core/java/android/service/controls/templates/RangeTemplate.java3
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.