1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.car.systembar;
18 
19 import android.content.Context;
20 import android.content.res.Resources;
21 
22 import com.android.systemui.CoreStartable;
23 import com.android.systemui.R;
24 import com.android.systemui.car.dagger.CarSysUIDynamicOverride;
25 import com.android.systemui.car.statusbar.UserNameViewController;
26 import com.android.systemui.car.statusicon.StatusIconPanelViewController;
27 import com.android.systemui.car.systembar.element.CarSystemBarElementController;
28 import com.android.systemui.car.users.CarSystemUIUserUtil;
29 import com.android.systemui.dagger.SysUISingleton;
30 import com.android.systemui.dagger.qualifiers.Main;
31 import com.android.systemui.settings.UserTracker;
32 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
33 
34 import dagger.Binds;
35 import dagger.BindsOptionalOf;
36 import dagger.Lazy;
37 import dagger.Module;
38 import dagger.Provides;
39 import dagger.multibindings.ClassKey;
40 import dagger.multibindings.IntoMap;
41 import dagger.multibindings.IntoSet;
42 import dagger.multibindings.Multibinds;
43 
44 import java.util.Map;
45 import java.util.Optional;
46 
47 import javax.inject.Provider;
48 
49 /**
50  * Dagger injection module for {@link CarSystemBar}.
51  *
52  * This module includes the non-@Inject classes used as part of the {@link CarSystemBar}, allowing
53  * extensions of SystemUI to override and provide their own implementations without replacing the
54  * default system bar class.
55  */
56 @Module
57 public abstract class CarSystemBarModule {
58     /**
59      * TODO(): b/260206944,
60      * @return CarSystemBarMediator for SecondaryMUMDSystemUI which blocks CarSystemBar#start()
61      * util RROs are applied, otherwise return CarSystemBar
62      */
63     @Provides
64     @IntoMap
65     @ClassKey(CarSystemBar.class)
bindCarSystemBarStartable( Lazy<CarSystemBar> systemBarService, Lazy<CarSystemBarMediator> applyRROService, @Main Resources resources)66     static CoreStartable bindCarSystemBarStartable(
67             Lazy<CarSystemBar> systemBarService,
68             Lazy<CarSystemBarMediator> applyRROService,
69             @Main Resources resources) {
70         if ((CarSystemUIUserUtil.isSecondaryMUMDSystemUI()
71                 || CarSystemUIUserUtil.isMUPANDSystemUI())
72                 && resources.getBoolean(R.bool.config_enableSecondaryUserRRO)) {
73             return applyRROService.get();
74         }
75         return systemBarService.get();
76     }
77 
78     @Provides
79     @IntoSet
provideCarSystemBarConfigListener( Lazy<CarSystemBar> systemBarService, Lazy<CarSystemBarMediator> applyRROService, @Main Resources resources)80     static ConfigurationListener provideCarSystemBarConfigListener(
81             Lazy<CarSystemBar> systemBarService,
82             Lazy<CarSystemBarMediator> applyRROService,
83             @Main Resources resources) {
84         if ((CarSystemUIUserUtil.isSecondaryMUMDSystemUI()
85                 || CarSystemUIUserUtil.isMUPANDSystemUI())
86                 && resources.getBoolean(R.bool.config_enableSecondaryUserRRO)) {
87             return applyRROService.get();
88         }
89         return systemBarService.get();
90     }
91 
92     @BindsOptionalOf
93     @CarSysUIDynamicOverride
optionalButtonSelectionStateListener()94     abstract ButtonSelectionStateListener optionalButtonSelectionStateListener();
95 
96     @SysUISingleton
97     @Provides
provideButtonSelectionStateListener(@arSysUIDynamicOverride Optional<ButtonSelectionStateListener> overrideButtonSelectionStateListener, ButtonSelectionStateController controller)98     static ButtonSelectionStateListener provideButtonSelectionStateListener(@CarSysUIDynamicOverride
99             Optional<ButtonSelectionStateListener> overrideButtonSelectionStateListener,
100             ButtonSelectionStateController controller) {
101         if (overrideButtonSelectionStateListener.isPresent()) {
102             return overrideButtonSelectionStateListener.get();
103         }
104         return new ButtonSelectionStateListener(controller);
105     }
106 
107     @BindsOptionalOf
108     @CarSysUIDynamicOverride
optionalButtonSelectionStateController()109     abstract ButtonSelectionStateController optionalButtonSelectionStateController();
110 
111     @SysUISingleton
112     @Provides
provideButtonSelectionStateController(Context context, @CarSysUIDynamicOverride Optional<ButtonSelectionStateController> controller)113     static ButtonSelectionStateController provideButtonSelectionStateController(Context context,
114             @CarSysUIDynamicOverride Optional<ButtonSelectionStateController> controller) {
115         if (controller.isPresent()) {
116             return controller.get();
117         }
118         return new ButtonSelectionStateController(context);
119     }
120 
121     @BindsOptionalOf
122     @CarSysUIDynamicOverride
optionalCarSystemBarController()123     abstract CarSystemBarController optionalCarSystemBarController();
124 
125     /**
126      * Allows for the replacement of {@link CarSystemBarController} class with a custom subclass.
127      * Note that this is not ideal and should be used as a last resort since there are no guarantees
128      * that there will not be changes upstream that break the dependencies here (creating additional
129      * maintenance burden).
130      */
131     @SysUISingleton
132     @Provides
provideCarSystemBarController( @arSysUIDynamicOverride Optional<CarSystemBarController> carSystemBarController, Context context, UserTracker userTracker, CarSystemBarViewFactory carSystemBarViewFactory, ButtonSelectionStateController buttonSelectionStateController, Lazy<UserNameViewController> userNameViewControllerLazy, Lazy<MicPrivacyChipViewController> micPrivacyChipViewControllerLazy, Lazy<CameraPrivacyChipViewController> cameraPrivacyChipViewControllerLazy, ButtonRoleHolderController buttonRoleHolderController, SystemBarConfigs systemBarConfigs, Provider<StatusIconPanelViewController.Builder> panelControllerBuilderProvider)133     static CarSystemBarController provideCarSystemBarController(
134             @CarSysUIDynamicOverride Optional<CarSystemBarController> carSystemBarController,
135             Context context,
136             UserTracker userTracker,
137             CarSystemBarViewFactory carSystemBarViewFactory,
138             ButtonSelectionStateController buttonSelectionStateController,
139             Lazy<UserNameViewController> userNameViewControllerLazy,
140             Lazy<MicPrivacyChipViewController> micPrivacyChipViewControllerLazy,
141             Lazy<CameraPrivacyChipViewController> cameraPrivacyChipViewControllerLazy,
142             ButtonRoleHolderController buttonRoleHolderController,
143             SystemBarConfigs systemBarConfigs,
144             Provider<StatusIconPanelViewController.Builder> panelControllerBuilderProvider) {
145         if (carSystemBarController.isPresent()) {
146             return carSystemBarController.get();
147         }
148         return new CarSystemBarController(context, userTracker, carSystemBarViewFactory,
149                 buttonSelectionStateController, userNameViewControllerLazy,
150                 micPrivacyChipViewControllerLazy, cameraPrivacyChipViewControllerLazy,
151                 buttonRoleHolderController, systemBarConfigs, panelControllerBuilderProvider);
152     }
153 
154     // CarSystemBarElements
155 
156     /** Empty set for CarSystemBarElements. */
157     @Multibinds
bindEmptyElementFactoryMap()158     abstract Map<Class<?>, CarSystemBarElementController.Factory> bindEmptyElementFactoryMap();
159 
160     /** Injects CarSystemBarPanelButtonViewController */
161     @Binds
162     @IntoMap
163     @ClassKey(CarSystemBarPanelButtonViewController.class)
bindSystemBarPanelButtonController( CarSystemBarPanelButtonViewController.Factory factory)164     public abstract CarSystemBarElementController.Factory bindSystemBarPanelButtonController(
165             CarSystemBarPanelButtonViewController.Factory factory);
166 
167     /** Injects DockViewControllerWrapper */
168     @Binds
169     @IntoMap
170     @ClassKey(DockViewControllerWrapper.class)
bindDockViewControllerWrapper( DockViewControllerWrapper.Factory factory)171     public abstract CarSystemBarElementController.Factory bindDockViewControllerWrapper(
172             DockViewControllerWrapper.Factory factory);
173 
174     /** Injects DataSubscriptionUnseenIconController */
175     @Binds
176     @IntoMap
177     @ClassKey(DataSubscriptionUnseenIconController.class)
bindDataSubscriptionUnseenIconController( DataSubscriptionUnseenIconController.Factory factory)178     public abstract CarSystemBarElementController.Factory bindDataSubscriptionUnseenIconController(
179             DataSubscriptionUnseenIconController.Factory factory);
180 }
181