blob: aa062eb2e051ca990ad4a2f31d62c25d7730a732 [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;
Jason Monkaa573e92017-01-27 17:00:29 -050032import com.android.systemui.statusbar.CommandQueue;
Evan Lairde1d13c92018-03-20 16:58:01 -040033import com.android.systemui.statusbar.StatusIconDisplayable;
34import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
35import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
Jason Monkaa573e92017-01-27 17:00:29 -050036import com.android.systemui.statusbar.policy.ConfigurationController;
37import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
Jason Monkaa573e92017-01-27 17:00:29 -050038import com.android.systemui.tuner.TunerService;
39import com.android.systemui.tuner.TunerService.Tunable;
40
41import java.io.FileDescriptor;
42import java.io.PrintWriter;
43import java.util.ArrayList;
Yong Shi4a50a8e2018-05-21 15:53:02 +080044import java.util.Collections;
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
Dave Mankoffbcaca8a2019-10-31 18:04:08 -040072 public StatusBarIconControllerImpl(Context context, CommandQueue commandQueue) {
Jason Monkaa573e92017-01-27 17:00:29 -050073 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
Dave Mankoffbcaca8a2019-10-31 18:04:08 -040081 commandQueue.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -050082 Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
83 }
84
85 @Override
86 public void addIconGroup(IconManager group) {
87 mIconGroups.add(group);
Evan Lairde1d13c92018-03-20 16:58:01 -040088 List<Slot> allSlots = getSlots();
89 for (int i = 0; i < allSlots.size(); i++) {
90 Slot slot = allSlots.get(i);
Evan Lairdeae911d2018-04-26 16:05:46 -040091 List<StatusBarIconHolder> holders = slot.getHolderListInViewOrder();
Evan Lairde1d13c92018-03-20 16:58:01 -040092 boolean blocked = mIconBlacklist.contains(slot.getName());
93
94 for (StatusBarIconHolder holder : holders) {
95 int tag = holder.getTag();
96 int viewIndex = getViewIndex(getSlotIndex(slot.getName()), holder.getTag());
97 group.onIconAdded(viewIndex, slot.getName(), blocked, holder);
Jason Monkaa573e92017-01-27 17:00:29 -050098 }
99 }
100 }
101
102 @Override
103 public void removeIconGroup(IconManager group) {
104 group.destroy();
105 mIconGroups.remove(group);
106 }
107
108 @Override
109 public void onTuningChanged(String key, String newValue) {
110 if (!ICON_BLACKLIST.equals(key)) {
111 return;
112 }
113 mIconBlacklist.clear();
114 mIconBlacklist.addAll(StatusBarIconController.getIconBlacklist(newValue));
Evan Lairde1d13c92018-03-20 16:58:01 -0400115 ArrayList<Slot> currentSlots = getSlots();
116 ArrayMap<Slot, List<StatusBarIconHolder>> slotsToReAdd = new ArrayMap<>();
117
118 // This is a little hacky... Peel off all of the holders on all of the slots
119 // but keep them around so they can be re-added
120
Jason Monkaa573e92017-01-27 17:00:29 -0500121 // Remove all the icons.
Evan Lairde1d13c92018-03-20 16:58:01 -0400122 for (int i = currentSlots.size() - 1; i >= 0; i--) {
123 Slot s = currentSlots.get(i);
Yong Shi4a50a8e2018-05-21 15:53:02 +0800124 slotsToReAdd.put(s, s.getHolderList());
Evan Lairde1d13c92018-03-20 16:58:01 -0400125 removeAllIconsForSlot(s.getName());
Jason Monkaa573e92017-01-27 17:00:29 -0500126 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400127
Jason Monkaa573e92017-01-27 17:00:29 -0500128 // Add them all back
Evan Lairde1d13c92018-03-20 16:58:01 -0400129 for (int i = 0; i < currentSlots.size(); i++) {
130 Slot item = currentSlots.get(i);
131 List<StatusBarIconHolder> iconsForSlot = slotsToReAdd.get(item);
132 if (iconsForSlot == null) continue;
133 for (StatusBarIconHolder holder : iconsForSlot) {
134 setIcon(getSlotIndex(item.getName()), holder);
135 }
Jason Monkaa573e92017-01-27 17:00:29 -0500136 }
137 }
138
139 private void loadDimens() {
140 }
141
Evan Lairde1d13c92018-03-20 16:58:01 -0400142 private void addSystemIcon(int index, StatusBarIconHolder holder) {
143 String slot = getSlotName(index);
144 int viewIndex = getViewIndex(index, holder.getTag());
Jason Monkaa573e92017-01-27 17:00:29 -0500145 boolean blocked = mIconBlacklist.contains(slot);
146
Evan Lairde1d13c92018-03-20 16:58:01 -0400147 mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, holder));
Jason Monkaa573e92017-01-27 17:00:29 -0500148 }
149
150 @Override
151 public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
152 int index = getSlotIndex(slot);
Evan Lairde1d13c92018-03-20 16:58:01 -0400153 StatusBarIconHolder holder = getIcon(index, 0);
154 if (holder == null) {
155 StatusBarIcon icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
156 Icon.createWithResource(
157 mContext, resourceId), 0, 0, contentDescription);
158 holder = StatusBarIconHolder.fromIcon(icon);
159 setIcon(index, holder);
Jason Monkaa573e92017-01-27 17:00:29 -0500160 } else {
Evan Lairde1d13c92018-03-20 16:58:01 -0400161 holder.getIcon().icon = Icon.createWithResource(mContext, resourceId);
162 holder.getIcon().contentDescription = contentDescription;
163 handleSet(index, holder);
164 }
165 }
166
167 /**
168 * Signal icons need to be handled differently, because they can be
169 * composite views
170 */
171 @Override
172 public void setSignalIcon(String slot, WifiIconState state) {
173
174 int index = getSlotIndex(slot);
175
176 if (state == null) {
177 removeIcon(index, 0);
178 return;
179 }
180
181 StatusBarIconHolder holder = getIcon(index, 0);
182 if (holder == null) {
183 holder = StatusBarIconHolder.fromWifiIconState(state);
184 setIcon(index, holder);
185 } else {
186 holder.setWifiState(state);
187 handleSet(index, holder);
188 }
189 }
190
191 /**
192 * Accept a list of MobileIconStates, which all live in the same slot(?!), and then are sorted
193 * by subId. Don't worry this definitely makes sense and works.
194 * @param slot da slot
195 * @param iconStates All of the mobile icon states
196 */
197 @Override
198 public void setMobileIcons(String slot, List<MobileIconState> iconStates) {
199 Slot mobileSlot = getSlot(slot);
200 int slotIndex = getSlotIndex(slot);
201
Yong Shi4a50a8e2018-05-21 15:53:02 +0800202 // Reverse the sort order to show icons with left to right([Slot1][Slot2]..).
203 // StatusBarIconList has UI design that first items go to the right of second items.
204 Collections.reverse(iconStates);
205
Evan Lairde1d13c92018-03-20 16:58:01 -0400206 for (MobileIconState state : iconStates) {
207 StatusBarIconHolder holder = mobileSlot.getHolderForTag(state.subId);
208 if (holder == null) {
209 holder = StatusBarIconHolder.fromMobileIconState(state);
210 setIcon(slotIndex, holder);
211 } else {
212 holder.setMobileState(state);
213 handleSet(slotIndex, holder);
214 }
Jason Monkaa573e92017-01-27 17:00:29 -0500215 }
216 }
217
218 @Override
219 public void setExternalIcon(String slot) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400220 int viewIndex = getViewIndex(getSlotIndex(slot), 0);
Jason Monkaa573e92017-01-27 17:00:29 -0500221 int height = mContext.getResources().getDimensionPixelSize(
222 R.dimen.status_bar_icon_drawing_size);
223 mIconGroups.forEach(l -> l.onIconExternal(viewIndex, height));
224 }
225
Evan Lairde1d13c92018-03-20 16:58:01 -0400226 //TODO: remove this (used in command queue and for 3rd party tiles?)
Jason Monkaa573e92017-01-27 17:00:29 -0500227 @Override
228 public void setIcon(String slot, StatusBarIcon icon) {
229 setIcon(getSlotIndex(slot), icon);
230 }
231
Evan Lairde1d13c92018-03-20 16:58:01 -0400232 /**
233 * For backwards compatibility, in the event that someone gives us a slot and a status bar icon
234 */
235 private void setIcon(int index, StatusBarIcon icon) {
236 if (icon == null) {
237 removeAllIconsForSlot(getSlotName(index));
238 return;
239 }
240
241 StatusBarIconHolder holder = StatusBarIconHolder.fromIcon(icon);
242 setIcon(index, holder);
243 }
244
Jason Monkaa573e92017-01-27 17:00:29 -0500245 @Override
Evan Lairde1d13c92018-03-20 16:58:01 -0400246 public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
247 boolean isNew = getIcon(index, holder.getTag()) == null;
248 super.setIcon(index, holder);
249
250 if (isNew) {
251 addSystemIcon(index, holder);
252 } else {
253 handleSet(index, holder);
254 }
Jason Monkaa573e92017-01-27 17:00:29 -0500255 }
256
257 public void setIconVisibility(String slot, boolean visibility) {
258 int index = getSlotIndex(slot);
Evan Lairde1d13c92018-03-20 16:58:01 -0400259 StatusBarIconHolder holder = getIcon(index, 0);
260 if (holder == null || holder.isVisible() == visibility) {
Jason Monkaa573e92017-01-27 17:00:29 -0500261 return;
262 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400263
264 holder.setVisible(visibility);
265 handleSet(index, holder);
266 }
267
268 public void removeIcon(String slot) {
269 removeAllIconsForSlot(slot);
Jason Monkaa573e92017-01-27 17:00:29 -0500270 }
271
272 @Override
Evan Lairde1d13c92018-03-20 16:58:01 -0400273 public void removeIcon(String slot, int tag) {
274 removeIcon(getSlotIndex(slot), tag);
275 }
276
277 @Override
278 public void removeAllIconsForSlot(String slotName) {
279 Slot slot = getSlot(slotName);
280 if (!slot.hasIconsInSlot()) {
Jason Monkaa573e92017-01-27 17:00:29 -0500281 return;
282 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400283
Evan Lairde1d13c92018-03-20 16:58:01 -0400284 int slotIndex = getSlotIndex(slotName);
Evan Lairdeae911d2018-04-26 16:05:46 -0400285 List<StatusBarIconHolder> iconsToRemove = slot.getHolderListInViewOrder();
Evan Lairde1d13c92018-03-20 16:58:01 -0400286 for (StatusBarIconHolder holder : iconsToRemove) {
287 int viewIndex = getViewIndex(slotIndex, holder.getTag());
288 slot.removeForTag(holder.getTag());
289 mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
290 }
291 }
292
293 @Override
294 public void removeIcon(int index, int tag) {
295 if (getIcon(index, tag) == null) {
296 return;
297 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400298 super.removeIcon(index, tag);
299 int viewIndex = getViewIndex(index, 0);
Jason Monkaa573e92017-01-27 17:00:29 -0500300 mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
301 }
302
Evan Lairde1d13c92018-03-20 16:58:01 -0400303 private void handleSet(int index, StatusBarIconHolder holder) {
304 int viewIndex = getViewIndex(index, holder.getTag());
Evan Lairde1d13c92018-03-20 16:58:01 -0400305 mIconGroups.forEach(l -> l.onSetIconHolder(viewIndex, holder));
Jason Monkaa573e92017-01-27 17:00:29 -0500306 }
307
Jason Monkaa573e92017-01-27 17:00:29 -0500308 @Override
309 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Evan Laird937d9fa2018-02-08 10:12:16 -0800310 pw.println(TAG + " state:");
311 for (IconManager manager : mIconGroups) {
312 if (manager.shouldLog()) {
313 ViewGroup group = manager.mGroup;
314 int N = group.getChildCount();
315 pw.println(" icon views: " + N);
316 for (int i = 0; i < N; i++) {
Evan Lairde1d13c92018-03-20 16:58:01 -0400317 StatusIconDisplayable ic = (StatusIconDisplayable) group.getChildAt(i);
Evan Laird937d9fa2018-02-08 10:12:16 -0800318 pw.println(" [" + i + "] icon=" + ic);
319 }
320 }
Jason Monkaa573e92017-01-27 17:00:29 -0500321 }
Evan Laird937d9fa2018-02-08 10:12:16 -0800322
Jason Monkaa573e92017-01-27 17:00:29 -0500323 super.dump(pw);
324 }
325
326 public void dispatchDemoCommand(String command, Bundle args) {
Evan Laird937d9fa2018-02-08 10:12:16 -0800327 for (IconManager manager : mIconGroups) {
328 if (manager.isDemoable()) {
329 manager.dispatchDemoCommand(command, args);
330 }
Jason Monkaa573e92017-01-27 17:00:29 -0500331 }
Jason Monkaa573e92017-01-27 17:00:29 -0500332 }
333
334 @Override
335 public void onDensityOrFontScaleChanged() {
336 loadDimens();
337 }
338}