blob: 1ba37a9bf9dd5a3c9a3b6202309db7343a57182d [file] [log] [blame]
Jorim Jaggi66ac1332015-01-21 19:22:26 +01001/*
Jason Monkaa573e92017-01-27 17:00:29 -05002 * Copyright (C) 2017 The Android Open Source Project
Jorim Jaggi66ac1332015-01-21 19:22:26 +01003 *
Jason Monkaa573e92017-01-27 17:00:29 -05004 * 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
Jorim Jaggi66ac1332015-01-21 19:22:26 +01006 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
Jason Monkaa573e92017-01-27 17:00:29 -05009 * 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.
Jorim Jaggi66ac1332015-01-21 19:22:26 +010013 */
14
15package com.android.systemui.statusbar.phone;
16
Charles He6a79b0d2017-09-18 09:50:58 +010017import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
18import static android.app.StatusBarManager.DISABLE_NONE;
Evan Lairde1d13c92018-03-20 16:58:01 -040019import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
20import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE;
21import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI;
Charles He6a79b0d2017-09-18 09:50:58 +010022
Jorim Jaggi66ac1332015-01-21 19:22:26 +010023import android.content.Context;
Evan Laird937d9fa2018-02-08 10:12:16 -080024import android.os.Bundle;
Jason Monk6eb906e2017-03-29 15:04:25 -040025import android.support.annotation.VisibleForTesting;
Jason Monk3b230072015-05-29 11:11:29 -040026import android.text.TextUtils;
27import android.util.ArraySet;
Evan Lairde1d13c92018-03-20 16:58:01 -040028import android.util.Log;
Jason Monk6d6672f2016-02-05 14:18:21 -050029import android.view.Gravity;
Jorim Jaggi66ac1332015-01-21 19:22:26 +010030import android.view.View;
31import android.view.ViewGroup;
Jorim Jaggidd0107a2015-01-21 22:23:48 +010032import android.widget.ImageView;
Jorim Jaggi66ac1332015-01-21 19:22:26 +010033import android.widget.LinearLayout;
Jason Monk6eb906e2017-03-29 15:04:25 -040034import android.widget.LinearLayout.LayoutParams;
Jason Monkaa573e92017-01-27 17:00:29 -050035
Jorim Jaggi66ac1332015-01-21 19:22:26 +010036import com.android.internal.statusbar.StatusBarIcon;
Evan Laird937d9fa2018-02-08 10:12:16 -080037import com.android.systemui.DemoMode;
Jason Monkde850bb2017-02-01 19:26:30 -050038import com.android.systemui.Dependency;
Jorim Jaggi66ac1332015-01-21 19:22:26 +010039import com.android.systemui.R;
Evan Lairde1d13c92018-03-20 16:58:01 -040040import com.android.systemui.statusbar.StatusIconDisplayable;
Jorim Jaggi66ac1332015-01-21 19:22:26 +010041import com.android.systemui.statusbar.StatusBarIconView;
Evan Lairde1d13c92018-03-20 16:58:01 -040042import com.android.systemui.statusbar.StatusBarMobileView;
43import com.android.systemui.statusbar.StatusBarWifiView;
44import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
45import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
Jason Monkaa573e92017-01-27 17:00:29 -050046import com.android.systemui.statusbar.policy.DarkIconDispatcher;
Evan Lairde1d13c92018-03-20 16:58:01 -040047import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
Charles He6a79b0d2017-09-18 09:50:58 +010048import com.android.systemui.util.Utils.DisableStateTracker;
Evan Lairde1d13c92018-03-20 16:58:01 -040049import java.util.List;
Jorim Jaggi66ac1332015-01-21 19:22:26 +010050
Jason Monkaa573e92017-01-27 17:00:29 -050051public interface StatusBarIconController {
Jorim Jaggi66ac1332015-01-21 19:22:26 +010052
Evan Lairde1d13c92018-03-20 16:58:01 -040053 /**
54 * When an icon is added with TAG_PRIMARY, it will be treated as the primary icon
55 * in that slot and not added as a sub slot.
56 */
57 public static final int TAG_PRIMARY = 0;
58
Jason Monkaa573e92017-01-27 17:00:29 -050059 public void addIconGroup(IconManager iconManager);
60 public void removeIconGroup(IconManager iconManager);
61 public void setExternalIcon(String slot);
62 public void setIcon(String slot, int resourceId, CharSequence contentDescription);
63 public void setIcon(String slot, StatusBarIcon icon);
Evan Lairde1d13c92018-03-20 16:58:01 -040064 public void setSignalIcon(String slot, WifiIconState state);
65 public void setMobileIcons(String slot, List<MobileIconState> states);
66 public void setIconVisibility(String slot, boolean b);
67 /**
68 * If you don't know what to pass for `tag`, either remove all icons for slot, or use
69 * TAG_PRIMARY to refer to the first icon at a given slot.
70 */
71 public void removeIcon(String slot, int tag);
72 public void removeAllIconsForSlot(String slot);
Jorim Jaggi66ac1332015-01-21 19:22:26 +010073
Jason Monk3b230072015-05-29 11:11:29 -040074 public static final String ICON_BLACKLIST = "icon_blacklist";
Jorim Jaggidd0107a2015-01-21 22:23:48 +010075
Jason Monk5e745172015-06-02 19:14:44 -040076 public static ArraySet<String> getIconBlacklist(String blackListStr) {
Jason Monkaa573e92017-01-27 17:00:29 -050077 ArraySet<String> ret = new ArraySet<>();
Jason Monk3e189872016-01-12 09:10:34 -050078 if (blackListStr == null) {
79 blackListStr = "rotate,headset";
80 }
81 String[] blacklist = blackListStr.split(",");
82 for (String slot : blacklist) {
83 if (!TextUtils.isEmpty(slot)) {
84 ret.add(slot);
Jason Monk3b230072015-05-29 11:11:29 -040085 }
86 }
87 return ret;
88 }
Selim Cinek3e7592d2016-04-11 09:35:54 +080089
Jason Monkaa573e92017-01-27 17:00:29 -050090 /**
Evan Laird058c8ae2018-01-12 14:26:10 -050091 * Version of ViewGroup that observes state from the DarkIconDispatcher.
Jason Monkaa573e92017-01-27 17:00:29 -050092 */
93 public static class DarkIconManager extends IconManager {
94 private final DarkIconDispatcher mDarkIconDispatcher;
95 private int mIconHPadding;
96
97 public DarkIconManager(LinearLayout linearLayout) {
98 super(linearLayout);
99 mIconHPadding = mContext.getResources().getDimensionPixelSize(
100 R.dimen.status_bar_icon_padding);
101 mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
102 }
103
104 @Override
Jason Monk6eb906e2017-03-29 15:04:25 -0400105 protected void onIconAdded(int index, String slot, boolean blocked,
Evan Lairde1d13c92018-03-20 16:58:01 -0400106 StatusBarIconHolder holder) {
107 StatusIconDisplayable view = addHolder(index, slot, blocked, holder);
108 mDarkIconDispatcher.addDarkReceiver((DarkReceiver) view);
Jason Monk6eb906e2017-03-29 15:04:25 -0400109 }
110
111 @Override
112 protected LayoutParams onCreateLayoutParams() {
Selim Cinek3e7592d2016-04-11 09:35:54 +0800113 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
114 ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
115 lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
Jason Monk6eb906e2017-03-29 15:04:25 -0400116 return lp;
Selim Cinek3e7592d2016-04-11 09:35:54 +0800117 }
Jason Monkaa573e92017-01-27 17:00:29 -0500118
119 @Override
120 protected void destroy() {
121 for (int i = 0; i < mGroup.getChildCount(); i++) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400122 mDarkIconDispatcher.removeDarkReceiver((DarkReceiver) mGroup.getChildAt(i));
Jason Monkaa573e92017-01-27 17:00:29 -0500123 }
124 mGroup.removeAllViews();
Selim Cinek3e7592d2016-04-11 09:35:54 +0800125 }
Jason Monkaa573e92017-01-27 17:00:29 -0500126
127 @Override
128 protected void onRemoveIcon(int viewIndex) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400129 mDarkIconDispatcher.removeDarkReceiver((DarkReceiver) mGroup.getChildAt(viewIndex));
Jason Monkaa573e92017-01-27 17:00:29 -0500130 super.onRemoveIcon(viewIndex);
131 }
132
133 @Override
134 public void onSetIcon(int viewIndex, StatusBarIcon icon) {
135 super.onSetIcon(viewIndex, icon);
Evan Lairde1d13c92018-03-20 16:58:01 -0400136 mDarkIconDispatcher.applyDark((DarkReceiver) mGroup.getChildAt(viewIndex));
Jason Monkaa573e92017-01-27 17:00:29 -0500137 }
Evan Laird937d9fa2018-02-08 10:12:16 -0800138
139 @Override
140 protected DemoStatusIcons createDemoStatusIcons() {
141 DemoStatusIcons icons = super.createDemoStatusIcons();
142 mDarkIconDispatcher.addDarkReceiver(icons);
143
144 return icons;
145 }
146
147 @Override
148 protected void exitDemoMode() {
149 mDarkIconDispatcher.removeDarkReceiver(mDemoStatusIcons);
150 super.exitDemoMode();
151 }
Selim Cinek3e7592d2016-04-11 09:35:54 +0800152 }
153
Jason Monk9cac5ff2017-06-02 11:35:50 -0400154 public static class TintedIconManager extends IconManager {
155 private int mColor;
156
157 public TintedIconManager(ViewGroup group) {
158 super(group);
159 }
160
161 @Override
Evan Lairde1d13c92018-03-20 16:58:01 -0400162 protected void onIconAdded(int index, String slot, boolean blocked,
163 StatusBarIconHolder holder) {
164 StatusIconDisplayable view = addHolder(index, slot, blocked, holder);
165 view.setStaticDrawableColor(mColor);
Evan Laird20b87bf2018-04-12 09:54:11 -0400166 view.setDecorColor(mColor);
Jason Monk9cac5ff2017-06-02 11:35:50 -0400167 }
168
169 public void setTint(int color) {
170 mColor = color;
171 for (int i = 0; i < mGroup.getChildCount(); i++) {
172 View child = mGroup.getChildAt(i);
Evan Lairde1d13c92018-03-20 16:58:01 -0400173 if (child instanceof StatusIconDisplayable) {
174 StatusIconDisplayable icon = (StatusIconDisplayable) child;
Jason Monk9cac5ff2017-06-02 11:35:50 -0400175 icon.setStaticDrawableColor(mColor);
Evan Laird20b87bf2018-04-12 09:54:11 -0400176 icon.setDecorColor(mColor);
Jason Monk9cac5ff2017-06-02 11:35:50 -0400177 }
178 }
179 }
Evan Laird937d9fa2018-02-08 10:12:16 -0800180
181 @Override
182 protected DemoStatusIcons createDemoStatusIcons() {
183 DemoStatusIcons icons = super.createDemoStatusIcons();
184 icons.setColor(mColor);
185 return icons;
186 }
Jason Monk9cac5ff2017-06-02 11:35:50 -0400187 }
188
Jason Monkaa573e92017-01-27 17:00:29 -0500189 /**
190 * Turns info from StatusBarIconController into ImageViews in a ViewGroup.
191 */
Evan Laird937d9fa2018-02-08 10:12:16 -0800192 public static class IconManager implements DemoMode {
Jason Monkaa573e92017-01-27 17:00:29 -0500193 protected final ViewGroup mGroup;
194 protected final Context mContext;
195 protected final int mIconSize;
Evan Laird937d9fa2018-02-08 10:12:16 -0800196 // Whether or not these icons show up in dumpsys
197 protected boolean mShouldLog = false;
198
199 // Enables SystemUI demo mode to take effect in this group
200 protected boolean mDemoable = true;
Evan Lairde1d13c92018-03-20 16:58:01 -0400201 private boolean mIsInDemoMode;
Evan Laird937d9fa2018-02-08 10:12:16 -0800202 protected DemoStatusIcons mDemoStatusIcons;
Jason Monkaa573e92017-01-27 17:00:29 -0500203
204 public IconManager(ViewGroup group) {
205 mGroup = group;
206 mContext = group.getContext();
207 mIconSize = mContext.getResources().getDimensionPixelSize(
208 com.android.internal.R.dimen.status_bar_icon_size);
Charles He6a79b0d2017-09-18 09:50:58 +0100209
210 DisableStateTracker tracker =
211 new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS);
212 mGroup.addOnAttachStateChangeListener(tracker);
213 if (mGroup.isAttachedToWindow()) {
214 // In case we miss the first onAttachedToWindow event
215 tracker.onViewAttachedToWindow(mGroup);
216 }
Jason Monkaa573e92017-01-27 17:00:29 -0500217 }
218
Evan Laird937d9fa2018-02-08 10:12:16 -0800219 public boolean isDemoable() {
220 return mDemoable;
221 }
222
223 public void setIsDemoable(boolean demoable) {
224 mDemoable = demoable;
225 }
226
227 public void setShouldLog(boolean should) {
228 mShouldLog = should;
229 }
230
231 public boolean shouldLog() {
232 return mShouldLog;
233 }
234
Jason Monk6eb906e2017-03-29 15:04:25 -0400235 protected void onIconAdded(int index, String slot, boolean blocked,
Evan Lairde1d13c92018-03-20 16:58:01 -0400236 StatusBarIconHolder holder) {
237 addHolder(index, slot, blocked, holder);
Jason Monk6eb906e2017-03-29 15:04:25 -0400238 }
239
Evan Lairde1d13c92018-03-20 16:58:01 -0400240 protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked,
241 StatusBarIconHolder holder) {
242 switch (holder.getType()) {
243 case TYPE_ICON:
244 return addIcon(index, slot, blocked, holder.getIcon());
245
246 case TYPE_WIFI:
247 return addSignalIcon(index, slot, holder.getWifiState());
248
249 case TYPE_MOBILE:
250 return addMobileIcon(index, slot, holder.getMobileState());
251 }
252
253 return null;
254 }
255
256 @VisibleForTesting
Jason Monk6eb906e2017-03-29 15:04:25 -0400257 protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
258 StatusBarIcon icon) {
259 StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
Jason Monkaa573e92017-01-27 17:00:29 -0500260 view.set(icon);
Jason Monk6eb906e2017-03-29 15:04:25 -0400261 mGroup.addView(view, index, onCreateLayoutParams());
262 return view;
263 }
264
265 @VisibleForTesting
Evan Lairde1d13c92018-03-20 16:58:01 -0400266 protected StatusBarWifiView addSignalIcon(int index, String slot, WifiIconState state) {
267 StatusBarWifiView view = onCreateStatusBarWifiView(slot);
268 view.applyWifiState(state);
269 mGroup.addView(view, index, onCreateLayoutParams());
270
271 if (mIsInDemoMode) {
272 mDemoStatusIcons.addDemoWifiView(state);
273 }
274 return view;
275 }
276
277 @VisibleForTesting
278 protected StatusBarMobileView addMobileIcon(int index, String slot, MobileIconState state) {
279 StatusBarMobileView view = onCreateStatusBarMobileView(slot);
280 view.applyMobileState(state);
281 mGroup.addView(view, index, onCreateLayoutParams());
282
283 if (mIsInDemoMode) {
284 mDemoStatusIcons.addMobileView(state);
285 }
286 return view;
287 }
288
289 private StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) {
Jason Monk6eb906e2017-03-29 15:04:25 -0400290 return new StatusBarIconView(mContext, slot, null, blocked);
291 }
292
Evan Lairde1d13c92018-03-20 16:58:01 -0400293 private StatusBarWifiView onCreateStatusBarWifiView(String slot) {
Evan Laird20b87bf2018-04-12 09:54:11 -0400294 StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, slot);
Evan Lairde1d13c92018-03-20 16:58:01 -0400295 return view;
296 }
297
298 private StatusBarMobileView onCreateStatusBarMobileView(String slot) {
299 StatusBarMobileView view = StatusBarMobileView.fromContext(mContext);
300 view.setSlot(slot);
301 return view;
302 }
303
Jason Monk6eb906e2017-03-29 15:04:25 -0400304 protected LinearLayout.LayoutParams onCreateLayoutParams() {
305 return new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
Jason Monkaa573e92017-01-27 17:00:29 -0500306 }
307
308 protected void destroy() {
309 mGroup.removeAllViews();
310 }
311
312 protected void onIconExternal(int viewIndex, int height) {
313 ImageView imageView = (ImageView) mGroup.getChildAt(viewIndex);
314 imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
315 imageView.setAdjustViewBounds(true);
316 setHeightAndCenter(imageView, height);
317 }
318
319 protected void onDensityOrFontScaleChanged() {
320 for (int i = 0; i < mGroup.getChildCount(); i++) {
321 View child = mGroup.getChildAt(i);
322 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
323 ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
324 child.setLayoutParams(lp);
325 }
326 }
327
328 private void setHeightAndCenter(ImageView imageView, int height) {
329 ViewGroup.LayoutParams params = imageView.getLayoutParams();
330 params.height = height;
331 if (params instanceof LinearLayout.LayoutParams) {
332 ((LinearLayout.LayoutParams) params).gravity = Gravity.CENTER_VERTICAL;
333 }
334 imageView.setLayoutParams(params);
335 }
336
337 protected void onRemoveIcon(int viewIndex) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400338 if (mIsInDemoMode) {
339 mDemoStatusIcons.onRemoveIcon((StatusIconDisplayable) mGroup.getChildAt(viewIndex));
340 }
Jason Monkaa573e92017-01-27 17:00:29 -0500341 mGroup.removeViewAt(viewIndex);
342 }
343
344 public void onSetIcon(int viewIndex, StatusBarIcon icon) {
345 StatusBarIconView view = (StatusBarIconView) mGroup.getChildAt(viewIndex);
346 view.set(icon);
347 }
Evan Laird937d9fa2018-02-08 10:12:16 -0800348
Evan Lairde1d13c92018-03-20 16:58:01 -0400349 public void onSetIconHolder(int viewIndex, StatusBarIconHolder holder) {
350 switch (holder.getType()) {
351 case TYPE_ICON:
352 onSetIcon(viewIndex, holder.getIcon());
353 return;
354 case TYPE_WIFI:
355 onSetSignalIcon(viewIndex, holder.getWifiState());
356 return;
357
358 case TYPE_MOBILE:
359 onSetMobileIcon(viewIndex, holder.getMobileState());
360 default:
361 break;
362 }
363 }
364
365 public void onSetSignalIcon(int viewIndex, WifiIconState state) {
366 StatusBarWifiView wifiView = (StatusBarWifiView) mGroup.getChildAt(viewIndex);
367 if (wifiView != null) {
368 wifiView.applyWifiState(state);
369 }
370
371 if (mIsInDemoMode) {
372 mDemoStatusIcons.updateWifiState(state);
373 }
374 }
375
376 public void onSetMobileIcon(int viewIndex, MobileIconState state) {
377 StatusBarMobileView view = (StatusBarMobileView) mGroup.getChildAt(viewIndex);
378 if (view != null) {
379 view.applyMobileState(state);
380 }
381
382 if (mIsInDemoMode) {
383 mDemoStatusIcons.updateMobileState(state);
384 }
385 }
386
Evan Laird937d9fa2018-02-08 10:12:16 -0800387 @Override
388 public void dispatchDemoCommand(String command, Bundle args) {
389 if (!mDemoable) {
390 return;
391 }
392
Evan Lairde1d13c92018-03-20 16:58:01 -0400393 if (command.equals(COMMAND_EXIT)) {
394 if (mDemoStatusIcons != null) {
395 mDemoStatusIcons.dispatchDemoCommand(command, args);
396 exitDemoMode();
397 }
398 mIsInDemoMode = false;
Evan Laird937d9fa2018-02-08 10:12:16 -0800399 } else {
400 if (mDemoStatusIcons == null) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400401 mIsInDemoMode = true;
Evan Laird937d9fa2018-02-08 10:12:16 -0800402 mDemoStatusIcons = createDemoStatusIcons();
403 }
404 mDemoStatusIcons.dispatchDemoCommand(command, args);
405 }
406 }
407
408 protected void exitDemoMode() {
409 mDemoStatusIcons.remove();
410 mDemoStatusIcons = null;
411 }
412
413 protected DemoStatusIcons createDemoStatusIcons() {
414 return new DemoStatusIcons((LinearLayout) mGroup, mIconSize);
415 }
Selim Cinek3e7592d2016-04-11 09:35:54 +0800416 }
Jorim Jaggi66ac1332015-01-21 19:22:26 +0100417}