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