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.media.dagger.MediaModule.QUICK_QS_PANEL; 20 import static com.android.systemui.qs.dagger.QSScopeModule.QS_USING_COLLAPSED_LANDSCAPE_MEDIA; 21 import static com.android.systemui.qs.dagger.QSScopeModule.QS_USING_MEDIA_PLAYER; 22 23 import androidx.annotation.VisibleForTesting; 24 25 import com.android.internal.logging.MetricsLogger; 26 import com.android.internal.logging.UiEventLogger; 27 import com.android.systemui.dump.DumpManager; 28 import com.android.systemui.haptics.qs.QSLongPressEffect; 29 import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor; 30 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager; 31 import com.android.systemui.media.controls.ui.view.MediaHost; 32 import com.android.systemui.plugins.qs.QSTile; 33 import com.android.systemui.qs.customize.QSCustomizerController; 34 import com.android.systemui.qs.dagger.QSScope; 35 import com.android.systemui.qs.logging.QSLogger; 36 import com.android.systemui.res.R; 37 import com.android.systemui.statusbar.policy.SplitShadeStateController; 38 import com.android.systemui.util.leak.RotationUtils; 39 40 import kotlinx.coroutines.flow.StateFlow; 41 42 import java.util.ArrayList; 43 import java.util.List; 44 45 import javax.inject.Inject; 46 import javax.inject.Named; 47 import javax.inject.Provider; 48 49 50 /** Controller for {@link QuickQSPanel}. */ 51 @QSScope 52 public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> { 53 54 private final Provider<Boolean> mUsingCollapsedLandscapeMediaProvider; 55 56 private final MediaCarouselInteractor mMediaCarouselInteractor; 57 58 @Inject QuickQSPanelController(QuickQSPanel view, QSHost qsHost, QSCustomizerController qsCustomizerController, @Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer, @Named(QUICK_QS_PANEL) MediaHost mediaHost, @Named(QS_USING_COLLAPSED_LANDSCAPE_MEDIA) Provider<Boolean> usingCollapsedLandscapeMediaProvider, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, DumpManager dumpManager, SplitShadeStateController splitShadeStateController, Provider<QSLongPressEffect> longPressEffectProvider, MediaCarouselInteractor mediaCarouselInteractor )59 QuickQSPanelController(QuickQSPanel view, QSHost qsHost, 60 QSCustomizerController qsCustomizerController, 61 @Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer, 62 @Named(QUICK_QS_PANEL) MediaHost mediaHost, 63 @Named(QS_USING_COLLAPSED_LANDSCAPE_MEDIA) 64 Provider<Boolean> usingCollapsedLandscapeMediaProvider, 65 MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, 66 DumpManager dumpManager, SplitShadeStateController splitShadeStateController, 67 Provider<QSLongPressEffect> longPressEffectProvider, 68 MediaCarouselInteractor mediaCarouselInteractor 69 ) { 70 super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, 71 uiEventLogger, qsLogger, dumpManager, splitShadeStateController, 72 longPressEffectProvider); 73 mUsingCollapsedLandscapeMediaProvider = usingCollapsedLandscapeMediaProvider; 74 mMediaCarouselInteractor = mediaCarouselInteractor; 75 } 76 77 @Override onInit()78 protected void onInit() { 79 super.onInit(); 80 updateMediaExpansion(); 81 mMediaHost.setShowsOnlyActiveMedia(true); 82 mMediaHost.init(MediaHierarchyManager.LOCATION_QQS); 83 } 84 85 @Override getMediaVisibleFlow()86 StateFlow<Boolean> getMediaVisibleFlow() { 87 return mMediaCarouselInteractor.getHasActiveMediaOrRecommendation(); 88 } 89 updateMediaExpansion()90 private void updateMediaExpansion() { 91 int rotation = getRotation(); 92 boolean isLandscape = rotation == RotationUtils.ROTATION_LANDSCAPE 93 || rotation == RotationUtils.ROTATION_SEASCAPE; 94 boolean usingCollapsedLandscapeMedia = mUsingCollapsedLandscapeMediaProvider.get(); 95 if (!usingCollapsedLandscapeMedia || !isLandscape) { 96 mMediaHost.setExpansion(MediaHost.EXPANDED); 97 } else { 98 mMediaHost.setExpansion(MediaHost.COLLAPSED); 99 } 100 } 101 102 @VisibleForTesting getRotation()103 protected int getRotation() { 104 return RotationUtils.getRotation(getContext()); 105 } 106 107 @Override onViewAttached()108 protected void onViewAttached() { 109 super.onViewAttached(); 110 } 111 112 @Override onViewDetached()113 protected void onViewDetached() { 114 super.onViewDetached(); 115 } 116 setMaxTiles(int parseNumTiles)117 private void setMaxTiles(int parseNumTiles) { 118 mView.setMaxTiles(parseNumTiles); 119 setTiles(); 120 } 121 122 @Override onConfigurationChanged()123 protected void onConfigurationChanged() { 124 int newMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_tiles); 125 if (newMaxTiles != mView.getNumQuickTiles()) { 126 setMaxTiles(newMaxTiles); 127 } 128 updateMediaExpansion(); 129 } 130 131 @Override setTiles()132 public void setTiles() { 133 List<QSTile> tiles = new ArrayList<>(); 134 for (QSTile tile : mHost.getTiles()) { 135 tiles.add(tile); 136 if (tiles.size() == mView.getNumQuickTiles()) { 137 break; 138 } 139 } 140 super.setTiles(tiles, /* collapsedView */ true); 141 } 142 setContentMargins(int marginStart, int marginEnd)143 public void setContentMargins(int marginStart, int marginEnd) { 144 mView.setContentMargins(marginStart, marginEnd, mMediaHost.getHostView()); 145 } 146 getNumQuickTiles()147 public int getNumQuickTiles() { 148 return mView.getNumQuickTiles(); 149 } 150 } 151