summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt33
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt21
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt5
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt98
-rw-r--r--packages/SystemUI/res/layout/ongoing_activity_chip_content.xml (renamed from packages/SystemUI/res/layout/ongoing_activity_chip.xml)18
-rw-r--r--packages/SystemUI/res/layout/ongoing_activity_chip_primary.xml23
-rw-r--r--packages/SystemUI/res/layout/ongoing_activity_chip_secondary.xml23
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml4
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/res/values/styles.xml9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/SecondaryOngoingActivityChip.kt40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt21
19 files changed, 238 insertions, 124 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
index 40f13bbbf908..17076b4d7505 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
@@ -306,12 +306,13 @@ class NotifChipsViewModelTest : SysuiTestCase() {
@Test
@EnableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
- fun chips_basicTime_hiddenIfAutomaticallyPromoted() =
+ fun chips_basicTime_timeHiddenIfAutomaticallyPromoted() =
kosmos.runTest {
val latest by collectLastValue(underTest.chips)
val promotedContentBuilder =
PromotedNotificationContentModel.Builder("notif").apply {
+ this.wasPromotedAutomatically = true
this.time =
PromotedNotificationContentModel.When(
time = 6543L,
@@ -334,6 +335,36 @@ class NotifChipsViewModelTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
+ fun chips_basicTime_timeShownIfNotAutomaticallyPromoted() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.chips)
+
+ val promotedContentBuilder =
+ PromotedNotificationContentModel.Builder("notif").apply {
+ this.wasPromotedAutomatically = false
+ this.time =
+ PromotedNotificationContentModel.When(
+ time = 6543L,
+ mode = PromotedNotificationContentModel.When.Mode.BasicTime,
+ )
+ }
+ setNotifs(
+ listOf(
+ activeNotificationModel(
+ key = "notif",
+ statusBarChipIcon = mock<StatusBarIconView>(),
+ promotedContent = promotedContentBuilder.build(),
+ )
+ )
+ )
+
+ assertThat(latest).hasSize(1)
+ assertThat(latest!![0])
+ .isInstanceOf(OngoingActivityChipModel.Shown.ShortTimeDelta::class.java)
+ }
+
+ @Test
@DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
fun chips_basicTime_isShortTimeDelta() =
kosmos.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt
index 5fbdfbf17df4..0c992e0b348b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt
@@ -40,7 +40,7 @@ class ChipBackgroundContainerTest : SysuiTestCase() {
allowTestableLooperAsMainThread()
TestableLooper.get(this).runWithLooper {
val chipView =
- LayoutInflater.from(context).inflate(R.layout.ongoing_activity_chip, null)
+ LayoutInflater.from(context).inflate(R.layout.ongoing_activity_chip_primary, null)
underTest = chipView.requireViewById(R.id.ongoing_activity_chip_background)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt
index 6f7711759603..9483f6df05f5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt
@@ -48,7 +48,7 @@ class ChipChronometerTest : SysuiTestCase() {
allowTestableLooperAsMainThread()
TestableLooper.get(this).runWithLooper {
val chipView =
- LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+ LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
textView = chipView.findViewById(R.id.ongoing_activity_chip_time)!!
measureTextView()
calculateDoesNotFixText()
@@ -161,7 +161,7 @@ class ChipChronometerTest : SysuiTestCase() {
private fun measureTextView() {
textView.measure(
View.MeasureSpec.makeMeasureSpec(TEXT_VIEW_MAX_WIDTH, View.MeasureSpec.AT_MOST),
- View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
index 26c6eb5dc47a..92271198cac0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
@@ -35,6 +35,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_WAS_AUTOMATICALLY_PROMOTED
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style
import com.android.systemui.testKosmos
@@ -110,6 +111,26 @@ class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {
@Test
@EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractContent_wasPromotedAutomatically_false() {
+ val entry = createEntry { extras.putBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, false) }
+
+ val content = extractContent(entry)
+
+ assertThat(content!!.wasPromotedAutomatically).isFalse()
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractContent_wasPromotedAutomatically_true() {
+ val entry = createEntry { extras.putBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, true) }
+
+ val content = extractContent(entry)
+
+ assertThat(content!!.wasPromotedAutomatically).isTrue()
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
@DisableFlags(android.app.Flags.FLAG_API_RICH_ONGOING)
fun extractContent_apiFlagOff_shortCriticalTextNotExtracted() {
val entry = createEntry { setShortCriticalText(TEST_SHORT_CRITICAL_TEXT) }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
index f76ee5e3ebc9..cd3539d6b9a5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
@@ -114,7 +114,8 @@ class OngoingCallControllerViaListenerTest : SysuiTestCase() {
fun setUp() {
allowTestableLooperAsMainThread()
TestableLooper.get(this).runWithLooper {
- chipView = LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+ chipView =
+ LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
}
MockitoAnnotations.initMocks(this)
@@ -498,7 +499,7 @@ class OngoingCallControllerViaListenerTest : SysuiTestCase() {
lateinit var newChipView: View
TestableLooper.get(this).runWithLooper {
newChipView =
- LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+ LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
}
// Change the chip view associated with the controller.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
index 647b5f86fcee..cf512cdee800 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
@@ -29,7 +29,6 @@ import android.widget.LinearLayout
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON
-import com.android.systemui.Flags.FLAG_STATUS_BAR_CHIPS_MODERNIZATION
import com.android.systemui.Flags.FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS
import com.android.systemui.Flags.FLAG_STATUS_BAR_USE_REPOS_FOR_CALL_CHIP
import com.android.systemui.SysuiTestCase
@@ -104,7 +103,8 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
fun setUp() {
allowTestableLooperAsMainThread()
TestableLooper.get(this).runWithLooper {
- chipView = LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+ chipView =
+ LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
}
whenever(mockStatusBarWindowControllerStore.defaultDisplay)
@@ -134,12 +134,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
testScope.runCurrent()
reset(mockOngoingCallListener)
- whenever(
- mockIActivityManager.getUidProcessState(
- eq(CALL_UID),
- any(),
- )
- )
+ whenever(mockIActivityManager.getUidProcessState(eq(CALL_UID), any()))
.thenReturn(PROC_STATE_INVISIBLE)
}
@@ -225,38 +220,18 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
@Test
fun notifRepoHasOngoingCallNotifThenScreeningNotif_listenerNotifiedTwice() {
- setNotifOnRepo(
- activeNotificationModel(
- key = "notif",
- callType = CallType.Ongoing,
- )
- )
+ setNotifOnRepo(activeNotificationModel(key = "notif", callType = CallType.Ongoing))
- setNotifOnRepo(
- activeNotificationModel(
- key = "notif",
- callType = CallType.Screening,
- )
- )
+ setNotifOnRepo(activeNotificationModel(key = "notif", callType = CallType.Screening))
verify(mockOngoingCallListener, times(2)).onOngoingCallStateChanged(any())
}
@Test
fun notifRepoHasOngoingCallNotifThenScreeningNotif_repoUpdated() {
- setNotifOnRepo(
- activeNotificationModel(
- key = "notif",
- callType = CallType.Ongoing,
- )
- )
+ setNotifOnRepo(activeNotificationModel(key = "notif", callType = CallType.Ongoing))
- setNotifOnRepo(
- activeNotificationModel(
- key = "notif",
- callType = CallType.Screening,
- )
- )
+ setNotifOnRepo(activeNotificationModel(key = "notif", callType = CallType.Screening))
assertThat(ongoingCallRepository.ongoingCallState.value)
.isInstanceOf(OngoingCallModel.NoCall::class.java)
@@ -289,7 +264,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
chipView.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
- View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
)
assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_time)?.measuredWidth)
@@ -309,7 +284,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
chipView.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
- View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
)
assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_time)?.measuredWidth)
@@ -323,11 +298,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
// Re-create the notification each time so that it's considered a different object and
// will re-trigger the whole flow.
setNotifOnRepo(
- activeNotificationModel(
- key = "notif$i",
- callType = CallType.Ongoing,
- whenTime = 44,
- )
+ activeNotificationModel(key = "notif$i", callType = CallType.Ongoing, whenTime = 44)
)
}
@@ -337,12 +308,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
/** Regression test for b/216248574. */
@Test
fun repoHasCallNotif_getUidProcessStateThrowsException_noCrash() {
- whenever(
- mockIActivityManager.getUidProcessState(
- eq(CALL_UID),
- any(),
- )
- )
+ whenever(mockIActivityManager.getUidProcessState(eq(CALL_UID), any()))
.thenThrow(SecurityException())
// No assert required, just check no crash
@@ -352,14 +318,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
/** Regression test for b/216248574. */
@Test
fun repoHasCallNotif_registerUidObserverThrowsException_noCrash() {
- whenever(
- mockIActivityManager.registerUidObserver(
- any(),
- any(),
- any(),
- any(),
- )
- )
+ whenever(mockIActivityManager.registerUidObserver(any(), any(), any(), any()))
.thenThrow(SecurityException())
// No assert required, just check no crash
@@ -416,11 +375,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
@Test
fun hasOngoingCall_repoHasUnrelatedNotif_returnsFalse() {
setNotifOnRepo(
- activeNotificationModel(
- key = "unrelated",
- callType = CallType.None,
- uid = CALL_UID,
- )
+ activeNotificationModel(key = "unrelated", callType = CallType.None, uid = CALL_UID)
)
assertThat(controller.hasOngoingCall()).isFalse()
@@ -441,20 +396,11 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
@Test
fun hasOngoingCall_repoHasCallNotifAndCallAppNotVisible_returnsTrue() {
- whenever(
- mockIActivityManager.getUidProcessState(
- eq(CALL_UID),
- any(),
- )
- )
+ whenever(mockIActivityManager.getUidProcessState(eq(CALL_UID), any()))
.thenReturn(PROC_STATE_INVISIBLE)
setNotifOnRepo(
- activeNotificationModel(
- key = "notif",
- callType = CallType.Ongoing,
- uid = CALL_UID,
- )
+ activeNotificationModel(key = "notif", callType = CallType.Ongoing, uid = CALL_UID)
)
assertThat(controller.hasOngoingCall()).isTrue()
@@ -466,11 +412,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
.thenReturn(PROC_STATE_VISIBLE)
setNotifOnRepo(
- activeNotificationModel(
- key = "notif",
- callType = CallType.Ongoing,
- uid = CALL_UID,
- )
+ activeNotificationModel(key = "notif", callType = CallType.Ongoing, uid = CALL_UID)
)
assertThat(controller.hasOngoingCall()).isFalse()
@@ -482,11 +424,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
controller.setChipView(invalidChipView)
setNotifOnRepo(
- activeNotificationModel(
- key = "notif",
- callType = CallType.Ongoing,
- uid = CALL_UID,
- )
+ activeNotificationModel(key = "notif", callType = CallType.Ongoing, uid = CALL_UID)
)
assertThat(controller.hasOngoingCall()).isFalse()
@@ -532,7 +470,7 @@ class OngoingCallControllerViaRepoTest : SysuiTestCase() {
lateinit var newChipView: View
TestableLooper.get(this).runWithLooper {
newChipView =
- LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+ LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
}
// Change the chip view associated with the controller.
diff --git a/packages/SystemUI/res/layout/ongoing_activity_chip.xml b/packages/SystemUI/res/layout/ongoing_activity_chip_content.xml
index 51217d4e27bd..6f42286d9fac 100644
--- a/packages/SystemUI/res/layout/ongoing_activity_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip_content.xml
@@ -13,17 +13,11 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<!-- Have the wrapper frame layout match the parent height so that we get a larger touch area for
- the chip. -->
-<FrameLayout
+
+<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|start"
- android:layout_marginStart="5dp"
->
- <!-- TODO(b/332662551): Update this content description when this supports more than just
- phone calls. -->
+ >
+
<com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
android:id="@+id/ongoing_activity_chip_background"
android:layout_width="wrap_content"
@@ -39,7 +33,7 @@
<ImageView
android:src="@*android:drawable/ic_phone"
android:id="@+id/ongoing_activity_chip_icon"
- android:contentDescription="@string/ongoing_phone_call_content_description"
+ android:contentDescription="@string/ongoing_call_content_description"
android:layout_width="@dimen/ongoing_activity_chip_icon_size"
android:layout_height="@dimen/ongoing_activity_chip_icon_size"
android:tint="?android:attr/colorPrimary"
@@ -72,4 +66,4 @@
/>
</com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer>
-</FrameLayout>
+</merge>
diff --git a/packages/SystemUI/res/layout/ongoing_activity_chip_primary.xml b/packages/SystemUI/res/layout/ongoing_activity_chip_primary.xml
new file mode 100644
index 000000000000..114fe6c0d849
--- /dev/null
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip_primary.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 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.
+ -->
+
+<FrameLayout
+ style="@style/StatusBar.Chip.RootView">
+
+ <include layout="@layout/ongoing_activity_chip_content" />
+
+</FrameLayout>
+
diff --git a/packages/SystemUI/res/layout/ongoing_activity_chip_secondary.xml b/packages/SystemUI/res/layout/ongoing_activity_chip_secondary.xml
new file mode 100644
index 000000000000..81a782236a49
--- /dev/null
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip_secondary.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 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.
+ -->
+
+<com.android.systemui.statusbar.chips.ui.view.SecondaryOngoingActivityChip
+ style="@style/StatusBar.Chip.RootView">
+
+ <include layout="@layout/ongoing_activity_chip_content" />
+
+</com.android.systemui.statusbar.chips.ui.view.SecondaryOngoingActivityChip>
+
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 1f4dea91db01..e4da4729ad0d 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -103,10 +103,10 @@
android:gravity="center_vertical|start"
/>
- <include layout="@layout/ongoing_activity_chip"
+ <include layout="@layout/ongoing_activity_chip_primary"
android:id="@+id/ongoing_activity_chip_primary"/>
- <include layout="@layout/ongoing_activity_chip"
+ <include layout="@layout/ongoing_activity_chip_secondary"
android:id="@+id/ongoing_activity_chip_secondary"
android:visibility="gone"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 399c2d60094d..cd37c22c8bc3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3367,8 +3367,8 @@
<!-- Accessibility announcement to inform user to unlock using the fingerprint sensor [CHAR LIMIT=NONE] -->
<string name="accessibility_fingerprint_bouncer">Authentication required. Touch the fingerprint sensor to authenticate.</string>
- <!-- Content description for a chip in the status bar showing that the user is currently on a phone call. [CHAR LIMIT=NONE] -->
- <string name="ongoing_phone_call_content_description">Ongoing phone call</string>
+ <!-- Content description for a chip in the status bar showing that the user is currently on a call. [CHAR LIMIT=NONE] -->
+ <string name="ongoing_call_content_description">Ongoing call</string>
<!-- Provider Model: Default title of the mobile network in the mobile layout. [CHAR LIMIT=50] -->
<string name="mobile_data_settings_title">Mobile data</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 71806781b98e..0503dbfab71d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -73,6 +73,15 @@
<style name="StatusBar" />
<style name="StatusBar.Chip" />
+ <style name="StatusBar.Chip.RootView">
+ <item name="android:layout_width">wrap_content</item>
+ <!-- Have the root chip view match the parent height so that we get a larger touch area for
+ the chip. -->
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:layout_gravity">center_vertical|start</item>
+ <item name="android:layout_marginStart">5dp</item>
+ </style>
+
<style name="StatusBar.Chip.Text">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
index 85b50d3320dd..de08e3891902 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
@@ -132,7 +132,7 @@ constructor(
private val phoneIcon =
Icon.Resource(
com.android.internal.R.drawable.ic_phone,
- ContentDescription.Resource(R.string.ongoing_phone_call_content_description),
+ ContentDescription.Resource(R.string.ongoing_call_content_description),
)
private val TAG = "CallVM".pad()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
index a7dbb47bc609..bcd8cfaa5c5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
@@ -100,14 +100,14 @@ constructor(
)
}
- if (Flags.promoteNotificationsAutomatically()) {
+ if (
+ Flags.promoteNotificationsAutomatically() &&
+ this.promotedContent.wasPromotedAutomatically
+ ) {
// When we're promoting notifications automatically, the `when` time set on the
// notification will likely just be set to the current time, which would cause the chip
// to always show "now". We don't want early testers to get that experience since it's
// not what will happen at launch, so just don't show any time.
- // TODO(b/364653005): Only ignore the `when` time if the notification was
- // *automatically* promoted (as opposed to being legitimately promoted by the
- // criteria). We'll need to track that status somehow.
return OngoingActivityChipModel.Shown.IconOnly(icon, colors, onClickListener)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
index 0c4c1a71ccc7..c40df98f39ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
@@ -149,10 +149,9 @@ object OngoingActivityChipBinder {
// 1. Set up the right visual params.
with(iconView) {
id = CUSTOM_ICON_VIEW_ID
- // TODO(b/354930838): Update the content description to not include "phone" and maybe
- // include the app name.
+ // TODO(b/354930838): For RON chips, use the app name for the content description.
contentDescription =
- context.resources.getString(R.string.ongoing_phone_call_content_description)
+ context.resources.getString(R.string.ongoing_call_content_description)
tintView(iconTint)
}
@@ -349,14 +348,21 @@ object OngoingActivityChipBinder {
}
// Clickable chips need to be a minimum size for accessibility purposes, but let
// non-clickable chips be smaller.
- if (chipModel.onClickListener != null) {
- chipBackgroundView.minimumWidth =
+ val minimumWidth =
+ if (chipModel.onClickListener != null) {
chipBackgroundView.context.resources.getDimensionPixelSize(
R.dimen.min_clickable_item_size
)
- } else {
- chipBackgroundView.minimumWidth = 0
- }
+ } else {
+ 0
+ }
+ // The background view needs the minimum width so it only fills the area required (e.g. the
+ // 3-2-1 screen record countdown chip isn't tappable so it should have a small-width
+ // background).
+ chipBackgroundView.minimumWidth = minimumWidth
+ // The root view needs the minimum width so the second chip can hide if there isn't enough
+ // room for the chip -- see [SecondaryOngoingActivityChip].
+ chipView.minimumWidth = minimumWidth
}
@IdRes private val CUSTOM_ICON_VIEW_ID = R.id.ongoing_activity_chip_custom_icon
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/SecondaryOngoingActivityChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/SecondaryOngoingActivityChip.kt
new file mode 100644
index 000000000000..f790dc94f7f2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/SecondaryOngoingActivityChip.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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.chips.ui.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+
+/**
+ * A custom class for the secondary ongoing activity chip. This class will completely hide itself if
+ * there isn't enough room for the mimimum size chip.
+ *
+ * [this.minimumWidth] must be set correctly in order for this class to work.
+ */
+class SecondaryOngoingActivityChip(context: Context, attrs: AttributeSet) :
+ FrameLayout(context, attrs) {
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+ if (measuredWidth < this.minimumWidth) {
+ // There isn't enough room to fit even the minimum content required, so hide completely.
+ // Changing visibility ensures that the content description is not read aloud.
+ visibility = GONE
+ setMeasuredDimension(0, 0)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt
index bb164848320e..395746280f6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt
@@ -22,7 +22,16 @@ import com.android.systemui.statusbar.notification.collection.coordinator.dagger
import javax.inject.Inject
/** A coordinator that may automatically promote certain notifications. */
-interface AutomaticPromotionCoordinator : Coordinator
+interface AutomaticPromotionCoordinator : Coordinator {
+ companion object {
+ /**
+ * An extra that should be set on notifications that were automatically promoted. Used in
+ * case we want to disable certain features for only automatically promoted notifications
+ * (but not normally promoted notifications).
+ */
+ const val EXTRA_WAS_AUTOMATICALLY_PROMOTED = "android.wasAutomaticallyPromoted"
+ }
+}
/** A default implementation of [AutomaticPromotionCoordinator] that doesn't promote anything. */
@CoordinatorScope
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
index 7d2827666227..df2eb08e8fa4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
@@ -24,14 +24,14 @@ import android.app.Notification.EXTRA_CHRONOMETER_COUNT_DOWN
import android.app.Notification.EXTRA_SUB_TEXT
import android.app.Notification.EXTRA_TEXT
import android.app.Notification.EXTRA_TITLE
-import android.app.Notification.FLAG_PROMOTED_ONGOING
import android.app.Notification.ProgressStyle
import android.content.Context
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.shade.ShadeDisplayAware
-import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_WAS_AUTOMATICALLY_PROMOTED
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Companion.isPromotedForStatusBarChip
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.When
import javax.inject.Inject
@@ -65,12 +65,8 @@ constructor(
return null
}
- // Notification.isPromotedOngoing checks the ui_rich_ongoing flag, but we want the status
- // bar chip to be ready before all the features behind the ui_rich_ongoing flag are ready.
- val isPromotedForStatusBarChip =
- StatusBarNotifChips.isEnabled && (notification.flags and FLAG_PROMOTED_ONGOING) != 0
- val isPromoted = notification.isPromotedOngoing() || isPromotedForStatusBarChip
- if (!isPromoted) {
+ // The status bar chips rely on this extractor, so take them into account for promotion.
+ if (!isPromotedForStatusBarChip(notification)) {
logger.logExtractionSkipped(entry, "isPromotedOngoing returned false")
return null
}
@@ -80,6 +76,8 @@ constructor(
// TODO: Pitch a fit if style is unsupported or mandatory fields are missing once
// FLAG_PROMOTED_ONGOING is set reliably and we're not testing status bar chips.
+ contentBuilder.wasPromotedAutomatically =
+ notification.extras.getBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, false)
contentBuilder.skeletonSmallIcon = entry.icons.aodIcon?.sourceIcon
contentBuilder.appName = notification.loadHeaderAppName(context)
contentBuilder.subText = notification.subText()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
index 74809fd8622f..258d80c60cd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar.notification.promoted.shared.model
import android.annotation.DrawableRes
+import android.app.Notification
+import android.app.Notification.FLAG_PROMOTED_ONGOING
import android.graphics.drawable.Icon
import androidx.annotation.ColorInt
import com.android.internal.widget.NotificationProgressModel
@@ -31,6 +33,10 @@ data class PromotedNotificationContentModel(
val identity: Identity,
// for all styles:
+ /**
+ * True if this notification was automatically promoted - see [AutomaticPromotionCoordinator].
+ */
+ val wasPromotedAutomatically: Boolean,
val skeletonSmallIcon: Icon?, // TODO(b/377568176): Make into an IconModel.
val appName: CharSequence?,
val subText: CharSequence?,
@@ -58,6 +64,7 @@ data class PromotedNotificationContentModel(
val progress: NotificationProgressModel?,
) {
class Builder(val key: String) {
+ var wasPromotedAutomatically: Boolean = false
var skeletonSmallIcon: Icon? = null
var appName: CharSequence? = null
var subText: CharSequence? = null
@@ -83,6 +90,7 @@ data class PromotedNotificationContentModel(
fun build() =
PromotedNotificationContentModel(
identity = Identity(key, style),
+ wasPromotedAutomatically = wasPromotedAutomatically,
skeletonSmallIcon = skeletonSmallIcon,
appName = appName,
subText = subText,
@@ -134,5 +142,18 @@ data class PromotedNotificationContentModel(
@JvmStatic
fun featureFlagEnabled(): Boolean =
PromotedNotificationUi.isEnabled || StatusBarNotifChips.isEnabled
+
+ /**
+ * Returns true if the given notification should be considered promoted when deciding
+ * whether or not to show the status bar chip UI.
+ */
+ fun isPromotedForStatusBarChip(notification: Notification): Boolean {
+ // Notification.isPromotedOngoing checks the ui_rich_ongoing flag, but we want the
+ // status bar chip to be ready before all the features behind the ui_rich_ongoing flag
+ // are ready.
+ val isPromotedForStatusBarChip =
+ StatusBarNotifChips.isEnabled && (notification.flags and FLAG_PROMOTED_ONGOING) != 0
+ return notification.isPromotedOngoing() || isPromotedForStatusBarChip
+ }
}
}