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

Commit 0930d795 authored by Justin Weir's avatar Justin Weir
Browse files

Update modules to allow empty impls

This change sets up the ability to replace calls to
CentralSurfacesImpl.getShadeViewController by injecting a
ShadeViewController via Dagger. Now that ShadeViewController is a
singleton it can be injected in the singleton scope, removing the
need for access via CSI. However, variants without a shade cannot
inject SVC without bringing in all of NPVCs dependencies. By
temporarily adding empty implementations of the shade interfaces
and a module to inject those instead, variants will avoid picking
up many unnecessary dependencies during this cleanup work.

Bug: 288868098
Bug: 291620003
Test: updated and ran affected test
Change-Id: If7918ed932a8945d2e014ffd1a741ba93ae17580
Merged-In: If7918ed932a8945d2e014ffd1a741ba93ae17580
parent 066951a1
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -43,8 +43,6 @@ import com.android.systemui.rotationlock.RotationLockModule;
import com.android.systemui.screenshot.ReferenceScreenshotModule;
import com.android.systemui.settings.dagger.MultiUserUtilsModule;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeControllerImpl;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyboardShortcutsModule;
@@ -150,9 +148,6 @@ public abstract class ReferenceSystemUIModule {
    @Binds
    abstract DockManager bindDockManager(DockManagerImpl dockManager);

    @Binds
    abstract ShadeController provideShadeController(ShadeControllerImpl shadeController);

    @SysUISingleton
    @Provides
    @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
+1 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ import java.util.concurrent.Executor
import javax.inject.Inject
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.shade.ShadeModule.Companion.SHADE_HEADER
import com.android.systemui.shade.ShadeViewProviderModule.Companion.SHADE_HEADER
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import javax.inject.Named

+33 −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.shade

import com.android.systemui.dagger.SysUISingleton
import dagger.Binds
import dagger.Module

/** Fulfills dependencies on the shade with empty implementations for variants with no shade. */
@Module
abstract class ShadeEmptyImplModule {
    @Binds
    @SysUISingleton
    abstract fun bindsShadeViewController(svc: ShadeViewControllerEmptyImpl): ShadeViewController

    @Binds
    @SysUISingleton
    abstract fun bindsShadeController(sc: ShadeControllerEmptyImpl): ShadeController
}
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_H
import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_TRANSITION_ID
import com.android.systemui.shade.ShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
import com.android.systemui.shade.ShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
import com.android.systemui.shade.ShadeModule.Companion.SHADE_HEADER
import com.android.systemui.shade.ShadeViewProviderModule.Companion.SHADE_HEADER
import com.android.systemui.shade.carrier.ShadeCarrierGroup
import com.android.systemui.shade.carrier.ShadeCarrierGroupController
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
+4 −295
Original line number Diff line number Diff line
@@ -16,311 +16,20 @@

package com.android.systemui.shade

import android.annotation.SuppressLint
import android.content.ContentResolver
import android.os.Handler
import android.view.LayoutInflater
import android.view.ViewStub
import androidx.constraintlayout.motion.widget.MotionLayout
import com.android.keyguard.LockIconView
import com.android.systemui.CoreStartable
import com.android.systemui.R
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.biometrics.AuthRippleController
import com.android.systemui.biometrics.AuthRippleView
import com.android.systemui.compose.ComposeFacade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.ui.view.SceneWindowRootView
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.NotificationShelfController
import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent
import com.android.systemui.statusbar.notification.shelf.ui.viewbinder.NotificationShelfViewBinderWrapperControllerImpl
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.phone.TapAgainView
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.tuner.TunerService
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import javax.inject.Named
import javax.inject.Provider

/** Module for classes related to the notification shade. */
@Module(includes = [StartShadeModule::class])
@Module(includes = [StartShadeModule::class, ShadeViewProviderModule::class])
abstract class ShadeModule {

    @Binds
    @IntoMap
    @ClassKey(AuthRippleController::class)
    abstract fun bindAuthRippleController(controller: AuthRippleController): CoreStartable

    @Binds
    @SysUISingleton
    abstract fun bindsShadeViewController(
        notificationPanelViewController: NotificationPanelViewController
    ): ShadeViewController

    companion object {
        const val SHADE_HEADER = "large_screen_shade_header"

        @SuppressLint("InflateParams") // Root views don't have parents.
        @Provides
        @SysUISingleton
        fun providesWindowRootView(
            layoutInflater: LayoutInflater,
            featureFlags: FeatureFlags,
            @Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
            viewModelProvider: Provider<SceneContainerViewModel>,
            @Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
            containerConfigProvider: Provider<SceneContainerConfig>,
            @Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
            scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>,
        ): WindowRootView {
            return if (
                featureFlags.isEnabled(Flags.SCENE_CONTAINER) && ComposeFacade.isComposeAvailable()
            ) {
                val sceneWindowRootView =
                    layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView
                sceneWindowRootView.init(
                    viewModel = viewModelProvider.get(),
                    containerConfig = containerConfigProvider.get(),
                    scenes = scenesProvider.get(),
                )
                sceneWindowRootView
            } else {
                layoutInflater.inflate(R.layout.super_notification_shade, null)
            }
                as WindowRootView?
                ?: throw IllegalStateException("Window root view could not be properly inflated")
        }

        @Provides
        @SysUISingleton
        // TODO(b/277762009): Do something similar to
        //  {@link StatusBarWindowModule.InternalWindowView} so that only
        //  {@link NotificationShadeWindowViewController} can inject this view.
        fun providesNotificationShadeWindowView(
            root: WindowRootView,
            featureFlags: FeatureFlags,
        ): NotificationShadeWindowView {
            if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
                return root.findViewById(R.id.legacy_window_root)
            }
            return root as NotificationShadeWindowView?
                ?: throw IllegalStateException("root view not a NotificationShadeWindowView")
        }

        // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
        @Provides
        @SysUISingleton
        fun providesNotificationStackScrollLayout(
            notificationShadeWindowView: NotificationShadeWindowView,
        ): NotificationStackScrollLayout {
            return notificationShadeWindowView.findViewById(R.id.notification_stack_scroller)
        }

        @Provides
        @SysUISingleton
        fun providesNotificationShelfController(
            featureFlags: FeatureFlags,
            newImpl: Provider<NotificationShelfViewBinderWrapperControllerImpl>,
            notificationShelfComponentBuilder: NotificationShelfComponent.Builder,
            layoutInflater: LayoutInflater,
            notificationStackScrollLayout: NotificationStackScrollLayout,
        ): NotificationShelfController {
            return if (featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
                newImpl.get()
            } else {
                val shelfView =
                    layoutInflater.inflate(
                        R.layout.status_bar_notification_shelf,
                        notificationStackScrollLayout,
                        false
                    ) as NotificationShelf
                val component =
                    notificationShelfComponentBuilder.notificationShelf(shelfView).build()
                val notificationShelfController = component.notificationShelfController
                notificationShelfController.init()
                notificationShelfController
            }
        }

        // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
        @Provides
        @SysUISingleton
        fun providesNotificationPanelView(
            notificationShadeWindowView: NotificationShadeWindowView,
        ): NotificationPanelView {
            return notificationShadeWindowView.findViewById(R.id.notification_panel)
        }

        /**
         * Constructs a new, unattached [KeyguardBottomAreaView].
         *
         * Note that this is explicitly _not_ a singleton, as we want to be able to reinflate it
         */
        @Provides
        fun providesKeyguardBottomAreaView(
            npv: NotificationPanelView,
            layoutInflater: LayoutInflater,
        ): KeyguardBottomAreaView {
            return layoutInflater.inflate(R.layout.keyguard_bottom_area, npv, false)
                as KeyguardBottomAreaView
        }

        @Provides
        @SysUISingleton
        fun providesLightRevealScrim(
            notificationShadeWindowView: NotificationShadeWindowView,
        ): LightRevealScrim {
            return notificationShadeWindowView.findViewById(R.id.light_reveal_scrim)
        }

        @Provides
        @SysUISingleton
        fun providesKeyguardRootView(
            notificationShadeWindowView: NotificationShadeWindowView,
        ): KeyguardRootView {
            return notificationShadeWindowView.findViewById(R.id.keyguard_root_view)
        }

        @Provides
        @SysUISingleton
        fun providesSharedNotificationContainer(
            notificationShadeWindowView: NotificationShadeWindowView,
        ): SharedNotificationContainer {
            return notificationShadeWindowView.findViewById(R.id.shared_notification_container)
        }

        // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
        @Provides
        @SysUISingleton
        fun providesAuthRippleView(
            notificationShadeWindowView: NotificationShadeWindowView,
        ): AuthRippleView? {
            return notificationShadeWindowView.findViewById(R.id.auth_ripple)
        }

        // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
        @Provides
        @SysUISingleton
        fun providesLockIconView(
            keyguardRootView: KeyguardRootView,
            notificationPanelView: NotificationPanelView,
            featureFlags: FeatureFlags
        ): LockIconView {
            if (featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
                return keyguardRootView.findViewById(R.id.lock_icon_view)
            } else {
                return notificationPanelView.findViewById(R.id.lock_icon_view)
            }
        }

        // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
        @Provides
        @SysUISingleton
        fun providesTapAgainView(
            notificationPanelView: NotificationPanelView,
        ): TapAgainView {
            return notificationPanelView.findViewById(R.id.shade_falsing_tap_again)
        }

        // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
        @Provides
        @SysUISingleton
        fun providesNotificationsQuickSettingsContainer(
            notificationShadeWindowView: NotificationShadeWindowView,
        ): NotificationsQuickSettingsContainer {
            return notificationShadeWindowView.findViewById(R.id.notification_container_parent)
        }

        // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
        @Provides
        @SysUISingleton
        @Named(SHADE_HEADER)
        fun providesShadeHeaderView(
            notificationShadeWindowView: NotificationShadeWindowView,
        ): MotionLayout {
            val stub = notificationShadeWindowView.findViewById<ViewStub>(R.id.qs_header_stub)
            val layoutId = R.layout.combined_qs_header
            stub.layoutResource = layoutId
            return stub.inflate() as MotionLayout
        }

        @Provides
        @SysUISingleton
        fun providesCombinedShadeHeadersConstraintManager(): CombinedShadeHeadersConstraintManager {
            return CombinedShadeHeadersConstraintManagerImpl
        }

        // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
        @Provides
        @SysUISingleton
        @Named(SHADE_HEADER)
        fun providesBatteryMeterView(@Named(SHADE_HEADER) view: MotionLayout): BatteryMeterView {
            return view.findViewById(R.id.batteryRemainingIcon)
        }

        @Provides
        @SysUISingleton
        @Named(SHADE_HEADER)
        fun providesBatteryMeterViewController(
            @Named(SHADE_HEADER) batteryMeterView: BatteryMeterView,
            userTracker: UserTracker,
            configurationController: ConfigurationController,
            tunerService: TunerService,
            @Main mainHandler: Handler,
            contentResolver: ContentResolver,
            batteryController: BatteryController,
        ): BatteryMeterViewController {
            return BatteryMeterViewController(
                batteryMeterView,
                StatusBarLocation.QS,
                userTracker,
                configurationController,
                tunerService,
                mainHandler,
                contentResolver,
                batteryController,
            )
        }

        @Provides
        @SysUISingleton
        @Named(SHADE_HEADER)
        fun providesOngoingPrivacyChip(
            @Named(SHADE_HEADER) header: MotionLayout,
        ): OngoingPrivacyChip {
            return header.findViewById(R.id.privacy_chip)
        }

        @Provides
    @Binds
    @SysUISingleton
        @Named(SHADE_HEADER)
        fun providesStatusIconContainer(
            @Named(SHADE_HEADER) header: MotionLayout,
        ): StatusIconContainer {
            return header.findViewById(R.id.statusIcons)
        }
    }
    abstract fun bindsShadeController(shadeControllerImpl: ShadeControllerImpl): ShadeController
}
Loading