• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.qs;
18 
19 import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE;
20 import static com.android.systemui.media.dagger.MediaModule.QS_PANEL;
21 import static com.android.systemui.qs.QSPanel.QS_SHOW_BRIGHTNESS;
22 import static com.android.systemui.qs.dagger.QSScopeModule.QS_USING_MEDIA_PLAYER;
23 
24 import android.view.MotionEvent;
25 import android.view.View;
26 
27 import androidx.annotation.Nullable;
28 
29 import com.android.internal.logging.MetricsLogger;
30 import com.android.internal.logging.UiEventLogger;
31 import com.android.systemui.dump.DumpManager;
32 import com.android.systemui.haptics.qs.QSLongPressEffect;
33 import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor;
34 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager;
35 import com.android.systemui.media.controls.ui.view.MediaHost;
36 import com.android.systemui.media.controls.ui.view.MediaHostState;
37 import com.android.systemui.plugins.FalsingManager;
38 import com.android.systemui.qs.customize.QSCustomizerController;
39 import com.android.systemui.qs.dagger.QSScope;
40 import com.android.systemui.qs.logging.QSLogger;
41 import com.android.systemui.scene.shared.flag.SceneContainerFlag;
42 import com.android.systemui.settings.brightness.BrightnessController;
43 import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
44 import com.android.systemui.settings.brightness.BrightnessSliderController;
45 import com.android.systemui.settings.brightness.MirrorController;
46 import com.android.systemui.shade.ShadeDisplayAware;
47 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
48 import com.android.systemui.statusbar.policy.ConfigurationController;
49 import com.android.systemui.statusbar.policy.SplitShadeStateController;
50 import com.android.systemui.tuner.TunerService;
51 
52 import kotlinx.coroutines.flow.StateFlow;
53 
54 import javax.inject.Inject;
55 import javax.inject.Named;
56 import javax.inject.Provider;
57 
58 
59 /**
60  * Controller for {@link QSPanel}.
61  */
62 @QSScope
63 public class QSPanelController extends QSPanelControllerBase<QSPanel> {
64 
65     private final TunerService mTunerService;
66     private final QSCustomizerController mQsCustomizerController;
67     private final QSTileRevealController.Factory mQsTileRevealControllerFactory;
68     private final FalsingManager mFalsingManager;
69     private BrightnessController mBrightnessController;
70     private BrightnessSliderController mBrightnessSliderController;
71     private BrightnessMirrorHandler mBrightnessMirrorHandler;
72     private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
73     private boolean mListening;
74 
75     private final boolean mSceneContainerEnabled;
76 
77     private int mLastDensity;
78     private final BrightnessSliderController.Factory mBrightnessSliderControllerFactory;
79     private final BrightnessController.Factory mBrightnessControllerFactory;
80 
81     protected final MediaCarouselInteractor mMediaCarouselInteractor;
82 
83     private View.OnTouchListener mTileLayoutTouchListener = new View.OnTouchListener() {
84         @Override
85         public boolean onTouch(View v, MotionEvent event) {
86             if (event.getActionMasked() == MotionEvent.ACTION_UP) {
87                 mFalsingManager.isFalseTouch(QS_SWIPE_SIDE);
88             }
89             return false;
90         }
91     };
92 
93     @Inject
QSPanelController(QSPanel view, TunerService tunerService, QSHost qsHost, QSCustomizerController qsCustomizerController, @Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer, @Named(QS_PANEL) MediaHost mediaHost, QSTileRevealController.Factory qsTileRevealControllerFactory, DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory, BrightnessSliderController.Factory brightnessSliderFactory, FalsingManager falsingManager, StatusBarKeyguardViewManager statusBarKeyguardViewManager, SplitShadeStateController splitShadeStateController, Provider<QSLongPressEffect> longPRessEffectProvider, MediaCarouselInteractor mediaCarouselInteractor, @ShadeDisplayAware ConfigurationController configurationController)94     QSPanelController(QSPanel view, TunerService tunerService,
95             QSHost qsHost, QSCustomizerController qsCustomizerController,
96             @Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
97             @Named(QS_PANEL) MediaHost mediaHost,
98             QSTileRevealController.Factory qsTileRevealControllerFactory,
99             DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
100             QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
101             BrightnessSliderController.Factory brightnessSliderFactory,
102             FalsingManager falsingManager,
103             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
104             SplitShadeStateController splitShadeStateController,
105             Provider<QSLongPressEffect> longPRessEffectProvider,
106             MediaCarouselInteractor mediaCarouselInteractor,
107             @ShadeDisplayAware ConfigurationController configurationController) {
108         super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost,
109                 metricsLogger, uiEventLogger, qsLogger, dumpManager, splitShadeStateController,
110                 longPRessEffectProvider, configurationController);
111         mTunerService = tunerService;
112         mQsCustomizerController = qsCustomizerController;
113         mQsTileRevealControllerFactory = qsTileRevealControllerFactory;
114         mFalsingManager = falsingManager;
115         mBrightnessSliderControllerFactory = brightnessSliderFactory;
116         mBrightnessControllerFactory = brightnessControllerFactory;
117 
118         mBrightnessSliderController = brightnessSliderFactory.create(getContext(), mView);
119         mView.setBrightnessView(mBrightnessSliderController.getRootView());
120 
121         mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController);
122         mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
123         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
124         mLastDensity = view.getResources().getConfiguration().densityDpi;
125         mSceneContainerEnabled = SceneContainerFlag.isEnabled();
126         mMediaCarouselInteractor = mediaCarouselInteractor;
127     }
128 
129     @Override
onInit()130     public void onInit() {
131         super.onInit();
132         mMediaHost.setExpansion(MediaHostState.EXPANDED);
133         mMediaHost.setShowsOnlyActiveMedia(false);
134         mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
135         mQsCustomizerController.init();
136         mBrightnessSliderController.init();
137     }
138 
139     @Override
getMediaVisibleFlow()140     StateFlow<Boolean> getMediaVisibleFlow() {
141         return mMediaCarouselInteractor.getHasAnyMediaOrRecommendation();
142     }
143 
144     @Override
onViewAttached()145     protected void onViewAttached() {
146         super.onViewAttached();
147 
148         updateMediaDisappearParameters();
149 
150         mTunerService.addTunable(mView, QS_SHOW_BRIGHTNESS);
151         mView.updateResources();
152         mView.setSceneContainerEnabled(mSceneContainerEnabled);
153         if (mView.isListening()) {
154             refreshAllTiles();
155         }
156         switchTileLayout(true);
157         mBrightnessMirrorHandler.onQsPanelAttached();
158         PagedTileLayout pagedTileLayout= ((PagedTileLayout) mView.getOrCreateTileLayout());
159         pagedTileLayout.setOnTouchListener(mTileLayoutTouchListener);
160         maybeReinflateBrightnessSlider();
161     }
162 
163     @Override
createTileRevealController()164     protected QSTileRevealController createTileRevealController() {
165         return mQsTileRevealControllerFactory.create(
166                 this, (PagedTileLayout) mView.getOrCreateTileLayout());
167     }
168 
169     @Override
onViewDetached()170     protected void onViewDetached() {
171         mTunerService.removeTunable(mView);
172         mBrightnessMirrorHandler.onQsPanelDettached();
173         super.onViewDetached();
174     }
175 
176     @Override
onConfigurationChanged()177     protected void onConfigurationChanged() {
178         mView.updateResources();
179         maybeReinflateBrightnessSlider();
180         if (mView.isListening()) {
181             refreshAllTiles();
182         }
183     }
184 
maybeReinflateBrightnessSlider()185     private void maybeReinflateBrightnessSlider() {
186         int newDensity = mView.getResources().getConfiguration().densityDpi;
187         if (newDensity != mLastDensity) {
188             mLastDensity = newDensity;
189             reinflateBrightnessSlider();
190         }
191     }
192 
reinflateBrightnessSlider()193     private void reinflateBrightnessSlider() {
194         mBrightnessController.unregisterCallbacks();
195         mBrightnessSliderController =
196                 mBrightnessSliderControllerFactory.create(getContext(), mView);
197         mView.setBrightnessView(mBrightnessSliderController.getRootView());
198         mBrightnessController = mBrightnessControllerFactory.create(mBrightnessSliderController);
199         mBrightnessMirrorHandler.setBrightnessController(mBrightnessController);
200         mBrightnessSliderController.init();
201         if (mListening) {
202             mBrightnessController.registerCallbacks();
203         }
204     }
205 
206 
207     @Override
onSplitShadeChanged(boolean shouldUseSplitNotificationShade)208     protected void onSplitShadeChanged(boolean shouldUseSplitNotificationShade) {
209         ((PagedTileLayout) mView.getOrCreateTileLayout())
210                 .forceTilesRedistribution("Split shade state changed");
211         mView.setCanCollapse(!shouldUseSplitNotificationShade);
212     }
213 
214     /** */
setVisibility(int visibility)215     public void setVisibility(int visibility) {
216         mView.setVisibility(visibility);
217     }
218 
219     /** */
setListening(boolean listening, boolean expanded)220     public void setListening(boolean listening, boolean expanded) {
221         setListening(listening && expanded);
222 
223         if (listening != mListening) {
224             mListening = listening;
225             // Set the listening as soon as the QS fragment starts listening regardless of the
226             //expansion, so it will update the current brightness before the slider is visible.
227             if (listening) {
228                 mBrightnessController.registerCallbacks();
229             } else {
230                 mBrightnessController.unregisterCallbacks();
231             }
232         }
233     }
234 
setBrightnessMirror(@ullable MirrorController brightnessMirrorController)235     public void setBrightnessMirror(@Nullable MirrorController brightnessMirrorController) {
236         mBrightnessMirrorHandler.setController(brightnessMirrorController);
237     }
238 
239     /** Update appearance of QSPanel. */
updateResources()240     public void updateResources() {
241         mView.updateResources();
242     }
243 
244     /** Update state of all tiles. */
refreshAllTiles()245     public void refreshAllTiles() {
246         mBrightnessController.checkRestrictionAndSetEnabled();
247         super.refreshAllTiles();
248     }
249 
250     /** Start customizing the Quick Settings. */
showEdit(View view)251     public void showEdit(View view) {
252         view.post(() -> {
253             if (!mQsCustomizerController.isCustomizing()) {
254                 int[] loc = view.getLocationOnScreen();
255                 int x = loc[0] + view.getWidth() / 2;
256                 int y = loc[1] + view.getHeight() / 2;
257                 mQsCustomizerController.show(x, y, false);
258             }
259         });
260     }
261 
isLayoutRtl()262     public boolean isLayoutRtl() {
263         return mView.isLayoutRtl();
264     }
265 
266     /** */
setPageListener(PagedTileLayout.PageListener listener)267     public void setPageListener(PagedTileLayout.PageListener listener) {
268         mView.setPageListener(listener);
269     }
270 
isShown()271     public boolean isShown() {
272         return mView.isShown();
273     }
274 
275     /** */
setContentMargins(int startMargin, int endMargin)276     public void setContentMargins(int startMargin, int endMargin) {
277         mView.setContentMargins(startMargin, endMargin, mMediaHost.getHostView());
278     }
279 
280     /** */
setFooterPageIndicator(PageIndicator pageIndicator)281     public void setFooterPageIndicator(PageIndicator pageIndicator) {
282         mView.setFooterPageIndicator(pageIndicator);
283     }
284 
285     /** */
isExpanded()286     public boolean isExpanded() {
287         return mView.isExpanded();
288     }
289 
setPageMargin(int pageMarginStart, int pageMarginEnd)290     void setPageMargin(int pageMarginStart, int pageMarginEnd) {
291         mView.setPageMargin(pageMarginStart, pageMarginEnd);
292     }
293 
294     /**
295      * Determines if bouncer expansion is between 0 and 1 non-inclusive.
296      *
297      * @return if bouncer is in transit
298      */
isBouncerInTransit()299     public boolean isBouncerInTransit() {
300         return mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit();
301     }
302 
getPaddingBottom()303     public int getPaddingBottom() {
304         return mView.getPaddingBottom();
305     }
306 
getViewBottom()307     int getViewBottom() {
308         return mView.getBottom();
309     }
310 }
311 
312