summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/layout/ongoing_activity_chip.xml11
-rw-r--r--packages/SystemUI/res/values/dimens.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt60
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt135
6 files changed, 231 insertions, 13 deletions
diff --git a/packages/SystemUI/res/layout/ongoing_activity_chip.xml b/packages/SystemUI/res/layout/ongoing_activity_chip.xml
index cd5c37d43633..12967fcf8555 100644
--- a/packages/SystemUI/res/layout/ongoing_activity_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip.xml
@@ -23,8 +23,7 @@
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. -->
+ <!-- TODO(b/354930838): Fix these paddings for the new screen chips. -->
<com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
android:id="@+id/ongoing_activity_chip_background"
android:layout_width="wrap_content"
@@ -32,9 +31,8 @@
android:layout_gravity="center_vertical"
android:gravity="center"
android:background="@drawable/ongoing_activity_chip_bg"
- android:paddingStart="@dimen/ongoing_activity_chip_side_padding"
- android:paddingEnd="@dimen/ongoing_activity_chip_side_padding"
- android:contentDescription="@string/ongoing_phone_call_content_description"
+ android:paddingStart="@dimen/ongoing_activity_chip_side_padding_with_notif_icon"
+ android:paddingEnd="@dimen/ongoing_activity_chip_side_padding_with_notif_icon"
android:minWidth="@dimen/min_clickable_item_size"
>
@@ -44,6 +42,7 @@
android:layout_width="@dimen/ongoing_activity_chip_icon_size"
android:layout_height="@dimen/ongoing_activity_chip_icon_size"
android:tint="?android:attr/colorPrimary"
+ android:visibility="gone"
/>
<com.android.systemui.statusbar.chips.ui.view.ChipChronometer
@@ -52,7 +51,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:gravity="center|start"
- android:paddingStart="@dimen/ongoing_activity_chip_icon_text_padding"
+ android:paddingEnd="@dimen/ongoing_activity_chip_text_end_padding_with_notif_icon"
android:textAppearance="@android:style/TextAppearance.Material.Small"
android:fontFamily="@*android:string/config_headlineFontFamily"
android:textColor="?android:attr/colorPrimary"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index cf91326a4b76..0095f39daaa5 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1727,9 +1727,15 @@
<!-- Ongoing activity chip -->
<dimen name="ongoing_activity_chip_side_padding">12dp</dimen>
+ <!-- The start padding to use on the activity chip if the icon comes from the notification's smallIcon field (the small notif icons embed their own padding, so the chip itself can have less padding) -->
+ <dimen name="ongoing_activity_chip_side_padding_with_notif_icon">6dp</dimen>
<dimen name="ongoing_activity_chip_icon_size">16dp</dimen>
+ <!-- The size to use for the icon in the ongoing activity chip if the icon comes from the notification's smallIcon field -->
+ <dimen name="ongoing_activity_chip_notif_icon_size">22dp</dimen>
+
<!-- The padding between the icon and the text. -->
<dimen name="ongoing_activity_chip_icon_text_padding">4dp</dimen>
+ <dimen name="ongoing_activity_chip_text_end_padding_with_notif_icon">6dp</dimen>
<dimen name="ongoing_activity_chip_corner_radius">28dp</dimen>
<!-- Status bar user chip -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
index 331d3cc4c21b..a39c48772f1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
@@ -123,6 +123,8 @@ constructor(
// Construct the status bar icon view.
val sbIcon = iconBuilder.createIconView(entry)
sbIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE
+ val sbChipIcon = iconBuilder.createIconView(entry)
+ sbChipIcon.scaleType = ImageView.ScaleType.CENTER_INSIDE
// Construct the shelf icon view.
val shelfIcon = iconBuilder.createIconView(entry)
@@ -139,9 +141,17 @@ constructor(
try {
setIcon(entry, normalIconDescriptor, sbIcon)
+ setIcon(entry, normalIconDescriptor, sbChipIcon)
setIcon(entry, sensitiveIconDescriptor, shelfIcon)
setIcon(entry, sensitiveIconDescriptor, aodIcon)
- entry.icons = IconPack.buildPack(sbIcon, shelfIcon, aodIcon, entry.icons)
+ entry.icons =
+ IconPack.buildPack(
+ sbIcon,
+ sbChipIcon,
+ shelfIcon,
+ aodIcon,
+ entry.icons,
+ )
} catch (e: InflationException) {
entry.icons = IconPack.buildEmptyPack(entry.icons)
throw e
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java
index d029ce722af9..82bb5ef7a448 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconPack.java
@@ -29,6 +29,7 @@ public final class IconPack {
private final boolean mAreIconsAvailable;
@Nullable private final StatusBarIconView mStatusBarIcon;
+ @Nullable private final StatusBarIconView mStatusBarChipIcon;
@Nullable private final StatusBarIconView mShelfIcon;
@Nullable private final StatusBarIconView mAodIcon;
@@ -43,7 +44,7 @@ public final class IconPack {
* haven't been inflated yet or there was an error while inflating them).
*/
public static IconPack buildEmptyPack(@Nullable IconPack fromSource) {
- return new IconPack(false, null, null, null, fromSource);
+ return new IconPack(false, null, null, null, null, fromSource);
}
/**
@@ -51,20 +52,24 @@ public final class IconPack {
*/
public static IconPack buildPack(
@NonNull StatusBarIconView statusBarIcon,
+ @NonNull StatusBarIconView statusBarChipIcon,
@NonNull StatusBarIconView shelfIcon,
@NonNull StatusBarIconView aodIcon,
@Nullable IconPack source) {
- return new IconPack(true, statusBarIcon, shelfIcon, aodIcon, source);
+ return new IconPack(
+ true, statusBarIcon, statusBarChipIcon, shelfIcon, aodIcon, source);
}
private IconPack(
boolean areIconsAvailable,
@Nullable StatusBarIconView statusBarIcon,
+ @Nullable StatusBarIconView statusBarChipIcon,
@Nullable StatusBarIconView shelfIcon,
@Nullable StatusBarIconView aodIcon,
@Nullable IconPack source) {
mAreIconsAvailable = areIconsAvailable;
mStatusBarIcon = statusBarIcon;
+ mStatusBarChipIcon = statusBarChipIcon;
mShelfIcon = shelfIcon;
mAodIcon = aodIcon;
if (source != null) {
@@ -79,6 +84,17 @@ public final class IconPack {
}
/**
+ * The version of the notification icon that appears inside a chip within the status bar.
+ *
+ * Separate from {@link #getStatusBarIcon()} so that we don't have to worry about detaching and
+ * re-attaching the same view when the chip appears and hides.
+ */
+ @Nullable
+ public StatusBarIconView getStatusBarChipIcon() {
+ return mStatusBarChipIcon;
+ }
+
+ /**
* The version of the icon that appears in the "shelf" at the bottom of the notification shade.
* In general, this icon also appears somewhere on the notification and is "sucked" into the
* shelf as the scrolls beyond it.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index 9f98b54093c2..6c1aebc00862 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -25,8 +25,12 @@ import android.app.UidObserver
import android.content.Context
import android.util.Log
import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.annotation.IdRes
import androidx.annotation.VisibleForTesting
import com.android.internal.jank.InteractionJankMonitor
+import com.android.settingslib.Utils
import com.android.systemui.CoreStartable
import com.android.systemui.Dumpable
import com.android.systemui.Flags
@@ -37,6 +41,7 @@ import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
+import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.view.ChipChronometer
import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore
@@ -114,6 +119,7 @@ constructor(
Notification.EXTRA_CALL_TYPE,
-1
) == CALL_TYPE_ONGOING,
+ entry.icons.statusBarChipIcon,
statusBarSwipedAway = callNotificationInfo?.statusBarSwipedAway ?: false
)
if (newOngoingCallInfo == callNotificationInfo) {
@@ -156,8 +162,7 @@ constructor(
fun setChipView(chipView: View) {
tearDownChipView()
this.chipView = chipView
- val backgroundView: ChipBackgroundContainer? =
- chipView.findViewById(R.id.ongoing_activity_chip_background)
+ val backgroundView: ChipBackgroundContainer? = chipView.getBackgroundView()
backgroundView?.maxHeightFetcher = { statusBarWindowController.statusBarHeight }
if (hasOngoingCall()) {
updateChip()
@@ -236,6 +241,8 @@ constructor(
timeView.setShouldHideText(true)
timeView.stop()
}
+
+ updateChipIcon(currentCallNotificationInfo, currentChipView)
updateChipClickListener()
}
@@ -261,6 +268,38 @@ constructor(
}
}
+ private fun updateChipIcon(callInfo: CallNotificationInfo, currentChipView: View) {
+ val backgroundView = currentChipView.getBackgroundView() ?: return
+ backgroundView.removeView(currentChipView.getIconView())
+
+ val iconView = callInfo.iconView ?: return
+ with(iconView) {
+ id = ICON_ID
+ imageTintList = Utils.getColorAttr(context, android.R.attr.colorPrimary)
+ // TODO(b/354930838): Update the content description to not include "phone".
+ contentDescription =
+ context.resources.getString(R.string.ongoing_phone_call_content_description)
+ }
+
+ val currentParent = iconView.parent as? ViewGroup
+ // If we're reinflating the view, we may need to detach the icon view from the
+ // old chip before we reattach it to the new one.
+ // See also: NotificationIconContainerViewBinder#bindIcons.
+ if (currentParent != null && currentParent != backgroundView) {
+ currentParent.removeView(iconView)
+ currentParent.removeTransientView(iconView)
+ }
+ backgroundView.addView(iconView, /* index= */ 0, generateIconLayoutParams())
+ }
+
+ private fun generateIconLayoutParams(): FrameLayout.LayoutParams {
+ return FrameLayout.LayoutParams(iconSize, iconSize)
+ }
+
+ private val iconSize: Int
+ get() =
+ context.resources.getDimensionPixelSize(R.dimen.ongoing_activity_chip_notif_icon_size)
+
private fun updateChipClickListener() {
if (Flags.statusBarScreenSharingChips()) {
return
@@ -270,8 +309,7 @@ constructor(
return
}
val currentChipView = chipView
- val backgroundView =
- currentChipView?.findViewById<View>(R.id.ongoing_activity_chip_background)
+ val backgroundView = currentChipView?.getBackgroundView()
val intent = callNotificationInfo?.intent
if (currentChipView != null && backgroundView != null && intent != null) {
currentChipView.setOnClickListener {
@@ -324,6 +362,14 @@ constructor(
return this.findViewById(R.id.ongoing_activity_chip_time)
}
+ private fun View.getBackgroundView(): ChipBackgroundContainer? {
+ return this.findViewById(R.id.ongoing_activity_chip_background)
+ }
+
+ private fun View.getIconView(): View? {
+ return this.findViewById(ICON_ID)
+ }
+
/**
* If there's an active ongoing call, then we will force the status bar to always show, even if
* the user is in immersive mode. However, we also want to give users the ability to swipe away
@@ -353,6 +399,8 @@ constructor(
val uid: Int,
/** True if the call is currently ongoing (as opposed to incoming, screening, etc.). */
val isOngoing: Boolean,
+ /** The view that contains the icon to display in the chip. */
+ val iconView: StatusBarIconView?,
/** True if the user has swiped away the status bar while in this phone call. */
val statusBarSwipedAway: Boolean
) {
@@ -437,6 +485,10 @@ constructor(
}
}
}
+
+ companion object {
+ @IdRes private val ICON_ID = R.id.ongoing_activity_chip_icon
+ }
}
private fun isCallNotification(entry: NotificationEntry): Boolean {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
index 7273d9f55259..8aead706db13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
@@ -37,8 +37,10 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
+import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository
import com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureHandler
+import com.android.systemui.statusbar.notification.icon.IconPack
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
@@ -253,6 +255,139 @@ class OngoingCallControllerTest : SysuiTestCase() {
.isGreaterThan(0)
}
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun onEntryUpdated_notifIconsNotSet_noIconInChip() {
+ val notification = createOngoingCallNotifEntry()
+
+ notifCollectionListener.onEntryUpdated(notification)
+
+ assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_icon)).isNull()
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun onEntryUpdated_notifIconsSetToNull_noIconInChip() {
+ val notification = createOngoingCallNotifEntry()
+ notification.icons = IconPack.buildEmptyPack(/* fromSource= */ null)
+
+ notifCollectionListener.onEntryUpdated(notification)
+
+ assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_icon)).isNull()
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun onEntryUpdated_notifIconsIncluded_statusBarChipIconUsed() {
+ val notification = createOngoingCallNotifEntry()
+
+ val statusBarChipIconView =
+ StatusBarIconView(
+ context,
+ /* slot= */ "OngoingCallControllerTest",
+ notification.sbn,
+ )
+ notification.icons =
+ IconPack.buildPack(
+ /* statusBarIcon= */ mock(StatusBarIconView::class.java),
+ statusBarChipIconView,
+ /* shelfIcon= */ mock(StatusBarIconView::class.java),
+ /* aodIcon= */ mock(StatusBarIconView::class.java),
+ /* source= */ null,
+ )
+
+ notifCollectionListener.onEntryUpdated(notification)
+
+ assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_icon))
+ .isEqualTo(statusBarChipIconView)
+ assertThat(statusBarChipIconView.contentDescription)
+ .isEqualTo(context.resources.getString(R.string.ongoing_phone_call_content_description))
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun onEntryUpdated_newNotifIcon_newIconUsed() {
+ val notification = createOngoingCallNotifEntry()
+
+ val firstStatusBarChipIconView =
+ StatusBarIconView(
+ context,
+ /* slot= */ "OngoingCallControllerTest",
+ notification.sbn,
+ )
+ notification.icons =
+ IconPack.buildPack(
+ /* statusBarIcon= */ mock(StatusBarIconView::class.java),
+ firstStatusBarChipIconView,
+ /* shelfIcon= */ mock(StatusBarIconView::class.java),
+ /* aodIcon= */ mock(StatusBarIconView::class.java),
+ /* source= */ null,
+ )
+ notifCollectionListener.onEntryUpdated(notification)
+
+ assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_icon))
+ .isEqualTo(firstStatusBarChipIconView)
+
+ // WHEN the notification is updated with a new icon
+ val secondStatusBarChipIconView =
+ StatusBarIconView(
+ context,
+ /* slot= */ "OngoingCallControllerTestTheSecond",
+ notification.sbn,
+ )
+ notification.icons =
+ IconPack.buildPack(
+ /* statusBarIcon= */ mock(StatusBarIconView::class.java),
+ secondStatusBarChipIconView,
+ /* shelfIcon= */ mock(StatusBarIconView::class.java),
+ /* aodIcon= */ mock(StatusBarIconView::class.java),
+ /* source= */ null,
+ )
+ notifCollectionListener.onEntryUpdated(notification)
+
+ // THEN the new icon is used
+ assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_icon))
+ .isEqualTo(secondStatusBarChipIconView)
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS)
+ fun chipViewReinflated_iconViewMovedToNewChip() {
+ val notification = createOngoingCallNotifEntry()
+ val statusBarChipIconView =
+ StatusBarIconView(
+ context,
+ /* slot= */ "OngoingCallControllerTest",
+ notification.sbn,
+ )
+ notification.icons =
+ IconPack.buildPack(
+ /* statusBarIcon= */ mock(StatusBarIconView::class.java),
+ statusBarChipIconView,
+ /* shelfIcon= */ mock(StatusBarIconView::class.java),
+ /* aodIcon= */ mock(StatusBarIconView::class.java),
+ /* source= */ null,
+ )
+
+ notifCollectionListener.onEntryUpdated(notification)
+
+ assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_icon))
+ .isEqualTo(statusBarChipIconView)
+
+ // WHEN we get a new chip view
+ lateinit var newChipView: View
+ TestableLooper.get(this).runWithLooper {
+ newChipView =
+ LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+ }
+ controller.setChipView(newChipView)
+
+ // THEN the icon is detached from the old view and attached to the new one
+ assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_icon)).isNull()
+ assertThat(newChipView.findViewById<View>(R.id.ongoing_activity_chip_icon))
+ .isEqualTo(statusBarChipIconView)
+ }
+
/** Regression test for b/194731244. */
@Test
fun onEntryUpdated_calledManyTimes_uidObserverOnlyRegisteredOnce() {