blob: e0b1846fa7d07bc9e60a1c1e382cd4d02f916ed4 [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;
Yong Shi4a50a8e2018-05-21 15:53:02 +080045import java.util.Collections;
Evan Lairde1d13c92018-03-20 16:58:01 -040046import java.util.List;
Jason Monkaa573e92017-01-27 17:00:29 -050047
Jason Monk196d6392018-12-20 13:25:34 -050048import javax.inject.Inject;
49import javax.inject.Singleton;
50
Jason Monkaa573e92017-01-27 17:00:29 -050051/**
52 * Receives the callbacks from CommandQueue related to icons and tracks the state of
53 * all the icons. Dispatches this state to any IconManagers that are currently
54 * registered with it.
55 */
Jason Monk196d6392018-12-20 13:25:34 -050056@Singleton
Jason Monkaa573e92017-01-27 17:00:29 -050057public class StatusBarIconControllerImpl extends StatusBarIconList implements Tunable,
58 ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController {
Evan Lairde1d13c92018-03-20 16:58:01 -040059
Evan Laird937d9fa2018-02-08 10:12:16 -080060 private static final String TAG = "StatusBarIconController";
Jason Monkaa573e92017-01-27 17:00:29 -050061
Charles He6a79b0d2017-09-18 09:50:58 +010062 private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
63 private final ArraySet<String> mIconBlacklist = new ArraySet<>();
Jason Monkaa573e92017-01-27 17:00:29 -050064
Evan Lairde1d13c92018-03-20 16:58:01 -040065 // Points to light or dark context depending on the... context?
Jason Monkaa573e92017-01-27 17:00:29 -050066 private Context mContext;
Evan Lairde1d13c92018-03-20 16:58:01 -040067 private Context mLightContext;
68 private Context mDarkContext;
69
70 private boolean mIsDark = false;
Jason Monkaa573e92017-01-27 17:00:29 -050071
Jason Monk196d6392018-12-20 13:25:34 -050072 @Inject
Jason Monkaa573e92017-01-27 17:00:29 -050073 public StatusBarIconControllerImpl(Context context) {
74 super(context.getResources().getStringArray(
75 com.android.internal.R.array.config_statusBarIcons));
76 Dependency.get(ConfigurationController.class).addCallback(this);
Evan Lairde1d13c92018-03-20 16:58:01 -040077
Jason Monkaa573e92017-01-27 17:00:29 -050078 mContext = context;
79
80 loadDimens();
81
82 SysUiServiceProvider.getComponent(context, CommandQueue.class)
Jason Monkd7c98552018-12-04 11:14:50 -050083 .addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -050084 Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
85 }
86
87 @Override
88 public void addIconGroup(IconManager group) {
89 mIconGroups.add(group);
Evan Lairde1d13c92018-03-20 16:58:01 -040090 List<Slot> allSlots = getSlots();
91 for (int i = 0; i < allSlots.size(); i++) {
92 Slot slot = allSlots.get(i);
Evan Lairdeae911d2018-04-26 16:05:46 -040093 List<StatusBarIconHolder> holders = slot.getHolderListInViewOrder();
Evan Lairde1d13c92018-03-20 16:58:01 -040094 boolean blocked = mIconBlacklist.contains(slot.getName());
95
96 for (StatusBarIconHolder holder : holders) {
97 int tag = holder.getTag();
98 int viewIndex = getViewIndex(getSlotIndex(slot.getName()), holder.getTag());
99 group.onIconAdded(viewIndex, slot.getName(), blocked, holder);
Jason Monkaa573e92017-01-27 17:00:29 -0500100 }
101 }
102 }
103
104 @Override
105 public void removeIconGroup(IconManager group) {
106 group.destroy();
107 mIconGroups.remove(group);
108 }
109
110 @Override
111 public void onTuningChanged(String key, String newValue) {
112 if (!ICON_BLACKLIST.equals(key)) {
113 return;
114 }
115 mIconBlacklist.clear();
116 mIconBlacklist.addAll(StatusBarIconController.getIconBlacklist(newValue));
Evan Lairde1d13c92018-03-20 16:58:01 -0400117 ArrayList<Slot> currentSlots = getSlots();
118 ArrayMap<Slot, List<StatusBarIconHolder>> slotsToReAdd = new ArrayMap<>();
119
120 // This is a little hacky... Peel off all of the holders on all of the slots
121 // but keep them around so they can be re-added
122
Jason Monkaa573e92017-01-27 17:00:29 -0500123 // Remove all the icons.
Evan Lairde1d13c92018-03-20 16:58:01 -0400124 for (int i = currentSlots.size() - 1; i >= 0; i--) {
125 Slot s = currentSlots.get(i);
Yong Shi4a50a8e2018-05-21 15:53:02 +0800126 slotsToReAdd.put(s, s.getHolderList());
Evan Lairde1d13c92018-03-20 16:58:01 -0400127 removeAllIconsForSlot(s.getName());
Jason Monkaa573e92017-01-27 17:00:29 -0500128 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400129
Jason Monkaa573e92017-01-27 17:00:29 -0500130 // Add them all back
Evan Lairde1d13c92018-03-20 16:58:01 -0400131 for (int i = 0; i < currentSlots.size(); i++) {
132 Slot item = currentSlots.get(i);
133 List<StatusBarIconHolder> iconsForSlot = slotsToReAdd.get(item);
134 if (iconsForSlot == null) continue;
135 for (StatusBarIconHolder holder : iconsForSlot) {
136 setIcon(getSlotIndex(item.getName()), holder);
137 }
Jason Monkaa573e92017-01-27 17:00:29 -0500138 }
139 }
140
141 private void loadDimens() {
142 }
143
Evan Lairde1d13c92018-03-20 16:58:01 -0400144 private void addSystemIcon(int index, StatusBarIconHolder holder) {
145 String slot = getSlotName(index);
146 int viewIndex = getViewIndex(index, holder.getTag());
Jason Monkaa573e92017-01-27 17:00:29 -0500147 boolean blocked = mIconBlacklist.contains(slot);
148
Evan Lairde1d13c92018-03-20 16:58:01 -0400149 mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, holder));
Jason Monkaa573e92017-01-27 17:00:29 -0500150 }
151
152 @Override
153 public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
154 int index = getSlotIndex(slot);
Evan Lairde1d13c92018-03-20 16:58:01 -0400155 StatusBarIconHolder holder = getIcon(index, 0);
156 if (holder == null) {
157 StatusBarIcon icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
158 Icon.createWithResource(
159 mContext, resourceId), 0, 0, contentDescription);
160 holder = StatusBarIconHolder.fromIcon(icon);
161 setIcon(index, holder);
Jason Monkaa573e92017-01-27 17:00:29 -0500162 } else {
Evan Lairde1d13c92018-03-20 16:58:01 -0400163 holder.getIcon().icon = Icon.createWithResource(mContext, resourceId);
164 holder.getIcon().contentDescription = contentDescription;
165 handleSet(index, holder);
166 }
167 }
168
169 /**
170 * Signal icons need to be handled differently, because they can be
171 * composite views
172 */
173 @Override
174 public void setSignalIcon(String slot, WifiIconState state) {
175
176 int index = getSlotIndex(slot);
177
178 if (state == null) {
179 removeIcon(index, 0);
180 return;
181 }
182
183 StatusBarIconHolder holder = getIcon(index, 0);
184 if (holder == null) {
185 holder = StatusBarIconHolder.fromWifiIconState(state);
186 setIcon(index, holder);
187 } else {
188 holder.setWifiState(state);
189 handleSet(index, holder);
190 }
191 }
192
193 /**
194 * Accept a list of MobileIconStates, which all live in the same slot(?!), and then are sorted
195 * by subId. Don't worry this definitely makes sense and works.
196 * @param slot da slot
197 * @param iconStates All of the mobile icon states
198 */
199 @Override
200 public void setMobileIcons(String slot, List<MobileIconState> iconStates) {
201 Slot mobileSlot = getSlot(slot);
202 int slotIndex = getSlotIndex(slot);
203
Yong Shi4a50a8e2018-05-21 15:53:02 +0800204 // Reverse the sort order to show icons with left to right([Slot1][Slot2]..).
205 // StatusBarIconList has UI design that first items go to the right of second items.
206 Collections.reverse(iconStates);
207
Evan Lairde1d13c92018-03-20 16:58:01 -0400208 for (MobileIconState state : iconStates) {
209 StatusBarIconHolder holder = mobileSlot.getHolderForTag(state.subId);
210 if (holder == null) {
211 holder = StatusBarIconHolder.fromMobileIconState(state);
212 setIcon(slotIndex, holder);
213 } else {
214 holder.setMobileState(state);
215 handleSet(slotIndex, holder);
216 }
Jason Monkaa573e92017-01-27 17:00:29 -0500217 }
218 }
219
220 @Override
221 public void setExternalIcon(String slot) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400222 int viewIndex = getViewIndex(getSlotIndex(slot), 0);
Jason Monkaa573e92017-01-27 17:00:29 -0500223 int height = mContext.getResources().getDimensionPixelSize(
224 R.dimen.status_bar_icon_drawing_size);
225 mIconGroups.forEach(l -> l.onIconExternal(viewIndex, height));
226 }
227
Evan Lairde1d13c92018-03-20 16:58:01 -0400228 //TODO: remove this (used in command queue and for 3rd party tiles?)
Jason Monkaa573e92017-01-27 17:00:29 -0500229 @Override
230 public void setIcon(String slot, StatusBarIcon icon) {
231 setIcon(getSlotIndex(slot), icon);
232 }
233
Evan Lairde1d13c92018-03-20 16:58:01 -0400234 /**
235 * For backwards compatibility, in the event that someone gives us a slot and a status bar icon
236 */
237 private void setIcon(int index, StatusBarIcon icon) {
238 if (icon == null) {
239 removeAllIconsForSlot(getSlotName(index));
240 return;
241 }
242
243 StatusBarIconHolder holder = StatusBarIconHolder.fromIcon(icon);
244 setIcon(index, holder);
245 }
246
Jason Monkaa573e92017-01-27 17:00:29 -0500247 @Override
Evan Lairde1d13c92018-03-20 16:58:01 -0400248 public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
249 boolean isNew = getIcon(index, holder.getTag()) == null;
250 super.setIcon(index, holder);
251
252 if (isNew) {
253 addSystemIcon(index, holder);
254 } else {
255 handleSet(index, holder);
256 }
Jason Monkaa573e92017-01-27 17:00:29 -0500257 }
258
259 public void setIconVisibility(String slot, boolean visibility) {
260 int index = getSlotIndex(slot);
Evan Lairde1d13c92018-03-20 16:58:01 -0400261 StatusBarIconHolder holder = getIcon(index, 0);
262 if (holder == null || holder.isVisible() == visibility) {
Jason Monkaa573e92017-01-27 17:00:29 -0500263 return;
264 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400265
266 holder.setVisible(visibility);
267 handleSet(index, holder);
268 }
269
270 public void removeIcon(String slot) {
271 removeAllIconsForSlot(slot);
Jason Monkaa573e92017-01-27 17:00:29 -0500272 }
273
274 @Override
Evan Lairde1d13c92018-03-20 16:58:01 -0400275 public void removeIcon(String slot, int tag) {
276 removeIcon(getSlotIndex(slot), tag);
277 }
278
279 @Override
280 public void removeAllIconsForSlot(String slotName) {
281 Slot slot = getSlot(slotName);
282 if (!slot.hasIconsInSlot()) {
Jason Monkaa573e92017-01-27 17:00:29 -0500283 return;
284 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400285
Evan Lairde1d13c92018-03-20 16:58:01 -0400286 int slotIndex = getSlotIndex(slotName);
Evan Lairdeae911d2018-04-26 16:05:46 -0400287 List<StatusBarIconHolder> iconsToRemove = slot.getHolderListInViewOrder();
Evan Lairde1d13c92018-03-20 16:58:01 -0400288 for (StatusBarIconHolder holder : iconsToRemove) {
289 int viewIndex = getViewIndex(slotIndex, holder.getTag());
290 slot.removeForTag(holder.getTag());
291 mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
292 }
293 }
294
295 @Override
296 public void removeIcon(int index, int tag) {
297 if (getIcon(index, tag) == null) {
298 return;
299 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400300 super.removeIcon(index, tag);
301 int viewIndex = getViewIndex(index, 0);
Jason Monkaa573e92017-01-27 17:00:29 -0500302 mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
303 }
304
Evan Lairde1d13c92018-03-20 16:58:01 -0400305 private void handleSet(int index, StatusBarIconHolder holder) {
306 int viewIndex = getViewIndex(index, holder.getTag());
Evan Lairde1d13c92018-03-20 16:58:01 -0400307 mIconGroups.forEach(l -> l.onSetIconHolder(viewIndex, holder));
Jason Monkaa573e92017-01-27 17:00:29 -0500308 }
309
Jason Monkaa573e92017-01-27 17:00:29 -0500310 @Override
311 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Evan Laird937d9fa2018-02-08 10:12:16 -0800312 pw.println(TAG + " state:");
313 for (IconManager manager : mIconGroups) {
314 if (manager.shouldLog()) {
315 ViewGroup group = manager.mGroup;
316 int N = group.getChildCount();
317 pw.println(" icon views: " + N);
318 for (int i = 0; i < N; i++) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400319 StatusIconDisplayable ic = (StatusIconDisplayable) group.getChildAt(i);
Evan Laird937d9fa2018-02-08 10:12:16 -0800320 pw.println(" [" + i + "] icon=" + ic);
321 }
322 }
Jason Monkaa573e92017-01-27 17:00:29 -0500323 }
Evan Laird937d9fa2018-02-08 10:12:16 -0800324
Jason Monkaa573e92017-01-27 17:00:29 -0500325 super.dump(pw);
326 }
327
328 public void dispatchDemoCommand(String command, Bundle args) {
Evan Laird937d9fa2018-02-08 10:12:16 -0800329 for (IconManager manager : mIconGroups) {
330 if (manager.isDemoable()) {
331 manager.dispatchDemoCommand(command, args);
332 }
Jason Monkaa573e92017-01-27 17:00:29 -0500333 }
Jason Monkaa573e92017-01-27 17:00:29 -0500334 }
335
336 @Override
337 public void onDensityOrFontScaleChanged() {
338 loadDimens();
339 }
340}