Merge "Retain old logic for prohibiting battery estimate on the devices with center cutout." into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ce066a86b1
@@ -152,9 +152,7 @@ public class QuickStatusBarHeader extends FrameLayout {
|
||||
Configuration config = mContext.getResources().getConfiguration();
|
||||
setDatePrivacyContainersWidth(config.orientation == Configuration.ORIENTATION_LANDSCAPE);
|
||||
|
||||
// QS will always show the estimate, and BatteryMeterView handles the case where
|
||||
// it's unavailable or charging
|
||||
mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
|
||||
updateBatteryMode();
|
||||
|
||||
mIconsAlphaAnimatorFixed = new TouchAnimator.Builder()
|
||||
.addFloat(mIconContainer, "alpha", 0, 1)
|
||||
@@ -460,24 +458,24 @@ public class QuickStatusBarHeader extends FrameLayout {
|
||||
(LinearLayout.LayoutParams) mDatePrivacySeparator.getLayoutParams();
|
||||
LinearLayout.LayoutParams mClockIconsSeparatorLayoutParams =
|
||||
(LinearLayout.LayoutParams) mClockIconsSeparator.getLayoutParams();
|
||||
if (cutout != null) {
|
||||
Rect topCutout = cutout.getBoundingRectTop();
|
||||
if (topCutout.isEmpty() || hasCornerCutout) {
|
||||
datePrivacySeparatorLayoutParams.width = 0;
|
||||
mDatePrivacySeparator.setVisibility(View.GONE);
|
||||
mClockIconsSeparatorLayoutParams.width = 0;
|
||||
setSeparatorVisibility(false);
|
||||
mShowClockIconsSeparator = false;
|
||||
mHasCenterCutout = false;
|
||||
} else {
|
||||
datePrivacySeparatorLayoutParams.width = topCutout.width();
|
||||
mDatePrivacySeparator.setVisibility(View.VISIBLE);
|
||||
mClockIconsSeparatorLayoutParams.width = topCutout.width();
|
||||
mShowClockIconsSeparator = true;
|
||||
setSeparatorVisibility(mKeyguardExpansionFraction == 0f);
|
||||
mHasCenterCutout = true;
|
||||
}
|
||||
|
||||
Rect topCutout = cutout == null ? null : cutout.getBoundingRectTop();
|
||||
if (topCutout == null || topCutout.isEmpty() || hasCornerCutout) {
|
||||
datePrivacySeparatorLayoutParams.width = 0;
|
||||
mDatePrivacySeparator.setVisibility(View.GONE);
|
||||
mClockIconsSeparatorLayoutParams.width = 0;
|
||||
setSeparatorVisibility(false);
|
||||
mShowClockIconsSeparator = false;
|
||||
mHasCenterCutout = false;
|
||||
} else {
|
||||
datePrivacySeparatorLayoutParams.width = topCutout.width();
|
||||
mDatePrivacySeparator.setVisibility(View.VISIBLE);
|
||||
mClockIconsSeparatorLayoutParams.width = topCutout.width();
|
||||
mShowClockIconsSeparator = true;
|
||||
setSeparatorVisibility(mKeyguardExpansionFraction == 0f);
|
||||
mHasCenterCutout = true;
|
||||
}
|
||||
|
||||
mDatePrivacySeparator.setLayoutParams(datePrivacySeparatorLayoutParams);
|
||||
mClockIconsSeparator.setLayoutParams(mClockIconsSeparatorLayoutParams);
|
||||
mCutOutPaddingLeft = sbInsets.first;
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.os.Bundle
|
||||
import android.os.Trace
|
||||
import android.os.Trace.TRACE_TAG_APP
|
||||
import android.util.Pair
|
||||
import android.view.DisplayCutout
|
||||
import android.view.View
|
||||
import android.view.WindowInsets
|
||||
import android.widget.TextView
|
||||
@@ -91,7 +92,8 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
||||
private val featureFlags: FeatureFlags,
|
||||
private val qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
|
||||
private val combinedShadeHeadersConstraintManager: CombinedShadeHeadersConstraintManager,
|
||||
private val demoModeController: DemoModeController
|
||||
private val demoModeController: DemoModeController,
|
||||
private val qsBatteryModeController: QsBatteryModeController,
|
||||
) : ViewController<View>(header), Dumpable {
|
||||
|
||||
companion object {
|
||||
@@ -129,9 +131,8 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
||||
private val iconContainer: StatusIconContainer = header.findViewById(R.id.statusIcons)
|
||||
private val qsCarrierGroup: QSCarrierGroup = header.findViewById(R.id.carrier_group)
|
||||
|
||||
private var cutoutLeft = 0
|
||||
private var cutoutRight = 0
|
||||
private var roundedCorners = 0
|
||||
private var cutout: DisplayCutout? = null
|
||||
private var lastInsets: WindowInsets? = null
|
||||
|
||||
private var qsDisabled = false
|
||||
@@ -273,7 +274,6 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
||||
|
||||
// battery settings same as in QS icons
|
||||
batteryMeterViewController.ignoreTunerUpdates()
|
||||
batteryIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
|
||||
|
||||
iconManager = tintedIconManagerFactory.create(iconContainer, StatusBarLocation.QS)
|
||||
iconManager.setTint(
|
||||
@@ -305,6 +305,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
||||
|
||||
if (header is MotionLayout) {
|
||||
header.setOnApplyWindowInsetsListener(insetListener)
|
||||
|
||||
clock.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
|
||||
val newPivot = if (v.isLayoutRtl) v.width.toFloat() else 0f
|
||||
v.pivotX = newPivot
|
||||
@@ -376,11 +377,13 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
||||
}
|
||||
|
||||
private fun updateConstraintsForInsets(view: MotionLayout, insets: WindowInsets) {
|
||||
val cutout = insets.displayCutout
|
||||
val cutout = insets.displayCutout.also {
|
||||
this.cutout = it
|
||||
}
|
||||
|
||||
val sbInsets: Pair<Int, Int> = insetsProvider.getStatusBarContentInsetsForCurrentRotation()
|
||||
cutoutLeft = sbInsets.first
|
||||
cutoutRight = sbInsets.second
|
||||
val cutoutLeft = sbInsets.first
|
||||
val cutoutRight = sbInsets.second
|
||||
val hasCornerCutout: Boolean = insetsProvider.currentRotationHasCornerCutout()
|
||||
updateQQSPaddings()
|
||||
// Set these guides as the left/right limits for content that lives in the top row, using
|
||||
@@ -408,6 +411,13 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
||||
}
|
||||
|
||||
view.updateAllConstraints(changes)
|
||||
updateBatteryMode()
|
||||
}
|
||||
|
||||
private fun updateBatteryMode() {
|
||||
qsBatteryModeController.getBatteryMode(cutout, qsExpandedFraction)?.let {
|
||||
batteryIcon.setPercentShowMode(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateScrollY() {
|
||||
@@ -475,6 +485,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
||||
if (header is MotionLayout && !largeScreenActive && visible) {
|
||||
logInstantEvent("updatePosition: $qsExpandedFraction")
|
||||
header.progress = qsExpandedFraction
|
||||
updateBatteryMode()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,6 +522,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
||||
val padding = resources.getDimensionPixelSize(R.dimen.qs_panel_padding)
|
||||
header.setPadding(padding, header.paddingTop, padding, header.paddingBottom)
|
||||
updateQQSPaddings()
|
||||
qsBatteryModeController.updateResources()
|
||||
}
|
||||
|
||||
private fun updateQQSPaddings() {
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.android.systemui.shade
|
||||
|
||||
import android.content.Context
|
||||
import android.view.DisplayCutout
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.battery.BatteryMeterView
|
||||
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Controls [BatteryMeterView.BatteryPercentMode]. It takes into account cutout and qs-qqs
|
||||
* transition fraction when determining the mode.
|
||||
*/
|
||||
class QsBatteryModeController
|
||||
@Inject
|
||||
constructor(
|
||||
private val context: Context,
|
||||
private val insetsProvider: StatusBarContentInsetsProvider,
|
||||
) {
|
||||
|
||||
private companion object {
|
||||
// MotionLayout frames are in [0, 100]. Where 0 and 100 are reserved for start and end
|
||||
// frames.
|
||||
const val MOTION_LAYOUT_MAX_FRAME = 100
|
||||
// We add a single buffer frame to ensure that battery view faded out completely when we are
|
||||
// about to change it's state
|
||||
const val BUFFER_FRAME_COUNT = 1
|
||||
}
|
||||
|
||||
private var fadeInStartFraction: Float = 0f
|
||||
private var fadeOutCompleteFraction: Float = 0f
|
||||
|
||||
init {
|
||||
updateResources()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an appropriate [BatteryMeterView.BatteryPercentMode] for the [qsExpandedFraction] and
|
||||
* [cutout]. We don't show battery estimation in qqs header on the devices with center cutout.
|
||||
* The result might be null when the battery icon is invisible during the qs-qqs transition
|
||||
* animation.
|
||||
*/
|
||||
@BatteryMeterView.BatteryPercentMode
|
||||
fun getBatteryMode(cutout: DisplayCutout?, qsExpandedFraction: Float): Int? =
|
||||
when {
|
||||
qsExpandedFraction > fadeInStartFraction -> BatteryMeterView.MODE_ESTIMATE
|
||||
qsExpandedFraction < fadeOutCompleteFraction ->
|
||||
if (hasCenterCutout(cutout)) {
|
||||
BatteryMeterView.MODE_ON
|
||||
} else {
|
||||
BatteryMeterView.MODE_ESTIMATE
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun updateResources() {
|
||||
fadeInStartFraction =
|
||||
(context.resources.getInteger(R.integer.fade_in_start_frame) - BUFFER_FRAME_COUNT) /
|
||||
MOTION_LAYOUT_MAX_FRAME.toFloat()
|
||||
fadeOutCompleteFraction =
|
||||
(context.resources.getInteger(R.integer.fade_out_complete_frame) + BUFFER_FRAME_COUNT) /
|
||||
MOTION_LAYOUT_MAX_FRAME.toFloat()
|
||||
}
|
||||
|
||||
private fun hasCenterCutout(cutout: DisplayCutout?): Boolean =
|
||||
cutout?.let {
|
||||
!insetsProvider.currentRotationHasCornerCutout() && !it.boundingRectTop.isEmpty
|
||||
}
|
||||
?: false
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.content.res.Resources
|
||||
import android.content.res.XmlResourceParser
|
||||
import android.graphics.Rect
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.view.Display
|
||||
import android.view.DisplayCutout
|
||||
import android.view.View
|
||||
import android.view.ViewPropertyAnimator
|
||||
@@ -77,9 +78,11 @@ import org.mockito.Mockito.clearInvocations
|
||||
import org.mockito.Mockito.inOrder
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.reset
|
||||
import org.mockito.Mockito.same
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
private val EMPTY_CHANGES = ConstraintsChanges()
|
||||
|
||||
@@ -133,6 +136,7 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
||||
|
||||
@Mock
|
||||
private lateinit var mockedContext: Context
|
||||
private lateinit var viewContext: Context
|
||||
@Mock(answer = Answers.RETURNS_MOCKS)
|
||||
private lateinit var view: MotionLayout
|
||||
|
||||
@@ -143,6 +147,7 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var largeScreenConstraints: ConstraintSet
|
||||
@Mock private lateinit var demoModeController: DemoModeController
|
||||
@Mock private lateinit var qsBatteryModeController: QsBatteryModeController
|
||||
|
||||
@JvmField @Rule
|
||||
val mockitoRule = MockitoJUnit.rule()
|
||||
@@ -175,7 +180,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
||||
.thenReturn(qsCarrierGroupControllerBuilder)
|
||||
whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
|
||||
|
||||
whenever(view.context).thenReturn(context)
|
||||
viewContext = spy(context)
|
||||
whenever(view.context).thenReturn(viewContext)
|
||||
whenever(view.resources).thenReturn(context.resources)
|
||||
whenever(view.setVisibility(ArgumentMatchers.anyInt())).then {
|
||||
viewVisibility = it.arguments[0] as Int
|
||||
@@ -192,19 +198,20 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
||||
setUpMotionLayout(view)
|
||||
|
||||
controller = LargeScreenShadeHeaderController(
|
||||
view,
|
||||
statusBarIconController,
|
||||
iconManagerFactory,
|
||||
privacyIconsController,
|
||||
insetsProvider,
|
||||
configurationController,
|
||||
variableDateViewControllerFactory,
|
||||
batteryMeterViewController,
|
||||
dumpManager,
|
||||
featureFlags,
|
||||
qsCarrierGroupControllerBuilder,
|
||||
combinedShadeHeadersConstraintManager,
|
||||
demoModeController
|
||||
view,
|
||||
statusBarIconController,
|
||||
iconManagerFactory,
|
||||
privacyIconsController,
|
||||
insetsProvider,
|
||||
configurationController,
|
||||
variableDateViewControllerFactory,
|
||||
batteryMeterViewController,
|
||||
dumpManager,
|
||||
featureFlags,
|
||||
qsCarrierGroupControllerBuilder,
|
||||
combinedShadeHeadersConstraintManager,
|
||||
demoModeController,
|
||||
qsBatteryModeController,
|
||||
)
|
||||
whenever(view.isAttachedToWindow).thenReturn(true)
|
||||
controller.init()
|
||||
@@ -218,13 +225,29 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
||||
|
||||
verify(batteryMeterViewController).init()
|
||||
verify(batteryMeterViewController).ignoreTunerUpdates()
|
||||
verify(batteryMeterView).setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
|
||||
|
||||
val inOrder = inOrder(qsCarrierGroupControllerBuilder)
|
||||
inOrder.verify(qsCarrierGroupControllerBuilder).setQSCarrierGroup(carrierGroup)
|
||||
inOrder.verify(qsCarrierGroupControllerBuilder).build()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `battery mode controller called when qsExpandedFraction changes`() {
|
||||
whenever(qsBatteryModeController.getBatteryMode(same(null), eq(0f)))
|
||||
.thenReturn(BatteryMeterView.MODE_ON)
|
||||
whenever(qsBatteryModeController.getBatteryMode(same(null), eq(1f)))
|
||||
.thenReturn(BatteryMeterView.MODE_ESTIMATE)
|
||||
controller.qsVisible = true
|
||||
|
||||
val times = 10
|
||||
repeat(times) {
|
||||
controller.qsExpandedFraction = it / (times - 1).toFloat()
|
||||
}
|
||||
|
||||
verify(batteryMeterView).setPercentShowMode(BatteryMeterView.MODE_ON)
|
||||
verify(batteryMeterView).setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClockPivotLtr() {
|
||||
val width = 200
|
||||
@@ -684,11 +707,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
||||
configurationController.notifyDensityOrFontScaleChanged()
|
||||
|
||||
val captor = ArgumentCaptor.forClass(XmlResourceParser::class.java)
|
||||
verify(qqsConstraints).load(eq(context), capture(captor))
|
||||
verify(qqsConstraints).load(eq(viewContext), capture(captor))
|
||||
assertThat(captor.value.getResId()).isEqualTo(R.xml.qqs_header)
|
||||
verify(qsConstraints).load(eq(context), capture(captor))
|
||||
verify(qsConstraints).load(eq(viewContext), capture(captor))
|
||||
assertThat(captor.value.getResId()).isEqualTo(R.xml.qs_header)
|
||||
verify(largeScreenConstraints).load(eq(context), capture(captor))
|
||||
verify(largeScreenConstraints).load(eq(viewContext), capture(captor))
|
||||
assertThat(captor.value.getResId()).isEqualTo(R.xml.large_screen_shade_header)
|
||||
}
|
||||
|
||||
@@ -786,6 +809,13 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
||||
whenever(insetsProvider.getStatusBarContentInsetsForCurrentRotation())
|
||||
.thenReturn(Pair(0, 0).toAndroidPair())
|
||||
whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(false)
|
||||
setupCurrentInsets(null)
|
||||
}
|
||||
|
||||
private fun setupCurrentInsets(cutout: DisplayCutout?) {
|
||||
val mockedDisplay =
|
||||
mock<Display>().also { display -> whenever(display.cutout).thenReturn(cutout) }
|
||||
whenever(viewContext.display).thenReturn(mockedDisplay)
|
||||
}
|
||||
|
||||
private fun<T, U> Pair<T, U>.toAndroidPair(): android.util.Pair<T, U> {
|
||||
|
||||
@@ -76,6 +76,7 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var mockedContext: Context
|
||||
@Mock private lateinit var demoModeController: DemoModeController
|
||||
@Mock private lateinit var qsBatteryModeController: QsBatteryModeController
|
||||
|
||||
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
|
||||
var viewVisibility = View.GONE
|
||||
@@ -130,8 +131,9 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
|
||||
featureFlags,
|
||||
qsCarrierGroupControllerBuilder,
|
||||
combinedShadeHeadersConstraintManager,
|
||||
demoModeController
|
||||
)
|
||||
demoModeController,
|
||||
qsBatteryModeController,
|
||||
)
|
||||
whenever(view.isAttachedToWindow).thenReturn(true)
|
||||
mLargeScreenShadeHeaderController.init()
|
||||
carrierIconSlots = listOf(
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.android.systemui.shade
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Rect
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.view.DisplayCutout
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.battery.BatteryMeterView
|
||||
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class QsBatteryModeControllerTest : SysuiTestCase() {
|
||||
|
||||
private companion object {
|
||||
val CENTER_TOP_CUTOUT: DisplayCutout =
|
||||
mock<DisplayCutout>().also {
|
||||
whenever(it.boundingRectTop).thenReturn(Rect(10, 0, 20, 10))
|
||||
}
|
||||
|
||||
const val MOTION_LAYOUT_MAX_FRAME = 100
|
||||
const val QQS_START_FRAME = 14
|
||||
const val QS_END_FRAME = 58
|
||||
}
|
||||
|
||||
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()!!
|
||||
|
||||
@Mock private lateinit var insetsProvider: StatusBarContentInsetsProvider
|
||||
@Mock private lateinit var mockedContext: Context
|
||||
@Mock private lateinit var mockedResources: Resources
|
||||
|
||||
private lateinit var controller: QsBatteryModeController // under test
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
whenever(mockedContext.resources).thenReturn(mockedResources)
|
||||
whenever(mockedResources.getInteger(R.integer.fade_in_start_frame)).thenReturn(QS_END_FRAME)
|
||||
whenever(mockedResources.getInteger(R.integer.fade_out_complete_frame))
|
||||
.thenReturn(QQS_START_FRAME)
|
||||
|
||||
controller = QsBatteryModeController(mockedContext, insetsProvider)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns MODE_ON for qqs with center cutout`() {
|
||||
assertThat(
|
||||
controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.prevFrameToFraction())
|
||||
)
|
||||
.isEqualTo(BatteryMeterView.MODE_ON)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns MODE_ESTIMATE for qs with center cutout`() {
|
||||
assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.nextFrameToFraction()))
|
||||
.isEqualTo(BatteryMeterView.MODE_ESTIMATE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns MODE_ON for qqs with corner cutout`() {
|
||||
whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(true)
|
||||
|
||||
assertThat(
|
||||
controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.prevFrameToFraction())
|
||||
)
|
||||
.isEqualTo(BatteryMeterView.MODE_ESTIMATE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns MODE_ESTIMATE for qs with corner cutout`() {
|
||||
whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(true)
|
||||
|
||||
assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.nextFrameToFraction()))
|
||||
.isEqualTo(BatteryMeterView.MODE_ESTIMATE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns null in-between`() {
|
||||
assertThat(
|
||||
controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.nextFrameToFraction())
|
||||
)
|
||||
.isNull()
|
||||
assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.prevFrameToFraction()))
|
||||
.isNull()
|
||||
}
|
||||
|
||||
private fun Int.prevFrameToFraction(): Float = (this - 1) / MOTION_LAYOUT_MAX_FRAME.toFloat()
|
||||
private fun Int.nextFrameToFraction(): Float = (this + 1) / MOTION_LAYOUT_MAX_FRAME.toFloat()
|
||||
}
|
||||
Reference in New Issue
Block a user