Merge "Retain old logic for prohibiting battery estimate on the devices with center cutout." into tm-qpr-dev am: ce066a86b1
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21317121 Change-Id: Ided7acf29b5a545e88ecd4c1d1215a7b7bc4b4b1 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -152,9 +152,7 @@ public class QuickStatusBarHeader extends FrameLayout {
|
|||||||
Configuration config = mContext.getResources().getConfiguration();
|
Configuration config = mContext.getResources().getConfiguration();
|
||||||
setDatePrivacyContainersWidth(config.orientation == Configuration.ORIENTATION_LANDSCAPE);
|
setDatePrivacyContainersWidth(config.orientation == Configuration.ORIENTATION_LANDSCAPE);
|
||||||
|
|
||||||
// QS will always show the estimate, and BatteryMeterView handles the case where
|
updateBatteryMode();
|
||||||
// it's unavailable or charging
|
|
||||||
mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
|
|
||||||
|
|
||||||
mIconsAlphaAnimatorFixed = new TouchAnimator.Builder()
|
mIconsAlphaAnimatorFixed = new TouchAnimator.Builder()
|
||||||
.addFloat(mIconContainer, "alpha", 0, 1)
|
.addFloat(mIconContainer, "alpha", 0, 1)
|
||||||
@@ -460,24 +458,24 @@ public class QuickStatusBarHeader extends FrameLayout {
|
|||||||
(LinearLayout.LayoutParams) mDatePrivacySeparator.getLayoutParams();
|
(LinearLayout.LayoutParams) mDatePrivacySeparator.getLayoutParams();
|
||||||
LinearLayout.LayoutParams mClockIconsSeparatorLayoutParams =
|
LinearLayout.LayoutParams mClockIconsSeparatorLayoutParams =
|
||||||
(LinearLayout.LayoutParams) mClockIconsSeparator.getLayoutParams();
|
(LinearLayout.LayoutParams) mClockIconsSeparator.getLayoutParams();
|
||||||
if (cutout != null) {
|
|
||||||
Rect topCutout = cutout.getBoundingRectTop();
|
Rect topCutout = cutout == null ? null : cutout.getBoundingRectTop();
|
||||||
if (topCutout.isEmpty() || hasCornerCutout) {
|
if (topCutout == null || topCutout.isEmpty() || hasCornerCutout) {
|
||||||
datePrivacySeparatorLayoutParams.width = 0;
|
datePrivacySeparatorLayoutParams.width = 0;
|
||||||
mDatePrivacySeparator.setVisibility(View.GONE);
|
mDatePrivacySeparator.setVisibility(View.GONE);
|
||||||
mClockIconsSeparatorLayoutParams.width = 0;
|
mClockIconsSeparatorLayoutParams.width = 0;
|
||||||
setSeparatorVisibility(false);
|
setSeparatorVisibility(false);
|
||||||
mShowClockIconsSeparator = false;
|
mShowClockIconsSeparator = false;
|
||||||
mHasCenterCutout = false;
|
mHasCenterCutout = false;
|
||||||
} else {
|
} else {
|
||||||
datePrivacySeparatorLayoutParams.width = topCutout.width();
|
datePrivacySeparatorLayoutParams.width = topCutout.width();
|
||||||
mDatePrivacySeparator.setVisibility(View.VISIBLE);
|
mDatePrivacySeparator.setVisibility(View.VISIBLE);
|
||||||
mClockIconsSeparatorLayoutParams.width = topCutout.width();
|
mClockIconsSeparatorLayoutParams.width = topCutout.width();
|
||||||
mShowClockIconsSeparator = true;
|
mShowClockIconsSeparator = true;
|
||||||
setSeparatorVisibility(mKeyguardExpansionFraction == 0f);
|
setSeparatorVisibility(mKeyguardExpansionFraction == 0f);
|
||||||
mHasCenterCutout = true;
|
mHasCenterCutout = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mDatePrivacySeparator.setLayoutParams(datePrivacySeparatorLayoutParams);
|
mDatePrivacySeparator.setLayoutParams(datePrivacySeparatorLayoutParams);
|
||||||
mClockIconsSeparator.setLayoutParams(mClockIconsSeparatorLayoutParams);
|
mClockIconsSeparator.setLayoutParams(mClockIconsSeparatorLayoutParams);
|
||||||
mCutOutPaddingLeft = sbInsets.first;
|
mCutOutPaddingLeft = sbInsets.first;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.os.Bundle
|
|||||||
import android.os.Trace
|
import android.os.Trace
|
||||||
import android.os.Trace.TRACE_TAG_APP
|
import android.os.Trace.TRACE_TAG_APP
|
||||||
import android.util.Pair
|
import android.util.Pair
|
||||||
|
import android.view.DisplayCutout
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
@@ -91,7 +92,8 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
|||||||
private val featureFlags: FeatureFlags,
|
private val featureFlags: FeatureFlags,
|
||||||
private val qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
|
private val qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
|
||||||
private val combinedShadeHeadersConstraintManager: CombinedShadeHeadersConstraintManager,
|
private val combinedShadeHeadersConstraintManager: CombinedShadeHeadersConstraintManager,
|
||||||
private val demoModeController: DemoModeController
|
private val demoModeController: DemoModeController,
|
||||||
|
private val qsBatteryModeController: QsBatteryModeController,
|
||||||
) : ViewController<View>(header), Dumpable {
|
) : ViewController<View>(header), Dumpable {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -129,9 +131,8 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
|||||||
private val iconContainer: StatusIconContainer = header.findViewById(R.id.statusIcons)
|
private val iconContainer: StatusIconContainer = header.findViewById(R.id.statusIcons)
|
||||||
private val qsCarrierGroup: QSCarrierGroup = header.findViewById(R.id.carrier_group)
|
private val qsCarrierGroup: QSCarrierGroup = header.findViewById(R.id.carrier_group)
|
||||||
|
|
||||||
private var cutoutLeft = 0
|
|
||||||
private var cutoutRight = 0
|
|
||||||
private var roundedCorners = 0
|
private var roundedCorners = 0
|
||||||
|
private var cutout: DisplayCutout? = null
|
||||||
private var lastInsets: WindowInsets? = null
|
private var lastInsets: WindowInsets? = null
|
||||||
|
|
||||||
private var qsDisabled = false
|
private var qsDisabled = false
|
||||||
@@ -273,7 +274,6 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
|||||||
|
|
||||||
// battery settings same as in QS icons
|
// battery settings same as in QS icons
|
||||||
batteryMeterViewController.ignoreTunerUpdates()
|
batteryMeterViewController.ignoreTunerUpdates()
|
||||||
batteryIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
|
|
||||||
|
|
||||||
iconManager = tintedIconManagerFactory.create(iconContainer, StatusBarLocation.QS)
|
iconManager = tintedIconManagerFactory.create(iconContainer, StatusBarLocation.QS)
|
||||||
iconManager.setTint(
|
iconManager.setTint(
|
||||||
@@ -305,6 +305,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
|||||||
|
|
||||||
if (header is MotionLayout) {
|
if (header is MotionLayout) {
|
||||||
header.setOnApplyWindowInsetsListener(insetListener)
|
header.setOnApplyWindowInsetsListener(insetListener)
|
||||||
|
|
||||||
clock.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
|
clock.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
|
||||||
val newPivot = if (v.isLayoutRtl) v.width.toFloat() else 0f
|
val newPivot = if (v.isLayoutRtl) v.width.toFloat() else 0f
|
||||||
v.pivotX = newPivot
|
v.pivotX = newPivot
|
||||||
@@ -376,11 +377,13 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateConstraintsForInsets(view: MotionLayout, insets: WindowInsets) {
|
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()
|
val sbInsets: Pair<Int, Int> = insetsProvider.getStatusBarContentInsetsForCurrentRotation()
|
||||||
cutoutLeft = sbInsets.first
|
val cutoutLeft = sbInsets.first
|
||||||
cutoutRight = sbInsets.second
|
val cutoutRight = sbInsets.second
|
||||||
val hasCornerCutout: Boolean = insetsProvider.currentRotationHasCornerCutout()
|
val hasCornerCutout: Boolean = insetsProvider.currentRotationHasCornerCutout()
|
||||||
updateQQSPaddings()
|
updateQQSPaddings()
|
||||||
// Set these guides as the left/right limits for content that lives in the top row, using
|
// 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)
|
view.updateAllConstraints(changes)
|
||||||
|
updateBatteryMode()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateBatteryMode() {
|
||||||
|
qsBatteryModeController.getBatteryMode(cutout, qsExpandedFraction)?.let {
|
||||||
|
batteryIcon.setPercentShowMode(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateScrollY() {
|
private fun updateScrollY() {
|
||||||
@@ -475,6 +485,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
|||||||
if (header is MotionLayout && !largeScreenActive && visible) {
|
if (header is MotionLayout && !largeScreenActive && visible) {
|
||||||
logInstantEvent("updatePosition: $qsExpandedFraction")
|
logInstantEvent("updatePosition: $qsExpandedFraction")
|
||||||
header.progress = qsExpandedFraction
|
header.progress = qsExpandedFraction
|
||||||
|
updateBatteryMode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,6 +522,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
|
|||||||
val padding = resources.getDimensionPixelSize(R.dimen.qs_panel_padding)
|
val padding = resources.getDimensionPixelSize(R.dimen.qs_panel_padding)
|
||||||
header.setPadding(padding, header.paddingTop, padding, header.paddingBottom)
|
header.setPadding(padding, header.paddingTop, padding, header.paddingBottom)
|
||||||
updateQQSPaddings()
|
updateQQSPaddings()
|
||||||
|
qsBatteryModeController.updateResources()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateQQSPaddings() {
|
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.content.res.XmlResourceParser
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.view.Display
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewPropertyAnimator
|
import android.view.ViewPropertyAnimator
|
||||||
@@ -77,9 +78,11 @@ import org.mockito.Mockito.clearInvocations
|
|||||||
import org.mockito.Mockito.inOrder
|
import org.mockito.Mockito.inOrder
|
||||||
import org.mockito.Mockito.never
|
import org.mockito.Mockito.never
|
||||||
import org.mockito.Mockito.reset
|
import org.mockito.Mockito.reset
|
||||||
|
import org.mockito.Mockito.same
|
||||||
|
import org.mockito.Mockito.spy
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.Mockito.`when` as whenever
|
|
||||||
import org.mockito.junit.MockitoJUnit
|
import org.mockito.junit.MockitoJUnit
|
||||||
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
|
||||||
private val EMPTY_CHANGES = ConstraintsChanges()
|
private val EMPTY_CHANGES = ConstraintsChanges()
|
||||||
|
|
||||||
@@ -133,6 +136,7 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var mockedContext: Context
|
private lateinit var mockedContext: Context
|
||||||
|
private lateinit var viewContext: Context
|
||||||
@Mock(answer = Answers.RETURNS_MOCKS)
|
@Mock(answer = Answers.RETURNS_MOCKS)
|
||||||
private lateinit var view: MotionLayout
|
private lateinit var view: MotionLayout
|
||||||
|
|
||||||
@@ -143,6 +147,7 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
|||||||
@Mock
|
@Mock
|
||||||
private lateinit var largeScreenConstraints: ConstraintSet
|
private lateinit var largeScreenConstraints: ConstraintSet
|
||||||
@Mock private lateinit var demoModeController: DemoModeController
|
@Mock private lateinit var demoModeController: DemoModeController
|
||||||
|
@Mock private lateinit var qsBatteryModeController: QsBatteryModeController
|
||||||
|
|
||||||
@JvmField @Rule
|
@JvmField @Rule
|
||||||
val mockitoRule = MockitoJUnit.rule()
|
val mockitoRule = MockitoJUnit.rule()
|
||||||
@@ -175,7 +180,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
|||||||
.thenReturn(qsCarrierGroupControllerBuilder)
|
.thenReturn(qsCarrierGroupControllerBuilder)
|
||||||
whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
|
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.resources).thenReturn(context.resources)
|
||||||
whenever(view.setVisibility(ArgumentMatchers.anyInt())).then {
|
whenever(view.setVisibility(ArgumentMatchers.anyInt())).then {
|
||||||
viewVisibility = it.arguments[0] as Int
|
viewVisibility = it.arguments[0] as Int
|
||||||
@@ -192,19 +198,20 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
|||||||
setUpMotionLayout(view)
|
setUpMotionLayout(view)
|
||||||
|
|
||||||
controller = LargeScreenShadeHeaderController(
|
controller = LargeScreenShadeHeaderController(
|
||||||
view,
|
view,
|
||||||
statusBarIconController,
|
statusBarIconController,
|
||||||
iconManagerFactory,
|
iconManagerFactory,
|
||||||
privacyIconsController,
|
privacyIconsController,
|
||||||
insetsProvider,
|
insetsProvider,
|
||||||
configurationController,
|
configurationController,
|
||||||
variableDateViewControllerFactory,
|
variableDateViewControllerFactory,
|
||||||
batteryMeterViewController,
|
batteryMeterViewController,
|
||||||
dumpManager,
|
dumpManager,
|
||||||
featureFlags,
|
featureFlags,
|
||||||
qsCarrierGroupControllerBuilder,
|
qsCarrierGroupControllerBuilder,
|
||||||
combinedShadeHeadersConstraintManager,
|
combinedShadeHeadersConstraintManager,
|
||||||
demoModeController
|
demoModeController,
|
||||||
|
qsBatteryModeController,
|
||||||
)
|
)
|
||||||
whenever(view.isAttachedToWindow).thenReturn(true)
|
whenever(view.isAttachedToWindow).thenReturn(true)
|
||||||
controller.init()
|
controller.init()
|
||||||
@@ -218,13 +225,29 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
|||||||
|
|
||||||
verify(batteryMeterViewController).init()
|
verify(batteryMeterViewController).init()
|
||||||
verify(batteryMeterViewController).ignoreTunerUpdates()
|
verify(batteryMeterViewController).ignoreTunerUpdates()
|
||||||
verify(batteryMeterView).setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
|
|
||||||
|
|
||||||
val inOrder = inOrder(qsCarrierGroupControllerBuilder)
|
val inOrder = inOrder(qsCarrierGroupControllerBuilder)
|
||||||
inOrder.verify(qsCarrierGroupControllerBuilder).setQSCarrierGroup(carrierGroup)
|
inOrder.verify(qsCarrierGroupControllerBuilder).setQSCarrierGroup(carrierGroup)
|
||||||
inOrder.verify(qsCarrierGroupControllerBuilder).build()
|
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
|
@Test
|
||||||
fun testClockPivotLtr() {
|
fun testClockPivotLtr() {
|
||||||
val width = 200
|
val width = 200
|
||||||
@@ -684,11 +707,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
|||||||
configurationController.notifyDensityOrFontScaleChanged()
|
configurationController.notifyDensityOrFontScaleChanged()
|
||||||
|
|
||||||
val captor = ArgumentCaptor.forClass(XmlResourceParser::class.java)
|
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)
|
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)
|
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)
|
assertThat(captor.value.getResId()).isEqualTo(R.xml.large_screen_shade_header)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,6 +809,13 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
|
|||||||
whenever(insetsProvider.getStatusBarContentInsetsForCurrentRotation())
|
whenever(insetsProvider.getStatusBarContentInsetsForCurrentRotation())
|
||||||
.thenReturn(Pair(0, 0).toAndroidPair())
|
.thenReturn(Pair(0, 0).toAndroidPair())
|
||||||
whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(false)
|
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> {
|
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 mockedContext: Context
|
||||||
@Mock private lateinit var demoModeController: DemoModeController
|
@Mock private lateinit var demoModeController: DemoModeController
|
||||||
|
@Mock private lateinit var qsBatteryModeController: QsBatteryModeController
|
||||||
|
|
||||||
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
|
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
|
||||||
var viewVisibility = View.GONE
|
var viewVisibility = View.GONE
|
||||||
@@ -130,8 +131,9 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
|
|||||||
featureFlags,
|
featureFlags,
|
||||||
qsCarrierGroupControllerBuilder,
|
qsCarrierGroupControllerBuilder,
|
||||||
combinedShadeHeadersConstraintManager,
|
combinedShadeHeadersConstraintManager,
|
||||||
demoModeController
|
demoModeController,
|
||||||
)
|
qsBatteryModeController,
|
||||||
|
)
|
||||||
whenever(view.isAttachedToWindow).thenReturn(true)
|
whenever(view.isAttachedToWindow).thenReturn(true)
|
||||||
mLargeScreenShadeHeaderController.init()
|
mLargeScreenShadeHeaderController.init()
|
||||||
carrierIconSlots = listOf(
|
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