blob: f846036248d4293c6ded82bd847aa86c5cf9dc2b [file] [log] [blame]
Jason Monkaa573e92017-01-27 17:00:29 -05001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar.phone;
18
Evan Lairde1d13c92018-03-20 16:58:01 -040019import android.annotation.NonNull;
Jason Monkaa573e92017-01-27 17:00:29 -050020import android.content.Context;
21import android.graphics.drawable.Icon;
22import android.os.Bundle;
23import android.os.UserHandle;
Evan Lairde1d13c92018-03-20 16:58:01 -040024import android.util.ArrayMap;
Jason Monkaa573e92017-01-27 17:00:29 -050025import android.util.ArraySet;
Jason Monkaa573e92017-01-27 17:00:29 -050026import android.view.ViewGroup;
Jason Monkaa573e92017-01-27 17:00:29 -050027
28import com.android.internal.statusbar.StatusBarIcon;
29import com.android.systemui.Dependency;
30import com.android.systemui.Dumpable;
31import com.android.systemui.R;
32import com.android.systemui.SysUiServiceProvider;
33import com.android.systemui.statusbar.CommandQueue;
Evan Lairde1d13c92018-03-20 16:58:01 -040034import com.android.systemui.statusbar.StatusIconDisplayable;
35import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
36import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
Jason Monkaa573e92017-01-27 17:00:29 -050037import com.android.systemui.statusbar.policy.ConfigurationController;
38import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
Jason Monkaa573e92017-01-27 17:00:29 -050039import com.android.systemui.tuner.TunerService;
40import com.android.systemui.tuner.TunerService.Tunable;
41
42import java.io.FileDescriptor;
43import java.io.PrintWriter;
44import java.util.ArrayList;
Evan Lairde1d13c92018-03-20 16:58:01 -040045import java.util.List;
Jason Monkaa573e92017-01-27 17:00:29 -050046
Jason Monk196d6392018-12-20 13:25:34 -050047import javax.inject.Inject;
48import javax.inject.Singleton;
49
Jason Monkaa573e92017-01-27 17:00:29 -050050/**
51 * Receives the callbacks from CommandQueue related to icons and tracks the state of
52 * all the icons. Dispatches this state to any IconManagers that are currently
53 * registered with it.
54 */
Jason Monk196d6392018-12-20 13:25:34 -050055@Singleton
Jason Monkaa573e92017-01-27 17:00:29 -050056public class StatusBarIconControllerImpl extends StatusBarIconList implements Tunable,
57 ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController {
Evan Lairde1d13c92018-03-20 16:58:01 -040058
Evan Laird937d9fa2018-02-08 10:12:16 -080059 private static final String TAG = "StatusBarIconController";
Jason Monkaa573e92017-01-27 17:00:29 -050060
Charles He6a79b0d2017-09-18 09:50:58 +010061 private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
62 private final ArraySet<String> mIconBlacklist = new ArraySet<>();
Jason Monkaa573e92017-01-27 17:00:29 -050063
Evan Lairde1d13c92018-03-20 16:58:01 -040064 // Points to light or dark context depending on the... context?
Jason Monkaa573e92017-01-27 17:00:29 -050065 private Context mContext;
Evan Lairde1d13c92018-03-20 16:58:01 -040066 private Context mLightContext;
67 private Context mDarkContext;
68
69 private boolean mIsDark = false;
Jason Monkaa573e92017-01-27 17:00:29 -050070
Jason Monk196d6392018-12-20 13:25:34 -050071 @Inject
Jason Monkaa573e92017-01-27 17:00:29 -050072 public StatusBarIconControllerImpl(Context context) {
73 super(context.getResources().getStringArray(
74 com.android.internal.R.array.config_statusBarIcons));
75 Dependency.get(ConfigurationController.class).addCallback(this);
Evan Lairde1d13c92018-03-20 16:58:01 -040076
Jason Monkaa573e92017-01-27 17:00:29 -050077 mContext = context;
78
79 loadDimens();
80
81 SysUiServiceProvider.getComponent(context, CommandQueue.class)
Jason Monkd7c98552018-12-04 11:14:50 -050082 .addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -050083 Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
84 }
85
86 @Override
87 public void addIconGroup(IconManager group) {
88 mIconGroups.add(group);
Evan Lairde1d13c92018-03-20 16:58:01 -040089 List<Slot> allSlots = getSlots();
90 for (int i = 0; i < allSlots.size(); i++) {
91 Slot slot = allSlots.get(i);
Evan Lairdeae911d2018-04-26 16:05:46 -040092 List<StatusBarIconHolder> holders = slot.getHolderListInViewOrder();
Evan Lairde1d13c92018-03-20 16:58:01 -040093 boolean blocked = mIconBlacklist.contains(slot.getName());
94
95 for (StatusBarIconHolder holder : holders) {
96 int tag = holder.getTag();
97 int viewIndex = getViewIndex(getSlotIndex(slot.getName()), holder.getTag());
98 group.onIconAdded(viewIndex, slot.getName(), blocked, holder);
Jason Monkaa573e92017-01-27 17:00:29 -050099 }
100 }
101 }
102
103 @Override
104 public void removeIconGroup(IconManager group) {
105 group.destroy();
106 mIconGroups.remove(group);
107 }
108
109 @Override
110 public void onTuningChanged(String key, String newValue) {
111 if (!ICON_BLACKLIST.equals(key)) {
112 return;
113 }
114 mIconBlacklist.clear();
115 mIconBlacklist.addAll(StatusBarIconController.getIconBlacklist(newValue));
Evan Lairde1d13c92018-03-20 16:58:01 -0400116 ArrayList<Slot> currentSlots = getSlots();
117 ArrayMap<Slot, List<StatusBarIconHolder>> slotsToReAdd = new ArrayMap<>();
118
119 // This is a little hacky... Peel off all of the holders on all of the slots
120 // but keep them around so they can be re-added
121
Jason Monkaa573e92017-01-27 17:00:29 -0500122 // Remove all the icons.
Evan Lairde1d13c92018-03-20 16:58:01 -0400123 for (int i = currentSlots.size() - 1; i >= 0; i--) {
124 Slot s = currentSlots.get(i);
Evan Lairdeae911d2018-04-26 16:05:46 -0400125 slotsToReAdd.put(s, s.getHolderListInViewOrder());
Evan Lairde1d13c92018-03-20 16:58:01 -0400126 removeAllIconsForSlot(s.getName());
Jason Monkaa573e92017-01-27 17:00:29 -0500127 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400128
Jason Monkaa573e92017-01-27 17:00:29 -0500129 // Add them all back
Evan Lairde1d13c92018-03-20 16:58:01 -0400130 for (int i = 0; i < currentSlots.size(); i++) {
131 Slot item = currentSlots.get(i);
132 List<StatusBarIconHolder> iconsForSlot = slotsToReAdd.get(item);
133 if (iconsForSlot == null) continue;
134 for (StatusBarIconHolder holder : iconsForSlot) {
135 setIcon(getSlotIndex(item.getName()), holder);
136 }
Jason Monkaa573e92017-01-27 17:00:29 -0500137 }
138 }
139
140 private void loadDimens() {
141 }
142
Evan Lairde1d13c92018-03-20 16:58:01 -0400143 private void addSystemIcon(int index, StatusBarIconHolder holder) {
144 String slot = getSlotName(index);
145 int viewIndex = getViewIndex(index, holder.getTag());
Jason Monkaa573e92017-01-27 17:00:29 -0500146 boolean blocked = mIconBlacklist.contains(slot);
147
Evan Lairde1d13c92018-03-20 16:58:01 -0400148 mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, holder));
Jason Monkaa573e92017-01-27 17:00:29 -0500149 }
150
151 @Override
152 public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
153 int index = getSlotIndex(slot);
Evan Lairde1d13c92018-03-20 16:58:01 -0400154 StatusBarIconHolder holder = getIcon(index, 0);
155 if (holder == null) {
156 StatusBarIcon icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
157 Icon.createWithResource(
158 mContext, resourceId), 0, 0, contentDescription);
159 holder = StatusBarIconHolder.fromIcon(icon);
160 setIcon(index, holder);
Jason Monkaa573e92017-01-27 17:00:29 -0500161 } else {
Evan Lairde1d13c92018-03-20 16:58:01 -0400162 holder.getIcon().icon = Icon.createWithResource(mContext, resourceId);
163 holder.getIcon().contentDescription = contentDescription;
164 handleSet(index, holder);
165 }
166 }
167
168 /**
169 * Signal icons need to be handled differently, because they can be
170 * composite views
171 */
172 @Override
173 public void setSignalIcon(String slot, WifiIconState state) {
174
175 int index = getSlotIndex(slot);
176
177 if (state == null) {
178 removeIcon(index, 0);
179 return;
180 }
181
182 StatusBarIconHolder holder = getIcon(index, 0);
183 if (holder == null) {
184 holder = StatusBarIconHolder.fromWifiIconState(state);
185 setIcon(index, holder);
186 } else {
187 holder.setWifiState(state);
188 handleSet(index, holder);
189 }
190 }
191
192 /**
193 * Accept a list of MobileIconStates, which all live in the same slot(?!), and then are sorted
194 * by subId. Don't worry this definitely makes sense and works.
195 * @param slot da slot
196 * @param iconStates All of the mobile icon states
197 */
198 @Override
199 public void setMobileIcons(String slot, List<MobileIconState> iconStates) {
200 Slot mobileSlot = getSlot(slot);
201 int slotIndex = getSlotIndex(slot);
202
203 for (MobileIconState state : iconStates) {
204 StatusBarIconHolder holder = mobileSlot.getHolderForTag(state.subId);
205 if (holder == null) {
206 holder = StatusBarIconHolder.fromMobileIconState(state);
207 setIcon(slotIndex, holder);
208 } else {
209 holder.setMobileState(state);
210 handleSet(slotIndex, holder);
211 }
Jason Monkaa573e92017-01-27 17:00:29 -0500212 }
213 }
214
215 @Override
216 public void setExternalIcon(String slot) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400217 int viewIndex = getViewIndex(getSlotIndex(slot), 0);
Jason Monkaa573e92017-01-27 17:00:29 -0500218 int height = mContext.getResources().getDimensionPixelSize(
219 R.dimen.status_bar_icon_drawing_size);
220 mIconGroups.forEach(l -> l.onIconExternal(viewIndex, height));
221 }
222
Evan Lairde1d13c92018-03-20 16:58:01 -0400223 //TODO: remove this (used in command queue and for 3rd party tiles?)
Jason Monkaa573e92017-01-27 17:00:29 -0500224 @Override
225 public void setIcon(String slot, StatusBarIcon icon) {
226 setIcon(getSlotIndex(slot), icon);
227 }
228
Evan Lairde1d13c92018-03-20 16:58:01 -0400229 /**
230 * For backwards compatibility, in the event that someone gives us a slot and a status bar icon
231 */
232 private void setIcon(int index, StatusBarIcon icon) {
233 if (icon == null) {
234 removeAllIconsForSlot(getSlotName(index));
235 return;
236 }
237
238 StatusBarIconHolder holder = StatusBarIconHolder.fromIcon(icon);
239 setIcon(index, holder);
240 }
241
Jason Monkaa573e92017-01-27 17:00:29 -0500242 @Override
Evan Lairde1d13c92018-03-20 16:58:01 -0400243 public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
244 boolean isNew = getIcon(index, holder.getTag()) == null;
245 super.setIcon(index, holder);
246
247 if (isNew) {
248 addSystemIcon(index, holder);
249 } else {
250 handleSet(index, holder);
251 }
Jason Monkaa573e92017-01-27 17:00:29 -0500252 }
253
254 public void setIconVisibility(String slot, boolean visibility) {
255 int index = getSlotIndex(slot);
Evan Lairde1d13c92018-03-20 16:58:01 -0400256 StatusBarIconHolder holder = getIcon(index, 0);
257 if (holder == null || holder.isVisible() == visibility) {
Jason Monkaa573e92017-01-27 17:00:29 -0500258 return;
259 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400260
261 holder.setVisible(visibility);
262 handleSet(index, holder);
263 }
264
265 public void removeIcon(String slot) {
266 removeAllIconsForSlot(slot);
Jason Monkaa573e92017-01-27 17:00:29 -0500267 }
268
269 @Override
Evan Lairde1d13c92018-03-20 16:58:01 -0400270 public void removeIcon(String slot, int tag) {
271 removeIcon(getSlotIndex(slot), tag);
272 }
273
274 @Override
275 public void removeAllIconsForSlot(String slotName) {
276 Slot slot = getSlot(slotName);
277 if (!slot.hasIconsInSlot()) {
Jason Monkaa573e92017-01-27 17:00:29 -0500278 return;
279 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400280
Evan Lairde1d13c92018-03-20 16:58:01 -0400281 int slotIndex = getSlotIndex(slotName);
Evan Lairdeae911d2018-04-26 16:05:46 -0400282 List<StatusBarIconHolder> iconsToRemove = slot.getHolderListInViewOrder();
Evan Lairde1d13c92018-03-20 16:58:01 -0400283 for (StatusBarIconHolder holder : iconsToRemove) {
284 int viewIndex = getViewIndex(slotIndex, holder.getTag());
285 slot.removeForTag(holder.getTag());
286 mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
287 }
288 }
289
290 @Override
291 public void removeIcon(int index, int tag) {
292 if (getIcon(index, tag) == null) {
293 return;
294 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400295 super.removeIcon(index, tag);
296 int viewIndex = getViewIndex(index, 0);
Jason Monkaa573e92017-01-27 17:00:29 -0500297 mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
298 }
299
Evan Lairde1d13c92018-03-20 16:58:01 -0400300 private void handleSet(int index, StatusBarIconHolder holder) {
301 int viewIndex = getViewIndex(index, holder.getTag());
Evan Lairde1d13c92018-03-20 16:58:01 -0400302 mIconGroups.forEach(l -> l.onSetIconHolder(viewIndex, holder));
Jason Monkaa573e92017-01-27 17:00:29 -0500303 }
304
Jason Monkaa573e92017-01-27 17:00:29 -0500305 @Override
306 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Evan Laird937d9fa2018-02-08 10:12:16 -0800307 pw.println(TAG + " state:");
308 for (IconManager manager : mIconGroups) {
309 if (manager.shouldLog()) {
310 ViewGroup group = manager.mGroup;
311 int N = group.getChildCount();
312 pw.println(" icon views: " + N);
313 for (int i = 0; i < N; i++) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400314 StatusIconDisplayable ic = (StatusIconDisplayable) group.getChildAt(i);
Evan Laird937d9fa2018-02-08 10:12:16 -0800315 pw.println(" [" + i + "] icon=" + ic);
316 }
317 }
Jason Monkaa573e92017-01-27 17:00:29 -0500318 }
Evan Laird937d9fa2018-02-08 10:12:16 -0800319
Jason Monkaa573e92017-01-27 17:00:29 -0500320 super.dump(pw);
321 }
322
323 public void dispatchDemoCommand(String command, Bundle args) {
Evan Laird937d9fa2018-02-08 10:12:16 -0800324 for (IconManager manager : mIconGroups) {
325 if (manager.isDemoable()) {
326 manager.dispatchDemoCommand(command, args);
327 }
Jason Monkaa573e92017-01-27 17:00:29 -0500328 }
Jason Monkaa573e92017-01-27 17:00:29 -0500329 }
330
331 @Override
332 public void onDensityOrFontScaleChanged() {
333 loadDimens();
334 }
335}