1 /* <lambda>null2 * Copyright (C) 2025 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.pipeline.battery.domain.interactor 18 19 import com.android.systemui.dagger.SysUISingleton 20 import com.android.systemui.statusbar.pipeline.battery.data.repository.BatteryRepository 21 import javax.inject.Inject 22 import kotlinx.coroutines.flow.combine 23 import kotlinx.coroutines.flow.filterNotNull 24 import kotlinx.coroutines.flow.map 25 26 @SysUISingleton 27 class BatteryInteractor @Inject constructor(repo: BatteryRepository) { 28 /** The current level in the range of [0-100] */ 29 val level = repo.level.filterNotNull() 30 31 /** Whether the battery has been fully charged */ 32 val isFull = level.map { isBatteryFull(it) } 33 34 /** 35 * For the sake of battery views, consider it to be "charging" if plugged in. This allows users 36 * to easily confirm that the device is properly plugged in, even if its' technically not 37 * charging due to issues with the source. 38 */ 39 val isCharging = repo.isPluggedIn 40 41 /** 42 * The critical level (see [CRITICAL_LEVEL]) defines the level below which we might want to 43 * display an error UI. E.g., show the battery as red. 44 */ 45 val isCritical = level.map { it <= CRITICAL_LEVEL } 46 47 /** @see [BatteryRepository.isStateUnknown] for docs. The battery cannot be detected */ 48 val isStateUnknown = repo.isStateUnknown 49 50 /** @see [BatteryRepository.isBatteryDefenderEnabled] */ 51 val isBatteryDefenderEnabled = repo.isBatteryDefenderEnabled 52 53 /** @see [BatteryRepository.isPowerSaveEnabled] */ 54 val powerSave = repo.isPowerSaveEnabled 55 56 /** @see [BatteryRepository.isShowBatteryPercentSettingEnabled] */ 57 val isBatteryPercentSettingEnabled = repo.isShowBatteryPercentSettingEnabled 58 59 /** 60 * The battery attribution (@see [BatteryAttributionModel]) describes the attribution that best 61 * represents the current battery charging state. If charging, the attribution is 62 * [BatteryAttributionModel.Charging], etc. 63 * 64 * This flow can be used to canonically describe the battery state charging state. 65 */ 66 val batteryAttributionType = 67 combine(isCharging, powerSave, isBatteryDefenderEnabled) { charging, powerSave, defend -> 68 if (powerSave) { 69 BatteryAttributionModel.PowerSave 70 } else if (defend) { 71 BatteryAttributionModel.Defend 72 } else if (charging) { 73 BatteryAttributionModel.Charging 74 } else { 75 null 76 } 77 } 78 79 /** @see [BatteryRepository.batteryTimeRemainingEstimate] */ 80 val batteryTimeRemainingEstimate = repo.batteryTimeRemainingEstimate 81 82 companion object { 83 /** Level below which we consider to be critically low */ 84 private const val CRITICAL_LEVEL = 20 85 86 fun isBatteryFull(level: Int) = level >= 100 87 } 88 } 89 90 /** The charging state, and therefore attribution for the battery */ 91 enum class BatteryAttributionModel { 92 Defend, 93 PowerSave, 94 Charging, 95 } 96