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

Commit 7a021dc2 authored by Andreas Miko's avatar Andreas Miko
Browse files

Make BundleHeaderViewModel Activatable and managed by Dagger

Bug: b/389839492 b/416131251
Test: Manually verified bundle still works
Flag: com.android.systemui.notification_bundle_ui
Change-Id: I46b1898a15e9c9ac76bd1a3a941ce64ffbfa3629
parent 361d3d08
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -141,6 +141,7 @@ import com.android.systemui.statusbar.notification.collection.render.Notificatio
import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.notification.row.dagger.BundleRowComponent;
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -306,6 +307,7 @@ import javax.inject.Named;
                NotificationRowComponent.class,
                WindowRootViewComponent.class,
                SystemUIDisplaySubcomponent.class,
                BundleRowComponent.class,
        })
public abstract class SystemUIModule {

+21 −20
Original line number Diff line number Diff line
@@ -19,7 +19,9 @@ package com.android.systemui.statusbar.notification.collection.render
import android.content.Context
import android.view.ViewGroup
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.lifecycle.WindowLifecycleState
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.lifecycle.viewModel
import com.android.systemui.settings.UserTracker
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.NotificationPresenter
@@ -30,16 +32,13 @@ import com.android.systemui.statusbar.notification.collection.coordinator.Bundle
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.RowInflaterTask
import com.android.systemui.statusbar.notification.row.RowInflaterTaskLogger
import com.android.systemui.statusbar.notification.row.dagger.BundleRowComponent
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent
import com.android.systemui.statusbar.notification.row.domain.interactor.BundleInteractor
import com.android.systemui.statusbar.notification.row.icon.AppIconProvider
import com.android.systemui.statusbar.notification.row.ui.viewmodel.BundleHeaderViewModel
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.util.time.SystemClock
import dagger.Lazy
import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.CoroutineDispatcher

/** Class that handles inflating BundleEntry view and controller, for use by NodeSpecBuilder. */
@SysUISingleton
@@ -47,6 +46,7 @@ class BundleBarn
@Inject
constructor(
    private val rowComponent: ExpandableNotificationRowComponent.Builder,
    private val bundleRowComponentBuilder: BundleRowComponent.Builder,
    private val rowInflaterTaskProvider: Provider<RowInflaterTask>,
    private val listContainer: NotificationListContainer,
    @ShadeDisplayAware val context: Context,
@@ -54,8 +54,6 @@ constructor(
    val logger: RowInflaterTaskLogger,
    val userTracker: UserTracker,
    private val presenterLazy: Lazy<NotificationPresenter?>? = null,
    private val appIconProvider: AppIconProvider,
    @Background private val backgroundDispatcher: CoroutineDispatcher,
) : PipelineDumpable {

    /**
@@ -66,16 +64,16 @@ constructor(

    /** Build view and controller for BundleEntry. */
    fun inflateBundleEntry(bundleEntry: BundleEntry) {
        debugBundleLog(TAG, { "inflateBundleEntry: ${bundleEntry.key}" })
        debugBundleLog(TAG) { "inflateBundleEntry: ${bundleEntry.key}" }
        if (keyToControllerMap.containsKey(bundleEntry.key)) {
            // Skip if bundle is inflating or inflated.
            debugBundleLog(TAG, { "already in map: ${bundleEntry.key}" })
            debugBundleLog(TAG) { "already in map: ${bundleEntry.key}" }
            return
        }
        val parent: ViewGroup = listContainer.getViewParentForNotification()
        val inflationFinishedListener: (ExpandableNotificationRow) -> Unit = { row ->
            // A subset of NotificationRowBinderImpl.inflateViews
            debugBundleLog(TAG, { "finished inflating: ${bundleEntry.key}" })
            debugBundleLog(TAG) { "finished inflating: ${bundleEntry.key}" }
            bundleEntry.row = row
            val component =
                rowComponent
@@ -87,17 +85,20 @@ constructor(
            controller.init(bundleEntry)
            keyToControllerMap[bundleEntry.key] = controller

            // TODO(389839492): Construct BundleHeaderViewModel (or even ENRViewModel) by dagger
            val bundleInteractor =
                BundleInteractor(
                    repository = bundleEntry.bundleRepository,
                    appIconProvider = appIconProvider,
                    context = context,
                    backgroundDispatcher = backgroundDispatcher,
                )
            row.initBundleHeader(BundleHeaderViewModel(bundleInteractor))
            val bundleRowComponent =
                bundleRowComponentBuilder.bindBundleRepository(bundleEntry.bundleRepository).build()

            row.repeatWhenAttached {
                row.viewModel(
                    traceName = "BundleHeaderViewModel",
                    minWindowLifecycleState = WindowLifecycleState.ATTACHED,
                    factory = bundleRowComponent.bundleViewModelFactory()::create,
                ) { viewModel ->
                    row.initBundleHeader(viewModel)
                }
            }
        }
        debugBundleLog(TAG, { "calling inflate: ${bundleEntry.key}" })
        debugBundleLog(TAG) { "calling inflate: ${bundleEntry.key}" }
        keyToControllerMap[bundleEntry.key] = null
        rowInflaterTaskProvider
            .get()
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.row.dagger

import com.android.systemui.statusbar.notification.row.data.repository.BundleRepository
import com.android.systemui.statusbar.notification.row.ui.viewmodel.BundleHeaderViewModel
import dagger.BindsInstance
import dagger.Subcomponent

/** This dagger component is used to init the ViewModel and Interactors needed for a bundle row */
@Subcomponent
@BundleRowScope
interface BundleRowComponent {

    fun bundleViewModelFactory(): BundleHeaderViewModel.Factory

    @Subcomponent.Builder
    interface Builder {
        @BindsInstance fun bindBundleRepository(repository: BundleRepository): Builder

        fun build(): BundleRowComponent
    }
}
+32 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.row.dagger;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;

import javax.inject.Scope;

/**
 * Scope annotation for singleton items within the BundleRowComponent.
 */
@Documented
@Retention(RUNTIME)
@Scope
public @interface BundleRowScope {}
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ import java.lang.annotation.Retention;
import javax.inject.Scope;

/**
 * Scope annotation for singleton items within the CentralSurfacesComponent.
 * Scope annotation for singleton items within the ExpandableNotificationRowComponent.
 */
@Documented
@Retention(RUNTIME)
Loading