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

Commit eba65c07 authored by Evan Laird's avatar Evan Laird Committed by Android (Google) Code Review
Browse files

Merge "[battery] implement USE_RUDIMENTARY_BATTERY" into main

parents 78375ebc 2582051e
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -686,6 +686,16 @@ flag {
    bug: "364360986"
}

flag {
    name: "status_bar_rudimentary_battery"
    namespace: "systemui"
    description: "Bugfix flag to control the percentage-outside-battery behavior"
    bug: "408730362"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "new_volume_panel"
    namespace: "systemui"
+4 −2
Original line number Diff line number Diff line
@@ -57,7 +57,8 @@ import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler
import com.android.systemui.statusbar.layout.mockStatusBarContentInsetsProvider
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager
import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.batteryViewModelFactory
import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.batteryWithPercentViewModelFactory
import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.unifiedBatteryViewModelFactory
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -195,7 +196,8 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {
            statusBarIconController,
            iconManagerFactory,
            batteryMeterViewController,
            kosmos.batteryViewModelFactory,
            kosmos.batteryWithPercentViewModelFactory,
            kosmos.unifiedBatteryViewModelFactory,
            shadeViewStateProvider,
            keyguardStateController,
            keyguardBypassController,
+12 −4
Original line number Diff line number Diff line
@@ -31,7 +31,8 @@ import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.Idle
import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel
import com.android.systemui.statusbar.phone.domain.interactor.IsAreaDark
import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel
import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryNextToPercentViewModel
import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.UnifiedBatteryViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.model.ChipsVisibilityModel
import com.android.systemui.statusbar.pipeline.shared.ui.model.SystemInfoCombinedVisibilityModel
import com.android.systemui.statusbar.pipeline.shared.ui.model.VisibilityModel
@@ -72,9 +73,16 @@ class FakeHomeStatusBarViewModel(

    override val canShowOngoingActivityChips: Flow<Boolean> = MutableStateFlow(false)

    override val batteryViewModelFactory: BatteryViewModel.Factory =
        object : BatteryViewModel.Factory {
            override fun create(): BatteryViewModel = mock(BatteryViewModel::class.java)
    override val batteryNextToPercentViewModel: BatteryNextToPercentViewModel.Factory =
        object : BatteryNextToPercentViewModel.Factory {
            override fun create(): BatteryNextToPercentViewModel =
                mock(BatteryNextToPercentViewModel::class.java)
        }

    override val unifiedBatteryViewModel: UnifiedBatteryViewModel.Factory =
        object : UnifiedBatteryViewModel.Factory {
            override fun create(): UnifiedBatteryViewModel =
                mock(UnifiedBatteryViewModel::class.java)
        }
    override val systemStatusIconsViewModelFactory: SystemStatusIconsViewModel.Factory =
        object : SystemStatusIconsViewModel.Factory {
+45 −15
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import androidx.core.view.doOnLayout
import androidx.core.view.isVisible
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.app.animation.Interpolators
import com.android.compose.theme.PlatformTheme
import com.android.keyguard.AlphaOptimizedLinearLayout
import com.android.settingslib.Utils
import com.android.systemui.Dumpable
@@ -70,6 +71,7 @@ import com.android.systemui.shade.carrier.ShadeCarrierGroupController
import com.android.systemui.shade.data.repository.ShadeDisplaysRepository
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
import com.android.systemui.statusbar.core.NewStatusBarIcons
import com.android.systemui.statusbar.core.RudimentaryBattery
import com.android.systemui.statusbar.data.repository.StatusBarContentInsetsProviderStore
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
@@ -77,8 +79,11 @@ import com.android.systemui.statusbar.phone.StatusOverlayHoverListenerFactory
import com.android.systemui.statusbar.phone.domain.interactor.IsAreaDark
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager
import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithChargeStatus
import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithEstimate
import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel
import com.android.systemui.statusbar.pipeline.battery.ui.composable.ShowPercentMode
import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryNextToPercentViewModel
import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.UnifiedBatteryViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.view.SystemStatusIconsLayoutHelper
import com.android.systemui.statusbar.policy.Clock
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -115,7 +120,8 @@ constructor(
    private val shadeDisplaysRepositoryLazy: Lazy<ShadeDisplaysRepository>,
    private val variableDateViewControllerFactory: VariableDateViewController.Factory,
    @Named(SHADE_HEADER) private val batteryMeterViewController: BatteryMeterViewController,
    private val batteryViewModelFactory: BatteryViewModel.Factory,
    private val unifiedBatteryViewModelFactory: UnifiedBatteryViewModel.Factory,
    private val tandemBatteryViewModelFactory: BatteryNextToPercentViewModel.Factory,
    private val dumpManager: DumpManager,
    private val shadeCarrierGroupControllerBuilder: ShadeCarrierGroupController.Builder,
    private val combinedShadeHeadersConstraintManager: CombinedShadeHeadersConstraintManager,
@@ -364,19 +370,7 @@ constructor(
            SystemStatusIconsLayoutHelper.configurePaddingForNewStatusBarIcons(statusIcons)

            // Configure the compose battery view
            val batteryComposeView =
                ComposeView(mView.context).apply {
                    setContent {
                        id = R.id.battery_meter_composable_view
                        val showBatteryEstimate by showBatteryEstimate.collectAsStateWithLifecycle()
                        BatteryWithEstimate(
                            modifier = Modifier.wrapContentSize(),
                            viewModelFactory = batteryViewModelFactory,
                            isDarkProvider = { IsAreaDark { true } },
                            showEstimate = showBatteryEstimate,
                        )
                    }
                }
            val batteryComposeView = createBatteryComposeView()
            mView.requireViewById<ViewGroup>(R.id.hover_system_icons_container).apply {
                addView(batteryComposeView, -1)
            }
@@ -393,6 +387,42 @@ constructor(
        privacyIconsController.onParentVisible()
    }

    private fun createBatteryComposeView(): ComposeView {
        return if (RudimentaryBattery.isEnabled) {
            ComposeView(mView.context).apply {
                setContent {
                    PlatformTheme {
                        id = R.id.battery_meter_composable_view
                        val showBatteryEstimate by showBatteryEstimate.collectAsStateWithLifecycle()
                        BatteryWithChargeStatus(
                            modifier = Modifier.wrapContentSize(),
                            viewModelFactory = tandemBatteryViewModelFactory,
                            isDarkProvider = { IsAreaDark { true } },
                            showPercentMode =
                                if (showBatteryEstimate) ShowPercentMode.PreferEstimate
                                else ShowPercentMode.Always,
                        )
                    }
                }
            }
        } else {
            ComposeView(mView.context).apply {
                setContent {
                    PlatformTheme {
                        id = R.id.battery_meter_composable_view
                        val showBatteryEstimate by showBatteryEstimate.collectAsStateWithLifecycle()
                        BatteryWithEstimate(
                            modifier = Modifier.wrapContentSize(),
                            viewModelFactory = unifiedBatteryViewModelFactory,
                            isDarkProvider = { IsAreaDark { true } },
                            showEstimate = showBatteryEstimate,
                        )
                    }
                }
            }
        }
    }

    override fun onViewAttached() {
        privacyIconsController.chipVisibilityListener = chipVisibilityListener
        updateVisibility()
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.core

import com.android.systemui.Flags
import com.android.systemui.flags.FlagToken
import com.android.systemui.flags.RefactorFlagUtils

/**
 * A rudimentary battery eschews the mid-century-modern approach of percent-in-battery and instead
 * yields a battery pure in its iconography. Next to it is a Text object which handles the more
 * mundane task of relaying a textual vibe on the overall percentage therein as likewise represented
 * as the fill level of the aforementioned "battery" (henceforth known as "battery") icon.
 */
object RudimentaryBattery {
    /** Aconfig flag for percent-outside-battery */
    const val FLAG_NAME = Flags.FLAG_STATUS_BAR_RUDIMENTARY_BATTERY

    /** Is the refactor enabled. Dependency on [StatusBarRootModernization] */
    @JvmStatic
    inline val isEnabled
        get() =
            Flags.statusBarRudimentaryBattery() &&
                StatusBarRootModernization.isEnabled &&
                NewStatusBarIcons.isEnabled

    /** A token used for dependency declaration */
    val token: FlagToken
        get() = FlagToken(FLAG_NAME, isEnabled)

    /**
     * Called to ensure code is only run when the flag is enabled. This protects users from the
     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
     * build to ensure that the refactor author catches issues in testing.
     */
    @JvmStatic
    inline fun isUnexpectedlyInLegacyMode() =
        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)

    /**
     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
     * the flag is not enabled to ensure that the refactor author catches issues in testing.
     * Caution!! Using this check incorrectly will cause crashes in nextfood builds!
     */
    @JvmStatic
    @Deprecated("Avoid crashing.", ReplaceWith("if (this.isUnexpectedlyInLegacyMode()) return"))
    inline fun unsafeAssertInNewMode() =
        RefactorFlagUtils.unsafeAssertInNewMode(isEnabled, FLAG_NAME)

    /**
     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
     * the flag is enabled to ensure that the refactor author catches issues in testing.
     */
    @JvmStatic
    inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
}
Loading