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

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

Merge "Create NotificationStatsLogger" into main

parents 601277a9 3d812fbe
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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

/** A [CoreStartable] that does nothing. */
class NoOpCoreStartable : CoreStartable {
    override fun start() {}
}
+148 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.dagger

import com.android.systemui.CoreStartable
import com.android.systemui.NoOpCoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.UiBackground
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
import com.android.systemui.statusbar.NotificationListener
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider
import com.android.systemui.statusbar.notification.logging.NotificationLogger
import com.android.systemui.statusbar.notification.logging.NotificationLogger.ExpansionStateLogger
import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationRowStatsLogger
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationStatsLogger
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationStatsLoggerImpl
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationLoggerViewModel
import com.android.systemui.util.kotlin.JavaAdapter
import com.android.systemui.util.kotlin.getOrNull
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import java.util.Optional
import java.util.concurrent.Executor
import javax.inject.Provider

@Module
interface NotificationStatsLoggerModule {

    /** Binds an implementation to the [NotificationStatsLogger]. */
    @Binds fun bindsStatsLoggerImpl(impl: NotificationStatsLoggerImpl): NotificationStatsLogger

    companion object {

        /** Provides a [NotificationStatsLogger] if the refactor flag is on. */
        @Provides
        fun provideStatsLogger(
            provider: Provider<NotificationStatsLogger>
        ): Optional<NotificationStatsLogger> {
            return if (NotificationsLiveDataStoreRefactor.isEnabled) {
                Optional.of(provider.get())
            } else {
                Optional.empty()
            }
        }

        /** Provides a [NotificationLoggerViewModel] if the refactor flag is on. */
        @Provides
        fun provideViewModel(
            provider: Provider<NotificationLoggerViewModel>
        ): Optional<NotificationLoggerViewModel> {
            return if (NotificationsLiveDataStoreRefactor.isEnabled) {
                Optional.of(provider.get())
            } else {
                Optional.empty()
            }
        }

        /** Provides the legacy [NotificationLogger] if the refactor flag is off. */
        @Provides
        @SysUISingleton
        fun provideLegacyLoggerOptional(
            notificationListener: NotificationListener?,
            @UiBackground uiBgExecutor: Executor?,
            notifLiveDataStore: NotifLiveDataStore?,
            visibilityProvider: NotificationVisibilityProvider?,
            notifPipeline: NotifPipeline?,
            statusBarStateController: StatusBarStateController?,
            windowRootViewVisibilityInteractor: WindowRootViewVisibilityInteractor?,
            javaAdapter: JavaAdapter?,
            expansionStateLogger: ExpansionStateLogger?,
            notificationPanelLogger: NotificationPanelLogger?
        ): Optional<NotificationLogger> {
            return if (NotificationsLiveDataStoreRefactor.isEnabled) {
                Optional.empty()
            } else {
                Optional.of(
                    NotificationLogger(
                        notificationListener,
                        uiBgExecutor,
                        notifLiveDataStore,
                        visibilityProvider,
                        notifPipeline,
                        statusBarStateController,
                        windowRootViewVisibilityInteractor,
                        javaAdapter,
                        expansionStateLogger,
                        notificationPanelLogger
                    )
                )
            }
        }

        /**
         * Provides a the legacy [NotificationLogger] or the new [NotificationStatsLogger] to the
         * notification row.
         *
         * TODO(b/308623704) remove the [NotificationRowStatsLogger] interface, and provide a
         *   [NotificationStatsLogger] to the row directly.
         */
        @Provides
        fun provideRowStatsLogger(
            newProvider: Provider<NotificationStatsLogger>,
            legacyLoggerOptional: Optional<NotificationLogger>,
        ): NotificationRowStatsLogger {
            return legacyLoggerOptional.getOrNull() ?: newProvider.get()
        }

        /**
         * Binds the legacy [NotificationLogger] as a [CoreStartable] if the feature flag is off, or
         * binds a no-op [CoreStartable] otherwise.
         *
         * The old [NotificationLogger] is a [CoreStartable], because it's managing its own data
         * updates, but the new [NotificationStatsLogger] is not. Currently Dagger doesn't support
         * optionally binding entries with @[IntoMap], therefore we provide a no-op [CoreStartable]
         * here if the feature flag is on, but this can be removed once the flag is released.
         */
        @Provides
        @IntoMap
        @ClassKey(NotificationLogger::class)
        fun provideCoreStartable(
            legacyLoggerOptional: Optional<NotificationLogger>
        ): CoreStartable {
            return legacyLoggerOptional.getOrNull() ?: NoOpCoreStartable()
        }
    }
}
+8 −42
Original line number Diff line number Diff line
@@ -17,14 +17,12 @@
package com.android.systemui.statusbar.notification.dagger;

import android.content.Context;
import android.service.notification.NotificationListenerService;

import com.android.internal.jank.InteractionJankMonitor;
import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.res.R;
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
@@ -67,7 +65,6 @@ import com.android.systemui.statusbar.notification.interruption.NotificationInte
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProviderImpl;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionRefactor;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger;
import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerImpl;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -80,7 +77,8 @@ import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.kotlin.JavaAdapter;

import javax.inject.Provider;

import dagger.Binds;
import dagger.Module;
@@ -88,10 +86,6 @@ import dagger.Provides;
import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;

import java.util.concurrent.Executor;

import javax.inject.Provider;

/**
 * Dagger Module for classes found within the com.android.systemui.statusbar.notification package.
 */
@@ -104,6 +98,7 @@ import javax.inject.Provider;
        NotificationSectionHeadersModule.class,
        ActivatableNotificationViewModelModule.class,
        NotificationMemoryModule.class,
        NotificationStatsLoggerModule.class,
})
public interface NotificationsModule {
    @Binds
@@ -128,39 +123,6 @@ public interface NotificationsModule {
    VisibilityLocationProvider bindVisibilityLocationProvider(
            VisibilityLocationProviderDelegator visibilityLocationProviderDelegator);

    /** Provides an instance of {@link NotificationLogger} */
    @SysUISingleton
    @Provides
    static NotificationLogger provideNotificationLogger(
            NotificationListener notificationListener,
            @UiBackground Executor uiBgExecutor,
            NotifLiveDataStore notifLiveDataStore,
            NotificationVisibilityProvider visibilityProvider,
            NotifPipeline notifPipeline,
            StatusBarStateController statusBarStateController,
            WindowRootViewVisibilityInteractor windowRootViewVisibilityInteractor,
            JavaAdapter javaAdapter,
            NotificationLogger.ExpansionStateLogger expansionStateLogger,
            NotificationPanelLogger notificationPanelLogger) {
        return new NotificationLogger(
                notificationListener,
                uiBgExecutor,
                notifLiveDataStore,
                visibilityProvider,
                notifPipeline,
                statusBarStateController,
                windowRootViewVisibilityInteractor,
                javaAdapter,
                expansionStateLogger,
                notificationPanelLogger);
    }

    /** Binds {@link NotificationLogger} as a {@link CoreStartable}. */
    @Binds
    @IntoMap
    @ClassKey(NotificationLogger.class)
    CoreStartable bindsNotificationLogger(NotificationLogger notificationLogger);

    /** Provides an instance of {@link NotificationPanelLogger} */
    @SysUISingleton
    @Provides
@@ -271,6 +233,10 @@ public interface NotificationsModule {
    @Binds
    NotifLiveDataStore bindNotifLiveDataStore(NotifLiveDataStoreImpl notifLiveDataStoreImpl);

    /** */
    @Binds
    NotificationListenerService bindNotificationListener(NotificationListener notificationListener);

    /** */
    @Provides
    @SysUISingleton
+12 −1
Original line number Diff line number Diff line
@@ -55,6 +55,12 @@ data class ActiveNotificationsStore(
     * invoking [get].
     */
    val renderList: List<Key> = emptyList(),

    /**
     * Map of notification key to rank, where rank is the 0-based index of the notification on the
     * system server, meaning that in the unfiltered flattened list of notification entries.
     */
    val rankingsMap: Map<String, Int> = emptyMap()
) {
    operator fun get(key: Key): ActiveNotificationEntryModel? {
        return when (key) {
@@ -74,8 +80,9 @@ data class ActiveNotificationsStore(
        private val groups = mutableMapOf<String, ActiveNotificationGroupModel>()
        private val individuals = mutableMapOf<String, ActiveNotificationModel>()
        private val renderList = mutableListOf<Key>()
        private var rankingsMap: Map<String, Int> = emptyMap()

        fun build() = ActiveNotificationsStore(groups, individuals, renderList)
        fun build() = ActiveNotificationsStore(groups, individuals, renderList, rankingsMap)

        fun addEntry(entry: ActiveNotificationEntryModel) {
            when (entry) {
@@ -95,5 +102,9 @@ data class ActiveNotificationsStore(
            individuals[group.summary.key] = group.summary
            group.children.forEach { individuals[it.key] = it }
        }

        fun setRankingsMap(map: Map<String, Int>) {
            rankingsMap = map.toMap()
        }
    }
}
+21 −1
Original line number Diff line number Diff line
@@ -33,7 +33,10 @@ constructor(
    private val repository: ActiveNotificationListRepository,
    @Background private val backgroundDispatcher: CoroutineDispatcher,
) {
    /** Notifications actively presented to the user in the notification stack, in order. */
    /**
     * Top level list of Notifications actively presented to the user in the notification stack, in
     * order.
     */
    val topLevelRepresentativeNotifications: Flow<List<ActiveNotificationModel>> =
        repository.activeNotifications
            .map { store ->
@@ -51,6 +54,13 @@ constructor(
            }
            .flowOn(backgroundDispatcher)

    /**
     * Flattened list of Notifications actively presented to the user in the notification stack, in
     * order.
     */
    val allRepresentativeNotifications: Flow<Map<String, ActiveNotificationModel>> =
        repository.activeNotifications.map { store -> store.individuals }

    /** Are any notifications being actively presented in the notification stack? */
    val areAnyNotificationsPresent: Flow<Boolean> =
        repository.activeNotifications
@@ -65,6 +75,16 @@ constructor(
    val areAnyNotificationsPresentValue: Boolean
        get() = repository.activeNotifications.value.renderList.isNotEmpty()

    /**
     * Map of notification key to rank, where rank is the 0-based index of the notification in the
     * system server, meaning that in the unfiltered flattened list of notification entries. Used
     * for logging purposes.
     *
     * @see [com.android.systemui.statusbar.notification.stack.ui.view.NotificationStatsLogger].
     */
    val activeNotificationRanks: Flow<Map<String, Int>> =
        repository.activeNotifications.map { store -> store.rankingsMap }

    /** Are there are any notifications that can be cleared by the "Clear all" button? */
    val hasClearableNotifications: Flow<Boolean> =
        repository.notifStats
Loading