Loading packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt +9 −8 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.demomode.DemoMode import com.android.systemui.demomode.DemoModeController import com.android.systemui.dump.DumpManager import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.plugins.ActivityStarter import com.android.systemui.qs.ChipVisibilityListener import com.android.systemui.qs.HeaderPrivacyIconsController Loading @@ -82,7 +83,7 @@ import com.android.systemui.statusbar.phone.domain.interactor.IsAreaDark import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithChargeStatus import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithEstimate import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithPercent import com.android.systemui.statusbar.pipeline.battery.ui.composable.ShowPercentMode import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryNextToPercentViewModel import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel Loading Loading @@ -122,7 +123,7 @@ constructor( private val shadeDisplaysRepositoryLazy: Lazy<ShadeDisplaysRepository>, private val variableDateViewControllerFactory: VariableDateViewController.Factory, @Named(SHADE_HEADER) private val batteryMeterViewController: BatteryMeterViewController, private val unifiedBatteryViewModelFactory: BatteryViewModel.AlwaysShowPercent.Factory, private val unifiedBatteryViewModelFactory: BatteryViewModel.BasedOnUserSetting.Factory, private val tandemBatteryViewModelFactory: BatteryNextToPercentViewModel.Factory, private val dumpManager: DumpManager, private val shadeCarrierGroupControllerBuilder: ShadeCarrierGroupController.Builder, Loading Loading @@ -448,14 +449,14 @@ constructor( id = R.id.battery_meter_composable_view val showBatteryEstimate by showBatteryEstimate.collectAsStateWithLifecycle() val dark = isSystemInDarkTheme() BatteryWithEstimate( val viewModel = rememberViewModel(traceName = "UnifiedBattery") { unifiedBatteryViewModelFactory.create() } BatteryWithPercent( modifier = Modifier.wrapContentSize(), viewModelFactory = unifiedBatteryViewModelFactory, viewModel = viewModel, isDarkProvider = { IsAreaDark { dark } }, textColor = if (notificationShadeBlur()) Color(context.getColor(R.color.shade_header_text_color)) else Color.White, showPercent = viewModel.isBatteryPercentSettingEnabled, showEstimate = showBatteryEstimate, ) } Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +2 −2 Original line number Diff line number Diff line Loading @@ -143,7 +143,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat private final TintedIconManager.Factory mTintedIconManagerFactory; private final BatteryMeterViewController mBatteryMeterViewController; private final BatteryNextToPercentViewModel.Factory mTandemBatteryViewModelFactory; private final BatteryViewModel.ShowPercentWhenChargingOrSetting.Factory mBatteryViewModel; private final BatteryViewModel.BasedOnUserSetting.Factory mBatteryViewModel; private final ShadeViewStateProvider mShadeViewStateProvider; private final KeyguardStateController mKeyguardStateController; private final KeyguardBypassController mKeyguardBypassController; Loading Loading @@ -365,7 +365,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat TintedIconManager.Factory tintedIconManagerFactory, BatteryMeterViewController batteryMeterViewController, BatteryNextToPercentViewModel.Factory tandemBatteryViewModelFactory, BatteryViewModel.ShowPercentWhenChargingOrSetting.Factory batteryViewModel, BatteryViewModel.BasedOnUserSetting.Factory batteryViewModel, ShadeViewStateProvider shadeViewStateProvider, KeyguardStateController keyguardStateController, KeyguardBypassController bypassController, Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/data/repository/BatteryRepository.kt +52 −13 Original line number Diff line number Diff line Loading @@ -17,7 +17,10 @@ package com.android.systemui.statusbar.pipeline.battery.data.repository import android.content.Context import android.provider.Settings import android.database.ContentObserver import android.os.Handler import android.os.Looper import android.os.UserHandle import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background Loading @@ -34,12 +37,15 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.scan import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.suspendCancellableCoroutine import lineageos.providers.LineageSettings /** Repository-style state for battery information. */ interface BatteryRepository { Loading @@ -64,10 +70,16 @@ interface BatteryRepository { val isStateUnknown: Flow<Boolean> /** * [Settings.System.SHOW_BATTERY_PERCENT]. A user setting to indicate whether we should show the * battery percentage in the home screen status bar * [LineageSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT]. A user setting to indicate whether * we should show the battery percentage in the home screen status bar */ val isShowBatteryPercentSettingEnabled: StateFlow<Boolean> val showBatteryPercentMode: StateFlow<Int> companion object { const val SHOW_PERCENT_HIDDEN = 0 const val SHOW_PERCENT_INSIDE = 1 const val SHOW_PERCENT_NEXT_TO = 2 } /** * If available, this flow yields a string that describes the approximate time remaining for the Loading Loading @@ -153,16 +165,43 @@ constructor( override val isStateUnknown = batteryState.map { it.isStateUnknown } override val isShowBatteryPercentSettingEnabled = run { val default = context.resources.getBoolean( com.android.internal.R.bool.config_defaultBatteryPercentageSetting override val showBatteryPercentMode = callbackFlow { val resolver = context.contentResolver val uri = LineageSettings.System.getUriFor( LineageSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT ) settingsRepository .boolSetting(name = Settings.System.SHOW_BATTERY_PERCENT, defaultValue = default) .flowOn(bgDispatcher) .stateIn(scope, SharingStarted.Lazily, default) fun readMode(): Int { return LineageSettings.System.getIntForUser( resolver, LineageSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, BatteryRepository.SHOW_PERCENT_HIDDEN, UserHandle.USER_CURRENT ) } val observer = object : ContentObserver(Handler(Looper.getMainLooper())) { override fun onChange(selfChange: Boolean) { trySend(readMode()) } } resolver.registerContentObserver(uri, /* notifyForDescendants = */ false, observer, UserHandle.USER_ALL) // Emit current value immediately trySend(readMode()) awaitClose { resolver.unregisterContentObserver(observer) } } .distinctUntilChanged() .flowOn(bgDispatcher) .stateIn( scope = scope, started = SharingStarted.Lazily, initialValue = BatteryRepository.SHOW_PERCENT_HIDDEN ) /** Get and re-fetch the estimate every 2 minutes while active */ private val estimate: Flow<String?> = flow { Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/domain/interactor/BatteryInteractor.kt +23 −3 Original line number Diff line number Diff line Loading @@ -17,15 +17,23 @@ package com.android.systemui.statusbar.pipeline.battery.domain.interactor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.statusbar.pipeline.battery.data.repository.BatteryRepository import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class BatteryInteractor @Inject constructor(repo: BatteryRepository) { class BatteryInteractor @Inject constructor( private val repo: BatteryRepository, @Background private val appScope: CoroutineScope, ) { /** The current level in the range of [0-100], or null if we don't know the level yet */ val level = combine(repo.isStateUnknown, repo.level) { unknown, level -> Loading Loading @@ -66,8 +74,20 @@ class BatteryInteractor @Inject constructor(repo: BatteryRepository) { /** @see [BatteryRepository.isPowerSaveEnabled] */ val powerSave = repo.isPowerSaveEnabled /** @see [BatteryRepository.isShowBatteryPercentSettingEnabled] */ val isBatteryPercentSettingEnabled = repo.isShowBatteryPercentSettingEnabled /** @see [BatteryRepository.showBatteryPercentMode] */ val showBatteryPercentMode: StateFlow<Int> = repo.showBatteryPercentMode // Mode == 1 val showPercentInsideIcon: StateFlow<Boolean> = repo.showBatteryPercentMode .map { it == BatteryRepository.SHOW_PERCENT_INSIDE } .stateIn(appScope, SharingStarted.Lazily, false) // Mode == 2 val showPercentNextToIcon: StateFlow<Boolean> = repo.showBatteryPercentMode .map { it == BatteryRepository.SHOW_PERCENT_NEXT_TO } .stateIn(appScope, SharingStarted.Lazily, false) /** * The battery attribution (@see [BatteryAttributionModel]) describes the attribution that best Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/ui/binder/UnifiedBatteryViewBinder.kt +4 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.statusbar.pipeline.battery.ui.binder import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier Loading @@ -32,9 +31,8 @@ import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.phone.domain.interactor.IsAreaDark import com.android.systemui.statusbar.pipeline.battery.ui.composable.UnifiedBattery import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithPercent import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel.Companion.STATUS_BAR_BATTERY_HEIGHT import kotlinx.coroutines.flow.Flow /** In cases where the battery needs to be bound to an existing android view */ Loading @@ -61,15 +59,14 @@ object UnifiedBatteryViewBinder { } val isDark by isAreaDark.collectAsStateWithLifecycle(IsAreaDark { true }) val height = with(LocalDensity.current) { STATUS_BAR_BATTERY_HEIGHT.toDp() } UnifiedBattery( BatteryWithPercent( modifier = Modifier.height(height) Modifier .wrapContentWidth() .sysuiResTag(BatteryViewModel.TEST_TAG), viewModel = viewModel, isDarkProvider = { isDark }, showPercent = viewModel.isBatteryPercentSettingEnabled, ) } } Loading Loading
packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt +9 −8 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.demomode.DemoMode import com.android.systemui.demomode.DemoModeController import com.android.systemui.dump.DumpManager import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.plugins.ActivityStarter import com.android.systemui.qs.ChipVisibilityListener import com.android.systemui.qs.HeaderPrivacyIconsController Loading @@ -82,7 +83,7 @@ import com.android.systemui.statusbar.phone.domain.interactor.IsAreaDark import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithChargeStatus import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithEstimate import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithPercent import com.android.systemui.statusbar.pipeline.battery.ui.composable.ShowPercentMode import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryNextToPercentViewModel import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel Loading Loading @@ -122,7 +123,7 @@ constructor( private val shadeDisplaysRepositoryLazy: Lazy<ShadeDisplaysRepository>, private val variableDateViewControllerFactory: VariableDateViewController.Factory, @Named(SHADE_HEADER) private val batteryMeterViewController: BatteryMeterViewController, private val unifiedBatteryViewModelFactory: BatteryViewModel.AlwaysShowPercent.Factory, private val unifiedBatteryViewModelFactory: BatteryViewModel.BasedOnUserSetting.Factory, private val tandemBatteryViewModelFactory: BatteryNextToPercentViewModel.Factory, private val dumpManager: DumpManager, private val shadeCarrierGroupControllerBuilder: ShadeCarrierGroupController.Builder, Loading Loading @@ -448,14 +449,14 @@ constructor( id = R.id.battery_meter_composable_view val showBatteryEstimate by showBatteryEstimate.collectAsStateWithLifecycle() val dark = isSystemInDarkTheme() BatteryWithEstimate( val viewModel = rememberViewModel(traceName = "UnifiedBattery") { unifiedBatteryViewModelFactory.create() } BatteryWithPercent( modifier = Modifier.wrapContentSize(), viewModelFactory = unifiedBatteryViewModelFactory, viewModel = viewModel, isDarkProvider = { IsAreaDark { dark } }, textColor = if (notificationShadeBlur()) Color(context.getColor(R.color.shade_header_text_color)) else Color.White, showPercent = viewModel.isBatteryPercentSettingEnabled, showEstimate = showBatteryEstimate, ) } Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +2 −2 Original line number Diff line number Diff line Loading @@ -143,7 +143,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat private final TintedIconManager.Factory mTintedIconManagerFactory; private final BatteryMeterViewController mBatteryMeterViewController; private final BatteryNextToPercentViewModel.Factory mTandemBatteryViewModelFactory; private final BatteryViewModel.ShowPercentWhenChargingOrSetting.Factory mBatteryViewModel; private final BatteryViewModel.BasedOnUserSetting.Factory mBatteryViewModel; private final ShadeViewStateProvider mShadeViewStateProvider; private final KeyguardStateController mKeyguardStateController; private final KeyguardBypassController mKeyguardBypassController; Loading Loading @@ -365,7 +365,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat TintedIconManager.Factory tintedIconManagerFactory, BatteryMeterViewController batteryMeterViewController, BatteryNextToPercentViewModel.Factory tandemBatteryViewModelFactory, BatteryViewModel.ShowPercentWhenChargingOrSetting.Factory batteryViewModel, BatteryViewModel.BasedOnUserSetting.Factory batteryViewModel, ShadeViewStateProvider shadeViewStateProvider, KeyguardStateController keyguardStateController, KeyguardBypassController bypassController, Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/data/repository/BatteryRepository.kt +52 −13 Original line number Diff line number Diff line Loading @@ -17,7 +17,10 @@ package com.android.systemui.statusbar.pipeline.battery.data.repository import android.content.Context import android.provider.Settings import android.database.ContentObserver import android.os.Handler import android.os.Looper import android.os.UserHandle import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background Loading @@ -34,12 +37,15 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.scan import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.suspendCancellableCoroutine import lineageos.providers.LineageSettings /** Repository-style state for battery information. */ interface BatteryRepository { Loading @@ -64,10 +70,16 @@ interface BatteryRepository { val isStateUnknown: Flow<Boolean> /** * [Settings.System.SHOW_BATTERY_PERCENT]. A user setting to indicate whether we should show the * battery percentage in the home screen status bar * [LineageSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT]. A user setting to indicate whether * we should show the battery percentage in the home screen status bar */ val isShowBatteryPercentSettingEnabled: StateFlow<Boolean> val showBatteryPercentMode: StateFlow<Int> companion object { const val SHOW_PERCENT_HIDDEN = 0 const val SHOW_PERCENT_INSIDE = 1 const val SHOW_PERCENT_NEXT_TO = 2 } /** * If available, this flow yields a string that describes the approximate time remaining for the Loading Loading @@ -153,16 +165,43 @@ constructor( override val isStateUnknown = batteryState.map { it.isStateUnknown } override val isShowBatteryPercentSettingEnabled = run { val default = context.resources.getBoolean( com.android.internal.R.bool.config_defaultBatteryPercentageSetting override val showBatteryPercentMode = callbackFlow { val resolver = context.contentResolver val uri = LineageSettings.System.getUriFor( LineageSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT ) settingsRepository .boolSetting(name = Settings.System.SHOW_BATTERY_PERCENT, defaultValue = default) .flowOn(bgDispatcher) .stateIn(scope, SharingStarted.Lazily, default) fun readMode(): Int { return LineageSettings.System.getIntForUser( resolver, LineageSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, BatteryRepository.SHOW_PERCENT_HIDDEN, UserHandle.USER_CURRENT ) } val observer = object : ContentObserver(Handler(Looper.getMainLooper())) { override fun onChange(selfChange: Boolean) { trySend(readMode()) } } resolver.registerContentObserver(uri, /* notifyForDescendants = */ false, observer, UserHandle.USER_ALL) // Emit current value immediately trySend(readMode()) awaitClose { resolver.unregisterContentObserver(observer) } } .distinctUntilChanged() .flowOn(bgDispatcher) .stateIn( scope = scope, started = SharingStarted.Lazily, initialValue = BatteryRepository.SHOW_PERCENT_HIDDEN ) /** Get and re-fetch the estimate every 2 minutes while active */ private val estimate: Flow<String?> = flow { Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/domain/interactor/BatteryInteractor.kt +23 −3 Original line number Diff line number Diff line Loading @@ -17,15 +17,23 @@ package com.android.systemui.statusbar.pipeline.battery.domain.interactor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.statusbar.pipeline.battery.data.repository.BatteryRepository import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class BatteryInteractor @Inject constructor(repo: BatteryRepository) { class BatteryInteractor @Inject constructor( private val repo: BatteryRepository, @Background private val appScope: CoroutineScope, ) { /** The current level in the range of [0-100], or null if we don't know the level yet */ val level = combine(repo.isStateUnknown, repo.level) { unknown, level -> Loading Loading @@ -66,8 +74,20 @@ class BatteryInteractor @Inject constructor(repo: BatteryRepository) { /** @see [BatteryRepository.isPowerSaveEnabled] */ val powerSave = repo.isPowerSaveEnabled /** @see [BatteryRepository.isShowBatteryPercentSettingEnabled] */ val isBatteryPercentSettingEnabled = repo.isShowBatteryPercentSettingEnabled /** @see [BatteryRepository.showBatteryPercentMode] */ val showBatteryPercentMode: StateFlow<Int> = repo.showBatteryPercentMode // Mode == 1 val showPercentInsideIcon: StateFlow<Boolean> = repo.showBatteryPercentMode .map { it == BatteryRepository.SHOW_PERCENT_INSIDE } .stateIn(appScope, SharingStarted.Lazily, false) // Mode == 2 val showPercentNextToIcon: StateFlow<Boolean> = repo.showBatteryPercentMode .map { it == BatteryRepository.SHOW_PERCENT_NEXT_TO } .stateIn(appScope, SharingStarted.Lazily, false) /** * The battery attribution (@see [BatteryAttributionModel]) describes the attribution that best Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/ui/binder/UnifiedBatteryViewBinder.kt +4 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.statusbar.pipeline.battery.ui.binder import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier Loading @@ -32,9 +31,8 @@ import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.phone.domain.interactor.IsAreaDark import com.android.systemui.statusbar.pipeline.battery.ui.composable.UnifiedBattery import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithPercent import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel.Companion.STATUS_BAR_BATTERY_HEIGHT import kotlinx.coroutines.flow.Flow /** In cases where the battery needs to be bound to an existing android view */ Loading @@ -61,15 +59,14 @@ object UnifiedBatteryViewBinder { } val isDark by isAreaDark.collectAsStateWithLifecycle(IsAreaDark { true }) val height = with(LocalDensity.current) { STATUS_BAR_BATTERY_HEIGHT.toDp() } UnifiedBattery( BatteryWithPercent( modifier = Modifier.height(height) Modifier .wrapContentWidth() .sysuiResTag(BatteryViewModel.TEST_TAG), viewModel = viewModel, isDarkProvider = { isDark }, showPercent = viewModel.isBatteryPercentSettingEnabled, ) } } Loading