1 package com.android.systemui.shade
2 
3 import android.content.Context
4 import android.content.res.Resources
5 import android.graphics.Rect
6 import android.testing.AndroidTestingRunner
7 import android.view.DisplayCutout
8 import androidx.test.filters.SmallTest
9 import com.android.systemui.R
10 import com.android.systemui.SysuiTestCase
11 import com.android.systemui.battery.BatteryMeterView
12 import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
13 import com.android.systemui.util.mockito.mock
14 import com.android.systemui.util.mockito.whenever
15 import com.google.common.truth.Truth.assertThat
16 import org.junit.Before
17 import org.junit.Rule
18 import org.junit.Test
19 import org.junit.runner.RunWith
20 import org.mockito.Mock
21 import org.mockito.junit.MockitoJUnit
22 
23 @SmallTest
24 @RunWith(AndroidTestingRunner::class)
25 class QsBatteryModeControllerTest : SysuiTestCase() {
26 
27     private companion object {
28         val CENTER_TOP_CUTOUT: DisplayCutout =
29             mock<DisplayCutout>().also {
30                 whenever(it.boundingRectTop).thenReturn(Rect(10, 0, 20, 10))
31             }
32 
33         const val MOTION_LAYOUT_MAX_FRAME = 100
34         const val QQS_START_FRAME = 14
35         const val QS_END_FRAME = 58
36     }
37 
38     @JvmField @Rule val mockitoRule = MockitoJUnit.rule()!!
39 
40     @Mock private lateinit var insetsProvider: StatusBarContentInsetsProvider
41     @Mock private lateinit var mockedContext: Context
42     @Mock private lateinit var mockedResources: Resources
43 
44     private lateinit var controller: QsBatteryModeController // under test
45 
46     @Before
47     fun setup() {
48         whenever(mockedContext.resources).thenReturn(mockedResources)
49         whenever(mockedResources.getInteger(R.integer.fade_in_start_frame)).thenReturn(QS_END_FRAME)
50         whenever(mockedResources.getInteger(R.integer.fade_out_complete_frame))
51             .thenReturn(QQS_START_FRAME)
52 
53         controller = QsBatteryModeController(mockedContext, insetsProvider)
54     }
55 
56     @Test
57     fun returnsMODE_ONforQqsWithCenterCutout() {
58         assertThat(
59                 controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.prevFrameToFraction())
60             )
61             .isEqualTo(BatteryMeterView.MODE_ON)
62     }
63 
64     @Test
65     fun returnsMODE_ESTIMATEforQsWithCenterCutout() {
66         assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.nextFrameToFraction()))
67             .isEqualTo(BatteryMeterView.MODE_ESTIMATE)
68     }
69 
70     @Test
71     fun returnsMODE_ONforQqsWithCornerCutout() {
72         whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(true)
73 
74         assertThat(
75                 controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.prevFrameToFraction())
76             )
77             .isEqualTo(BatteryMeterView.MODE_ESTIMATE)
78     }
79 
80     @Test
81     fun returnsMODE_ESTIMATEforQsWithCornerCutout() {
82         whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(true)
83 
84         assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.nextFrameToFraction()))
85             .isEqualTo(BatteryMeterView.MODE_ESTIMATE)
86     }
87 
88     @Test
89     fun returnsNullInBetween() {
90         assertThat(
91                 controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.nextFrameToFraction())
92             )
93             .isNull()
94         assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.prevFrameToFraction()))
95             .isNull()
96     }
97 
98     private fun Int.prevFrameToFraction(): Float = (this - 1) / MOTION_LAYOUT_MAX_FRAME.toFloat()
99     private fun Int.nextFrameToFraction(): Float = (this + 1) / MOTION_LAYOUT_MAX_FRAME.toFloat()
100 }
101