1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.statusbar.phone; 16 17 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON; 18 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE; 19 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE_NEW; 20 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI; 21 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI_NEW; 22 23 import android.annotation.Nullable; 24 import android.content.Context; 25 import android.os.Bundle; 26 import android.text.TextUtils; 27 import android.util.ArraySet; 28 import android.view.Gravity; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.widget.ImageView; 32 import android.widget.LinearLayout; 33 import android.widget.LinearLayout.LayoutParams; 34 35 import androidx.annotation.VisibleForTesting; 36 37 import com.android.internal.statusbar.StatusBarIcon; 38 import com.android.systemui.R; 39 import com.android.systemui.dagger.SysUISingleton; 40 import com.android.systemui.demomode.DemoModeCommandReceiver; 41 import com.android.systemui.plugins.DarkIconDispatcher; 42 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; 43 import com.android.systemui.statusbar.BaseStatusBarFrameLayout; 44 import com.android.systemui.statusbar.StatusBarIconView; 45 import com.android.systemui.statusbar.StatusBarMobileView; 46 import com.android.systemui.statusbar.StatusBarWifiView; 47 import com.android.systemui.statusbar.StatusIconDisplayable; 48 import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider; 49 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState; 50 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState; 51 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState; 52 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags; 53 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter; 54 import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconsBinder; 55 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView; 56 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel; 57 import com.android.systemui.statusbar.pipeline.wifi.ui.WifiUiAdapter; 58 import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView; 59 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel; 60 import com.android.systemui.util.Assert; 61 62 import java.util.ArrayList; 63 import java.util.List; 64 65 import javax.inject.Inject; 66 67 public interface StatusBarIconController { 68 69 /** 70 * When an icon is added with TAG_PRIMARY, it will be treated as the primary icon 71 * in that slot and not added as a sub slot. 72 */ 73 int TAG_PRIMARY = 0; 74 75 /** */ addIconGroup(IconManager iconManager)76 void addIconGroup(IconManager iconManager); 77 /** */ removeIconGroup(IconManager iconManager)78 void removeIconGroup(IconManager iconManager); 79 80 /** Refresh the state of an IconManager by recreating the views */ refreshIconGroup(IconManager iconManager)81 void refreshIconGroup(IconManager iconManager); 82 83 /** 84 * Adds or updates an icon that comes from an active tile service. 85 * 86 * If the icon is null, the icon will be removed. 87 */ setIconFromTile(String slot, @Nullable StatusBarIcon icon)88 void setIconFromTile(String slot, @Nullable StatusBarIcon icon); 89 90 /** Removes an icon that had come from an active tile service. */ removeIconForTile(String slot)91 void removeIconForTile(String slot); 92 93 /** 94 * Adds or updates an icon for the given slot for **internal system icons**. 95 * 96 * TODO(b/265307726): Re-name this to `setInternalIcon`. 97 */ setIcon(String slot, int resourceId, CharSequence contentDescription)98 void setIcon(String slot, int resourceId, CharSequence contentDescription); 99 100 /** */ setWifiIcon(String slot, WifiIconState state)101 void setWifiIcon(String slot, WifiIconState state); 102 103 /** 104 * Sets up a wifi icon using the new data pipeline. No effect if the wifi icon has already been 105 * set up (inflated and added to the view hierarchy). 106 * 107 * This method completely replaces {@link #setWifiIcon} with the information from the new wifi 108 * data pipeline. Icons will automatically keep their state up to date, so we don't have to 109 * worry about funneling state objects through anymore. 110 */ setNewWifiIcon()111 void setNewWifiIcon(); 112 113 /** */ setMobileIcons(String slot, List<MobileIconState> states)114 void setMobileIcons(String slot, List<MobileIconState> states); 115 116 /** 117 * This method completely replaces {@link #setMobileIcons} with the information from the new 118 * mobile data pipeline. Icons will automatically keep their state up to date, so we don't have 119 * to worry about funneling MobileIconState objects through anymore. 120 */ setNewMobileIconSubIds(List<Integer> subIds)121 void setNewMobileIconSubIds(List<Integer> subIds); 122 /** 123 * Display the no calling & SMS icons. 124 */ setCallStrengthIcons(String slot, List<CallIndicatorIconState> states)125 void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states); 126 127 /** 128 * Display the no calling & SMS icons. 129 */ setNoCallingIcons(String slot, List<CallIndicatorIconState> states)130 void setNoCallingIcons(String slot, List<CallIndicatorIconState> states); 131 setIconVisibility(String slot, boolean b)132 public void setIconVisibility(String slot, boolean b); 133 134 /** 135 * Sets the live region mode for the icon 136 * 137 * @param slot Icon slot to set region for 138 * @param accessibilityLiveRegion live region mode for the icon 139 * @see android.view.View#setAccessibilityLiveRegion(int) 140 */ setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion)141 void setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion); 142 143 /** 144 * If you don't know what to pass for `tag`, either remove all icons for slot, or use 145 * TAG_PRIMARY to refer to the first icon at a given slot. 146 */ removeIcon(String slot, int tag)147 void removeIcon(String slot, int tag); 148 149 /** 150 * TODO(b/265307726): Re-name this to `removeAllIconsForInternalSlot`. 151 */ removeAllIconsForSlot(String slot)152 void removeAllIconsForSlot(String slot); 153 154 // TODO: See if we can rename this tunable name. 155 String ICON_HIDE_LIST = "icon_blacklist"; 156 157 /** Reads the default hide list from config value unless hideListStr is provided. */ getIconHideList(Context context, String hideListStr)158 static ArraySet<String> getIconHideList(Context context, String hideListStr) { 159 ArraySet<String> ret = new ArraySet<>(); 160 String[] hideList = hideListStr == null 161 ? context.getResources().getStringArray(R.array.config_statusBarIconsToExclude) 162 : hideListStr.split(","); 163 for (String slot : hideList) { 164 if (!TextUtils.isEmpty(slot)) { 165 ret.add(slot); 166 } 167 } 168 return ret; 169 } 170 171 /** 172 * Version of ViewGroup that observes state from the DarkIconDispatcher. 173 */ 174 class DarkIconManager extends IconManager { 175 private final DarkIconDispatcher mDarkIconDispatcher; 176 private int mIconHPadding; 177 DarkIconManager( LinearLayout linearLayout, StatusBarLocation location, StatusBarPipelineFlags statusBarPipelineFlags, WifiUiAdapter wifiUiAdapter, MobileUiAdapter mobileUiAdapter, MobileContextProvider mobileContextProvider, DarkIconDispatcher darkIconDispatcher)178 public DarkIconManager( 179 LinearLayout linearLayout, 180 StatusBarLocation location, 181 StatusBarPipelineFlags statusBarPipelineFlags, 182 WifiUiAdapter wifiUiAdapter, 183 MobileUiAdapter mobileUiAdapter, 184 MobileContextProvider mobileContextProvider, 185 DarkIconDispatcher darkIconDispatcher) { 186 super(linearLayout, 187 location, 188 statusBarPipelineFlags, 189 wifiUiAdapter, 190 mobileUiAdapter, 191 mobileContextProvider); 192 mIconHPadding = mContext.getResources().getDimensionPixelSize( 193 R.dimen.status_bar_icon_padding); 194 mDarkIconDispatcher = darkIconDispatcher; 195 } 196 197 @Override onIconAdded(int index, String slot, boolean blocked, StatusBarIconHolder holder)198 protected void onIconAdded(int index, String slot, boolean blocked, 199 StatusBarIconHolder holder) { 200 StatusIconDisplayable view = addHolder(index, slot, blocked, holder); 201 mDarkIconDispatcher.addDarkReceiver((DarkReceiver) view); 202 } 203 204 @Override onCreateLayoutParams()205 protected LayoutParams onCreateLayoutParams() { 206 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 207 ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize); 208 lp.setMargins(mIconHPadding, 0, mIconHPadding, 0); 209 return lp; 210 } 211 212 @Override destroy()213 protected void destroy() { 214 for (int i = 0; i < mGroup.getChildCount(); i++) { 215 mDarkIconDispatcher.removeDarkReceiver((DarkReceiver) mGroup.getChildAt(i)); 216 } 217 mGroup.removeAllViews(); 218 } 219 220 @Override onRemoveIcon(int viewIndex)221 protected void onRemoveIcon(int viewIndex) { 222 mDarkIconDispatcher.removeDarkReceiver((DarkReceiver) mGroup.getChildAt(viewIndex)); 223 super.onRemoveIcon(viewIndex); 224 } 225 226 @Override onSetIcon(int viewIndex, StatusBarIcon icon)227 public void onSetIcon(int viewIndex, StatusBarIcon icon) { 228 super.onSetIcon(viewIndex, icon); 229 mDarkIconDispatcher.applyDark((DarkReceiver) mGroup.getChildAt(viewIndex)); 230 } 231 232 @Override createDemoStatusIcons()233 protected DemoStatusIcons createDemoStatusIcons() { 234 DemoStatusIcons icons = super.createDemoStatusIcons(); 235 mDarkIconDispatcher.addDarkReceiver(icons); 236 237 return icons; 238 } 239 240 @Override exitDemoMode()241 protected void exitDemoMode() { 242 mDarkIconDispatcher.removeDarkReceiver(mDemoStatusIcons); 243 super.exitDemoMode(); 244 } 245 246 @SysUISingleton 247 public static class Factory { 248 private final StatusBarPipelineFlags mStatusBarPipelineFlags; 249 private final WifiUiAdapter mWifiUiAdapter; 250 private final MobileContextProvider mMobileContextProvider; 251 private final MobileUiAdapter mMobileUiAdapter; 252 private final DarkIconDispatcher mDarkIconDispatcher; 253 254 @Inject Factory( StatusBarPipelineFlags statusBarPipelineFlags, WifiUiAdapter wifiUiAdapter, MobileContextProvider mobileContextProvider, MobileUiAdapter mobileUiAdapter, DarkIconDispatcher darkIconDispatcher)255 public Factory( 256 StatusBarPipelineFlags statusBarPipelineFlags, 257 WifiUiAdapter wifiUiAdapter, 258 MobileContextProvider mobileContextProvider, 259 MobileUiAdapter mobileUiAdapter, 260 DarkIconDispatcher darkIconDispatcher) { 261 mStatusBarPipelineFlags = statusBarPipelineFlags; 262 mWifiUiAdapter = wifiUiAdapter; 263 mMobileContextProvider = mobileContextProvider; 264 mMobileUiAdapter = mobileUiAdapter; 265 mDarkIconDispatcher = darkIconDispatcher; 266 } 267 create(LinearLayout group, StatusBarLocation location)268 public DarkIconManager create(LinearLayout group, StatusBarLocation location) { 269 return new DarkIconManager( 270 group, 271 location, 272 mStatusBarPipelineFlags, 273 mWifiUiAdapter, 274 mMobileUiAdapter, 275 mMobileContextProvider, 276 mDarkIconDispatcher); 277 } 278 } 279 } 280 281 /** 282 * 283 */ 284 class TintedIconManager extends IconManager { 285 private int mColor; 286 TintedIconManager( ViewGroup group, StatusBarLocation location, StatusBarPipelineFlags statusBarPipelineFlags, WifiUiAdapter wifiUiAdapter, MobileUiAdapter mobileUiAdapter, MobileContextProvider mobileContextProvider )287 public TintedIconManager( 288 ViewGroup group, 289 StatusBarLocation location, 290 StatusBarPipelineFlags statusBarPipelineFlags, 291 WifiUiAdapter wifiUiAdapter, 292 MobileUiAdapter mobileUiAdapter, 293 MobileContextProvider mobileContextProvider 294 ) { 295 super(group, 296 location, 297 statusBarPipelineFlags, 298 wifiUiAdapter, 299 mobileUiAdapter, 300 mobileContextProvider); 301 } 302 303 @Override onIconAdded(int index, String slot, boolean blocked, StatusBarIconHolder holder)304 protected void onIconAdded(int index, String slot, boolean blocked, 305 StatusBarIconHolder holder) { 306 StatusIconDisplayable view = addHolder(index, slot, blocked, holder); 307 view.setStaticDrawableColor(mColor); 308 view.setDecorColor(mColor); 309 } 310 setTint(int color)311 public void setTint(int color) { 312 mColor = color; 313 for (int i = 0; i < mGroup.getChildCount(); i++) { 314 View child = mGroup.getChildAt(i); 315 if (child instanceof StatusIconDisplayable) { 316 StatusIconDisplayable icon = (StatusIconDisplayable) child; 317 icon.setStaticDrawableColor(mColor); 318 icon.setDecorColor(mColor); 319 } 320 } 321 } 322 323 @Override createDemoStatusIcons()324 protected DemoStatusIcons createDemoStatusIcons() { 325 DemoStatusIcons icons = super.createDemoStatusIcons(); 326 icons.setColor(mColor); 327 return icons; 328 } 329 330 @SysUISingleton 331 public static class Factory { 332 private final StatusBarPipelineFlags mStatusBarPipelineFlags; 333 private final WifiUiAdapter mWifiUiAdapter; 334 private final MobileContextProvider mMobileContextProvider; 335 private final MobileUiAdapter mMobileUiAdapter; 336 337 @Inject Factory( StatusBarPipelineFlags statusBarPipelineFlags, WifiUiAdapter wifiUiAdapter, MobileUiAdapter mobileUiAdapter, MobileContextProvider mobileContextProvider )338 public Factory( 339 StatusBarPipelineFlags statusBarPipelineFlags, 340 WifiUiAdapter wifiUiAdapter, 341 MobileUiAdapter mobileUiAdapter, 342 MobileContextProvider mobileContextProvider 343 ) { 344 mStatusBarPipelineFlags = statusBarPipelineFlags; 345 mWifiUiAdapter = wifiUiAdapter; 346 mMobileUiAdapter = mobileUiAdapter; 347 mMobileContextProvider = mobileContextProvider; 348 } 349 create(ViewGroup group, StatusBarLocation location)350 public TintedIconManager create(ViewGroup group, StatusBarLocation location) { 351 return new TintedIconManager( 352 group, 353 location, 354 mStatusBarPipelineFlags, 355 mWifiUiAdapter, 356 mMobileUiAdapter, 357 mMobileContextProvider); 358 } 359 } 360 } 361 362 /** 363 * Turns info from StatusBarIconController into ImageViews in a ViewGroup. 364 */ 365 class IconManager implements DemoModeCommandReceiver { 366 protected final ViewGroup mGroup; 367 private final StatusBarPipelineFlags mStatusBarPipelineFlags; 368 private final MobileContextProvider mMobileContextProvider; 369 private final LocationBasedWifiViewModel mWifiViewModel; 370 private final MobileIconsViewModel mMobileIconsViewModel; 371 372 protected final Context mContext; 373 protected final int mIconSize; 374 // Whether or not these icons show up in dumpsys 375 protected boolean mShouldLog = false; 376 private StatusBarIconController mController; 377 private final StatusBarLocation mLocation; 378 379 // Enables SystemUI demo mode to take effect in this group 380 protected boolean mDemoable = true; 381 private boolean mIsInDemoMode; 382 protected DemoStatusIcons mDemoStatusIcons; 383 384 protected ArrayList<String> mBlockList = new ArrayList<>(); 385 IconManager( ViewGroup group, StatusBarLocation location, StatusBarPipelineFlags statusBarPipelineFlags, WifiUiAdapter wifiUiAdapter, MobileUiAdapter mobileUiAdapter, MobileContextProvider mobileContextProvider )386 public IconManager( 387 ViewGroup group, 388 StatusBarLocation location, 389 StatusBarPipelineFlags statusBarPipelineFlags, 390 WifiUiAdapter wifiUiAdapter, 391 MobileUiAdapter mobileUiAdapter, 392 MobileContextProvider mobileContextProvider 393 ) { 394 mGroup = group; 395 mStatusBarPipelineFlags = statusBarPipelineFlags; 396 mMobileContextProvider = mobileContextProvider; 397 mContext = group.getContext(); 398 mIconSize = mContext.getResources().getDimensionPixelSize( 399 com.android.internal.R.dimen.status_bar_icon_size); 400 mLocation = location; 401 402 if (statusBarPipelineFlags.runNewMobileIconsBackend()) { 403 // This starts the flow for the new pipeline, and will notify us of changes if 404 // {@link StatusBarPipelineFlags#useNewMobileIcons} is also true. 405 mMobileIconsViewModel = mobileUiAdapter.getMobileIconsViewModel(); 406 MobileIconsBinder.bind(mGroup, mMobileIconsViewModel); 407 } else { 408 mMobileIconsViewModel = null; 409 } 410 411 if (statusBarPipelineFlags.runNewWifiIconBackend()) { 412 // This starts the flow for the new pipeline, and will notify us of changes if 413 // {@link StatusBarPipelineFlags#useNewWifiIcon} is also true. 414 mWifiViewModel = wifiUiAdapter.bindGroup(mGroup, mLocation); 415 } else { 416 mWifiViewModel = null; 417 } 418 } 419 isDemoable()420 public boolean isDemoable() { 421 return mDemoable; 422 } 423 setIsDemoable(boolean demoable)424 public void setIsDemoable(boolean demoable) { 425 mDemoable = demoable; 426 } 427 setController(StatusBarIconController controller)428 void setController(StatusBarIconController controller) { 429 mController = controller; 430 } 431 setBlockList(@ullable List<String> blockList)432 public void setBlockList(@Nullable List<String> blockList) { 433 Assert.isMainThread(); 434 mBlockList.clear(); 435 mBlockList.addAll(blockList); 436 if (mController != null) { 437 mController.refreshIconGroup(this); 438 } 439 } 440 setShouldLog(boolean should)441 public void setShouldLog(boolean should) { 442 mShouldLog = should; 443 } 444 shouldLog()445 public boolean shouldLog() { 446 return mShouldLog; 447 } 448 onIconAdded(int index, String slot, boolean blocked, StatusBarIconHolder holder)449 protected void onIconAdded(int index, String slot, boolean blocked, 450 StatusBarIconHolder holder) { 451 addHolder(index, slot, blocked, holder); 452 } 453 addHolder(int index, String slot, boolean blocked, StatusBarIconHolder holder)454 protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked, 455 StatusBarIconHolder holder) { 456 // This is a little hacky, and probably regrettable, but just set `blocked` on any icon 457 // that is in our blocked list, then we'll never see it 458 if (mBlockList.contains(slot)) { 459 blocked = true; 460 } 461 switch (holder.getType()) { 462 case TYPE_ICON: 463 return addIcon(index, slot, blocked, holder.getIcon()); 464 465 case TYPE_WIFI: 466 return addWifiIcon(index, slot, holder.getWifiState()); 467 468 case TYPE_WIFI_NEW: 469 return addNewWifiIcon(index, slot); 470 471 case TYPE_MOBILE: 472 return addMobileIcon(index, slot, holder.getMobileState()); 473 474 case TYPE_MOBILE_NEW: 475 return addNewMobileIcon(index, slot, holder.getTag()); 476 } 477 478 return null; 479 } 480 481 @VisibleForTesting addIcon(int index, String slot, boolean blocked, StatusBarIcon icon)482 protected StatusBarIconView addIcon(int index, String slot, boolean blocked, 483 StatusBarIcon icon) { 484 StatusBarIconView view = onCreateStatusBarIconView(slot, blocked); 485 view.set(icon); 486 mGroup.addView(view, index, onCreateLayoutParams()); 487 return view; 488 } 489 490 @VisibleForTesting addWifiIcon(int index, String slot, WifiIconState state)491 protected StatusIconDisplayable addWifiIcon(int index, String slot, WifiIconState state) { 492 if (mStatusBarPipelineFlags.useNewWifiIcon()) { 493 throw new IllegalStateException("Attempting to add a wifi icon while the new " 494 + "icons are enabled is not supported"); 495 } 496 497 final StatusBarWifiView view = onCreateStatusBarWifiView(slot); 498 view.applyWifiState(state); 499 mGroup.addView(view, index, onCreateLayoutParams()); 500 501 if (mIsInDemoMode) { 502 mDemoStatusIcons.addDemoWifiView(state); 503 } 504 return view; 505 } 506 addNewWifiIcon(int index, String slot)507 protected StatusIconDisplayable addNewWifiIcon(int index, String slot) { 508 if (!mStatusBarPipelineFlags.useNewWifiIcon()) { 509 throw new IllegalStateException("Attempting to add a wifi icon using the new" 510 + "pipeline, but the enabled flag is false."); 511 } 512 513 ModernStatusBarWifiView view = onCreateModernStatusBarWifiView(slot); 514 mGroup.addView(view, index, onCreateLayoutParams()); 515 516 if (mIsInDemoMode) { 517 mDemoStatusIcons.addModernWifiView(mWifiViewModel); 518 } 519 520 return view; 521 } 522 523 @VisibleForTesting addMobileIcon( int index, String slot, MobileIconState state )524 protected StatusIconDisplayable addMobileIcon( 525 int index, 526 String slot, 527 MobileIconState state 528 ) { 529 if (mStatusBarPipelineFlags.useNewMobileIcons()) { 530 throw new IllegalStateException("Attempting to add a mobile icon while the new " 531 + "icons are enabled is not supported"); 532 } 533 534 // Use the `subId` field as a key to query for the correct context 535 StatusBarMobileView mobileView = onCreateStatusBarMobileView(state.subId, slot); 536 mobileView.applyMobileState(state); 537 mGroup.addView(mobileView, index, onCreateLayoutParams()); 538 539 if (mIsInDemoMode) { 540 Context mobileContext = mMobileContextProvider 541 .getMobileContextForSub(state.subId, mContext); 542 mDemoStatusIcons.addMobileView(state, mobileContext); 543 } 544 return mobileView; 545 } 546 addNewMobileIcon( int index, String slot, int subId )547 protected StatusIconDisplayable addNewMobileIcon( 548 int index, 549 String slot, 550 int subId 551 ) { 552 if (!mStatusBarPipelineFlags.useNewMobileIcons()) { 553 throw new IllegalStateException("Attempting to add a mobile icon using the new" 554 + "pipeline, but the enabled flag is false."); 555 } 556 557 BaseStatusBarFrameLayout view = onCreateModernStatusBarMobileView(slot, subId); 558 mGroup.addView(view, index, onCreateLayoutParams()); 559 560 if (mIsInDemoMode) { 561 mDemoStatusIcons.addModernMobileView( 562 mContext, 563 mMobileIconsViewModel.getLogger(), 564 subId); 565 } 566 567 return view; 568 } 569 onCreateStatusBarIconView(String slot, boolean blocked)570 private StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) { 571 return new StatusBarIconView(mContext, slot, null, blocked); 572 } 573 onCreateStatusBarWifiView(String slot)574 private StatusBarWifiView onCreateStatusBarWifiView(String slot) { 575 StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, slot); 576 return view; 577 } 578 onCreateModernStatusBarWifiView(String slot)579 private ModernStatusBarWifiView onCreateModernStatusBarWifiView(String slot) { 580 return ModernStatusBarWifiView.constructAndBind(mContext, slot, mWifiViewModel); 581 } 582 onCreateStatusBarMobileView(int subId, String slot)583 private StatusBarMobileView onCreateStatusBarMobileView(int subId, String slot) { 584 Context mobileContext = mMobileContextProvider.getMobileContextForSub(subId, mContext); 585 StatusBarMobileView view = StatusBarMobileView 586 .fromContext(mobileContext, slot); 587 return view; 588 } 589 onCreateModernStatusBarMobileView( String slot, int subId)590 private ModernStatusBarMobileView onCreateModernStatusBarMobileView( 591 String slot, int subId) { 592 Context mobileContext = mMobileContextProvider.getMobileContextForSub(subId, mContext); 593 return ModernStatusBarMobileView 594 .constructAndBind( 595 mobileContext, 596 mMobileIconsViewModel.getLogger(), 597 slot, 598 mMobileIconsViewModel.viewModelForSub(subId, mLocation) 599 ); 600 } 601 onCreateLayoutParams()602 protected LinearLayout.LayoutParams onCreateLayoutParams() { 603 return new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize); 604 } 605 destroy()606 protected void destroy() { 607 mGroup.removeAllViews(); 608 } 609 onDensityOrFontScaleChanged()610 protected void onDensityOrFontScaleChanged() { 611 for (int i = 0; i < mGroup.getChildCount(); i++) { 612 View child = mGroup.getChildAt(i); 613 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 614 ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize); 615 child.setLayoutParams(lp); 616 } 617 } 618 setHeightAndCenter(ImageView imageView, int height)619 private void setHeightAndCenter(ImageView imageView, int height) { 620 ViewGroup.LayoutParams params = imageView.getLayoutParams(); 621 params.height = height; 622 if (params instanceof LinearLayout.LayoutParams) { 623 ((LinearLayout.LayoutParams) params).gravity = Gravity.CENTER_VERTICAL; 624 } 625 imageView.setLayoutParams(params); 626 } 627 onRemoveIcon(int viewIndex)628 protected void onRemoveIcon(int viewIndex) { 629 if (mIsInDemoMode) { 630 mDemoStatusIcons.onRemoveIcon((StatusIconDisplayable) mGroup.getChildAt(viewIndex)); 631 } 632 mGroup.removeViewAt(viewIndex); 633 } 634 onSetIcon(int viewIndex, StatusBarIcon icon)635 public void onSetIcon(int viewIndex, StatusBarIcon icon) { 636 StatusBarIconView view = (StatusBarIconView) mGroup.getChildAt(viewIndex); 637 view.set(icon); 638 } 639 onSetIconHolder(int viewIndex, StatusBarIconHolder holder)640 public void onSetIconHolder(int viewIndex, StatusBarIconHolder holder) { 641 switch (holder.getType()) { 642 case TYPE_ICON: 643 onSetIcon(viewIndex, holder.getIcon()); 644 return; 645 case TYPE_WIFI: 646 onSetWifiIcon(viewIndex, holder.getWifiState()); 647 return; 648 case TYPE_MOBILE: 649 onSetMobileIcon(viewIndex, holder.getMobileState()); 650 return; 651 case TYPE_MOBILE_NEW: 652 case TYPE_WIFI_NEW: 653 // Nothing, the new icons update themselves 654 return; 655 default: 656 break; 657 } 658 } 659 onSetWifiIcon(int viewIndex, WifiIconState state)660 public void onSetWifiIcon(int viewIndex, WifiIconState state) { 661 View view = mGroup.getChildAt(viewIndex); 662 if (view instanceof StatusBarWifiView) { 663 ((StatusBarWifiView) view).applyWifiState(state); 664 } else if (view instanceof ModernStatusBarWifiView) { 665 // ModernStatusBarWifiView will automatically apply state based on its callbacks, so 666 // we don't need to call applyWifiState. 667 } else { 668 throw new IllegalStateException("View at " + viewIndex + " must be of type " 669 + "StatusBarWifiView or ModernStatusBarWifiView"); 670 } 671 672 if (mIsInDemoMode) { 673 mDemoStatusIcons.updateWifiState(state); 674 } 675 } 676 onSetMobileIcon(int viewIndex, MobileIconState state)677 public void onSetMobileIcon(int viewIndex, MobileIconState state) { 678 View view = mGroup.getChildAt(viewIndex); 679 if (view instanceof StatusBarMobileView) { 680 ((StatusBarMobileView) view).applyMobileState(state); 681 } else { 682 // ModernStatusBarMobileView automatically updates via the ViewModel 683 throw new IllegalStateException("Cannot update ModernStatusBarMobileView outside of" 684 + "the new pipeline"); 685 } 686 687 if (mIsInDemoMode) { 688 Context mobileContext = mMobileContextProvider 689 .getMobileContextForSub(state.subId, mContext); 690 mDemoStatusIcons.updateMobileState(state, mobileContext); 691 } 692 } 693 694 @Override dispatchDemoCommand(String command, Bundle args)695 public void dispatchDemoCommand(String command, Bundle args) { 696 if (!mDemoable) { 697 return; 698 } 699 700 mDemoStatusIcons.dispatchDemoCommand(command, args); 701 } 702 703 @Override onDemoModeStarted()704 public void onDemoModeStarted() { 705 mIsInDemoMode = true; 706 if (mDemoStatusIcons == null) { 707 mDemoStatusIcons = createDemoStatusIcons(); 708 if (mStatusBarPipelineFlags.useNewWifiIcon()) { 709 mDemoStatusIcons.addModernWifiView(mWifiViewModel); 710 } 711 } 712 mDemoStatusIcons.onDemoModeStarted(); 713 } 714 715 @Override onDemoModeFinished()716 public void onDemoModeFinished() { 717 if (mDemoStatusIcons != null) { 718 mDemoStatusIcons.onDemoModeFinished(); 719 exitDemoMode(); 720 mIsInDemoMode = false; 721 } 722 } 723 exitDemoMode()724 protected void exitDemoMode() { 725 mDemoStatusIcons.remove(); 726 mDemoStatusIcons = null; 727 } 728 createDemoStatusIcons()729 protected DemoStatusIcons createDemoStatusIcons() { 730 return new DemoStatusIcons( 731 (LinearLayout) mGroup, 732 mMobileIconsViewModel, 733 mLocation, 734 mIconSize 735 ); 736 } 737 } 738 } 739