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