1 package com.android.systemui.shade 2 3 import android.content.Context 4 import android.view.DisplayCutout 5 import com.android.systemui.battery.BatteryMeterView 6 import com.android.systemui.res.R 7 import com.android.systemui.statusbar.data.repository.StatusBarContentInsetsProviderStore 8 import javax.inject.Inject 9 10 /** 11 * Controls [BatteryMeterView.BatteryPercentMode]. It takes into account cutout and qs-qqs 12 * transition fraction when determining the mode. 13 */ 14 class QsBatteryModeController 15 @Inject 16 constructor( 17 @ShadeDisplayAware private val context: Context, 18 insetsProviderStore: StatusBarContentInsetsProviderStore, 19 ) { 20 21 private val insetsProvider = insetsProviderStore.defaultDisplay 22 23 private companion object { 24 // MotionLayout frames are in [0, 100]. Where 0 and 100 are reserved for start and end 25 // frames. 26 const val MOTION_LAYOUT_MAX_FRAME = 100 27 // We add a single buffer frame to ensure that battery view faded out completely when we are 28 // about to change it's state 29 const val BUFFER_FRAME_COUNT = 1 30 } 31 32 private var fadeInStartFraction: Float = 0f 33 private var fadeOutCompleteFraction: Float = 0f 34 35 init { 36 updateResources() 37 } 38 39 /** 40 * Returns an appropriate [BatteryMeterView.BatteryPercentMode] for the [qsExpandedFraction] and 41 * [cutout]. We don't show battery estimation in qqs header on the devices with center cutout. 42 * The result might be null when the battery icon is invisible during the qs-qqs transition 43 * animation. 44 */ 45 @BatteryMeterView.BatteryPercentMode getBatteryModenull46 fun getBatteryMode(cutout: DisplayCutout?, qsExpandedFraction: Float): Int? = 47 when { 48 qsExpandedFraction > fadeInStartFraction -> BatteryMeterView.MODE_ESTIMATE 49 qsExpandedFraction < fadeOutCompleteFraction -> 50 if (hasCenterCutout(cutout)) { 51 BatteryMeterView.MODE_ON 52 } else { 53 BatteryMeterView.MODE_ESTIMATE 54 } 55 else -> null 56 } 57 updateResourcesnull58 fun updateResources() { 59 fadeInStartFraction = 60 (context.resources.getInteger(R.integer.fade_in_start_frame) - BUFFER_FRAME_COUNT) / 61 MOTION_LAYOUT_MAX_FRAME.toFloat() 62 fadeOutCompleteFraction = 63 (context.resources.getInteger(R.integer.fade_out_complete_frame) + BUFFER_FRAME_COUNT) / 64 MOTION_LAYOUT_MAX_FRAME.toFloat() 65 } 66 hasCenterCutoutnull67 private fun hasCenterCutout(cutout: DisplayCutout?): Boolean = 68 cutout?.let { 69 !insetsProvider.currentRotationHasCornerCutout() && !it.boundingRectTop.isEmpty 70 } ?: false 71 } 72