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