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

Commit 6c84ea65 authored by András Kurucz's avatar András Kurucz Committed by Android (Google) Code Review
Browse files

Merge "Update NotificationStatsLogger when a Notification is updated or removed" into main

parents 5609be03 dd54dcf7
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import com.android.systemui.statusbar.notification.collection.PipelineDumper
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import javax.inject.Inject

/**
@@ -61,6 +62,7 @@ class NotifCoordinatorsImpl @Inject constructor(
        sensitiveContentCoordinator: SensitiveContentCoordinator,
        dismissibilityCoordinator: DismissibilityCoordinator,
        dreamCoordinator: DreamCoordinator,
        statsLoggerCoordinator: NotificationStatsLoggerCoordinator,
) : NotifCoordinators {

    private val mCoreCoordinators: MutableList<CoreCoordinator> = ArrayList()
@@ -104,6 +106,10 @@ class NotifCoordinatorsImpl @Inject constructor(
            mCoordinators.add(dreamCoordinator)
        }

        if (NotificationsLiveDataStoreRefactor.isEnabled) {
            mCoordinators.add(statsLoggerCoordinator)
        }

        // Manually add Ordered Sections
        mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp
        mOrderedSections.add(colorizedFgsCoordinator.sectioner) // ForegroundService
+51 −0
Original line number Diff line number Diff line
/*
 * 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.notification.collection.coordinator

import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationStatsLogger
import java.util.Optional
import javax.inject.Inject

@CoordinatorScope
class NotificationStatsLoggerCoordinator
@Inject
constructor(private val loggerOptional: Optional<NotificationStatsLogger>) : Coordinator {

    private val collectionListener =
        object : NotifCollectionListener {
            override fun onEntryUpdated(entry: NotificationEntry) {
                super.onEntryUpdated(entry)
                loggerOptional.ifPresent { it.onNotificationUpdated(entry.key) }
            }

            override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
                super.onEntryRemoved(entry, reason)
                loggerOptional.ifPresent { it.onNotificationRemoved(entry.key) }
            }
        }
    override fun attach(pipeline: NotifPipeline) {
        if (NotificationsLiveDataStoreRefactor.isUnexpectedlyInLegacyMode()) {
            return
        }
        pipeline.addCollectionListener(collectionListener)
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -29,9 +29,7 @@ interface NotificationStatsLogger : NotificationRowStatsLogger {
        activeNotifications: List<ActiveNotificationModel>,
    )
    fun onLockscreenOrShadeNotInteractive(activeNotifications: List<ActiveNotificationModel>)
    fun onNotificationRemoved(key: String)
    fun onNotificationUpdated(key: String)
    fun onNotificationListUpdated(
    fun onNotificationLocationsChanged(
        locationsProvider: Callable<Map<String, Int>>,
        notificationRanks: Map<String, Int>,
    )
@@ -41,4 +39,6 @@ interface NotificationStatsLogger : NotificationRowStatsLogger {
        location: Int,
        isUserAction: Boolean
    )
    fun onNotificationRemoved(key: String)
    fun onNotificationUpdated(key: String)
}
+3 −4
Original line number Diff line number Diff line
@@ -53,10 +53,11 @@ constructor(

    private val expansionStates: MutableMap<String, ExpansionState> =
        ConcurrentHashMap<String, ExpansionState>()
    private val lastReportedExpansionValues: MutableMap<String, Boolean> =
    @VisibleForTesting
    val lastReportedExpansionValues: MutableMap<String, Boolean> =
        ConcurrentHashMap<String, Boolean>()

    override fun onNotificationListUpdated(
    override fun onNotificationLocationsChanged(
        locationsProvider: Callable<Map<String, Int>>,
        notificationRanks: Map<String, Int>,
    ) {
@@ -152,14 +153,12 @@ constructor(
            )
    }

    // TODO(b/308623704) wire this in with NotifPipeline updates
    override fun onNotificationRemoved(key: String) {
        // No need to track expansion states for Notifications that are removed.
        expansionStates.remove(key)
        lastReportedExpansionValues.remove(key)
    }

    // TODO(b/308623704) wire this in with NotifPipeline updates
    override fun onNotificationUpdated(key: String) {
        // When the Notification is updated, we should consider it as not yet logged.
        lastReportedExpansionValues.remove(key)
+7 −5
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ object NotificationStatsLoggerBinder {
        logger: NotificationStatsLogger,
        viewModel: NotificationLoggerViewModel,
    ) {
        // Updates the logger about whether the Notification panel, and the individual Notifications
        // are visible to the user.
        viewModel.isLockscreenOrShadeInteractive
            .sample(
                combine(viewModel.isOnLockScreen, viewModel.activeNotifications, ::Pair),
@@ -52,14 +54,14 @@ object NotificationStatsLoggerBinder {
                        isOnLockScreen = isOnLockScreen,
                        activeNotifications = notifications,
                    )
                    view.onNotificationsUpdated
                        // Delay the updates with [NOTIFICATION_UPDATES_PERIOD_MS]. If the original
                    view.onNotificationLocationsUpdated
                        // Delay the updates with [NOTIFICATION_UPDATE_PERIOD_MS]. If the original
                        // flow emits more than once during this period, only the latest value is
                        // emitted, meaning that we won't log the intermediate Notification states.
                        .throttle(NOTIFICATION_UPDATE_PERIOD_MS)
                        .sample(viewModel.activeNotificationRanks, ::Pair)
                        .collect { (locationsProvider, notificationRanks) ->
                            logger.onNotificationListUpdated(locationsProvider, notificationRanks)
                        .collect { (locationsProvider, ranks) ->
                            logger.onNotificationLocationsChanged(locationsProvider, ranks)
                        }
                } else {
                    logger.onLockscreenOrShadeNotInteractive(
@@ -70,7 +72,7 @@ object NotificationStatsLoggerBinder {
    }
}

private val NotificationStackScrollLayout.onNotificationsUpdated
private val NotificationStackScrollLayout.onNotificationLocationsUpdated
    get() =
        ConflatedCallbackFlow.conflatedCallbackFlow {
            val callback =
Loading