• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.systemui.plugins.qs;
16 
17 import android.annotation.NonNull;
18 import android.content.Context;
19 import android.content.res.Resources;
20 import android.graphics.drawable.Drawable;
21 import android.metrics.LogMaker;
22 import android.service.quicksettings.Tile;
23 import android.text.TextUtils;
24 
25 import androidx.annotation.Nullable;
26 
27 import com.android.internal.logging.InstanceId;
28 import com.android.systemui.animation.Expandable;
29 import com.android.systemui.plugins.annotations.DependsOn;
30 import com.android.systemui.plugins.annotations.ProvidesInterface;
31 import com.android.systemui.plugins.qs.QSTile.Callback;
32 import com.android.systemui.plugins.qs.QSTile.Icon;
33 import com.android.systemui.plugins.qs.QSTile.State;
34 
35 import java.util.Objects;
36 import java.util.function.Supplier;
37 
38 @ProvidesInterface(version = QSTile.VERSION)
39 @DependsOn(target = QSIconView.class)
40 @DependsOn(target = Callback.class)
41 @DependsOn(target = Icon.class)
42 @DependsOn(target = State.class)
43 public interface QSTile {
44     int VERSION = 4;
45 
getTileSpec()46     String getTileSpec();
47 
isAvailable()48     boolean isAvailable();
setTileSpec(String tileSpec)49     void setTileSpec(String tileSpec);
50 
clearState()51     @Deprecated default void clearState() {}
refreshState()52     void refreshState();
53 
addCallback(Callback callback)54     void addCallback(Callback callback);
removeCallback(Callback callback)55     void removeCallback(Callback callback);
removeCallbacks()56     void removeCallbacks();
57 
58     /**
59      * The tile was clicked.
60      *
61      * @param expandable {@link Expandable} that was clicked.
62      */
click(@ullable Expandable expandable)63     void click(@Nullable Expandable expandable);
64 
65     /**
66      * The tile secondary click was triggered.
67      *
68      * @param expandable {@link Expandable} that was clicked.
69      */
secondaryClick(@ullable Expandable expandable)70     void secondaryClick(@Nullable Expandable expandable);
71 
72     /**
73      * The tile was long clicked.
74      *
75      * @param expandable {@link Expandable} that was clicked.
76      */
longClick(@ullable Expandable expandable)77     void longClick(@Nullable Expandable expandable);
78 
userSwitch(int currentUser)79     void userSwitch(int currentUser);
80 
81     /**
82      * @deprecated not needed as {@link com.android.internal.logging.UiEvent} will use
83      * {@link #getMetricsSpec}
84      */
85     @Deprecated
getMetricsCategory()86     int getMetricsCategory();
87 
setListening(Object client, boolean listening)88     void setListening(Object client, boolean listening);
setDetailListening(boolean show)89     void setDetailListening(boolean show);
90 
destroy()91     void destroy();
92 
getTileLabel()93     CharSequence getTileLabel();
94 
getState()95     State getState();
96 
populate(LogMaker logMaker)97     default LogMaker populate(LogMaker logMaker) {
98         return logMaker;
99     }
100 
101     /**
102      * Return a string to be used to identify the tile in UiEvents.
103      */
getMetricsSpec()104     default String getMetricsSpec() {
105         return getClass().getSimpleName();
106     }
107 
108     /**
109      * Return an {@link InstanceId} to be used to identify the tile in UiEvents.
110      */
getInstanceId()111     InstanceId getInstanceId();
112 
isTileReady()113     default boolean isTileReady() {
114         return false;
115     }
116 
117     /**
118      * Return whether the tile is set to its listening state and therefore receiving updates and
119      * refreshes from controllers
120      */
isListening()121     boolean isListening();
122 
123     @ProvidesInterface(version = Callback.VERSION)
124     interface Callback {
125         static final int VERSION = 2;
onStateChanged(State state)126         void onStateChanged(State state);
127     }
128 
129     @ProvidesInterface(version = Icon.VERSION)
130     public static abstract class Icon {
131         public static final int VERSION = 1;
getDrawable(Context context)132         abstract public Drawable getDrawable(Context context);
133 
getInvisibleDrawable(Context context)134         public Drawable getInvisibleDrawable(Context context) {
135             return getDrawable(context);
136         }
137 
138         @Override
hashCode()139         public int hashCode() {
140             return Icon.class.hashCode();
141         }
142 
getPadding()143         public int getPadding() {
144             return 0;
145         }
146 
147         @Override
148         @NonNull
toString()149         public String toString() {
150             return "Icon";
151         }
152     }
153 
154     @ProvidesInterface(version = State.VERSION)
155     public static class State {
156         public static final int VERSION = 1;
157         public static final int DEFAULT_STATE = Tile.STATE_ACTIVE;
158 
159         public Icon icon;
160         public Supplier<Icon> iconSupplier;
161         public int state = DEFAULT_STATE;
162         public CharSequence label;
163         @Nullable public CharSequence secondaryLabel;
164         public CharSequence contentDescription;
165         @Nullable public CharSequence stateDescription;
166         public CharSequence dualLabelContentDescription;
167         public boolean disabledByPolicy;
168         public boolean dualTarget = false;
169         public boolean isTransient = false;
170         public String expandedAccessibilityClassName;
171         public boolean handlesLongClick = true;
172         @Nullable
173         public Drawable sideViewCustomDrawable;
174         public String spec;
175 
176         /** Get the state text. */
getStateText(int arrayResId, Resources resources)177         public CharSequence getStateText(int arrayResId, Resources resources) {
178             if (state == Tile.STATE_UNAVAILABLE || this instanceof QSTile.BooleanState) {
179                 String[] array = resources.getStringArray(arrayResId);
180                 return array[state];
181             } else {
182                 return "";
183             }
184         }
185 
186         /** Get the text for secondaryLabel. */
getSecondaryLabel(CharSequence stateText)187         public CharSequence getSecondaryLabel(CharSequence stateText) {
188             // Use a local reference as the value might change from other threads
189             CharSequence localSecondaryLabel = secondaryLabel;
190             if (TextUtils.isEmpty(localSecondaryLabel)) {
191                 return stateText;
192             }
193             return localSecondaryLabel;
194         }
195 
copyTo(State other)196         public boolean copyTo(State other) {
197             if (other == null) throw new IllegalArgumentException();
198             if (!other.getClass().equals(getClass())) throw new IllegalArgumentException();
199             final boolean changed = !Objects.equals(other.spec, spec)
200                     || !Objects.equals(other.icon, icon)
201                     || !Objects.equals(other.iconSupplier, iconSupplier)
202                     || !Objects.equals(other.label, label)
203                     || !Objects.equals(other.secondaryLabel, secondaryLabel)
204                     || !Objects.equals(other.contentDescription, contentDescription)
205                     || !Objects.equals(other.stateDescription, stateDescription)
206                     || !Objects.equals(other.dualLabelContentDescription,
207                             dualLabelContentDescription)
208                     || !Objects.equals(other.expandedAccessibilityClassName,
209                             expandedAccessibilityClassName)
210                     || !Objects.equals(other.disabledByPolicy, disabledByPolicy)
211                     || !Objects.equals(other.state, state)
212                     || !Objects.equals(other.isTransient, isTransient)
213                     || !Objects.equals(other.dualTarget, dualTarget)
214                     || !Objects.equals(other.handlesLongClick, handlesLongClick)
215                     || !Objects.equals(other.sideViewCustomDrawable, sideViewCustomDrawable);
216             other.spec = spec;
217             other.icon = icon;
218             other.iconSupplier = iconSupplier;
219             other.label = label;
220             other.secondaryLabel = secondaryLabel;
221             other.contentDescription = contentDescription;
222             other.stateDescription = stateDescription;
223             other.dualLabelContentDescription = dualLabelContentDescription;
224             other.expandedAccessibilityClassName = expandedAccessibilityClassName;
225             other.disabledByPolicy = disabledByPolicy;
226             other.state = state;
227             other.dualTarget = dualTarget;
228             other.isTransient = isTransient;
229             other.handlesLongClick = handlesLongClick;
230             other.sideViewCustomDrawable = sideViewCustomDrawable;
231             return changed;
232         }
233 
234         @Override
toString()235         public String toString() {
236             return toStringBuilder().toString();
237         }
238 
239         // Used in dumps to determine current state of a tile.
240         // This string may be used for CTS testing of tiles, so removing elements is discouraged.
toStringBuilder()241         protected StringBuilder toStringBuilder() {
242             final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
243             sb.append("spec=").append(spec);
244             sb.append(",icon=").append(icon);
245             sb.append(",iconSupplier=").append(iconSupplier);
246             sb.append(",label=").append(label);
247             sb.append(",secondaryLabel=").append(secondaryLabel);
248             sb.append(",contentDescription=").append(contentDescription);
249             sb.append(",stateDescription=").append(stateDescription);
250             sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
251             sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName);
252             sb.append(",disabledByPolicy=").append(disabledByPolicy);
253             sb.append(",dualTarget=").append(dualTarget);
254             sb.append(",isTransient=").append(isTransient);
255             sb.append(",state=").append(state);
256             sb.append(",sideViewCustomDrawable=").append(sideViewCustomDrawable);
257             return sb.append(']');
258         }
259 
copy()260         public State copy() {
261             State state = new State();
262             copyTo(state);
263             return state;
264         }
265     }
266 
267     /**
268      * Distinguished from [BooleanState] for use-case purposes such as allowing null secondary label
269      */
270     @ProvidesInterface(version = AdapterState.VERSION)
271     class AdapterState extends State {
272         public static final int VERSION = 1;
273         public boolean value;
274         public boolean forceExpandIcon;
275 
276         @Override
copyTo(State other)277         public boolean copyTo(State other) {
278             final AdapterState o = (AdapterState) other;
279             final boolean changed = super.copyTo(other)
280                     || o.value != value
281                     || o.forceExpandIcon != forceExpandIcon;
282             o.value = value;
283             o.forceExpandIcon = forceExpandIcon;
284             return changed;
285         }
286 
287         @Override
toStringBuilder()288         protected StringBuilder toStringBuilder() {
289             final StringBuilder rt = super.toStringBuilder();
290             rt.insert(rt.length() - 1, ",value=" + value);
291             rt.insert(rt.length() - 1, ",forceExpandIcon=" + forceExpandIcon);
292             return rt;
293         }
294 
295         @Override
copy()296         public State copy() {
297             AdapterState state = new AdapterState();
298             copyTo(state);
299             return state;
300         }
301     }
302 
303     @ProvidesInterface(version = BooleanState.VERSION)
304     class BooleanState extends AdapterState {
305         public static final int VERSION = 1;
306 
307         @Override
copy()308         public State copy() {
309             BooleanState state = new BooleanState();
310             copyTo(state);
311             return state;
312         }
313     }
314 }
315