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