• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 
17 package com.android.systemui.statusbar.phone;
18 
19 import android.content.Context;
20 import android.content.res.Configuration;
21 import android.graphics.Rect;
22 import android.graphics.drawable.Icon;
23 import android.os.Bundle;
24 import android.os.UserHandle;
25 import android.util.Log;
26 import android.view.Gravity;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.widget.LinearLayout;
30 
31 import com.android.internal.statusbar.StatusBarIcon;
32 import com.android.systemui.R;
33 import com.android.systemui.demomode.DemoMode;
34 import com.android.systemui.plugins.DarkIconDispatcher;
35 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
36 import com.android.systemui.statusbar.StatusBarIconView;
37 import com.android.systemui.statusbar.StatusBarMobileView;
38 import com.android.systemui.statusbar.StatusBarWifiView;
39 import com.android.systemui.statusbar.StatusIconDisplayable;
40 import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
41 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
42 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
43 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger;
44 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
45 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
46 import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
47 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel;
48 
49 import java.util.ArrayList;
50 import java.util.List;
51 
52 //TODO: This should be a controller, not its own view
53 public class DemoStatusIcons extends StatusIconContainer implements DemoMode, DarkReceiver {
54     private static final String TAG = "DemoStatusIcons";
55 
56     private final LinearLayout mStatusIcons;
57     private final ArrayList<StatusBarMobileView> mMobileViews = new ArrayList<>();
58     private final ArrayList<ModernStatusBarMobileView> mModernMobileViews = new ArrayList<>();
59     private final int mIconSize;
60 
61     private StatusBarWifiView mWifiView;
62     private ModernStatusBarWifiView mModernWifiView;
63     private boolean mDemoMode;
64     private int mColor;
65 
66     private final MobileIconsViewModel mMobileIconsViewModel;
67     private final StatusBarLocation mLocation;
68 
DemoStatusIcons( LinearLayout statusIcons, MobileIconsViewModel mobileIconsViewModel, StatusBarLocation location, int iconSize )69     public DemoStatusIcons(
70             LinearLayout statusIcons,
71             MobileIconsViewModel mobileIconsViewModel,
72             StatusBarLocation location,
73             int iconSize
74     ) {
75         super(statusIcons.getContext());
76         mStatusIcons = statusIcons;
77         mIconSize = iconSize;
78         mColor = DarkIconDispatcher.DEFAULT_ICON_TINT;
79         mMobileIconsViewModel = mobileIconsViewModel;
80         mLocation = location;
81 
82         if (statusIcons instanceof StatusIconContainer) {
83             setShouldRestrictIcons(((StatusIconContainer) statusIcons).isRestrictingIcons());
84         } else {
85             setShouldRestrictIcons(false);
86         }
87         setLayoutParams(mStatusIcons.getLayoutParams());
88         setPadding(mStatusIcons.getPaddingLeft(), mStatusIcons.getPaddingTop(),
89                 mStatusIcons.getPaddingRight(), mStatusIcons.getPaddingBottom());
90         setOrientation(mStatusIcons.getOrientation());
91         setGravity(Gravity.CENTER_VERTICAL); // no LL.getGravity()
92         ViewGroup p = (ViewGroup) mStatusIcons.getParent();
93         p.addView(this, p.indexOfChild(mStatusIcons));
94     }
95 
remove()96     public void remove() {
97         mMobileViews.clear();
98         ((ViewGroup) getParent()).removeView(this);
99     }
100 
setColor(int color)101     public void setColor(int color) {
102         mColor = color;
103         updateColors();
104     }
105 
updateColors()106     private void updateColors() {
107         for (int i = 0; i < getChildCount(); i++) {
108             StatusIconDisplayable child = (StatusIconDisplayable) getChildAt(i);
109             child.setStaticDrawableColor(mColor);
110             child.setDecorColor(mColor);
111         }
112     }
113 
114     @Override
demoCommands()115     public List<String> demoCommands() {
116         List<String> commands = new ArrayList<>();
117         commands.add(COMMAND_STATUS);
118         return commands;
119     }
120 
121     @Override
onDemoModeStarted()122     public void onDemoModeStarted() {
123         mDemoMode = true;
124         mStatusIcons.setVisibility(View.GONE);
125         setVisibility(View.VISIBLE);
126     }
127 
128     @Override
onDemoModeFinished()129     public void onDemoModeFinished() {
130         mDemoMode = false;
131         mStatusIcons.setVisibility(View.VISIBLE);
132         mModernMobileViews.clear();
133         mMobileViews.clear();
134         setVisibility(View.GONE);
135     }
136 
137     @Override
dispatchDemoCommand(String command, Bundle args)138     public void dispatchDemoCommand(String command, Bundle args) {
139         String volume = args.getString("volume");
140         if (volume != null) {
141             int iconId = volume.equals("vibrate") ? R.drawable.stat_sys_ringer_vibrate
142                     : 0;
143             updateSlot("volume", null, iconId);
144         }
145         String zen = args.getString("zen");
146         if (zen != null) {
147             int iconId = zen.equals("dnd") ? R.drawable.stat_sys_dnd : 0;
148             updateSlot("zen", null, iconId);
149         }
150         String bt = args.getString("bluetooth");
151         if (bt != null) {
152             int iconId = bt.equals("connected")
153                     ? R.drawable.stat_sys_data_bluetooth_connected : 0;
154             updateSlot("bluetooth", null, iconId);
155         }
156         String location = args.getString("location");
157         if (location != null) {
158             int iconId = location.equals("show") ? PhoneStatusBarPolicy.LOCATION_STATUS_ICON_ID
159                     : 0;
160             updateSlot("location", null, iconId);
161         }
162         String alarm = args.getString("alarm");
163         if (alarm != null) {
164             int iconId = alarm.equals("show") ? R.drawable.stat_sys_alarm
165                     : 0;
166             updateSlot("alarm_clock", null, iconId);
167         }
168         String tty = args.getString("tty");
169         if (tty != null) {
170             int iconId = tty.equals("show") ? R.drawable.stat_sys_tty_mode
171                     : 0;
172             updateSlot("tty", null, iconId);
173         }
174         String mute = args.getString("mute");
175         if (mute != null) {
176             int iconId = mute.equals("show") ? android.R.drawable.stat_notify_call_mute
177                     : 0;
178             updateSlot("mute", null, iconId);
179         }
180         String speakerphone = args.getString("speakerphone");
181         if (speakerphone != null) {
182             int iconId = speakerphone.equals("show") ? android.R.drawable.stat_sys_speakerphone
183                     : 0;
184             updateSlot("speakerphone", null, iconId);
185         }
186         String cast = args.getString("cast");
187         if (cast != null) {
188             int iconId = cast.equals("show") ? R.drawable.stat_sys_cast : 0;
189             updateSlot("cast", null, iconId);
190         }
191         String hotspot = args.getString("hotspot");
192         if (hotspot != null) {
193             int iconId = hotspot.equals("show") ? R.drawable.stat_sys_hotspot : 0;
194             updateSlot("hotspot", null, iconId);
195         }
196     }
197 
198     /// Can only be used to update non-signal related slots
updateSlot(String slot, String iconPkg, int iconId)199     private void updateSlot(String slot, String iconPkg, int iconId) {
200         if (!mDemoMode) return;
201         if (iconPkg == null) {
202             iconPkg = mContext.getPackageName();
203         }
204         int removeIndex = -1;
205         for (int i = 0; i < getChildCount(); i++) {
206             View child = getChildAt(i);
207             if (!(child instanceof StatusBarIconView)) {
208                 continue;
209             }
210             StatusBarIconView v = (StatusBarIconView) child;
211             if (slot.equals(v.getTag())) {
212                 if (iconId == 0) {
213                     removeIndex = i;
214                     break;
215                 } else {
216                     StatusBarIcon icon = v.getStatusBarIcon();
217                     icon.visible = true;
218                     icon.icon = Icon.createWithResource(icon.icon.getResPackage(), iconId);
219                     v.set(icon);
220                     v.updateDrawable();
221                     return;
222                 }
223             }
224         }
225         if (iconId == 0) {
226             if (removeIndex != -1) {
227                 removeViewAt(removeIndex);
228             }
229             return;
230         }
231         StatusBarIcon icon = new StatusBarIcon(iconPkg, UserHandle.SYSTEM, iconId, 0, 0, "Demo");
232         icon.visible = true;
233         StatusBarIconView v = new StatusBarIconView(getContext(), slot, null, false);
234         v.setTag(slot);
235         v.set(icon);
236         v.setStaticDrawableColor(mColor);
237         v.setDecorColor(mColor);
238         addView(v, 0, createLayoutParams());
239     }
240 
addDemoWifiView(WifiIconState state)241     public void addDemoWifiView(WifiIconState state) {
242         Log.d(TAG, "addDemoWifiView: ");
243         StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, state.slot);
244 
245         int viewIndex = getChildCount();
246         // If we have mobile views, put wifi before them
247         for (int i = 0; i < getChildCount(); i++) {
248             View child = getChildAt(i);
249             if (child instanceof StatusBarMobileView
250                     || child instanceof ModernStatusBarMobileView) {
251                 viewIndex = i;
252                 break;
253             }
254         }
255 
256         mWifiView = view;
257         mWifiView.applyWifiState(state);
258         mWifiView.setStaticDrawableColor(mColor);
259         addView(view, viewIndex, createLayoutParams());
260     }
261 
updateWifiState(WifiIconState state)262     public void updateWifiState(WifiIconState state) {
263         Log.d(TAG, "updateWifiState: ");
264         if (mWifiView == null) {
265             addDemoWifiView(state);
266         } else {
267             mWifiView.applyWifiState(state);
268         }
269     }
270 
271     /**
272      * Add a new mobile icon view
273      */
addMobileView(MobileIconState state, Context mobileContext)274     public void addMobileView(MobileIconState state, Context mobileContext) {
275         Log.d(TAG, "addMobileView: ");
276         StatusBarMobileView view = StatusBarMobileView
277                 .fromContext(mobileContext, state.slot);
278 
279         view.applyMobileState(state);
280         view.setStaticDrawableColor(mColor);
281 
282         // mobile always goes at the end
283         mMobileViews.add(view);
284         addView(view, getChildCount(), createLayoutParams());
285     }
286 
287     /**
288      * Add a {@link ModernStatusBarMobileView}
289      * @param mobileContext possibly mcc/mnc overridden mobile context
290      * @param subId the subscriptionId for this mobile view
291      */
addModernMobileView( Context mobileContext, MobileViewLogger mobileViewLogger, int subId)292     public void addModernMobileView(
293             Context mobileContext,
294             MobileViewLogger mobileViewLogger,
295             int subId) {
296         Log.d(TAG, "addModernMobileView (subId=" + subId + ")");
297         ModernStatusBarMobileView view = ModernStatusBarMobileView.constructAndBind(
298                 mobileContext,
299                 mobileViewLogger,
300                 "mobile",
301                 mMobileIconsViewModel.viewModelForSub(subId, mLocation)
302         );
303 
304         // mobile always goes at the end
305         mModernMobileViews.add(view);
306         addView(view, getChildCount(), createLayoutParams());
307     }
308 
309     /**
310      * Add a {@link ModernStatusBarWifiView}
311      */
addModernWifiView(LocationBasedWifiViewModel viewModel)312     public void addModernWifiView(LocationBasedWifiViewModel viewModel) {
313         Log.d(TAG, "addModernDemoWifiView: ");
314         ModernStatusBarWifiView view = ModernStatusBarWifiView
315                 .constructAndBind(mContext, "wifi", viewModel);
316 
317         int viewIndex = getChildCount();
318         // If we have mobile views, put wifi before them
319         for (int i = 0; i < getChildCount(); i++) {
320             View child = getChildAt(i);
321             if (child instanceof StatusBarMobileView
322                     || child instanceof ModernStatusBarMobileView) {
323                 viewIndex = i;
324                 break;
325             }
326         }
327 
328         mModernWifiView = view;
329         mModernWifiView.setStaticDrawableColor(mColor);
330         addView(view, viewIndex, createLayoutParams());
331     }
332 
333     /**
334      * Apply an update to a mobile icon view for the given {@link MobileIconState}. For
335      * compatibility with {@link MobileContextProvider}, we have to recreate the view every time we
336      * update it, since the context (and thus the {@link Configuration}) may have changed
337      */
updateMobileState(MobileIconState state, Context mobileContext)338     public void updateMobileState(MobileIconState state, Context mobileContext) {
339         Log.d(TAG, "updateMobileState: " + state);
340 
341         // The mobile config provided by MobileContextProvider could have changed; always recreate
342         for (int i = 0; i < mMobileViews.size(); i++) {
343             StatusBarMobileView view = mMobileViews.get(i);
344             if (view.getState().subId == state.subId) {
345                 removeView(view);
346             }
347         }
348 
349         // Add the replacement or new icon
350         addMobileView(state, mobileContext);
351     }
352 
onRemoveIcon(StatusIconDisplayable view)353     public void onRemoveIcon(StatusIconDisplayable view) {
354         if (view.getSlot().equals("wifi")) {
355             if (view instanceof StatusBarWifiView) {
356                 removeView(mWifiView);
357                 mWifiView = null;
358             } else if (view instanceof ModernStatusBarWifiView) {
359                 Log.d(TAG, "onRemoveIcon: removing modern wifi view");
360                 removeView(mModernWifiView);
361                 mModernWifiView = null;
362             }
363         } else if (view instanceof StatusBarMobileView) {
364             StatusBarMobileView mobileView = matchingMobileView(view);
365             if (mobileView != null) {
366                 removeView(mobileView);
367                 mMobileViews.remove(mobileView);
368             }
369         } else if (view instanceof ModernStatusBarMobileView) {
370             ModernStatusBarMobileView mobileView = matchingModernMobileView(
371                     (ModernStatusBarMobileView) view);
372             if (mobileView != null) {
373                 removeView(mobileView);
374                 mModernMobileViews.remove(mobileView);
375             }
376         }
377     }
378 
matchingMobileView(StatusIconDisplayable otherView)379     private StatusBarMobileView matchingMobileView(StatusIconDisplayable otherView) {
380         if (!(otherView instanceof StatusBarMobileView)) {
381             return null;
382         }
383 
384         StatusBarMobileView v = (StatusBarMobileView) otherView;
385         for (StatusBarMobileView view : mMobileViews) {
386             if (view.getState().subId == v.getState().subId) {
387                 return view;
388             }
389         }
390 
391         return null;
392     }
393 
matchingModernMobileView(ModernStatusBarMobileView other)394     private ModernStatusBarMobileView matchingModernMobileView(ModernStatusBarMobileView other) {
395         for (ModernStatusBarMobileView v : mModernMobileViews) {
396             if (v.getSubId() == other.getSubId()) {
397                 return v;
398             }
399         }
400 
401         return null;
402     }
403 
createLayoutParams()404     private LayoutParams createLayoutParams() {
405         return new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
406     }
407 
408     @Override
onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint)409     public void onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint) {
410         setColor(DarkIconDispatcher.getTint(areas, mStatusIcons, tint));
411 
412         if (mWifiView != null) {
413             mWifiView.onDarkChanged(areas, darkIntensity, tint);
414         }
415         if (mModernWifiView != null) {
416             mModernWifiView.onDarkChanged(areas, darkIntensity, tint);
417         }
418         for (StatusBarMobileView view : mMobileViews) {
419             view.onDarkChanged(areas, darkIntensity, tint);
420         }
421         for (ModernStatusBarMobileView view : mModernMobileViews) {
422             view.onDarkChanged(areas, darkIntensity, tint);
423         }
424     }
425 }
426