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.graphics.Rect;
21 import android.graphics.drawable.Icon;
22 import android.os.Bundle;
23 import android.os.UserHandle;
24 import android.util.Log;
25 import android.view.Gravity;
26 import android.view.View;
27 import android.view.ViewGroup;
28 import android.widget.LinearLayout;
29 
30 import com.android.internal.statusbar.StatusBarIcon;
31 import com.android.systemui.R;
32 import com.android.systemui.demomode.DemoMode;
33 import com.android.systemui.plugins.DarkIconDispatcher;
34 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
35 import com.android.systemui.statusbar.StatusBarIconView;
36 import com.android.systemui.statusbar.StatusIconDisplayable;
37 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger;
38 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
39 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
40 import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
41 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel;
42 
43 import java.util.ArrayList;
44 import java.util.List;
45 
46 //TODO: This should be a controller, not its own view
47 public class DemoStatusIcons extends StatusIconContainer implements DemoMode, DarkReceiver {
48     private static final String TAG = "DemoStatusIcons";
49 
50     private final LinearLayout mStatusIcons;
51     private final ArrayList<ModernStatusBarMobileView> mModernMobileViews = new ArrayList<>();
52     private final int mIconSize;
53 
54     private ModernStatusBarWifiView mModernWifiView;
55     private boolean mDemoMode;
56     private int mColor;
57 
58     private final MobileIconsViewModel mMobileIconsViewModel;
59     private final StatusBarLocation mLocation;
60 
DemoStatusIcons( LinearLayout statusIcons, MobileIconsViewModel mobileIconsViewModel, StatusBarLocation location, int iconSize )61     public DemoStatusIcons(
62             LinearLayout statusIcons,
63             MobileIconsViewModel mobileIconsViewModel,
64             StatusBarLocation location,
65             int iconSize
66     ) {
67         super(statusIcons.getContext());
68         mStatusIcons = statusIcons;
69         mIconSize = iconSize;
70         mColor = DarkIconDispatcher.DEFAULT_ICON_TINT;
71         mMobileIconsViewModel = mobileIconsViewModel;
72         mLocation = location;
73 
74         if (statusIcons instanceof StatusIconContainer) {
75             setShouldRestrictIcons(((StatusIconContainer) statusIcons).isRestrictingIcons());
76         } else {
77             setShouldRestrictIcons(false);
78         }
79         setLayoutParams(mStatusIcons.getLayoutParams());
80         setPadding(mStatusIcons.getPaddingLeft(), mStatusIcons.getPaddingTop(),
81                 mStatusIcons.getPaddingRight(), mStatusIcons.getPaddingBottom());
82         setOrientation(mStatusIcons.getOrientation());
83         setGravity(Gravity.CENTER_VERTICAL); // no LL.getGravity()
84         ViewGroup p = (ViewGroup) mStatusIcons.getParent();
85         p.addView(this, p.indexOfChild(mStatusIcons));
86     }
87 
remove()88     public void remove() {
89         ((ViewGroup) getParent()).removeView(this);
90     }
91 
setColor(int color)92     public void setColor(int color) {
93         mColor = color;
94         updateColors();
95     }
96 
updateColors()97     private void updateColors() {
98         for (int i = 0; i < getChildCount(); i++) {
99             StatusIconDisplayable child = (StatusIconDisplayable) getChildAt(i);
100             child.setStaticDrawableColor(mColor);
101             child.setDecorColor(mColor);
102         }
103     }
104 
105     @Override
demoCommands()106     public List<String> demoCommands() {
107         List<String> commands = new ArrayList<>();
108         commands.add(COMMAND_STATUS);
109         return commands;
110     }
111 
112     @Override
onDemoModeStarted()113     public void onDemoModeStarted() {
114         mDemoMode = true;
115         mStatusIcons.setVisibility(View.GONE);
116         setVisibility(View.VISIBLE);
117     }
118 
119     @Override
onDemoModeFinished()120     public void onDemoModeFinished() {
121         mDemoMode = false;
122         mStatusIcons.setVisibility(View.VISIBLE);
123         mModernMobileViews.clear();
124         setVisibility(View.GONE);
125     }
126 
127     @Override
dispatchDemoCommand(String command, Bundle args)128     public void dispatchDemoCommand(String command, Bundle args) {
129         String volume = args.getString("volume");
130         if (volume != null) {
131             int iconId = volume.equals("vibrate") ? R.drawable.stat_sys_ringer_vibrate
132                     : 0;
133             updateSlot("volume", null, iconId);
134         }
135         String zen = args.getString("zen");
136         if (zen != null) {
137             int iconId = zen.equals("dnd") ? R.drawable.stat_sys_dnd : 0;
138             updateSlot("zen", null, iconId);
139         }
140         String bt = args.getString("bluetooth");
141         if (bt != null) {
142             int iconId = bt.equals("connected")
143                     ? R.drawable.stat_sys_data_bluetooth_connected : 0;
144             updateSlot("bluetooth", null, iconId);
145         }
146         String location = args.getString("location");
147         if (location != null) {
148             int iconId = location.equals("show") ? PhoneStatusBarPolicy.LOCATION_STATUS_ICON_ID
149                     : 0;
150             updateSlot("location", null, iconId);
151         }
152         String alarm = args.getString("alarm");
153         if (alarm != null) {
154             int iconId = alarm.equals("show") ? R.drawable.stat_sys_alarm
155                     : 0;
156             updateSlot("alarm_clock", null, iconId);
157         }
158         String tty = args.getString("tty");
159         if (tty != null) {
160             int iconId = tty.equals("show") ? R.drawable.stat_sys_tty_mode
161                     : 0;
162             updateSlot("tty", null, iconId);
163         }
164         String mute = args.getString("mute");
165         if (mute != null) {
166             int iconId = mute.equals("show") ? android.R.drawable.stat_notify_call_mute
167                     : 0;
168             updateSlot("mute", null, iconId);
169         }
170         String speakerphone = args.getString("speakerphone");
171         if (speakerphone != null) {
172             int iconId = speakerphone.equals("show") ? android.R.drawable.stat_sys_speakerphone
173                     : 0;
174             updateSlot("speakerphone", null, iconId);
175         }
176         String cast = args.getString("cast");
177         if (cast != null) {
178             int iconId = cast.equals("show") ? R.drawable.stat_sys_cast : 0;
179             updateSlot("cast", null, iconId);
180         }
181         String hotspot = args.getString("hotspot");
182         if (hotspot != null) {
183             int iconId = hotspot.equals("show") ? R.drawable.stat_sys_hotspot : 0;
184             updateSlot("hotspot", null, iconId);
185         }
186     }
187 
188     /// Can only be used to update non-signal related slots
updateSlot(String slot, String iconPkg, int iconId)189     private void updateSlot(String slot, String iconPkg, int iconId) {
190         if (!mDemoMode) return;
191         if (iconPkg == null) {
192             iconPkg = mContext.getPackageName();
193         }
194         int removeIndex = -1;
195         for (int i = 0; i < getChildCount(); i++) {
196             View child = getChildAt(i);
197             if (!(child instanceof StatusBarIconView)) {
198                 continue;
199             }
200             StatusBarIconView v = (StatusBarIconView) child;
201             if (slot.equals(v.getTag())) {
202                 if (iconId == 0) {
203                     removeIndex = i;
204                     break;
205                 } else {
206                     StatusBarIcon icon = v.getStatusBarIcon();
207                     icon.visible = true;
208                     icon.icon = Icon.createWithResource(icon.icon.getResPackage(), iconId);
209                     v.set(icon);
210                     v.updateDrawable();
211                     return;
212                 }
213             }
214         }
215         if (iconId == 0) {
216             if (removeIndex != -1) {
217                 removeViewAt(removeIndex);
218             }
219             return;
220         }
221         StatusBarIcon icon = new StatusBarIcon(iconPkg, UserHandle.SYSTEM, iconId, 0, 0, "Demo");
222         icon.visible = true;
223         StatusBarIconView v = new StatusBarIconView(getContext(), slot, null, false);
224         v.setTag(slot);
225         v.set(icon);
226         v.setStaticDrawableColor(mColor);
227         v.setDecorColor(mColor);
228         addView(v, 0, createLayoutParams());
229     }
230 
231     /**
232      * Add a {@link ModernStatusBarMobileView}
233      * @param mobileContext possibly mcc/mnc overridden mobile context
234      * @param subId the subscriptionId for this mobile view
235      */
addModernMobileView( Context mobileContext, MobileViewLogger mobileViewLogger, int subId)236     public void addModernMobileView(
237             Context mobileContext,
238             MobileViewLogger mobileViewLogger,
239             int subId) {
240         Log.d(TAG, "addModernMobileView (subId=" + subId + ")");
241         ModernStatusBarMobileView view = ModernStatusBarMobileView.constructAndBind(
242                 mobileContext,
243                 mobileViewLogger,
244                 "mobile",
245                 mMobileIconsViewModel.viewModelForSub(subId, mLocation)
246         );
247 
248         // mobile always goes at the end
249         mModernMobileViews.add(view);
250         addView(view, getChildCount(), createLayoutParams());
251     }
252 
253     /**
254      * Add a {@link ModernStatusBarWifiView}
255      */
addModernWifiView(LocationBasedWifiViewModel viewModel)256     public void addModernWifiView(LocationBasedWifiViewModel viewModel) {
257         Log.d(TAG, "addModernDemoWifiView: ");
258         ModernStatusBarWifiView view = ModernStatusBarWifiView
259                 .constructAndBind(mContext, "wifi", viewModel);
260 
261         int viewIndex = getChildCount();
262         // If we have mobile views, put wifi before them
263         for (int i = 0; i < getChildCount(); i++) {
264             View child = getChildAt(i);
265             if (child instanceof ModernStatusBarMobileView) {
266                 viewIndex = i;
267                 break;
268             }
269         }
270 
271         mModernWifiView = view;
272         mModernWifiView.setStaticDrawableColor(mColor);
273         addView(view, viewIndex, createLayoutParams());
274     }
275 
onRemoveIcon(StatusIconDisplayable view)276     public void onRemoveIcon(StatusIconDisplayable view) {
277         if (view.getSlot().equals("wifi")) {
278             if (view instanceof ModernStatusBarWifiView) {
279                 Log.d(TAG, "onRemoveIcon: removing modern wifi view");
280                 removeView(mModernWifiView);
281                 mModernWifiView = null;
282             }
283         } else if (view instanceof ModernStatusBarMobileView) {
284             ModernStatusBarMobileView mobileView = matchingModernMobileView(
285                     (ModernStatusBarMobileView) view);
286             if (mobileView != null) {
287                 removeView(mobileView);
288                 mModernMobileViews.remove(mobileView);
289             }
290         }
291     }
292 
matchingModernMobileView(ModernStatusBarMobileView other)293     private ModernStatusBarMobileView matchingModernMobileView(ModernStatusBarMobileView other) {
294         for (ModernStatusBarMobileView v : mModernMobileViews) {
295             if (v.getSubId() == other.getSubId()) {
296                 return v;
297             }
298         }
299 
300         return null;
301     }
302 
createLayoutParams()303     private LayoutParams createLayoutParams() {
304         return new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
305     }
306 
307     @Override
onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint)308     public void onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint) {
309         setColor(DarkIconDispatcher.getTint(areas, mStatusIcons, tint));
310 
311         if (mModernWifiView != null) {
312             mModernWifiView.onDarkChanged(areas, darkIntensity, tint);
313         }
314         for (ModernStatusBarMobileView view : mModernMobileViews) {
315             view.onDarkChanged(areas, darkIntensity, tint);
316         }
317     }
318 }
319