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     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 
copyTo(State other)120         public boolean copyTo(State other) {
121             if (other == null) throw new IllegalArgumentException();
122             if (!other.getClass().equals(getClass())) throw new IllegalArgumentException();
123             final boolean changed = !Objects.equals(other.icon, icon)
124                     || !Objects.equals(other.iconSupplier, iconSupplier)
125                     || !Objects.equals(other.label, label)
126                     || !Objects.equals(other.secondaryLabel, secondaryLabel)
127                     || !Objects.equals(other.contentDescription, contentDescription)
128                     || !Objects.equals(other.dualLabelContentDescription,
129                             dualLabelContentDescription)
130                     || !Objects.equals(other.expandedAccessibilityClassName,
131                             expandedAccessibilityClassName)
132                     || !Objects.equals(other.disabledByPolicy, disabledByPolicy)
133                     || !Objects.equals(other.state, state)
134                     || !Objects.equals(other.isTransient, isTransient)
135                     || !Objects.equals(other.dualTarget, dualTarget)
136                     || !Objects.equals(other.slash, slash);
137             other.icon = icon;
138             other.iconSupplier = iconSupplier;
139             other.label = label;
140             other.secondaryLabel = secondaryLabel;
141             other.contentDescription = contentDescription;
142             other.dualLabelContentDescription = dualLabelContentDescription;
143             other.expandedAccessibilityClassName = expandedAccessibilityClassName;
144             other.disabledByPolicy = disabledByPolicy;
145             other.state = state;
146             other.dualTarget = dualTarget;
147             other.isTransient = isTransient;
148             other.slash = slash != null ? slash.copy() : null;
149             return changed;
150         }
151 
152         @Override
toString()153         public String toString() {
154             return toStringBuilder().toString();
155         }
156 
toStringBuilder()157         protected StringBuilder toStringBuilder() {
158             final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
159             sb.append(",icon=").append(icon);
160             sb.append(",iconSupplier=").append(iconSupplier);
161             sb.append(",label=").append(label);
162             sb.append(",secondaryLabel=").append(secondaryLabel);
163             sb.append(",contentDescription=").append(contentDescription);
164             sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
165             sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName);
166             sb.append(",disabledByPolicy=").append(disabledByPolicy);
167             sb.append(",dualTarget=").append(dualTarget);
168             sb.append(",isTransient=").append(isTransient);
169             sb.append(",state=").append(state);
170             sb.append(",slash=\"").append(slash).append("\"");
171             return sb.append(']');
172         }
173 
copy()174         public State copy() {
175             State state = new State();
176             copyTo(state);
177             return state;
178         }
179     }
180 
181     @ProvidesInterface(version = BooleanState.VERSION)
182     public static class BooleanState extends State {
183         public static final int VERSION = 1;
184         public boolean value;
185 
186         @Override
copyTo(State other)187         public boolean copyTo(State other) {
188             final BooleanState o = (BooleanState) other;
189             final boolean changed = super.copyTo(other) || o.value != value;
190             o.value = value;
191             return changed;
192         }
193 
194         @Override
toStringBuilder()195         protected StringBuilder toStringBuilder() {
196             final StringBuilder rt = super.toStringBuilder();
197             rt.insert(rt.length() - 1, ",value=" + value);
198             return rt;
199         }
200 
201         @Override
copy()202         public State copy() {
203             BooleanState state = new BooleanState();
204             copyTo(state);
205             return state;
206         }
207     }
208 
209     @ProvidesInterface(version = SignalState.VERSION)
210     public static final class SignalState extends BooleanState {
211         public static final int VERSION = 1;
212         public boolean activityIn;
213         public boolean activityOut;
214         public boolean isOverlayIconWide;
215         public int overlayIconId;
216 
217         @Override
copyTo(State other)218         public boolean copyTo(State other) {
219             final SignalState o = (SignalState) other;
220             final boolean changed = o.activityIn != activityIn
221                     || o.activityOut != activityOut
222                     || o.isOverlayIconWide != isOverlayIconWide
223                     || o.overlayIconId != overlayIconId;
224             o.activityIn = activityIn;
225             o.activityOut = activityOut;
226             o.isOverlayIconWide = isOverlayIconWide;
227             o.overlayIconId = overlayIconId;
228             return super.copyTo(other) || changed;
229         }
230 
231         @Override
toStringBuilder()232         protected StringBuilder toStringBuilder() {
233             final StringBuilder rt = super.toStringBuilder();
234             rt.insert(rt.length() - 1, ",activityIn=" + activityIn);
235             rt.insert(rt.length() - 1, ",activityOut=" + activityOut);
236             return rt;
237         }
238 
239         @Override
copy()240         public State copy() {
241             SignalState state = new SignalState();
242             copyTo(state);
243             return state;
244         }
245     }
246 
247 
248     @ProvidesInterface(version = AirplaneBooleanState.VERSION)
249     public static class AirplaneBooleanState extends BooleanState {
250         public static final int VERSION = 1;
251         public boolean isAirplaneMode;
252 
253         @Override
copyTo(State other)254         public boolean copyTo(State other) {
255             final AirplaneBooleanState o = (AirplaneBooleanState) other;
256             final boolean changed = super.copyTo(other) || o.isAirplaneMode != isAirplaneMode;
257             o.isAirplaneMode = isAirplaneMode;
258             return changed;
259         }
260 
copy()261         public State copy() {
262             AirplaneBooleanState state = new AirplaneBooleanState();
263             copyTo(state);
264             return state;
265         }
266     }
267 
268     @ProvidesInterface(version = SlashState.VERSION)
269     public static class SlashState {
270         public static final int VERSION = 2;
271 
272         public boolean isSlashed;
273         public float rotation;
274 
275         @Override
toString()276         public String toString() {
277             return "isSlashed=" + isSlashed + ",rotation=" + rotation;
278         }
279 
280         @Override
equals(Object o)281         public boolean equals(Object o) {
282             if (o == null) return false;
283             try {
284                 return (((SlashState) o).rotation == rotation)
285                         && (((SlashState) o).isSlashed == isSlashed);
286             } catch (ClassCastException e) {
287                 return false;
288             }
289         }
290 
copy()291         public SlashState copy() {
292             SlashState state = new SlashState();
293             state.rotation = rotation;
294             state.isSlashed = isSlashed;
295             return state;
296         }
297     }
298 }
299