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