Loading packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +8 −3 Original line number Diff line number Diff line Loading @@ -323,9 +323,14 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi * Update the icon dimens and drawable with current resources */ public void updateIconDimens() { Trace.beginSection("StatusBarIconView#updateIconDimens"); try { reloadDimens(); updateDrawable(); maybeUpdateIconScaleDimens(); } finally { Trace.endSection(); } } private void reloadDimens() { Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt +26 −17 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.icon.domain.interactor import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.statusbar.data.repository.NotificationListenerSettingsRepository import com.android.systemui.statusbar.notification.data.repository.NotificationsKeyguardViewStateRepository Loading @@ -26,11 +27,13 @@ import com.android.systemui.statusbar.notification.shared.ActiveNotificationMode import com.android.wm.shell.bubbles.Bubbles import java.util.Optional import javax.inject.Inject import kotlin.coroutines.CoroutineContext import kotlin.jvm.optionals.getOrNull import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn /** Domain logic related to notification icons. */ class NotificationIconsInteractor Loading Loading @@ -103,11 +106,13 @@ constructor( class AlwaysOnDisplayNotificationIconsInteractor @Inject constructor( @Background bgContext: CoroutineContext, deviceEntryInteractor: DeviceEntryInteractor, iconsInteractor: NotificationIconsInteractor, ) { val aodNotifs: Flow<Set<ActiveNotificationModel>> = deviceEntryInteractor.isBypassEnabled.flatMapLatest { isBypassEnabled -> deviceEntryInteractor.isBypassEnabled .flatMapLatest { isBypassEnabled -> iconsInteractor.filteredNotifSet( showAmbient = false, showDismissed = false, Loading @@ -115,17 +120,20 @@ constructor( showPulsing = !isBypassEnabled, ) } .flowOn(bgContext) } /** Domain logic related to notification icons shown in the status bar. */ class StatusBarNotificationIconsInteractor @Inject constructor( @Background bgContext: CoroutineContext, iconsInteractor: NotificationIconsInteractor, settingsRepository: NotificationListenerSettingsRepository, ) { val statusBarNotifs: Flow<Set<ActiveNotificationModel>> = settingsRepository.showSilentStatusIcons.flatMapLatest { showSilentIcons -> settingsRepository.showSilentStatusIcons .flatMapLatest { showSilentIcons -> iconsInteractor.filteredNotifSet( forceShowHeadsUp = true, showAmbient = false, Loading @@ -134,4 +142,5 @@ constructor( showRepliedMessages = false, ) } .flowOn(bgContext) } packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerAlwaysOnDisplayViewBinder.kt +22 −19 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import androidx.lifecycle.lifecycleScope import com.android.app.tracing.traceSection import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel Loading Loading @@ -44,7 +45,8 @@ constructor( private val viewStore: AlwaysOnDisplayNotificationIconViewStore, ) { fun bindWhileAttached(view: NotificationIconContainer): DisposableHandle { return view.repeatWhenAttached { return traceSection("NICAlwaysOnDisplay#bindWhileAttached") { view.repeatWhenAttached { lifecycleScope.launch { launch { NotificationIconContainerViewBinder.bind( Loading @@ -68,6 +70,7 @@ constructor( } } } } /** [IconViewStore] for the always-on display. */ class AlwaysOnDisplayNotificationIconViewStore Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt +13 −10 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import androidx.lifecycle.lifecycleScope import com.android.app.tracing.traceSection import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.notification.collection.NotifCollection Loading @@ -39,7 +40,8 @@ constructor( private val viewStore: StatusBarNotificationIconViewStore, ) { fun bindWhileAttached(view: NotificationIconContainer): DisposableHandle { return view.repeatWhenAttached { return traceSection("NICStatusBar#bindWhileAttached") { view.repeatWhenAttached { lifecycleScope.launch { NotificationIconContainerViewBinder.bind( view = view, Loading @@ -53,6 +55,7 @@ constructor( } } } } /** [IconViewStore] for the status bar. */ class StatusBarNotificationIconViewStore @Inject constructor(notifCollection: NotifCollection) : Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt +79 −69 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import android.widget.FrameLayout import androidx.annotation.ColorInt import androidx.collection.ArrayMap import androidx.lifecycle.lifecycleScope import com.android.app.tracing.traceSection import com.android.internal.R as RInternal import com.android.internal.statusbar.StatusBarIcon import com.android.internal.util.ContrastColorUtil import com.android.systemui.common.ui.ConfigurationState Loading @@ -48,8 +50,10 @@ import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.Job import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** Binds a view-model to a [NotificationIconContainer]. */ Loading @@ -65,8 +69,8 @@ object NotificationIconContainerViewBinder { ): Unit = coroutineScope { launch { val contrastColorUtil = ContrastColorUtil.getInstance(view.context) val iconColors: Flow<NotificationIconColors> = viewModel.iconColors.mapNotNull { it.iconColors(view.viewBounds) } val iconColors: StateFlow<NotificationIconColors> = viewModel.iconColors.mapNotNull { it.iconColors(view.viewBounds) }.stateIn(this) viewModel.icons.bindIcons( view, configuration, Loading Loading @@ -111,6 +115,14 @@ object NotificationIconContainerViewBinder { ): Unit = coroutineScope { view.setUseIncreasedIconScale(true) launch { // Collect state shared across all icon views, so that we are not duplicating collects // for each individual icon. val color: StateFlow<Int> = configuration .getColorAttr(R.attr.wallpaperTextColor, DEFAULT_AOD_ICON_COLOR) .stateIn(this) val tintAlpha = viewModel.tintAlpha.stateIn(this) val animsEnabled = viewModel.areIconAnimationsEnabled.stateIn(this) viewModel.icons.bindIcons( view, configuration, Loading @@ -118,29 +130,15 @@ object NotificationIconContainerViewBinder { notifyBindingFailures = { failureTracker.aodFailures = it }, viewStore, ) { _, sbiv -> viewModel.bindAodStatusBarIconView(sbiv, configuration) } } launch { viewModel.areContainerChangesAnimated.bindAnimationsEnabled(view) } } private suspend fun NotificationIconContainerAlwaysOnDisplayViewModel.bindAodStatusBarIconView( sbiv: StatusBarIconView, configuration: ConfigurationState, ) { coroutineScope { launch { val color: Flow<Int> = configuration.getColorAttr( R.attr.wallpaperTextColor, DEFAULT_AOD_ICON_COLOR, ) StatusBarIconViewBinder.bindColor(sbiv, color) } launch { StatusBarIconViewBinder.bindColor(sbiv, color) } launch { StatusBarIconViewBinder.bindTintAlpha(sbiv, tintAlpha) } launch { StatusBarIconViewBinder.bindAnimationsEnabled(sbiv, areIconAnimationsEnabled) } launch { StatusBarIconViewBinder.bindAnimationsEnabled(sbiv, animsEnabled) } } } } launch { viewModel.areContainerChangesAnimated.bindAnimationsEnabled(view) } } /** Binds to [NotificationIconContainer.setAnimationsEnabled] */ private suspend fun Flow<Boolean>.bindAnimationsEnabled(view: NotificationIconContainer) { Loading Loading @@ -184,11 +182,9 @@ object NotificationIconContainerViewBinder { notifyBindingFailures: (Collection<String>) -> Unit, viewStore: IconViewStore, bindIcon: suspend (iconKey: String, view: StatusBarIconView) -> Unit = { _, _ -> }, ) { ): Unit = coroutineScope { val iconSizeFlow: Flow<Int> = configuration.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_icon_size_sp, ) configuration.getDimensionPixelSize(RInternal.dimen.status_bar_icon_size_sp) val iconHorizontalPaddingFlow: Flow<Int> = configuration.getDimensionPixelSize(R.dimen.status_bar_icon_horizontal_margin) val layoutParams: Flow<FrameLayout.LayoutParams> = Loading @@ -199,6 +195,7 @@ object NotificationIconContainerViewBinder { -> FrameLayout.LayoutParams(iconSize + 2 * iconHPadding, statusBarHeight) } .stateIn(this) try { bindIcons(view, layoutParams, notifyBindingFailures, viewStore, bindIcon) } finally { Loading @@ -217,7 +214,7 @@ object NotificationIconContainerViewBinder { val failedBindings = mutableSetOf<String>() val boundViewsByNotifKey = ArrayMap<String, Pair<StatusBarIconView, Job>>() var prevIcons = NotificationIconsViewData() collect { iconsData: NotificationIconsViewData -> collectTracingEach("NotifIconContainer#bindIcons") { iconsData: NotificationIconsViewData -> val iconsDiff = NotificationIconsViewData.computeDifference(iconsData, prevIcons) prevIcons = iconsData Loading @@ -231,9 +228,11 @@ object NotificationIconContainerViewBinder { for (notifKey in iconsDiff.removed) { failedBindings.remove(notifKey) val (child, job) = boundViewsByNotifKey.remove(notifKey) ?: continue traceSection("removeIcon") { view.removeView(child) job.cancel() } } // Add and bind. val toAdd: Sequence<String> = iconsDiff.added.asSequence() + failedBindings.toList() Loading @@ -245,12 +244,16 @@ object NotificationIconContainerViewBinder { continue } failedBindings.remove(notifKey) traceSection("addIcon") { (sbiv.parent as? ViewGroup)?.run { if (this !== view) { Log.wtf(TAG, "StatusBarIconView($notifKey) has an unexpected parent") Log.wtf( TAG, "StatusBarIconView($notifKey) has an unexpected parent", ) } // If the container was re-inflated and re-bound, then SBIVs might still be // attached to the prior view. // If the container was re-inflated and re-bound, then SBIVs might still // be attached to the prior view. removeView(sbiv) // The view might still be transiently added if it was just removed and // added again. Loading @@ -267,16 +270,17 @@ object NotificationIconContainerViewBinder { }, ) } } // Set the maximum number of icons to show in the container. Any icons over this // amount will render as an "overflow dot". val maxIconsAmount: Int = when (iconsData.limitType) { LimitType.MaximumIndex -> { iconsData.visibleIcons .asSequence() .take(iconsData.iconLimit) .count { info -> info.notifKey in boundViewsByNotifKey } iconsData.visibleIcons.asSequence().take(iconsData.iconLimit).count { info -> info.notifKey in boundViewsByNotifKey } } LimitType.MaximumAmount -> { iconsData.iconLimit Loading @@ -289,6 +293,7 @@ object NotificationIconContainerViewBinder { // Re-sort notification icons view.changeViewPositions { traceSection("re-sort") { val expectedChildren: List<StatusBarIconView> = iconsData.visibleIcons.mapNotNull { boundViewsByNotifKey[it.notifKey]?.first Loading @@ -307,6 +312,7 @@ object NotificationIconContainerViewBinder { } } } } /** * Track which groups are being replaced with a different icon instance, but with the same Loading Loading @@ -362,3 +368,7 @@ private val View.viewBounds: Rect /* bottom = */ top + height, ) } private suspend fun <T> Flow<T>.collectTracingEach(tag: String, collector: (T) -> Unit) { collect { traceSection(tag) { collector(it) } } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +8 −3 Original line number Diff line number Diff line Loading @@ -323,9 +323,14 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi * Update the icon dimens and drawable with current resources */ public void updateIconDimens() { Trace.beginSection("StatusBarIconView#updateIconDimens"); try { reloadDimens(); updateDrawable(); maybeUpdateIconScaleDimens(); } finally { Trace.endSection(); } } private void reloadDimens() { Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt +26 −17 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.icon.domain.interactor import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.statusbar.data.repository.NotificationListenerSettingsRepository import com.android.systemui.statusbar.notification.data.repository.NotificationsKeyguardViewStateRepository Loading @@ -26,11 +27,13 @@ import com.android.systemui.statusbar.notification.shared.ActiveNotificationMode import com.android.wm.shell.bubbles.Bubbles import java.util.Optional import javax.inject.Inject import kotlin.coroutines.CoroutineContext import kotlin.jvm.optionals.getOrNull import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn /** Domain logic related to notification icons. */ class NotificationIconsInteractor Loading Loading @@ -103,11 +106,13 @@ constructor( class AlwaysOnDisplayNotificationIconsInteractor @Inject constructor( @Background bgContext: CoroutineContext, deviceEntryInteractor: DeviceEntryInteractor, iconsInteractor: NotificationIconsInteractor, ) { val aodNotifs: Flow<Set<ActiveNotificationModel>> = deviceEntryInteractor.isBypassEnabled.flatMapLatest { isBypassEnabled -> deviceEntryInteractor.isBypassEnabled .flatMapLatest { isBypassEnabled -> iconsInteractor.filteredNotifSet( showAmbient = false, showDismissed = false, Loading @@ -115,17 +120,20 @@ constructor( showPulsing = !isBypassEnabled, ) } .flowOn(bgContext) } /** Domain logic related to notification icons shown in the status bar. */ class StatusBarNotificationIconsInteractor @Inject constructor( @Background bgContext: CoroutineContext, iconsInteractor: NotificationIconsInteractor, settingsRepository: NotificationListenerSettingsRepository, ) { val statusBarNotifs: Flow<Set<ActiveNotificationModel>> = settingsRepository.showSilentStatusIcons.flatMapLatest { showSilentIcons -> settingsRepository.showSilentStatusIcons .flatMapLatest { showSilentIcons -> iconsInteractor.filteredNotifSet( forceShowHeadsUp = true, showAmbient = false, Loading @@ -134,4 +142,5 @@ constructor( showRepliedMessages = false, ) } .flowOn(bgContext) }
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerAlwaysOnDisplayViewBinder.kt +22 −19 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import androidx.lifecycle.lifecycleScope import com.android.app.tracing.traceSection import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel Loading Loading @@ -44,7 +45,8 @@ constructor( private val viewStore: AlwaysOnDisplayNotificationIconViewStore, ) { fun bindWhileAttached(view: NotificationIconContainer): DisposableHandle { return view.repeatWhenAttached { return traceSection("NICAlwaysOnDisplay#bindWhileAttached") { view.repeatWhenAttached { lifecycleScope.launch { launch { NotificationIconContainerViewBinder.bind( Loading @@ -68,6 +70,7 @@ constructor( } } } } /** [IconViewStore] for the always-on display. */ class AlwaysOnDisplayNotificationIconViewStore Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt +13 −10 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import androidx.lifecycle.lifecycleScope import com.android.app.tracing.traceSection import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.notification.collection.NotifCollection Loading @@ -39,7 +40,8 @@ constructor( private val viewStore: StatusBarNotificationIconViewStore, ) { fun bindWhileAttached(view: NotificationIconContainer): DisposableHandle { return view.repeatWhenAttached { return traceSection("NICStatusBar#bindWhileAttached") { view.repeatWhenAttached { lifecycleScope.launch { NotificationIconContainerViewBinder.bind( view = view, Loading @@ -53,6 +55,7 @@ constructor( } } } } /** [IconViewStore] for the status bar. */ class StatusBarNotificationIconViewStore @Inject constructor(notifCollection: NotifCollection) : Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt +79 −69 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import android.widget.FrameLayout import androidx.annotation.ColorInt import androidx.collection.ArrayMap import androidx.lifecycle.lifecycleScope import com.android.app.tracing.traceSection import com.android.internal.R as RInternal import com.android.internal.statusbar.StatusBarIcon import com.android.internal.util.ContrastColorUtil import com.android.systemui.common.ui.ConfigurationState Loading @@ -48,8 +50,10 @@ import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.Job import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** Binds a view-model to a [NotificationIconContainer]. */ Loading @@ -65,8 +69,8 @@ object NotificationIconContainerViewBinder { ): Unit = coroutineScope { launch { val contrastColorUtil = ContrastColorUtil.getInstance(view.context) val iconColors: Flow<NotificationIconColors> = viewModel.iconColors.mapNotNull { it.iconColors(view.viewBounds) } val iconColors: StateFlow<NotificationIconColors> = viewModel.iconColors.mapNotNull { it.iconColors(view.viewBounds) }.stateIn(this) viewModel.icons.bindIcons( view, configuration, Loading Loading @@ -111,6 +115,14 @@ object NotificationIconContainerViewBinder { ): Unit = coroutineScope { view.setUseIncreasedIconScale(true) launch { // Collect state shared across all icon views, so that we are not duplicating collects // for each individual icon. val color: StateFlow<Int> = configuration .getColorAttr(R.attr.wallpaperTextColor, DEFAULT_AOD_ICON_COLOR) .stateIn(this) val tintAlpha = viewModel.tintAlpha.stateIn(this) val animsEnabled = viewModel.areIconAnimationsEnabled.stateIn(this) viewModel.icons.bindIcons( view, configuration, Loading @@ -118,29 +130,15 @@ object NotificationIconContainerViewBinder { notifyBindingFailures = { failureTracker.aodFailures = it }, viewStore, ) { _, sbiv -> viewModel.bindAodStatusBarIconView(sbiv, configuration) } } launch { viewModel.areContainerChangesAnimated.bindAnimationsEnabled(view) } } private suspend fun NotificationIconContainerAlwaysOnDisplayViewModel.bindAodStatusBarIconView( sbiv: StatusBarIconView, configuration: ConfigurationState, ) { coroutineScope { launch { val color: Flow<Int> = configuration.getColorAttr( R.attr.wallpaperTextColor, DEFAULT_AOD_ICON_COLOR, ) StatusBarIconViewBinder.bindColor(sbiv, color) } launch { StatusBarIconViewBinder.bindColor(sbiv, color) } launch { StatusBarIconViewBinder.bindTintAlpha(sbiv, tintAlpha) } launch { StatusBarIconViewBinder.bindAnimationsEnabled(sbiv, areIconAnimationsEnabled) } launch { StatusBarIconViewBinder.bindAnimationsEnabled(sbiv, animsEnabled) } } } } launch { viewModel.areContainerChangesAnimated.bindAnimationsEnabled(view) } } /** Binds to [NotificationIconContainer.setAnimationsEnabled] */ private suspend fun Flow<Boolean>.bindAnimationsEnabled(view: NotificationIconContainer) { Loading Loading @@ -184,11 +182,9 @@ object NotificationIconContainerViewBinder { notifyBindingFailures: (Collection<String>) -> Unit, viewStore: IconViewStore, bindIcon: suspend (iconKey: String, view: StatusBarIconView) -> Unit = { _, _ -> }, ) { ): Unit = coroutineScope { val iconSizeFlow: Flow<Int> = configuration.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_icon_size_sp, ) configuration.getDimensionPixelSize(RInternal.dimen.status_bar_icon_size_sp) val iconHorizontalPaddingFlow: Flow<Int> = configuration.getDimensionPixelSize(R.dimen.status_bar_icon_horizontal_margin) val layoutParams: Flow<FrameLayout.LayoutParams> = Loading @@ -199,6 +195,7 @@ object NotificationIconContainerViewBinder { -> FrameLayout.LayoutParams(iconSize + 2 * iconHPadding, statusBarHeight) } .stateIn(this) try { bindIcons(view, layoutParams, notifyBindingFailures, viewStore, bindIcon) } finally { Loading @@ -217,7 +214,7 @@ object NotificationIconContainerViewBinder { val failedBindings = mutableSetOf<String>() val boundViewsByNotifKey = ArrayMap<String, Pair<StatusBarIconView, Job>>() var prevIcons = NotificationIconsViewData() collect { iconsData: NotificationIconsViewData -> collectTracingEach("NotifIconContainer#bindIcons") { iconsData: NotificationIconsViewData -> val iconsDiff = NotificationIconsViewData.computeDifference(iconsData, prevIcons) prevIcons = iconsData Loading @@ -231,9 +228,11 @@ object NotificationIconContainerViewBinder { for (notifKey in iconsDiff.removed) { failedBindings.remove(notifKey) val (child, job) = boundViewsByNotifKey.remove(notifKey) ?: continue traceSection("removeIcon") { view.removeView(child) job.cancel() } } // Add and bind. val toAdd: Sequence<String> = iconsDiff.added.asSequence() + failedBindings.toList() Loading @@ -245,12 +244,16 @@ object NotificationIconContainerViewBinder { continue } failedBindings.remove(notifKey) traceSection("addIcon") { (sbiv.parent as? ViewGroup)?.run { if (this !== view) { Log.wtf(TAG, "StatusBarIconView($notifKey) has an unexpected parent") Log.wtf( TAG, "StatusBarIconView($notifKey) has an unexpected parent", ) } // If the container was re-inflated and re-bound, then SBIVs might still be // attached to the prior view. // If the container was re-inflated and re-bound, then SBIVs might still // be attached to the prior view. removeView(sbiv) // The view might still be transiently added if it was just removed and // added again. Loading @@ -267,16 +270,17 @@ object NotificationIconContainerViewBinder { }, ) } } // Set the maximum number of icons to show in the container. Any icons over this // amount will render as an "overflow dot". val maxIconsAmount: Int = when (iconsData.limitType) { LimitType.MaximumIndex -> { iconsData.visibleIcons .asSequence() .take(iconsData.iconLimit) .count { info -> info.notifKey in boundViewsByNotifKey } iconsData.visibleIcons.asSequence().take(iconsData.iconLimit).count { info -> info.notifKey in boundViewsByNotifKey } } LimitType.MaximumAmount -> { iconsData.iconLimit Loading @@ -289,6 +293,7 @@ object NotificationIconContainerViewBinder { // Re-sort notification icons view.changeViewPositions { traceSection("re-sort") { val expectedChildren: List<StatusBarIconView> = iconsData.visibleIcons.mapNotNull { boundViewsByNotifKey[it.notifKey]?.first Loading @@ -307,6 +312,7 @@ object NotificationIconContainerViewBinder { } } } } /** * Track which groups are being replaced with a different icon instance, but with the same Loading Loading @@ -362,3 +368,7 @@ private val View.viewBounds: Rect /* bottom = */ top + height, ) } private suspend fun <T> Flow<T>.collectTracingEach(tag: String, collector: (T) -> Unit) { collect { traceSection(tag) { collector(it) } } }