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.content.Context;
18 import android.graphics.drawable.Drawable;
19 import android.metrics.LogMaker;
20 import android.service.quicksettings.Tile;
21 
22 import com.android.systemui.plugins.annotations.DependsOn;
23 import com.android.systemui.plugins.annotations.ProvidesInterface;
24 import com.android.systemui.plugins.qs.QSTile.Callback;
25 import com.android.systemui.plugins.qs.QSTile.Icon;
26 import com.android.systemui.plugins.qs.QSTile.State;
27 
28 import java.util.Objects;
29 import java.util.function.Supplier;
30 
31 @ProvidesInterface(version = QSTile.VERSION)
32 @DependsOn(target = QSIconView.class)
33 @DependsOn(target = DetailAdapter.class)
34 @DependsOn(target = Callback.class)
35 @DependsOn(target = Icon.class)
36 @DependsOn(target = State.class)
37 public interface QSTile {
38     int VERSION = 1;
39 
getDetailAdapter()40     DetailAdapter getDetailAdapter();
getTileSpec()41     String getTileSpec();
42 
isAvailable()43     boolean isAvailable();
setTileSpec(String tileSpec)44     void setTileSpec(String tileSpec);
45 
clearState()46     @Deprecated default void clearState() {}
refreshState()47     void refreshState();
48 
addCallback(Callback callback)49     void addCallback(Callback callback);
removeCallback(Callback callback)50     void removeCallback(Callback callback);
removeCallbacks()51     void removeCallbacks();
52 
createTileView(Context context)53     QSIconView createTileView(Context context);
54 
click()55     void click();
secondaryClick()56     void secondaryClick();
longClick()57     void longClick();
58 
userSwitch(int currentUser)59     void userSwitch(int currentUser);
getMetricsCategory()60     int getMetricsCategory();
61 
setListening(Object client, boolean listening)62     void setListening(Object client, boolean listening);
setDetailListening(boolean show)63     void setDetailListening(boolean show);
64 
destroy()65     void destroy();
66 
getTileLabel()67     CharSequence getTileLabel();
68 
getState()69     State getState();
70 
populate(LogMaker logMaker)71     default LogMaker populate(LogMaker logMaker) {
72         return logMaker;
73     }
74 
75     @ProvidesInterface(version = Callback.VERSION)
76     public interface Callback {
77         public static final int VERSION = 1;
onStateChanged(State state)78         void onStateChanged(State state);
onShowDetail(boolean show)79         void onShowDetail(boolean show);
onToggleStateChanged(boolean state)80         void onToggleStateChanged(boolean state);
onScanStateChanged(boolean state)81         void onScanStateChanged(boolean state);
onAnnouncementRequested(CharSequence announcement)82         void onAnnouncementRequested(CharSequence announcement);
83     }
84 
85     @ProvidesInterface(version = Icon.VERSION)
86     public static abstract class Icon {
87         public static final int VERSION = 1;
getDrawable(Context context)88         abstract public Drawable getDrawable(Context context);
89 
getInvisibleDrawable(Context context)90         public Drawable getInvisibleDrawable(Context context) {
91             return getDrawable(context);
92         }
93 
94         @Override
hashCode()95         public int hashCode() {
96             return Icon.class.hashCode();
97         }
98 
getPadding()99         public int getPadding() {
100             return 0;
101         }
102     }
103 
104     @ProvidesInterface(version = State.VERSION)
105     public static class State {
106         public static final int VERSION = 1;
107         public Icon icon;
108         public Supplier<Icon> iconSupplier;
109         public int state = Tile.STATE_ACTIVE;
110         public CharSequence label;
111         public CharSequence secondaryLabel;
112         public CharSequence contentDescription;
113         public CharSequence dualLabelContentDescription;
114         public boolean disabledByPolicy;
115         public boolean dualTarget = false;
116         public boolean isTransient = false;
117         public String expandedAccessibilityClassName;
118         public SlashState slash;
119         public boolean handlesLongClick = true;
120         public boolean showRippleEffect = true;
121 
copyTo(State other)122         public boolean copyTo(State other) {
123             if (other == null) throw new IllegalArgumentException();
124             if (!other.getClass().equals(getClass())) throw new IllegalArgumentException();
125             final boolean changed = !Objects.equals(other.icon, icon)
126                     || !Objects.equals(other.iconSupplier, iconSupplier)
127                     || !Objects.equals(other.label, label)
128                     || !Objects.equals(other.secondaryLabel, secondaryLabel)
129                     || !Objects.equals(other.contentDescription, contentDescription)
130                     || !Objects.equals(other.dualLabelContentDescription,
131                             dualLabelContentDescription)
132                     || !Objects.equals(other.expandedAccessibilityClassName,
133                             expandedAccessibilityClassName)
134                     || !Objects.equals(other.disabledByPolicy, disabledByPolicy)
135                     || !Objects.equals(other.state, state)
136                     || !Objects.equals(other.isTransient, isTransient)
137                     || !Objects.equals(other.dualTarget, dualTarget)
138                     || !Objects.equals(other.slash, slash)
139                     || !Objects.equals(other.handlesLongClick, handlesLongClick)
140                     || !Objects.equals(other.showRippleEffect, showRippleEffect);
141             other.icon = icon;
142             other.iconSupplier = iconSupplier;
143             other.label = label;
144             other.secondaryLabel = secondaryLabel;
145             other.contentDescription = contentDescription;
146             other.dualLabelContentDescription = dualLabelContentDescription;
147             other.expandedAccessibilityClassName = expandedAccessibilityClassName;
148             other.disabledByPolicy = disabledByPolicy;
149             other.state = state;
150             other.dualTarget = dualTarget;
151             other.isTransient = isTransient;
152             other.slash = slash != null ? slash.copy() : null;
153             other.handlesLongClick = handlesLongClick;
154             other.showRippleEffect = showRippleEffect;
155             return changed;
156         }
157 
158         @Override
toString()159         public String toString() {
160             return toStringBuilder().toString();
161         }
162 
toStringBuilder()163         protected StringBuilder toStringBuilder() {
164             final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
165             sb.append(",icon=").append(icon);
166             sb.append(",iconSupplier=").append(iconSupplier);
167             sb.append(",label=").append(label);
168             sb.append(",secondaryLabel=").append(secondaryLabel);
169             sb.append(",contentDescription=").append(contentDescription);
170             sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
171             sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName);
172             sb.append(",disabledByPolicy=").append(disabledByPolicy);
173             sb.append(",dualTarget=").append(dualTarget);
174             sb.append(",isTransient=").append(isTransient);
175             sb.append(",state=").append(state);
176             sb.append(",slash=\"").append(slash).append("\"");
177             return sb.append(']');
178         }
179 
copy()180         public State copy() {
181             State state = new State();
182             copyTo(state);
183             return state;
184         }
185     }
186 
187     @ProvidesInterface(version = BooleanState.VERSION)
188     public static class BooleanState extends State {
189         public static final int VERSION = 1;
190         public boolean value;
191 
192         @Override
copyTo(State other)193         public boolean copyTo(State other) {
194             final BooleanState o = (BooleanState) other;
195             final boolean changed = super.copyTo(other) || o.value != value;
196             o.value = value;
197             return changed;
198         }
199 
200         @Override
toStringBuilder()201         protected StringBuilder toStringBuilder() {
202             final StringBuilder rt = super.toStringBuilder();
203             rt.insert(rt.length() - 1, ",value=" + value);
204             return rt;
205         }
206 
207         @Override
copy()208         public State copy() {
209             BooleanState state = new BooleanState();
210             copyTo(state);
211             return state;
212         }
213     }
214 
215     @ProvidesInterface(version = SignalState.VERSION)
216     public static final class SignalState extends BooleanState {
217         public static final int VERSION = 1;
218         public boolean activityIn;
219         public boolean activityOut;
220         public boolean isOverlayIconWide;
221         public int overlayIconId;
222 
223         @Override
copyTo(State other)224         public boolean copyTo(State other) {
225             final SignalState o = (SignalState) other;
226             final boolean changed = o.activityIn != activityIn
227                     || o.activityOut != activityOut
228                     || o.isOverlayIconWide != isOverlayIconWide
229                     || o.overlayIconId != overlayIconId;
230             o.activityIn = activityIn;
231             o.activityOut = activityOut;
232             o.isOverlayIconWide = isOverlayIconWide;
233             o.overlayIconId = overlayIconId;
234             return super.copyTo(other) || changed;
235         }
236 
237         @Override
toStringBuilder()238         protected StringBuilder toStringBuilder() {
239             final StringBuilder rt = super.toStringBuilder();
240             rt.insert(rt.length() - 1, ",activityIn=" + activityIn);
241             rt.insert(rt.length() - 1, ",activityOut=" + activityOut);
242             return rt;
243         }
244 
245         @Override
copy()246         public State copy() {
247             SignalState state = new SignalState();
248             copyTo(state);
249             return state;
250         }
251     }
252 
253     @ProvidesInterface(version = SlashState.VERSION)
254     public static class SlashState {
255         public static final int VERSION = 2;
256 
257         public boolean isSlashed;
258         public float rotation;
259 
260         @Override
toString()261         public String toString() {
262             return "isSlashed=" + isSlashed + ",rotation=" + rotation;
263         }
264 
265         @Override
equals(Object o)266         public boolean equals(Object o) {
267             if (o == null) return false;
268             try {
269                 return (((SlashState) o).rotation == rotation)
270                         && (((SlashState) o).isSlashed == isSlashed);
271             } catch (ClassCastException e) {
272                 return false;
273             }
274         }
275 
copy()276         public SlashState copy() {
277             SlashState state = new SlashState();
278             state.rotation = rotation;
279             state.isSlashed = isSlashed;
280             return state;
281         }
282     }
283 }
284