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