Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a939d8d6 authored by Steve Elliott's avatar Steve Elliott Committed by Android (Google) Code Review
Browse files

Merge "Reduce NICRefactor load on main dispatcher" into main

parents 0b0d0adc feace42e
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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() {
+26 −17
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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,
@@ -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,
@@ -134,4 +142,5 @@ constructor(
                    showRepliedMessages = false,
                )
            }
            .flowOn(bgContext)
}
+22 −19
Original line number Diff line number Diff line
@@ -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
@@ -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(
@@ -68,6 +70,7 @@ constructor(
            }
        }
    }
}

/** [IconViewStore] for the always-on display. */
class AlwaysOnDisplayNotificationIconViewStore
+13 −10
Original line number Diff line number Diff line
@@ -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
@@ -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,
@@ -53,6 +55,7 @@ constructor(
            }
        }
    }
}

/** [IconViewStore] for the status bar. */
class StatusBarNotificationIconViewStore @Inject constructor(notifCollection: NotifCollection) :
+79 −69
Original line number Diff line number Diff line
@@ -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
@@ -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]. */
@@ -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,
@@ -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,
@@ -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) {
@@ -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> =
@@ -199,6 +195,7 @@ object NotificationIconContainerViewBinder {
                    ->
                    FrameLayout.LayoutParams(iconSize + 2 * iconHPadding, statusBarHeight)
                }
                .stateIn(this)
        try {
            bindIcons(view, layoutParams, notifyBindingFailures, viewStore, bindIcon)
        } finally {
@@ -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

@@ -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()
@@ -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.
@@ -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
@@ -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
@@ -307,6 +312,7 @@ object NotificationIconContainerViewBinder {
                }
            }
        }
    }

    /**
     * Track which groups are being replaced with a different icon instance, but with the same
@@ -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