1 /* 2 * Copyright (C) 2016 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 static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; 20 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; 21 22 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; 23 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_TRANSPARENT; 24 25 import android.content.Context; 26 import android.graphics.Rect; 27 import android.util.Log; 28 import android.view.Display; 29 import android.view.InsetsFlags; 30 import android.view.ViewDebug; 31 import android.view.WindowInsetsController.Appearance; 32 33 import androidx.annotation.NonNull; 34 import androidx.annotation.Nullable; 35 36 import com.android.internal.colorextraction.ColorExtractor.GradientColors; 37 import com.android.internal.view.AppearanceRegion; 38 import com.android.systemui.dagger.qualifiers.Application; 39 import com.android.systemui.dagger.qualifiers.Main; 40 import com.android.systemui.dump.DumpManager; 41 import com.android.systemui.navigationbar.NavigationModeController; 42 import com.android.systemui.plugins.DarkIconDispatcher; 43 import com.android.systemui.statusbar.data.model.StatusBarAppearance; 44 import com.android.systemui.statusbar.data.repository.DarkIconDispatcherStore; 45 import com.android.systemui.statusbar.data.repository.StatusBarModePerDisplayRepository; 46 import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore; 47 import com.android.systemui.statusbar.layout.BoundsPair; 48 import com.android.systemui.statusbar.policy.BatteryController; 49 import com.android.systemui.util.Compile; 50 import com.android.systemui.util.kotlin.JavaAdapterKt; 51 52 import dagger.assisted.Assisted; 53 import dagger.assisted.AssistedFactory; 54 import dagger.assisted.AssistedInject; 55 56 import kotlin.coroutines.CoroutineContext; 57 58 import kotlinx.coroutines.CoroutineScope; 59 60 import java.io.PrintWriter; 61 import java.util.ArrayList; 62 63 import javax.inject.Inject; 64 65 /** 66 * Controls how light status bar flag applies to the icons. 67 */ 68 public class LightBarControllerImpl implements 69 BatteryController.BatteryStateChangeCallback, LightBarController { 70 71 private static final String TAG = "LightBarController"; 72 private static final boolean DEBUG_NAVBAR = Compile.IS_DEBUG; 73 private static final boolean DEBUG_LOGS = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG); 74 75 private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f; 76 77 private final int mDisplayId; 78 private final CoroutineScope mCoroutineScope; 79 private final SysuiDarkIconDispatcher mStatusBarIconController; 80 private final BatteryController mBatteryController; 81 private final NavigationModeController mNavModeController; 82 private final DumpManager mDumpManager; 83 private final StatusBarModePerDisplayRepository mStatusBarModeRepository; 84 private final CoroutineContext mMainContext; 85 private final BiometricUnlockController mBiometricUnlockController; 86 87 private LightBarTransitionsController mNavigationBarController; 88 private @Appearance int mAppearance; 89 private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0]; 90 private int mStatusBarMode; 91 private BoundsPair mStatusBarBounds = new BoundsPair(new Rect(), new Rect()); 92 private int mNavigationBarMode; 93 private int mNavigationMode; 94 95 /** 96 * Whether the navigation bar should be light factoring in already how much alpha the scrim has. 97 * "Light" refers to the background color of the navigation bar, so when this is true, 98 * it's referring to a state where the navigation bar icons are tinted dark. 99 */ 100 private boolean mNavigationLight; 101 102 /** 103 * Whether the flags indicate that a light navigation bar is requested. 104 * "Light" refers to the background color of the navigation bar, so when this is true, 105 * it's referring to a state where the navigation bar icons would be tinted dark. 106 * This doesn't factor in the scrim alpha yet. 107 */ 108 private boolean mHasLightNavigationBar; 109 110 /** 111 * {@code true} if {@link #mHasLightNavigationBar} should be ignored and forcefully make 112 * {@link #mNavigationLight} {@code false}. 113 */ 114 private boolean mForceDarkForScrim; 115 /** 116 * {@code true} if {@link #mHasLightNavigationBar} should be ignored and forcefully make 117 * {@link #mNavigationLight} {@code true}. 118 */ 119 private boolean mForceLightForScrim; 120 121 private boolean mQsCustomizing; 122 private boolean mQsExpanded; 123 private boolean mBouncerVisible; 124 private boolean mGlobalActionsVisible; 125 126 private boolean mDirectReplying; 127 private boolean mNavbarColorManagedByIme; 128 129 private boolean mIsCustomizingForBackNav; 130 131 private String mLastSetScrimStateLog; 132 private String mLastNavigationBarAppearanceChangedLog; 133 private StringBuilder mLogStringBuilder = null; 134 135 private final String mDumpableName; 136 137 private final NavigationModeController.ModeChangedListener mNavigationModeListener = 138 (mode) -> mNavigationMode = mode; 139 140 @AssistedInject LightBarControllerImpl( @ssisted int displayId, @Assisted CoroutineScope coroutineScope, @Assisted DarkIconDispatcher darkIconDispatcher, BatteryController batteryController, NavigationModeController navModeController, @Assisted StatusBarModePerDisplayRepository statusBarModeRepository, DumpManager dumpManager, @Main CoroutineContext mainContext, BiometricUnlockController biometricUnlockController)141 public LightBarControllerImpl( 142 @Assisted int displayId, 143 @Assisted CoroutineScope coroutineScope, 144 @Assisted DarkIconDispatcher darkIconDispatcher, 145 BatteryController batteryController, 146 NavigationModeController navModeController, 147 @Assisted StatusBarModePerDisplayRepository statusBarModeRepository, 148 DumpManager dumpManager, 149 @Main CoroutineContext mainContext, 150 BiometricUnlockController biometricUnlockController) { 151 mDisplayId = displayId; 152 mCoroutineScope = coroutineScope; 153 mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher; 154 mBatteryController = batteryController; 155 mNavModeController = navModeController; 156 mDumpManager = dumpManager; 157 mStatusBarModeRepository = statusBarModeRepository; 158 mMainContext = mainContext; 159 mBiometricUnlockController = biometricUnlockController; 160 String dumpableNameSuffix = 161 displayId == Display.DEFAULT_DISPLAY ? "" : String.valueOf(displayId); 162 mDumpableName = getClass().getSimpleName() + dumpableNameSuffix; 163 } 164 165 @Override start()166 public void start() { 167 if (mDisplayId == Display.DEFAULT_DISPLAY) { 168 // Can only register on default display, because NavigationBar creates its own instance 169 // as well as PerDisplayStore. 170 // TODO: b/380394368 - make sure there is only one instance per display. 171 mDumpManager.registerCriticalDumpable(mDumpableName, this); 172 } 173 mBatteryController.addCallback(this); 174 mNavigationMode = mNavModeController.addListener(mNavigationModeListener); 175 JavaAdapterKt.collectFlow( 176 mCoroutineScope, 177 mMainContext, 178 mStatusBarModeRepository.getStatusBarAppearance(), 179 this::onStatusBarAppearanceChanged); 180 } 181 182 @Override stop()183 public void stop() { 184 mDumpManager.unregisterDumpable(mDumpableName); 185 mBatteryController.removeCallback(this); 186 mNavModeController.removeListener(mNavigationModeListener); 187 } 188 189 @Override setNavigationBar(LightBarTransitionsController navigationBar)190 public void setNavigationBar(LightBarTransitionsController navigationBar) { 191 mNavigationBarController = navigationBar; 192 updateNavigation(); 193 } 194 onStatusBarAppearanceChanged(@ullable StatusBarAppearance params)195 private void onStatusBarAppearanceChanged(@Nullable StatusBarAppearance params) { 196 if (params == null) { 197 return; 198 } 199 int newStatusBarMode = params.getMode().toTransitionModeInt(); 200 boolean sbModeChanged = mStatusBarMode != newStatusBarMode; 201 mStatusBarMode = newStatusBarMode; 202 203 boolean sbBoundsChanged = !mStatusBarBounds.equals(params.getBounds()); 204 mStatusBarBounds = params.getBounds(); 205 206 onStatusBarAppearanceChanged( 207 params.getAppearanceRegions().toArray(new AppearanceRegion[0]), 208 sbModeChanged, 209 sbBoundsChanged, 210 params.getNavbarColorManagedByIme()); 211 } 212 onStatusBarAppearanceChanged( AppearanceRegion[] appearanceRegions, boolean sbModeChanged, boolean sbBoundsChanged, boolean navbarColorManagedByIme)213 private void onStatusBarAppearanceChanged( 214 AppearanceRegion[] appearanceRegions, 215 boolean sbModeChanged, 216 boolean sbBoundsChanged, 217 boolean navbarColorManagedByIme) { 218 final int numStacks = appearanceRegions.length; 219 boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks; 220 for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) { 221 stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]); 222 } 223 224 if (stackAppearancesChanged 225 || sbModeChanged 226 // Be sure to re-draw when the status bar bounds have changed because the status bar 227 // icons may have moved to be part of a different appearance region. See b/301605450 228 || sbBoundsChanged 229 || mIsCustomizingForBackNav) { 230 mAppearanceRegions = appearanceRegions; 231 updateStatus(mAppearanceRegions); 232 mIsCustomizingForBackNav = false; 233 } 234 mNavbarColorManagedByIme = navbarColorManagedByIme; 235 } 236 237 @Override onNavigationBarAppearanceChanged(@ppearance int appearance, boolean nbModeChanged, int navigationBarMode, boolean navbarColorManagedByIme)238 public void onNavigationBarAppearanceChanged(@Appearance int appearance, boolean nbModeChanged, 239 int navigationBarMode, boolean navbarColorManagedByIme) { 240 int diff = appearance ^ mAppearance; 241 if ((diff & APPEARANCE_LIGHT_NAVIGATION_BARS) != 0 || nbModeChanged) { 242 final boolean last = mNavigationLight; 243 mHasLightNavigationBar = isLight(appearance, navigationBarMode, 244 APPEARANCE_LIGHT_NAVIGATION_BARS); 245 final boolean ignoreScrimForce = mDirectReplying && mNavbarColorManagedByIme; 246 final boolean darkForScrim = mForceDarkForScrim && !ignoreScrimForce; 247 final boolean lightForScrim = mForceLightForScrim && !ignoreScrimForce; 248 final boolean darkForQs = (mQsCustomizing || mQsExpanded) && !mBouncerVisible; 249 final boolean darkForTop = darkForQs || mGlobalActionsVisible; 250 mNavigationLight = 251 ((mHasLightNavigationBar && !darkForScrim) || lightForScrim) && !darkForTop; 252 if (DEBUG_NAVBAR) { 253 mLastNavigationBarAppearanceChangedLog = getLogStringBuilder() 254 .append("onNavigationBarAppearanceChanged()") 255 .append(" appearance=").append(appearance) 256 .append(" nbModeChanged=").append(nbModeChanged) 257 .append(" navigationBarMode=").append(navigationBarMode) 258 .append(" navbarColorManagedByIme=").append(navbarColorManagedByIme) 259 .append(" mHasLightNavigationBar=").append(mHasLightNavigationBar) 260 .append(" ignoreScrimForce=").append(ignoreScrimForce) 261 .append(" darkForScrim=").append(darkForScrim) 262 .append(" lightForScrim=").append(lightForScrim) 263 .append(" darkForQs=").append(darkForQs) 264 .append(" darkForTop=").append(darkForTop) 265 .append(" mNavigationLight=").append(mNavigationLight) 266 .append(" last=").append(last) 267 .append(" timestamp=").append(System.currentTimeMillis()) 268 .toString(); 269 if (DEBUG_LOGS) Log.d(TAG, mLastNavigationBarAppearanceChangedLog); 270 } 271 if (mNavigationLight != last) { 272 updateNavigation(); 273 } 274 } 275 mAppearance = appearance; 276 mNavigationBarMode = navigationBarMode; 277 mNavbarColorManagedByIme = navbarColorManagedByIme; 278 } 279 280 @Override onNavigationBarModeChanged(int newBarMode)281 public void onNavigationBarModeChanged(int newBarMode) { 282 mHasLightNavigationBar = isLight(mAppearance, newBarMode, APPEARANCE_LIGHT_NAVIGATION_BARS); 283 } 284 reevaluate()285 private void reevaluate() { 286 onStatusBarAppearanceChanged( 287 mAppearanceRegions, 288 /* sbModeChanged= */ true, 289 /* sbBoundsChanged= */ true, 290 mNavbarColorManagedByIme); 291 onNavigationBarAppearanceChanged(mAppearance, true /* nbModeChanged */, 292 mNavigationBarMode, mNavbarColorManagedByIme); 293 } 294 295 @Override setQsCustomizing(boolean customizing)296 public void setQsCustomizing(boolean customizing) { 297 if (mQsCustomizing == customizing) return; 298 mQsCustomizing = customizing; 299 reevaluate(); 300 } 301 302 @Override setQsExpanded(boolean expanded)303 public void setQsExpanded(boolean expanded) { 304 if (mQsExpanded == expanded) return; 305 mQsExpanded = expanded; 306 reevaluate(); 307 } 308 309 @Override setGlobalActionsVisible(boolean visible)310 public void setGlobalActionsVisible(boolean visible) { 311 if (mGlobalActionsVisible == visible) return; 312 mGlobalActionsVisible = visible; 313 reevaluate(); 314 } 315 316 @Override customizeStatusBarAppearance(AppearanceRegion appearance)317 public void customizeStatusBarAppearance(AppearanceRegion appearance) { 318 if (appearance != null) { 319 final ArrayList<AppearanceRegion> appearancesList = new ArrayList<>(); 320 appearancesList.add(appearance); 321 for (int i = 0; i < mAppearanceRegions.length; i++) { 322 final AppearanceRegion ar = mAppearanceRegions[i]; 323 if (appearance.getBounds().contains(ar.getBounds())) { 324 continue; 325 } 326 appearancesList.add(ar); 327 } 328 329 final AppearanceRegion[] newAppearances = new AppearanceRegion[appearancesList.size()]; 330 updateStatus(appearancesList.toArray(newAppearances)); 331 mIsCustomizingForBackNav = true; 332 } else { 333 mIsCustomizingForBackNav = false; 334 updateStatus(mAppearanceRegions); 335 } 336 } 337 338 @Override setDirectReplying(boolean directReplying)339 public void setDirectReplying(boolean directReplying) { 340 if (mDirectReplying == directReplying) return; 341 mDirectReplying = directReplying; 342 reevaluate(); 343 } 344 345 @Override setScrimState(ScrimState scrimState, float scrimBehindAlpha, GradientColors scrimInFrontColor)346 public void setScrimState(ScrimState scrimState, float scrimBehindAlpha, 347 GradientColors scrimInFrontColor) { 348 boolean bouncerVisibleLast = mBouncerVisible; 349 boolean forceDarkForScrimLast = mForceDarkForScrim; 350 boolean forceLightForScrimLast = mForceLightForScrim; 351 mBouncerVisible = 352 scrimState == ScrimState.BOUNCER || scrimState == ScrimState.BOUNCER_SCRIMMED; 353 final boolean forceForScrim = mBouncerVisible 354 || scrimBehindAlpha >= NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD; 355 final boolean scrimColorIsLight = scrimInFrontColor.supportsDarkText(); 356 357 mForceDarkForScrim = forceForScrim && !scrimColorIsLight; 358 mForceLightForScrim = forceForScrim && scrimColorIsLight; 359 if (mBouncerVisible != bouncerVisibleLast) { 360 reevaluate(); 361 } else if (mHasLightNavigationBar) { 362 if (mForceDarkForScrim != forceDarkForScrimLast) reevaluate(); 363 } else { 364 if (mForceLightForScrim != forceLightForScrimLast) reevaluate(); 365 } 366 if (DEBUG_NAVBAR) { 367 mLastSetScrimStateLog = getLogStringBuilder() 368 .append("setScrimState()") 369 .append(" scrimState=").append(scrimState) 370 .append(" scrimBehindAlpha=").append(scrimBehindAlpha) 371 .append(" scrimInFrontColor=").append(scrimInFrontColor) 372 .append(" forceForScrim=").append(forceForScrim) 373 .append(" scrimColorIsLight=").append(scrimColorIsLight) 374 .append(" mHasLightNavigationBar=").append(mHasLightNavigationBar) 375 .append(" mBouncerVisible=").append(mBouncerVisible) 376 .append(" mForceDarkForScrim=").append(mForceDarkForScrim) 377 .append(" mForceLightForScrim=").append(mForceLightForScrim) 378 .append(" timestamp=").append(System.currentTimeMillis()) 379 .toString(); 380 if (DEBUG_LOGS) Log.d(TAG, mLastSetScrimStateLog); 381 } 382 } 383 384 @NonNull getLogStringBuilder()385 private StringBuilder getLogStringBuilder() { 386 if (mLogStringBuilder == null) { 387 mLogStringBuilder = new StringBuilder(); 388 } 389 mLogStringBuilder.setLength(0); 390 return mLogStringBuilder; 391 } 392 isLight(int appearance, int barMode, int flag)393 private static boolean isLight(int appearance, int barMode, int flag) { 394 final boolean isTransparentBar = (barMode == MODE_TRANSPARENT 395 || barMode == MODE_LIGHTS_OUT_TRANSPARENT); 396 final boolean light = (appearance & flag) != 0; 397 return isTransparentBar && light; 398 } 399 animateChange()400 private boolean animateChange() { 401 int unlockMode = mBiometricUnlockController.getMode(); 402 return unlockMode != BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING 403 && unlockMode != BiometricUnlockController.MODE_WAKE_AND_UNLOCK; 404 } 405 updateStatus(AppearanceRegion[] appearanceRegions)406 private void updateStatus(AppearanceRegion[] appearanceRegions) { 407 final int numStacks = appearanceRegions.length; 408 final ArrayList<Rect> lightBarBounds = new ArrayList<>(); 409 410 for (int i = 0; i < numStacks; i++) { 411 final AppearanceRegion ar = appearanceRegions[i]; 412 if (isLight(ar.getAppearance(), mStatusBarMode, APPEARANCE_LIGHT_STATUS_BARS)) { 413 lightBarBounds.add(ar.getBounds()); 414 } 415 } 416 417 if (lightBarBounds.isEmpty()) { 418 // If no one is light, all icons become white. 419 mStatusBarIconController 420 .getTransitionsController() 421 .setIconsDark(false, animateChange()); 422 } else if (lightBarBounds.size() == numStacks) { 423 // If all stacks are light, all icons get dark. 424 mStatusBarIconController.setIconsDarkArea(null); 425 mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange()); 426 } else { 427 // Not the same for every stack, magic! 428 mStatusBarIconController.setIconsDarkArea(lightBarBounds); 429 mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange()); 430 } 431 } 432 updateNavigation()433 private void updateNavigation() { 434 if (mNavigationBarController != null 435 && mNavigationBarController.supportsIconTintForNavMode(mNavigationMode)) { 436 mNavigationBarController.setIconsDark(mNavigationLight, animateChange()); 437 } 438 } 439 440 @Override onPowerSaveChanged(boolean isPowerSave)441 public void onPowerSaveChanged(boolean isPowerSave) { 442 reevaluate(); 443 } 444 445 @Override dump(PrintWriter pw, String[] args)446 public void dump(PrintWriter pw, String[] args) { 447 pw.println("LightBarController: "); 448 pw.print(" mAppearance="); pw.println(ViewDebug.flagsToString( 449 InsetsFlags.class, "appearance", mAppearance)); 450 final int numStacks = mAppearanceRegions.length; 451 for (int i = 0; i < numStacks; i++) { 452 final boolean isLight = isLight(mAppearanceRegions[i].getAppearance(), mStatusBarMode, 453 APPEARANCE_LIGHT_STATUS_BARS); 454 pw.print(" stack #"); pw.print(i); pw.print(": "); 455 pw.print(mAppearanceRegions[i].toString()); pw.print(" isLight="); pw.println(isLight); 456 } 457 458 pw.print(" mNavigationLight="); pw.println(mNavigationLight); 459 pw.print(" mHasLightNavigationBar="); pw.println(mHasLightNavigationBar); 460 pw.println(); 461 pw.print(" mStatusBarMode="); pw.print(mStatusBarMode); 462 pw.print(" mNavigationBarMode="); pw.println(mNavigationBarMode); 463 pw.println(); 464 pw.print(" mForceDarkForScrim="); pw.println(mForceDarkForScrim); 465 pw.print(" mForceLightForScrim="); pw.println(mForceLightForScrim); 466 pw.println(); 467 pw.print(" mQsCustomizing="); pw.println(mQsCustomizing); 468 pw.print(" mQsExpanded="); pw.println(mQsExpanded); 469 pw.print(" mBouncerVisible="); pw.println(mBouncerVisible); 470 pw.print(" mGlobalActionsVisible="); pw.println(mGlobalActionsVisible); 471 pw.print(" mDirectReplying="); pw.println(mDirectReplying); 472 pw.print(" mNavbarColorManagedByIme="); pw.println(mNavbarColorManagedByIme); 473 pw.println(); 474 pw.println(" Recent Calculation Logs:"); 475 pw.print(" "); pw.println(mLastSetScrimStateLog); 476 pw.print(" "); pw.println(mLastNavigationBarAppearanceChangedLog); 477 478 pw.println(); 479 480 LightBarTransitionsController transitionsController = 481 mStatusBarIconController.getTransitionsController(); 482 if (transitionsController != null) { 483 pw.println(" StatusBarTransitionsController:"); 484 transitionsController.dump(pw, args); 485 pw.println(); 486 } 487 488 if (mNavigationBarController != null) { 489 pw.println(" NavigationBarTransitionsController:"); 490 mNavigationBarController.dump(pw, args); 491 pw.println(); 492 } 493 } 494 495 /** Injectable factory for creating a {@link LightBarControllerImpl}. */ 496 @AssistedFactory 497 @FunctionalInterface 498 public interface Factory { 499 500 /** Creates a {@link LightBarControllerImpl}. */ create( int displayId, @NonNull CoroutineScope coroutineScope, @NonNull DarkIconDispatcher darkIconDispatcher, @NonNull StatusBarModePerDisplayRepository statusBarModePerDisplayRepository)501 LightBarControllerImpl create( 502 int displayId, 503 @NonNull CoroutineScope coroutineScope, 504 @NonNull DarkIconDispatcher darkIconDispatcher, 505 @NonNull StatusBarModePerDisplayRepository statusBarModePerDisplayRepository); 506 } 507 508 public static class LegacyFactory implements LightBarController.Factory { 509 510 private final Factory mFactory; 511 private final CoroutineScope mApplicationScope; 512 private final DarkIconDispatcherStore mDarkIconDispatcherStore; 513 private final StatusBarModeRepositoryStore mStatusBarModeRepositoryStore; 514 515 @Inject LegacyFactory( LightBarControllerImpl.Factory factory, @Application CoroutineScope applicationScope, DarkIconDispatcherStore darkIconDispatcherStore, StatusBarModeRepositoryStore statusBarModeRepositoryStore)516 public LegacyFactory( 517 LightBarControllerImpl.Factory factory, 518 @Application CoroutineScope applicationScope, 519 DarkIconDispatcherStore darkIconDispatcherStore, 520 StatusBarModeRepositoryStore statusBarModeRepositoryStore) { 521 mFactory = factory; 522 mApplicationScope = applicationScope; 523 mDarkIconDispatcherStore = darkIconDispatcherStore; 524 mStatusBarModeRepositoryStore = statusBarModeRepositoryStore; 525 } 526 527 @NonNull 528 @Override create(@onNull Context context)529 public LightBarController create(@NonNull Context context) { 530 // TODO: b/380394368 - Make sure correct per display instances are used. 531 LightBarControllerImpl lightBarController = mFactory.create( 532 context.getDisplayId(), 533 mApplicationScope, 534 mDarkIconDispatcherStore.getDefaultDisplay(), 535 mStatusBarModeRepositoryStore.getDefaultDisplay() 536 ); 537 // Calling start() manually to keep the legacy behavior. Before, LightBarControllerImpl 538 // was doing work in the constructor, which moved to start(). 539 lightBarController.start(); 540 return lightBarController; 541 } 542 } 543 } 544