summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Evan Laird <evanlaird@google.com> 2025-01-31 01:17:18 -0500
committer Evan Laird <evanlaird@google.com> 2025-02-10 19:28:07 -0500
commita2029c1924c0534b701af24407a6eb2f528f6c06 (patch)
treebfc12f61fcdf4c8a94a759bbd049200140385922
parent2f131f5edaa690dd8f6659a94ac12292d005566b (diff)
[sb] Use BatteryCanvas composable in the battery chip
Adds a new battery composable event chip, and a new chip view that hosts a single ComposeView so that we can reuse it in the future. Test: manual Bug: 391605373 Flag: com.android.settingslib.flags.new_status_bar_icons Flag: com.android.systemui.status_bar_root_modernization Change-Id: I7c5f8a3636f2464cdcf8b65c23b391de14e59275
-rw-r--r--packages/SystemUI/res/layout/battery_status_chip.xml12
-rw-r--r--packages/SystemUI/res/layout/status_bar_event_chip_compose.xml34
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/res/values/styles.xml13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/ui/view/BatteryStatusEventComposeChip.kt100
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/domain/interactor/BatteryInteractor.kt4
8 files changed, 168 insertions, 23 deletions
diff --git a/packages/SystemUI/res/layout/battery_status_chip.xml b/packages/SystemUI/res/layout/battery_status_chip.xml
index 74371839e247..7399651d4248 100644
--- a/packages/SystemUI/res/layout/battery_status_chip.xml
+++ b/packages/SystemUI/res/layout/battery_status_chip.xml
@@ -24,21 +24,13 @@
<LinearLayout
android:id="@+id/rounded_container"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/ongoing_appops_chip_height"
- android:layout_gravity="center"
- android:background="@drawable/statusbar_chip_bg"
- android:clipToOutline="true"
- android:gravity="center"
- android:maxWidth="@dimen/ongoing_appops_chip_max_width"
- android:minWidth="@dimen/ongoing_appops_chip_min_width">
+ style="@style/StatusBar.EventChip">
<com.android.systemui.battery.BatteryMeterView
android:id="@+id/battery_meter_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="10dp" />
+ android:layout_marginHorizontal="@dimen/ongoing_appops_chip_content_horizontal_margin" />
</LinearLayout>
</merge> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_event_chip_compose.xml b/packages/SystemUI/res/layout/status_bar_event_chip_compose.xml
new file mode 100644
index 000000000000..ff96ab15cd15
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_event_chip_compose.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical|end">
+
+ <LinearLayout
+ android:id="@+id/rounded_container"
+ style="@style/StatusBar.EventChip">
+
+ <!-- Stub for the composable -->
+ <androidx.compose.ui.platform.ComposeView
+ android:id="@+id/compose_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginHorizontal="@dimen/ongoing_appops_chip_content_horizontal_margin" />
+
+ </LinearLayout>
+</merge>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 648e4c2e3ac7..4b5c1baef0a5 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1254,6 +1254,8 @@
<dimen name="ongoing_appops_chip_side_padding">8dp</dimen>
<!-- Margin between icons of Ongoing App Ops chip -->
<dimen name="ongoing_appops_chip_icon_margin">4dp</dimen>
+ <!-- Side margins for the content of an appops chip -->
+ <dimen name="ongoing_appops_chip_content_horizontal_margin">10dp</dimen>
<!-- Icon size of Ongoing App Ops chip -->
<dimen name="ongoing_appops_chip_icon_size">16sp</dimen>
<!-- Radius of Ongoing App Ops chip corners -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 4961a7ece69a..8f808d389203 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -93,6 +93,19 @@
<item name="android:textColor">?android:attr/colorPrimary</item>
</style>
+ <style name="StatusBar.EventChip">
+ <item name="android:orientation">horizontal</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">center</item>
+ <item name="android:gravity">center</item>
+ <item name="android:clipToOutline">true</item>
+ <item name="android:background">@drawable/statusbar_chip_bg</item>
+ <item name="android:minHeight">@dimen/ongoing_appops_chip_height</item>
+ <item name="android:maxWidth">@dimen/ongoing_appops_chip_max_width</item>
+ <item name="android:minWidth">@dimen/ongoing_appops_chip_min_width</item>
+ </style>
+
<style name="Chipbar" />
<style name="Chipbar.Text" parent="@*android:style/TextAppearance.DeviceDefault.Notification.Title">
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt
index a58ce4162ddc..02cec13d2ce8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt
@@ -26,6 +26,7 @@ import com.android.settingslib.flags.Flags.newStatusBarIcons
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.unified.BatteryColors
import com.android.systemui.res.R
+import com.android.systemui.statusbar.core.NewStatusBarIcons
import com.android.systemui.statusbar.events.BackgroundAnimatableView
class BatteryStatusChip @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
@@ -37,6 +38,8 @@ class BatteryStatusChip @JvmOverloads constructor(context: Context, attrs: Attri
get() = batteryMeterView
init {
+ NewStatusBarIcons.assertInLegacyMode()
+
inflate(context, R.layout.battery_status_chip, this)
roundedContainer = requireViewById(R.id.rounded_container)
batteryMeterView = requireViewById(R.id.battery_meter_view)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
index ea1d7820c79c..5887eb6ad865 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
@@ -25,6 +25,8 @@ import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.privacy.PrivacyItem
import com.android.systemui.statusbar.BatteryStatusChip
import com.android.systemui.statusbar.ConnectedDisplayChip
+import com.android.systemui.statusbar.core.NewStatusBarIcons
+import com.android.systemui.statusbar.events.ui.view.BatteryStatusEventComposeChip
typealias ViewCreator = (context: Context) -> BackgroundAnimatableView
@@ -53,9 +55,7 @@ interface StatusEvent {
}
}
-class BGView(
- context: Context
-) : View(context), BackgroundAnimatableView {
+class BGView(context: Context) : View(context), BackgroundAnimatableView {
override val view: View
get() = this
@@ -65,9 +65,7 @@ class BGView(
}
@SuppressLint("AppCompatCustomView")
-class BGImageView(
- context: Context
-) : ImageView(context), BackgroundAnimatableView {
+class BGImageView(context: Context) : ImageView(context), BackgroundAnimatableView {
override val view: View
get() = this
@@ -84,8 +82,10 @@ class BatteryEvent(@IntRange(from = 0, to = 100) val batteryLevel: Int) : Status
override val shouldAnnounceAccessibilityEvent: Boolean = false
override val viewCreator: ViewCreator = { context ->
- BatteryStatusChip(context).apply {
- setBatteryLevel(batteryLevel)
+ if (NewStatusBarIcons.isEnabled) {
+ BatteryStatusEventComposeChip(batteryLevel, context)
+ } else {
+ BatteryStatusChip(context).apply { setBatteryLevel(batteryLevel) }
}
}
@@ -103,9 +103,7 @@ class ConnectedDisplayEvent : StatusEvent {
override var contentDescription: String? = ""
override val shouldAnnounceAccessibilityEvent: Boolean = true
- override val viewCreator: ViewCreator = { context ->
- ConnectedDisplayChip(context)
- }
+ override val viewCreator: ViewCreator = { context -> ConnectedDisplayChip(context) }
override fun toString(): String {
return javaClass.simpleName
@@ -134,7 +132,8 @@ open class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEven
}
override fun shouldUpdateFromEvent(other: StatusEvent?): Boolean {
- return other is PrivacyEvent && (other.privacyItems != privacyItems ||
+ return other is PrivacyEvent &&
+ (other.privacyItems != privacyItems ||
other.contentDescription != contentDescription ||
(other.forceVisible && !forceVisible))
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/ui/view/BatteryStatusEventComposeChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/ui/view/BatteryStatusEventComposeChip.kt
new file mode 100644
index 000000000000..a90e3ff4b2dc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/ui/view/BatteryStatusEventComposeChip.kt
@@ -0,0 +1,100 @@
+/*
+ * 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.events.ui.view
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.width
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.ComposeView
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.core.NewStatusBarIcons
+import com.android.systemui.statusbar.events.BackgroundAnimatableView
+import com.android.systemui.statusbar.pipeline.battery.domain.interactor.BatteryInteractor
+import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryColors.LightThemeChargingColors
+import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryFrame
+import com.android.systemui.statusbar.pipeline.battery.shared.ui.BatteryGlyph
+import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryCanvas
+import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel
+import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewModel.Companion.glyphRepresentation
+
+/**
+ * [StatusEvent] chip for the battery plugged in status event. Shows the current battery level and
+ * charging state in the status bar via the system event animation.
+ *
+ * This chip will fully replace [BatteryStatusChip] when [NewStatusBarIcons] is rolled out
+ */
+@SuppressLint("ViewConstructor")
+class BatteryStatusEventComposeChip
+@JvmOverloads
+constructor(level: Int, context: Context, attrs: AttributeSet? = null) :
+ FrameLayout(context, attrs), BackgroundAnimatableView {
+ private val roundedContainer: LinearLayout
+ private val composeInner: ComposeView
+ override val contentView: View
+ get() = composeInner
+
+ init {
+ NewStatusBarIcons.assertInNewMode()
+
+ inflate(context, R.layout.status_bar_event_chip_compose, this)
+ roundedContainer = requireViewById(R.id.rounded_container)
+ composeInner = requireViewById(R.id.compose_view)
+ composeInner.apply {
+ setContent {
+ val isFull = BatteryInteractor.isBatteryFull(level)
+ BatteryCanvas(
+ modifier =
+ Modifier.width(BatteryViewModel.STATUS_BAR_BATTERY_WIDTH)
+ .height(BatteryViewModel.STATUS_BAR_BATTERY_HEIGHT),
+ path = BatteryFrame.pathSpec,
+ // TODO(b/394659067): get a content description for this chip
+ contentDescription = "",
+ innerWidth = BatteryFrame.innerWidth,
+ innerHeight = BatteryFrame.innerHeight,
+ // This event only happens when plugged in, so we always show it as charging
+ glyphs =
+ if (isFull) listOf(BatteryGlyph.Bolt)
+ else level.glyphRepresentation() + BatteryGlyph.Bolt,
+ level = level,
+ isFull = isFull,
+ colorsProvider = { LightThemeChargingColors },
+ )
+ }
+ }
+ updateResources()
+ }
+
+ /**
+ * When animating as a chip in the status bar, we want to animate the width for the rounded
+ * container. We have to subtract our own top and left offset because the bounds come to us as
+ * absolute on-screen bounds.
+ */
+ override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) {
+ roundedContainer.setLeftTopRightBottom(l - left, t - top, r - left, b - top)
+ }
+
+ @SuppressLint("UseCompatLoadingForDrawables")
+ private fun updateResources() {
+ roundedContainer.background = mContext.getDrawable(R.drawable.statusbar_chip_bg)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/domain/interactor/BatteryInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/domain/interactor/BatteryInteractor.kt
index 8fdb6ee57587..d53cbabb1d19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/domain/interactor/BatteryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/battery/domain/interactor/BatteryInteractor.kt
@@ -29,7 +29,7 @@ class BatteryInteractor @Inject constructor(repo: BatteryRepository) {
val level = repo.level.filterNotNull()
/** Whether the battery has been fully charged */
- val isFull = level.map { it >= 100 }
+ val isFull = level.map { isBatteryFull(it) }
/**
* For the sake of battery views, consider it to be "charging" if plugged in. This allows users
@@ -82,6 +82,8 @@ class BatteryInteractor @Inject constructor(repo: BatteryRepository) {
companion object {
/** Level below which we consider to be critically low */
private const val CRITICAL_LEVEL = 20
+
+ fun isBatteryFull(level: Int) = level >= 100
}
}