diff options
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 + } } } |