Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15530467 authored by Anton Potapov's avatar Anton Potapov Committed by Automerger Merge Worker
Browse files

Merge "Retain old logic for prohibiting battery estimate on the devices with...

Merge "Retain old logic for prohibiting battery estimate on the devices with center cutout." into tm-qpr-dev am: ce066a86 am: e5455483

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21317121



Change-Id: I2123d3d78a6e79392f7855c0e916ae7dcdd61e19
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents a272517c e5455483
Loading
Loading
Loading
Loading
+18 −20
Original line number Diff line number Diff line
@@ -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,9 +458,9 @@ 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) {

        Rect topCutout = cutout == null ? null : cutout.getBoundingRectTop();
        if (topCutout == null || topCutout.isEmpty() || hasCornerCutout) {
            datePrivacySeparatorLayoutParams.width = 0;
            mDatePrivacySeparator.setVisibility(View.GONE);
            mClockIconsSeparatorLayoutParams.width = 0;
@@ -477,7 +475,7 @@ public class QuickStatusBarHeader extends FrameLayout {
            setSeparatorVisibility(mKeyguardExpansionFraction == 0f);
            mHasCenterCutout = true;
        }
        }

        mDatePrivacySeparator.setLayoutParams(datePrivacySeparatorLayoutParams);
        mClockIconsSeparator.setLayoutParams(mClockIconsSeparatorLayoutParams);
        mCutOutPaddingLeft = sbInsets.first;
+19 −7
Original line number Diff line number Diff line
@@ -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() {
+70 −0
Original line number Diff line number Diff line
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
}
+49 −19
Original line number Diff line number Diff line
@@ -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
@@ -204,7 +210,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
                featureFlags,
                qsCarrierGroupControllerBuilder,
                combinedShadeHeadersConstraintManager,
            demoModeController
                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> {
+4 −2
Original line number Diff line number Diff line
@@ -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,7 +131,8 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
                featureFlags,
                qsCarrierGroupControllerBuilder,
                combinedShadeHeadersConstraintManager,
                demoModeController
                demoModeController,
                qsBatteryModeController,
        )
        whenever(view.isAttachedToWindow).thenReturn(true)
        mLargeScreenShadeHeaderController.init()
Loading