| /* |
| * 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.templates; |
| |
| import android.annotation.CallSuper; |
| import android.annotation.IntDef; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.content.Context; |
| import android.os.Bundle; |
| import android.service.controls.Control; |
| import android.service.controls.actions.ControlAction; |
| import android.util.Log; |
| |
| import com.android.internal.util.Preconditions; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| |
| /** |
| * An abstract input template for a {@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} are determined by its |
| * {@link ControlTemplate}. |
| * @see ControlAction |
| */ |
| public abstract class ControlTemplate { |
| |
| private static final String TAG = "ControlTemplate"; |
| |
| private static final String KEY_TEMPLATE_ID = "key_template_id"; |
| private static final String KEY_TEMPLATE_TYPE = "key_template_type"; |
| |
| /** |
| * Singleton representing a {@link Control} with no input. |
| * @hide |
| */ |
| public static final @NonNull ControlTemplate NO_TEMPLATE = new ControlTemplate("") { |
| @Override |
| public int getTemplateType() { |
| return TYPE_NO_TEMPLATE; |
| } |
| }; |
| |
| /** |
| * Object returned when there is an unparcelling error. |
| * @hide |
| */ |
| private static final @NonNull ControlTemplate ERROR_TEMPLATE = new ControlTemplate("") { |
| @Override |
| public int getTemplateType() { |
| return TYPE_ERROR; |
| } |
| }; |
| |
| /** |
| * @hide |
| */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef({ |
| TYPE_ERROR, |
| TYPE_NO_TEMPLATE, |
| TYPE_TOGGLE, |
| TYPE_RANGE, |
| TYPE_THUMBNAIL, |
| TYPE_TOGGLE_RANGE, |
| TYPE_TEMPERATURE, |
| TYPE_STATELESS |
| }) |
| public @interface TemplateType {} |
| |
| /** |
| * Type identifier of the template returned by {@link #getErrorTemplate()}. |
| */ |
| public static final @TemplateType int TYPE_ERROR = -1; |
| |
| /** |
| * Type identifier of {@link ControlTemplate#getNoTemplateObject}. |
| */ |
| public static final @TemplateType int TYPE_NO_TEMPLATE = 0; |
| |
| /** |
| * Type identifier of {@link ToggleTemplate}. |
| */ |
| public static final @TemplateType int TYPE_TOGGLE = 1; |
| |
| /** |
| * Type identifier of {@link RangeTemplate}. |
| */ |
| public static final @TemplateType int TYPE_RANGE = 2; |
| |
| /** |
| * Type identifier of {@link ThumbnailTemplate}. |
| */ |
| public static final @TemplateType int TYPE_THUMBNAIL = 3; |
| |
| /** |
| * Type identifier of {@link ToggleRangeTemplate}. |
| */ |
| public static final @TemplateType int TYPE_TOGGLE_RANGE = 6; |
| |
| /** |
| * Type identifier of {@link TemperatureControlTemplate}. |
| */ |
| public static final @TemplateType int TYPE_TEMPERATURE = 7; |
| |
| /** |
| * Type identifier of {@link StatelessTemplate}. |
| */ |
| public static final @TemplateType int TYPE_STATELESS = 8; |
| |
| private @NonNull final String mTemplateId; |
| |
| /** |
| * @return the identifier for this object. |
| */ |
| @NonNull |
| public String getTemplateId() { |
| return mTemplateId; |
| } |
| |
| /** |
| * The template type associated with this class. |
| */ |
| public abstract @TemplateType int getTemplateType(); |
| |
| /** |
| * Obtain a {@link Bundle} describing this object populated with data. |
| * @return a {@link Bundle} containing the data that represents this object. |
| * @hide |
| */ |
| @CallSuper |
| @NonNull |
| Bundle getDataBundle() { |
| Bundle b = new Bundle(); |
| b.putInt(KEY_TEMPLATE_TYPE, getTemplateType()); |
| b.putString(KEY_TEMPLATE_ID, mTemplateId); |
| return b; |
| } |
| |
| private ControlTemplate() { |
| mTemplateId = ""; |
| } |
| |
| /** |
| * @param b |
| * @hide |
| */ |
| ControlTemplate(@NonNull Bundle b) { |
| mTemplateId = b.getString(KEY_TEMPLATE_ID); |
| } |
| |
| /** |
| * @hide |
| */ |
| ControlTemplate(@NonNull String templateId) { |
| Preconditions.checkNotNull(templateId); |
| mTemplateId = templateId; |
| } |
| |
| /** |
| * Call to prepare values for Binder transport. |
| * |
| * @hide |
| */ |
| public void prepareTemplateForBinder(@NonNull Context context) {} |
| |
| /** |
| * |
| * @param bundle |
| * @return |
| * @hide |
| */ |
| @NonNull |
| static ControlTemplate createTemplateFromBundle(@Nullable Bundle bundle) { |
| if (bundle == null) { |
| Log.e(TAG, "Null bundle"); |
| return ERROR_TEMPLATE; |
| } |
| int type = bundle.getInt(KEY_TEMPLATE_TYPE, TYPE_ERROR); |
| try { |
| switch (type) { |
| case TYPE_TOGGLE: |
| return new ToggleTemplate(bundle); |
| case TYPE_RANGE: |
| return new RangeTemplate(bundle); |
| case TYPE_THUMBNAIL: |
| return new ThumbnailTemplate(bundle); |
| case TYPE_TOGGLE_RANGE: |
| return new ToggleRangeTemplate(bundle); |
| case TYPE_TEMPERATURE: |
| return new TemperatureControlTemplate(bundle); |
| case TYPE_STATELESS: |
| return new StatelessTemplate(bundle); |
| case TYPE_NO_TEMPLATE: |
| return NO_TEMPLATE; |
| case TYPE_ERROR: |
| default: |
| return ERROR_TEMPLATE; |
| } |
| } catch (Exception e) { |
| Log.e(TAG, "Error creating template", e); |
| return ERROR_TEMPLATE; |
| } |
| } |
| |
| /** |
| * @return a singleton {@link ControlTemplate} used for indicating an error in unparceling. |
| */ |
| @NonNull |
| public static ControlTemplate getErrorTemplate() { |
| return ERROR_TEMPLATE; |
| } |
| |
| /** |
| * Get a singleton {@link ControlTemplate}, which supports no direct user input. |
| * |
| * Used by {@link Control.StatelessBuilder} when there is no known state. Can also be used |
| * in {@link Control.StatefulBuilder} for conveying information to a user about the |
| * {@link Control} but direct user interaction is not desired. Since this template has no |
| * corresponding {@link ControlAction}, any user interaction will launch the |
| * {@link Control#getAppIntent()}. |
| * |
| * @return a singleton {@link ControlTemplate} to indicate no specific template is used by |
| * this {@link Control} |
| */ |
| @NonNull |
| public static ControlTemplate getNoTemplateObject() { |
| return NO_TEMPLATE; |
| } |
| |
| } |