/* * Copyright (C) 2022 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 com.android.systemui.complication; import android.annotation.IntDef; import android.view.View; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * {@link Complication} is an interface for defining a complication, a visual component rendered * above a dream. {@link Complication} instances encapsulate the logic for generating the view to be * shown, along with the supporting control/logic. The decision for including the * {@link Complication} is not the responsibility of the {@link Complication}. This is instead * handled by domain logic and invocations to add and remove the {@link Complication} through * {@link com.android.systemui.dreams.DreamOverlayStateController#addComplication(Complication)} and * {@link com.android.systemui.dreams.DreamOverlayStateController#removeComplication(Complication)}. * A {@link Complication} also does not represent a specific instance of the view. Instead, it * should be viewed as a provider, where view instances are requested from it. The associated * {@link ViewHolder} interface is requested for each view request. This object is retained for the * view's lifetime, providing a container for any associated logic. The complication rendering * system will consult this {@link ViewHolder} for {@link View} to show and * {@link ComplicationLayoutParams} to position the view. {@link ComplicationLayoutParams} allow for * specifying the sizing and position of the {@link Complication}. * * The following code sample exhibits the entities and lifecycle involved with a * {@link Complication}. * *
{@code
 * // This component allows for the complication to generate a new ViewHolder for every request.
 * @Subcomponent
 * interface ExampleViewHolderComponent {
 *     @Subcomponent.Factory
 *     interface Factory {
 *         ExampleViewHolderComponent create();
 *     }
 *
 *     ExampleViewHolder getViewHolder();
 * }
 *
 * // An example entity that controls whether or not a complication should be included on dreams.
 * // Note how the complication is tracked by reference for removal.
 * public class ExampleComplicationProvider {
 *     private final DreamOverlayStateController mDreamOverlayStateController;
 *     private final ExampleComplication mComplication;
 *     @Inject
 *     public ExampleComplicationProvider(
 *             ExampleComplication complication,
 *             DreamOverlayStateController stateController) {
 *         mDreamOverlayStateController = stateController;
 *         mComplication = complication;
 *     }
 *
 *     public void onShowConditionsMet(boolean met) {
 *         if (met) {
 *             mDreamOverlayStateController.addComplication(mComplication);
 *         } else {
 *             mDreamOverlayStateController.removeComplication(mComplication);
 *         }
 *     }
 * }
 *
 * // An example complication. Note how a factory is created to supply a unique ViewHolder for each
 * // request. Also, there is no particular view instance members defined in the complication.
 * class ExampleComplication implements Complication {
 *     private final ExampleViewHolderComponent.Factory mFactory;
 *     @Inject
 *     public ExampleComplication(ExampleViewHolderComponent.Factory viewHolderComponentFactory) {
 *         mFactory = viewHolderComponentFactory;
 *     }
 *
 *     @Override
 *     public ViewHolder createView(ComplicationViewModel model) {
 *         return mFactory.create().getViewHolder();
 *     }
 * }
 *
 * // Not every ViewHolder needs to include a view controller. It is included here as an example of
 * // how such logic can be contained and associated with the ViewHolder lifecycle.
 * class ExampleViewController extends ViewController {
 *     protected ExampleViewController(FrameLayout view) {
 *         super(view);
 *     }
 *
 *     @Override
 *     protected void onViewAttached() { }
 *
 *     @Override
 *     protected void onViewDetached() { }
 * }
 *
 * // An example ViewHolder. This is the correct place to contain any value/logic associated with a
 * // particular instance of the ComplicationView.
 * class ExampleViewHolder implements Complication.ViewHolder {
 *     final FrameLayout mView;
 *     final ExampleViewController mController;
 *
 *     @Inject
 *     public ExampleViewHolder(Context context) {
 *         mView = new FrameLayout(context);
 *         mController = new ExampleViewController(mView);
 *     }
 *     @Override
 *     public View getView() {
 *         return mView;
 *     }
 *
 *     @Override
 *     public ComplicationLayoutParams getLayoutParams() {
 *         return new ComplicationLayoutParams(
 *                 200,
 *                 100,
 *                 ComplicationLayoutParams.POSITION_TOP | ComplicationLayoutParams.DIRECTION_END,
 *                 ComplicationLayoutParams.DIRECTION_DOWN,
 *                 4);
 *     }
 * }
 * }
 * 
*/ public interface Complication { @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "CATEGORY_" }, value = { CATEGORY_STANDARD, CATEGORY_SYSTEM, }) @interface Category {} /** * {@code CATEGORY_STANDARD} indicates the complication is a normal component. Rules and * settings, such as hiding all complications, will apply to this complication. */ int CATEGORY_STANDARD = 1 << 0; /** * {@code CATEGORY_SYSTEM} indicates complications driven by SystemUI. Usually, these are * core components that are not user controlled. These can potentially deviate from given * rule sets that would normally apply to {@code CATEGORY_STANDARD}. */ int CATEGORY_SYSTEM = 1 << 1; /** * The type of dream complications which can be provided by a {@link Complication}. */ @IntDef(prefix = {"COMPLICATION_TYPE_"}, flag = true, value = { COMPLICATION_TYPE_NONE, COMPLICATION_TYPE_TIME, COMPLICATION_TYPE_DATE, COMPLICATION_TYPE_WEATHER, COMPLICATION_TYPE_AIR_QUALITY, COMPLICATION_TYPE_CAST_INFO, COMPLICATION_TYPE_HOME_CONTROLS, COMPLICATION_TYPE_SMARTSPACE, COMPLICATION_TYPE_MEDIA_ENTRY }) @Retention(RetentionPolicy.SOURCE) @interface ComplicationType {} int COMPLICATION_TYPE_NONE = 0; int COMPLICATION_TYPE_TIME = 1; int COMPLICATION_TYPE_DATE = 1 << 1; int COMPLICATION_TYPE_WEATHER = 1 << 2; int COMPLICATION_TYPE_AIR_QUALITY = 1 << 3; int COMPLICATION_TYPE_CAST_INFO = 1 << 4; int COMPLICATION_TYPE_HOME_CONTROLS = 1 << 5; int COMPLICATION_TYPE_SMARTSPACE = 1 << 6; int COMPLICATION_TYPE_MEDIA_ENTRY = 1 << 7; /** * The {@link Host} interface specifies a way a {@link Complication} to communicate with its * parent entity for information and actions. */ interface Host { /** * Called to signal a {@link Complication} has requested to exit the dream. */ void requestExitDream(); } /** * The implementation of this interface is in charge of managing the visible state of * the shown complication. */ interface VisibilityController { /** * Called to set the visibility of all shown and future complications. Changes in visibility * will always be animated. * @param visibility The desired future visibility. */ void setVisibility(@View.Visibility int visibility); } /** * Returned through {@link Complication#createView(ComplicationViewModel)}, {@link ViewHolder} * is a container for a single {@link Complication} instance. The {@link Host} guarantees that * the {@link ViewHolder} will be retained for the lifetime of the {@link Complication} * instance's user. The view is responsible for providing the view that represents the * {@link Complication}. This object is the proper place to store any related entities, such as * a {@link com.android.systemui.util.ViewController} for the view. */ interface ViewHolder { /** * Returns the {@link View} associated with the {@link ViewHolder}. This {@link View} should * be stable and generated once. * @return */ View getView(); /** * Returns the {@link Category} associated with the {@link Complication}. {@link Category} * is a grouping which helps define the relationship of the {@link Complication} to * System UI and the rest of the system. It is used for presentation and other decisions. */ @Complication.Category default int getCategory() { return Complication.CATEGORY_STANDARD; } /** * Returns the {@link ComplicationLayoutParams} associated with this complication. The * values expressed here are treated as preference rather than requirement. The hosting * entity is free to modify/interpret the parameters as deemed fit. */ ComplicationLayoutParams getLayoutParams(); } /** * Generates a {@link ViewHolder} for the {@link Complication}. This captures both the view and * control logic for a single instance of the complication. The {@link Complication} may be * asked at any time to generate another view. * @param model The {@link ComplicationViewModel} associated with this particular * {@link Complication} instance. * @return a {@link ViewHolder} for this {@link Complication} instance. */ ViewHolder createView(ComplicationViewModel model); /** * Returns the types that must be present in order for this complication to participate on * the dream overlay. By default, this method returns * {@code Complication.COMPLICATION_TYPE_NONE} to indicate no types are required. * @return */ @Complication.ComplicationType default int getRequiredTypeAvailability() { return Complication.COMPLICATION_TYPE_NONE; } }