• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.complication;
18 
19 import android.annotation.IntDef;
20 import android.view.View;
21 
22 import java.lang.annotation.Retention;
23 import java.lang.annotation.RetentionPolicy;
24 
25 /**
26  * {@link Complication} is an interface for defining a complication, a visual component rendered
27  * above a dream. {@link Complication} instances encapsulate the logic for generating the view to be
28  * shown, along with the supporting control/logic. The decision for including the
29  * {@link Complication} is not the responsibility of the {@link Complication}. This is instead
30  * handled by domain logic and invocations to add and remove the {@link Complication} through
31  * {@link com.android.systemui.dreams.DreamOverlayStateController#addComplication(Complication)} and
32  * {@link com.android.systemui.dreams.DreamOverlayStateController#removeComplication(Complication)}.
33  * A {@link Complication} also does not represent a specific instance of the view. Instead, it
34  * should be viewed as a provider, where view instances are requested from it. The associated
35  * {@link ViewHolder} interface is requested for each view request. This object is retained for the
36  * view's lifetime, providing a container for any associated logic. The complication rendering
37  * system will consult this {@link ViewHolder} for {@link View} to show and
38  * {@link ComplicationLayoutParams} to position the view. {@link ComplicationLayoutParams} allow for
39  * specifying the sizing and position of the {@link Complication}.
40  *
41  * The following code sample exhibits the entities and lifecycle involved with a
42  * {@link Complication}.
43  *
44  * <pre>{@code
45  * // This component allows for the complication to generate a new ViewHolder for every request.
46  * @Subcomponent
47  * interface ExampleViewHolderComponent {
48  *     @Subcomponent.Factory
49  *     interface Factory {
50  *         ExampleViewHolderComponent create();
51  *     }
52  *
53  *     ExampleViewHolder getViewHolder();
54  * }
55  *
56  * // An example entity that controls whether or not a complication should be included on dreams.
57  * // Note how the complication is tracked by reference for removal.
58  * public class ExampleComplicationProvider {
59  *     private final DreamOverlayStateController mDreamOverlayStateController;
60  *     private final ExampleComplication mComplication;
61  *     @Inject
62  *     public ExampleComplicationProvider(
63  *             ExampleComplication complication,
64  *             DreamOverlayStateController stateController) {
65  *         mDreamOverlayStateController = stateController;
66  *         mComplication = complication;
67  *     }
68  *
69  *     public void onShowConditionsMet(boolean met) {
70  *         if (met) {
71  *             mDreamOverlayStateController.addComplication(mComplication);
72  *         } else {
73  *             mDreamOverlayStateController.removeComplication(mComplication);
74  *         }
75  *     }
76  * }
77  *
78  * // An example complication. Note how a factory is created to supply a unique ViewHolder for each
79  * // request. Also, there is no particular view instance members defined in the complication.
80  * class ExampleComplication implements Complication {
81  *     private final ExampleViewHolderComponent.Factory mFactory;
82  *     @Inject
83  *     public ExampleComplication(ExampleViewHolderComponent.Factory viewHolderComponentFactory) {
84  *         mFactory = viewHolderComponentFactory;
85  *     }
86  *
87  *     @Override
88  *     public ViewHolder createView(ComplicationViewModel model) {
89  *         return mFactory.create().getViewHolder();
90  *     }
91  * }
92  *
93  * // Not every ViewHolder needs to include a view controller. It is included here as an example of
94  * // how such logic can be contained and associated with the ViewHolder lifecycle.
95  * class ExampleViewController extends ViewController<FrameLayout> {
96  *     protected ExampleViewController(FrameLayout view) {
97  *         super(view);
98  *     }
99  *
100  *     @Override
101  *     protected void onViewAttached() { }
102  *
103  *     @Override
104  *     protected void onViewDetached() { }
105  * }
106  *
107  * // An example ViewHolder. This is the correct place to contain any value/logic associated with a
108  * // particular instance of the ComplicationView.
109  * class ExampleViewHolder implements Complication.ViewHolder {
110  *     final FrameLayout mView;
111  *     final ExampleViewController mController;
112  *
113  *     @Inject
114  *     public ExampleViewHolder(Context context) {
115  *         mView = new FrameLayout(context);
116  *         mController = new ExampleViewController(mView);
117  *     }
118  *     @Override
119  *     public View getView() {
120  *         return mView;
121  *     }
122  *
123  *     @Override
124  *     public ComplicationLayoutParams getLayoutParams() {
125  *         return new ComplicationLayoutParams(
126  *                 200,
127  *                 100,
128  *                 ComplicationLayoutParams.POSITION_TOP | ComplicationLayoutParams.DIRECTION_END,
129  *                 ComplicationLayoutParams.DIRECTION_DOWN,
130  *                 4);
131  *     }
132  * }
133  * }
134  * </pre>
135  */
136 public interface Complication {
137     @Retention(RetentionPolicy.SOURCE)
138     @IntDef(prefix = { "CATEGORY_" }, value = {
139             CATEGORY_STANDARD,
140             CATEGORY_SYSTEM,
141     })
142 
143     @interface Category {}
144     /**
145      * {@code CATEGORY_STANDARD} indicates the complication is a normal component. Rules and
146      * settings, such as hiding all complications, will apply to this complication.
147      */
148     int CATEGORY_STANDARD = 1 << 0;
149     /**
150      * {@code CATEGORY_SYSTEM} indicates complications driven by SystemUI. Usually, these are
151      * core components that are not user controlled. These can potentially deviate from given
152      * rule sets that would normally apply to {@code CATEGORY_STANDARD}.
153      */
154     int CATEGORY_SYSTEM = 1 << 1;
155 
156     /**
157      * The type of dream complications which can be provided by a {@link Complication}.
158      */
159     @IntDef(prefix = {"COMPLICATION_TYPE_"}, flag = true, value = {
160             COMPLICATION_TYPE_NONE,
161             COMPLICATION_TYPE_TIME,
162             COMPLICATION_TYPE_DATE,
163             COMPLICATION_TYPE_WEATHER,
164             COMPLICATION_TYPE_AIR_QUALITY,
165             COMPLICATION_TYPE_CAST_INFO,
166             COMPLICATION_TYPE_HOME_CONTROLS,
167             COMPLICATION_TYPE_SMARTSPACE,
168             COMPLICATION_TYPE_MEDIA_ENTRY
169     })
170     @Retention(RetentionPolicy.SOURCE)
171     @interface ComplicationType {}
172 
173     int COMPLICATION_TYPE_NONE = 0;
174     int COMPLICATION_TYPE_TIME = 1;
175     int COMPLICATION_TYPE_DATE = 1 << 1;
176     int COMPLICATION_TYPE_WEATHER = 1 << 2;
177     int COMPLICATION_TYPE_AIR_QUALITY = 1 << 3;
178     int COMPLICATION_TYPE_CAST_INFO = 1 << 4;
179     int COMPLICATION_TYPE_HOME_CONTROLS = 1 << 5;
180     int COMPLICATION_TYPE_SMARTSPACE = 1 << 6;
181     int COMPLICATION_TYPE_MEDIA_ENTRY = 1 << 7;
182 
183     /**
184      * The {@link Host} interface specifies a way a {@link Complication} to communicate with its
185      * parent entity for information and actions.
186      */
187     interface Host {
188         /**
189          * Called to signal a {@link Complication} has requested to exit the dream.
190          */
requestExitDream()191         void requestExitDream();
192     }
193 
194     /**
195      * The implementation of this interface is in charge of managing the visible state of
196      * the shown complication.
197      */
198     interface VisibilityController {
199         /**
200          * Called to set the visibility of all shown and future complications. Changes in visibility
201          * will always be animated.
202          * @param visibility The desired future visibility.
203          */
setVisibility(@iew.Visibility int visibility)204         void setVisibility(@View.Visibility int visibility);
205     }
206 
207     /**
208      * Returned through {@link Complication#createView(ComplicationViewModel)}, {@link ViewHolder}
209      * is a container for a single {@link Complication} instance. The {@link Host} guarantees that
210      * the {@link ViewHolder} will be retained for the lifetime of the {@link Complication}
211      * instance's user. The view is responsible for providing the view that represents the
212      * {@link Complication}. This object is the proper place to store any related entities, such as
213      * a {@link com.android.systemui.util.ViewController} for the view.
214      */
215     interface ViewHolder {
216         /**
217          * Returns the {@link View} associated with the {@link ViewHolder}. This {@link View} should
218          * be stable and generated once.
219          * @return
220          */
getView()221         View getView();
222 
223         /**
224          * Returns the {@link Category} associated with the {@link Complication}. {@link Category}
225          * is a grouping which helps define the relationship of the {@link Complication} to
226          * System UI and the rest of the system. It is used for presentation and other decisions.
227          */
228         @Complication.Category
getCategory()229         default int getCategory() {
230             return Complication.CATEGORY_STANDARD;
231         }
232 
233         /**
234          * Returns the {@link ComplicationLayoutParams} associated with this complication. The
235          * values expressed here are treated as preference rather than requirement. The hosting
236          * entity is free to modify/interpret the parameters as deemed fit.
237          */
getLayoutParams()238         ComplicationLayoutParams getLayoutParams();
239     }
240 
241     /**
242      * Generates a {@link ViewHolder} for the {@link Complication}. This captures both the view and
243      * control logic for a single instance of the complication. The {@link Complication} may be
244      * asked at any time to generate another view.
245      * @param model The {@link ComplicationViewModel} associated with this particular
246      *              {@link Complication} instance.
247      * @return a {@link ViewHolder} for this {@link Complication} instance.
248      */
createView(ComplicationViewModel model)249     ViewHolder createView(ComplicationViewModel model);
250 
251     /**
252      * Returns the types that must be present in order for this complication to participate on
253      * the dream overlay. By default, this method returns
254      * {@code Complication.COMPLICATION_TYPE_NONE} to indicate no types are required.
255      * @return
256      */
257     @Complication.ComplicationType
getRequiredTypeAvailability()258     default int getRequiredTypeAvailability() {
259         return Complication.COMPLICATION_TYPE_NONE;
260     }
261 }
262