Merge "Merge ControlState into Control"
This commit is contained in:
committed by
Android (Google) Code Review
commit
49fe4569a8
@@ -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,22 +379,12 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user