• 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.qs.dagger.QSFlagsModule.PM_LITE_ENABLED;
20 
21 import android.content.ClipData;
22 import android.content.ClipboardManager;
23 import android.content.Intent;
24 import android.graphics.drawable.Drawable;
25 import android.os.UserManager;
26 import android.text.TextUtils;
27 import android.view.View;
28 import android.widget.TextView;
29 import android.widget.Toast;
30 
31 import com.android.internal.jank.InteractionJankMonitor;
32 import com.android.internal.logging.MetricsLogger;
33 import com.android.internal.logging.UiEventLogger;
34 import com.android.internal.logging.nano.MetricsProto;
35 import com.android.keyguard.KeyguardUpdateMonitor;
36 import com.android.systemui.R;
37 import com.android.systemui.animation.ActivityLaunchAnimator;
38 import com.android.systemui.globalactions.GlobalActionsDialogLite;
39 import com.android.systemui.plugins.ActivityStarter;
40 import com.android.systemui.plugins.FalsingManager;
41 import com.android.systemui.qs.dagger.QSScope;
42 import com.android.systemui.settings.UserTracker;
43 import com.android.systemui.statusbar.phone.MultiUserSwitchController;
44 import com.android.systemui.statusbar.phone.SettingsButton;
45 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
46 import com.android.systemui.statusbar.policy.UserInfoController;
47 import com.android.systemui.tuner.TunerService;
48 import com.android.systemui.util.ViewController;
49 
50 import javax.inject.Inject;
51 import javax.inject.Named;
52 
53 /**
54  * Controller for {@link QSFooterView}.
55  */
56 @QSScope
57 public class QSFooterViewController extends ViewController<QSFooterView> implements QSFooter {
58 
59     private final UserManager mUserManager;
60     private final UserInfoController mUserInfoController;
61     private final ActivityStarter mActivityStarter;
62     private final DeviceProvisionedController mDeviceProvisionedController;
63     private final UserTracker mUserTracker;
64     private final QSPanelController mQsPanelController;
65     private final QuickQSPanelController mQuickQSPanelController;
66     private final TunerService mTunerService;
67     private final MetricsLogger mMetricsLogger;
68     private final FalsingManager mFalsingManager;
69     private final MultiUserSwitchController mMultiUserSwitchController;
70     private final SettingsButton mSettingsButton;
71     private final View mSettingsButtonContainer;
72     private final TextView mBuildText;
73     private final View mEdit;
74     private final PageIndicator mPageIndicator;
75     private final View mPowerMenuLite;
76     private final boolean mShowPMLiteButton;
77     private final GlobalActionsDialogLite mGlobalActionsDialog;
78     private final UiEventLogger mUiEventLogger;
79 
80     private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
81             new UserInfoController.OnUserInfoChangedListener() {
82         @Override
83         public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
84             boolean isGuestUser = mUserManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser());
85             mView.onUserInfoChanged(picture, isGuestUser);
86         }
87     };
88 
89     private final View.OnClickListener mSettingsOnClickListener = new View.OnClickListener() {
90         @Override
91         public void onClick(View v) {
92             // Don't do anything until views are unhidden. Don't do anything if the tap looks
93             // suspicious.
94             if (!mExpanded || mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
95                 return;
96             }
97 
98             if (v == mSettingsButton) {
99                 if (!mDeviceProvisionedController.isCurrentUserSetup()) {
100                     // If user isn't setup just unlock the device and dump them back at SUW.
101                     mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
102                     });
103                     return;
104                 }
105                 mMetricsLogger.action(
106                         mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
107                                 : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
108                 if (mSettingsButton.isTunerClick()) {
109                     mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
110                         if (isTunerEnabled()) {
111                             mTunerService.showResetRequest(
112                                     () -> {
113                                         // Relaunch settings so that the tuner disappears.
114                                         startSettingsActivity();
115                                     });
116                         } else {
117                             Toast.makeText(getContext(), R.string.tuner_toast,
118                                     Toast.LENGTH_LONG).show();
119                             mTunerService.setTunerEnabled(true);
120                         }
121                         startSettingsActivity();
122 
123                     });
124                 } else {
125                     startSettingsActivity();
126                 }
127             } else if (v == mPowerMenuLite) {
128                 mUiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS);
129                 mGlobalActionsDialog.showOrHideDialog(false, true);
130             }
131         }
132     };
133 
134     private boolean mListening;
135     private boolean mExpanded;
136 
137     @Inject
QSFooterViewController(QSFooterView view, UserManager userManager, UserInfoController userInfoController, ActivityStarter activityStarter, DeviceProvisionedController deviceProvisionedController, UserTracker userTracker, QSPanelController qsPanelController, MultiUserSwitchController multiUserSwitchController, QuickQSPanelController quickQSPanelController, TunerService tunerService, MetricsLogger metricsLogger, FalsingManager falsingManager, @Named(PM_LITE_ENABLED) boolean showPMLiteButton, GlobalActionsDialogLite globalActionsDialog, UiEventLogger uiEventLogger)138     QSFooterViewController(QSFooterView view, UserManager userManager,
139             UserInfoController userInfoController, ActivityStarter activityStarter,
140             DeviceProvisionedController deviceProvisionedController, UserTracker userTracker,
141             QSPanelController qsPanelController,
142             MultiUserSwitchController multiUserSwitchController,
143             QuickQSPanelController quickQSPanelController,
144             TunerService tunerService, MetricsLogger metricsLogger, FalsingManager falsingManager,
145             @Named(PM_LITE_ENABLED) boolean showPMLiteButton,
146             GlobalActionsDialogLite globalActionsDialog, UiEventLogger uiEventLogger) {
147         super(view);
148         mUserManager = userManager;
149         mUserInfoController = userInfoController;
150         mActivityStarter = activityStarter;
151         mDeviceProvisionedController = deviceProvisionedController;
152         mUserTracker = userTracker;
153         mQsPanelController = qsPanelController;
154         mQuickQSPanelController = quickQSPanelController;
155         mTunerService = tunerService;
156         mMetricsLogger = metricsLogger;
157         mFalsingManager = falsingManager;
158         mMultiUserSwitchController = multiUserSwitchController;
159 
160         mSettingsButton = mView.findViewById(R.id.settings_button);
161         mSettingsButtonContainer = mView.findViewById(R.id.settings_button_container);
162         mBuildText = mView.findViewById(R.id.build);
163         mEdit = mView.findViewById(android.R.id.edit);
164         mPageIndicator = mView.findViewById(R.id.footer_page_indicator);
165         mPowerMenuLite = mView.findViewById(R.id.pm_lite);
166         mShowPMLiteButton = showPMLiteButton;
167         mGlobalActionsDialog = globalActionsDialog;
168         mUiEventLogger = uiEventLogger;
169     }
170 
171     @Override
onInit()172     protected void onInit() {
173         super.onInit();
174         mMultiUserSwitchController.init();
175     }
176 
177     @Override
onViewAttached()178     protected void onViewAttached() {
179         if (mShowPMLiteButton) {
180             mPowerMenuLite.setVisibility(View.VISIBLE);
181             mPowerMenuLite.setOnClickListener(mSettingsOnClickListener);
182         } else {
183             mPowerMenuLite.setVisibility(View.GONE);
184         }
185         mView.addOnLayoutChangeListener(
186                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
187                         mView.updateAnimator(
188                                 right - left, mQuickQSPanelController.getNumQuickTiles()));
189         mSettingsButton.setOnClickListener(mSettingsOnClickListener);
190         mBuildText.setOnLongClickListener(view -> {
191             CharSequence buildText = mBuildText.getText();
192             if (!TextUtils.isEmpty(buildText)) {
193                 ClipboardManager service =
194                         mUserTracker.getUserContext().getSystemService(ClipboardManager.class);
195                 String label = getResources().getString(R.string.build_number_clip_data_label);
196                 service.setPrimaryClip(ClipData.newPlainText(label, buildText));
197                 Toast.makeText(getContext(), R.string.build_number_copy_toast, Toast.LENGTH_SHORT)
198                         .show();
199                 return true;
200             }
201             return false;
202         });
203 
204         mEdit.setOnClickListener(view -> {
205             if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
206                 return;
207             }
208             mActivityStarter.postQSRunnableDismissingKeyguard(() ->
209                     mQsPanelController.showEdit(view));
210         });
211 
212         mQsPanelController.setFooterPageIndicator(mPageIndicator);
213         mView.updateEverything(isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
214     }
215 
216     @Override
onViewDetached()217     protected void onViewDetached() {
218         setListening(false);
219     }
220 
221     @Override
setVisibility(int visibility)222     public void setVisibility(int visibility) {
223         mView.setVisibility(visibility);
224     }
225 
226     @Override
setExpanded(boolean expanded)227     public void setExpanded(boolean expanded) {
228         mExpanded = expanded;
229         mView.setExpanded(
230                 expanded, isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
231     }
232 
233     @Override
getHeight()234     public int getHeight() {
235         return mView.getHeight();
236     }
237 
238     @Override
setExpansion(float expansion)239     public void setExpansion(float expansion) {
240         mView.setExpansion(expansion);
241     }
242 
243     @Override
setListening(boolean listening)244     public void setListening(boolean listening) {
245         if (mListening == listening) {
246             return;
247         }
248 
249         mListening = listening;
250         if (mListening) {
251             mUserInfoController.addCallback(mOnUserInfoChangedListener);
252         } else {
253             mUserInfoController.removeCallback(mOnUserInfoChangedListener);
254         }
255     }
256 
257     @Override
setKeyguardShowing(boolean keyguardShowing)258     public void setKeyguardShowing(boolean keyguardShowing) {
259         mView.setKeyguardShowing();
260     }
261 
262     /** */
263     @Override
setExpandClickListener(View.OnClickListener onClickListener)264     public void setExpandClickListener(View.OnClickListener onClickListener) {
265         mView.setExpandClickListener(onClickListener);
266     }
267 
268     @Override
disable(int state1, int state2, boolean animate)269     public void disable(int state1, int state2, boolean animate) {
270         mView.disable(state2, isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
271     }
272 
startSettingsActivity()273     private void startSettingsActivity() {
274         ActivityLaunchAnimator.Controller animationController =
275                 mSettingsButtonContainer != null ? ActivityLaunchAnimator.Controller.fromView(
276                         mSettingsButtonContainer,
277                         InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON) : null;
278         mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
279                 true /* dismissShade */, animationController);
280     }
281 
isTunerEnabled()282     private boolean isTunerEnabled() {
283         return mTunerService.isTunerEnabled();
284     }
285 }
286