blob: e03db2c8b9c61b4694e3751e3b3ca6b31ab6b17d [file] [log] [blame]
Jason Monkaa573e92017-01-27 17:00:29 -05001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui.statusbar.phone;
16
Evan Laird4b68e2f72018-03-29 18:21:48 -040017import static android.app.StatusBarManager.DISABLE_CLOCK;
Jason Monkd3ee70c2017-08-30 17:05:24 -040018import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS;
19import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
20
Jason Monkaa573e92017-01-27 17:00:29 -050021import android.annotation.Nullable;
22import android.app.Fragment;
Jason Monkaa573e92017-01-27 17:00:29 -050023import android.os.Bundle;
felkachange6c03a02018-05-24 15:38:04 +080024import android.os.Parcelable;
25import android.util.SparseArray;
Jason Monkaa573e92017-01-27 17:00:29 -050026import android.view.LayoutInflater;
27import android.view.View;
28import android.view.ViewGroup;
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090029import android.view.ViewStub;
Jason Monkaa573e92017-01-27 17:00:29 -050030import android.widget.LinearLayout;
31
32import com.android.systemui.Dependency;
33import com.android.systemui.Interpolators;
34import com.android.systemui.R;
Beverly8fdb5332019-02-04 14:29:49 -050035import com.android.systemui.plugins.statusbar.StatusBarStateController;
Jason Monkaa573e92017-01-27 17:00:29 -050036import com.android.systemui.statusbar.CommandQueue;
Selim Cinekc7e4cb52019-06-20 15:41:45 -070037import com.android.systemui.statusbar.StatusBarState;
Jason Monkaa573e92017-01-27 17:00:29 -050038import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
Jason Monkaa573e92017-01-27 17:00:29 -050039import com.android.systemui.statusbar.policy.EncryptionHelper;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040040import com.android.systemui.statusbar.policy.KeyguardStateController;
Jason Monkaa573e92017-01-27 17:00:29 -050041import com.android.systemui.statusbar.policy.NetworkController;
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090042import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
Jason Monkaa573e92017-01-27 17:00:29 -050043
44/**
45 * Contains the collapsed status bar and handles hiding/showing based on disable flags
46 * and keyguard state. Also manages lifecycle to make sure the views it contains are being
47 * updated by the StatusBarIconController and DarkIconManager while it is attached.
48 */
Lucas Dupin2e43cfc2018-11-12 14:07:18 -080049public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks,
50 StatusBarStateController.StateListener {
Jason Monkaa573e92017-01-27 17:00:29 -050051
52 public static final String TAG = "CollapsedStatusBarFragment";
Jason Monk0a7d9f22017-03-15 11:03:06 -040053 private static final String EXTRA_PANEL_STATE = "panel_state";
Evan Laird937d9fa2018-02-08 10:12:16 -080054 public static final String STATUS_BAR_ICON_MANAGER_TAG = "status_bar_icon_manager";
Selim Cinek2627d722018-01-19 12:16:49 -080055 public static final int FADE_IN_DURATION = 320;
56 public static final int FADE_IN_DELAY = 50;
Jason Monkaa573e92017-01-27 17:00:29 -050057 private PhoneStatusBarView mStatusBar;
Lucas Dupin23a8d3b2018-10-08 20:57:35 -070058 private StatusBarStateController mStatusBarStateController;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040059 private KeyguardStateController mKeyguardStateController;
Jason Monkaa573e92017-01-27 17:00:29 -050060 private NetworkController mNetworkController;
61 private LinearLayout mSystemIconArea;
Evan Laird2cf56822017-12-18 11:22:39 -050062 private View mClockView;
Jason Monkaa573e92017-01-27 17:00:29 -050063 private View mNotificationIconAreaInner;
Beverly40770652019-02-15 15:49:49 -050064 private View mCenteredIconArea;
Jason Monkaa573e92017-01-27 17:00:29 -050065 private int mDisabled1;
66 private StatusBar mStatusBarComponent;
67 private DarkIconManager mDarkIconManager;
Kensuke Matsui21d1bf12017-03-14 13:27:20 +090068 private View mOperatorNameFrame;
Jason Monk297c04e2018-08-23 17:16:59 -040069 private CommandQueue mCommandQueue;
Jason Monkaa573e92017-01-27 17:00:29 -050070
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090071 private SignalCallback mSignalCallback = new SignalCallback() {
72 @Override
73 public void setIsAirplaneMode(NetworkController.IconState icon) {
Charles Chenf3d295c2018-11-30 18:15:21 +080074 mCommandQueue.recomputeDisableFlags(getContext().getDisplayId(), true /* animate */);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090075 }
76 };
77
Jason Monkaa573e92017-01-27 17:00:29 -050078 @Override
79 public void onCreate(@Nullable Bundle savedInstanceState) {
80 super.onCreate(savedInstanceState);
Lucas Dupinc8f16e82019-09-17 18:24:50 -040081 mKeyguardStateController = Dependency.get(KeyguardStateController.class);
Jason Monkaa573e92017-01-27 17:00:29 -050082 mNetworkController = Dependency.get(NetworkController.class);
Lucas Dupin23a8d3b2018-10-08 20:57:35 -070083 mStatusBarStateController = Dependency.get(StatusBarStateController.class);
Dave Mankoff4dd47fa2019-11-07 10:44:48 -050084 mStatusBarComponent = Dependency.get(StatusBar.class);
Dave Mankoffbcaca8a2019-10-31 18:04:08 -040085 mCommandQueue = Dependency.get(CommandQueue.class);
Jason Monkaa573e92017-01-27 17:00:29 -050086 }
87
88 @Override
89 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
90 Bundle savedInstanceState) {
91 return inflater.inflate(R.layout.status_bar, container, false);
92 }
93
94 @Override
95 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
96 super.onViewCreated(view, savedInstanceState);
97 mStatusBar = (PhoneStatusBarView) view;
Jason Monk0a7d9f22017-03-15 11:03:06 -040098 if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
felkachange6c03a02018-05-24 15:38:04 +080099 mStatusBar.restoreHierarchyState(
100 savedInstanceState.getSparseParcelableArray(EXTRA_PANEL_STATE));
Jason Monk0a7d9f22017-03-15 11:03:06 -0400101 }
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400102 mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons),
103 Dependency.get(CommandQueue.class));
Evan Laird937d9fa2018-02-08 10:12:16 -0800104 mDarkIconManager.setShouldLog(true);
Jason Monkaa573e92017-01-27 17:00:29 -0500105 Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
Jason Monk0a7d9f22017-03-15 11:03:06 -0400106 mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
Evan Laird2cf56822017-12-18 11:22:39 -0500107 mClockView = mStatusBar.findViewById(R.id.clock);
Jason Monk60033fc2017-03-24 11:26:35 -0400108 showSystemIconArea(false);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400109 showClock(false);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900110 initEmergencyCryptkeeperText();
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900111 initOperatorName();
Jason Monkaa573e92017-01-27 17:00:29 -0500112 }
113
114 @Override
Jason Monk0a7d9f22017-03-15 11:03:06 -0400115 public void onSaveInstanceState(Bundle outState) {
116 super.onSaveInstanceState(outState);
felkachange6c03a02018-05-24 15:38:04 +0800117 SparseArray<Parcelable> states = new SparseArray<>();
118 mStatusBar.saveHierarchyState(states);
119 outState.putSparseParcelableArray(EXTRA_PANEL_STATE, states);
Jason Monk0a7d9f22017-03-15 11:03:06 -0400120 }
121
122 @Override
Jason Monkaa573e92017-01-27 17:00:29 -0500123 public void onResume() {
124 super.onResume();
Jason Monkd7c98552018-12-04 11:14:50 -0500125 mCommandQueue.addCallback(this);
Jason Monkaf08c152018-12-04 11:12:39 -0500126 mStatusBarStateController.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500127 }
128
129 @Override
130 public void onPause() {
131 super.onPause();
Jason Monkd7c98552018-12-04 11:14:50 -0500132 mCommandQueue.removeCallback(this);
Jason Monkaf08c152018-12-04 11:12:39 -0500133 mStatusBarStateController.removeCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500134 }
135
136 @Override
137 public void onDestroyView() {
138 super.onDestroyView();
Jason Monkaa573e92017-01-27 17:00:29 -0500139 Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900140 if (mNetworkController.hasEmergencyCryptKeeperText()) {
141 mNetworkController.removeCallback(mSignalCallback);
142 }
Jason Monkaa573e92017-01-27 17:00:29 -0500143 }
144
145 public void initNotificationIconArea(NotificationIconAreaController
146 notificationIconAreaController) {
Jason Monk0a7d9f22017-03-15 11:03:06 -0400147 ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
Jason Monkaa573e92017-01-27 17:00:29 -0500148 mNotificationIconAreaInner =
149 notificationIconAreaController.getNotificationInnerAreaView();
150 if (mNotificationIconAreaInner.getParent() != null) {
151 ((ViewGroup) mNotificationIconAreaInner.getParent())
152 .removeView(mNotificationIconAreaInner);
153 }
154 notificationIconArea.addView(mNotificationIconAreaInner);
Beverly40770652019-02-15 15:49:49 -0500155
156 ViewGroup statusBarCenteredIconArea = mStatusBar.findViewById(R.id.centered_icon_area);
157 mCenteredIconArea = notificationIconAreaController.getCenteredNotificationAreaView();
158 if (mCenteredIconArea.getParent() != null) {
159 ((ViewGroup) mCenteredIconArea.getParent())
160 .removeView(mCenteredIconArea);
161 }
162 statusBarCenteredIconArea.addView(mCenteredIconArea);
163
Jason Monk60033fc2017-03-24 11:26:35 -0400164 // Default to showing until we know otherwise.
165 showNotificationIconArea(false);
Jason Monkaa573e92017-01-27 17:00:29 -0500166 }
167
168 @Override
Charles Chenf3d295c2018-11-30 18:15:21 +0800169 public void disable(int displayId, int state1, int state2, boolean animate) {
170 if (displayId != getContext().getDisplayId()) {
171 return;
172 }
Jason Monkaa573e92017-01-27 17:00:29 -0500173 state1 = adjustDisableFlags(state1);
174 final int old1 = mDisabled1;
175 final int diff1 = state1 ^ old1;
176 mDisabled1 = state1;
Jason Monkd3ee70c2017-08-30 17:05:24 -0400177 if ((diff1 & DISABLE_SYSTEM_INFO) != 0) {
178 if ((state1 & DISABLE_SYSTEM_INFO) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500179 hideSystemIconArea(animate);
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900180 hideOperatorName(animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500181 } else {
182 showSystemIconArea(animate);
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900183 showOperatorName(animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500184 }
185 }
Jason Monkd3ee70c2017-08-30 17:05:24 -0400186 if ((diff1 & DISABLE_NOTIFICATION_ICONS) != 0) {
187 if ((state1 & DISABLE_NOTIFICATION_ICONS) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500188 hideNotificationIconArea(animate);
189 } else {
190 showNotificationIconArea(animate);
191 }
192 }
Evan Lairdc1f231f2018-05-16 19:43:19 -0400193 // The clock may have already been hidden, but we might want to shift its
194 // visibility to GONE from INVISIBLE or vice versa
195 if ((diff1 & DISABLE_CLOCK) != 0 || mClockView.getVisibility() != clockHiddenMode()) {
Evan Laird4b68e2f72018-03-29 18:21:48 -0400196 if ((state1 & DISABLE_CLOCK) != 0) {
197 hideClock(animate);
198 } else {
199 showClock(animate);
200 }
201 }
Jason Monkaa573e92017-01-27 17:00:29 -0500202 }
203
204 protected int adjustDisableFlags(int state) {
Selim Cinekc7e4cb52019-06-20 15:41:45 -0700205 boolean headsUpVisible = mStatusBarComponent.headsUpShouldBeVisible();
206 if (headsUpVisible) {
207 state |= DISABLE_CLOCK;
208 }
209
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400210 if (!mKeyguardStateController.isLaunchTransitionFadingAway()
211 && !mKeyguardStateController.isKeyguardFadingAway()
Selim Cinekc7e4cb52019-06-20 15:41:45 -0700212 && shouldHideNotificationIcons()
213 && !(mStatusBarStateController.getState() == StatusBarState.KEYGUARD
214 && headsUpVisible)) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400215 state |= DISABLE_NOTIFICATION_ICONS;
216 state |= DISABLE_SYSTEM_INFO;
Evan Laird4b68e2f72018-03-29 18:21:48 -0400217 state |= DISABLE_CLOCK;
Jason Monkaa573e92017-01-27 17:00:29 -0500218 }
felkachangca4eee82018-06-29 15:34:28 +0800219
felkachangca4eee82018-06-29 15:34:28 +0800220
Jason Monkaa573e92017-01-27 17:00:29 -0500221 if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
222 if (mNetworkController.hasEmergencyCryptKeeperText()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400223 state |= DISABLE_NOTIFICATION_ICONS;
Jason Monkaa573e92017-01-27 17:00:29 -0500224 }
225 if (!mNetworkController.isRadioOn()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400226 state |= DISABLE_SYSTEM_INFO;
Jason Monkaa573e92017-01-27 17:00:29 -0500227 }
228 }
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700229
Lucas Dupin7fc9dc12019-01-03 09:19:43 -0800230 // The shelf will be hidden when dozing with a custom clock, we must show notification
231 // icons in this occasion.
232 if (mStatusBarStateController.isDozing()
Dave Mankoffaf8163f2020-01-08 14:24:35 -0500233 && mStatusBarComponent.getPanelController().hasCustomClock()) {
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700234 state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700235 }
236
Jason Monkaa573e92017-01-27 17:00:29 -0500237 return state;
238 }
239
240 private boolean shouldHideNotificationIcons() {
Selim Cinek3a49ba22017-08-10 11:17:39 -0700241 if (!mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded()) {
242 return true;
243 }
244 if (mStatusBarComponent.hideStatusBarIconsForBouncer()) {
245 return true;
246 }
247 return false;
Jason Monkaa573e92017-01-27 17:00:29 -0500248 }
249
250 public void hideSystemIconArea(boolean animate) {
251 animateHide(mSystemIconArea, animate);
252 }
253
254 public void showSystemIconArea(boolean animate) {
255 animateShow(mSystemIconArea, animate);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400256 }
257
258 public void hideClock(boolean animate) {
Evan Lairdc1f231f2018-05-16 19:43:19 -0400259 animateHiddenState(mClockView, clockHiddenMode(), animate);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400260 }
261
262 public void showClock(boolean animate) {
Evan Laird2cf56822017-12-18 11:22:39 -0500263 animateShow(mClockView, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500264 }
265
Evan Lairdc1f231f2018-05-16 19:43:19 -0400266 /**
267 * If panel is expanded/expanding it usually means QS shade is opening, so
268 * don't set the clock GONE otherwise it'll mess up the animation.
269 */
270 private int clockHiddenMode() {
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400271 if (!mStatusBar.isClosed() && !mKeyguardStateController.isShowing()
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700272 && !mStatusBarStateController.isDozing()) {
Evan Lairdc1f231f2018-05-16 19:43:19 -0400273 return View.INVISIBLE;
274 }
275 return View.GONE;
276 }
277
Jason Monkaa573e92017-01-27 17:00:29 -0500278 public void hideNotificationIconArea(boolean animate) {
279 animateHide(mNotificationIconAreaInner, animate);
Beverly40770652019-02-15 15:49:49 -0500280 animateHide(mCenteredIconArea, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500281 }
282
283 public void showNotificationIconArea(boolean animate) {
284 animateShow(mNotificationIconAreaInner, animate);
Beverly40770652019-02-15 15:49:49 -0500285 animateShow(mCenteredIconArea, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500286 }
287
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900288 public void hideOperatorName(boolean animate) {
289 if (mOperatorNameFrame != null) {
290 animateHide(mOperatorNameFrame, animate);
291 }
292 }
293
294 public void showOperatorName(boolean animate) {
295 if (mOperatorNameFrame != null) {
296 animateShow(mOperatorNameFrame, animate);
297 }
298 }
299
Jason Monkaa573e92017-01-27 17:00:29 -0500300 /**
Evan Laird74435e62018-05-04 11:58:30 -0400301 * Animate a view to INVISIBLE or GONE
Jason Monkaa573e92017-01-27 17:00:29 -0500302 */
Evan Laird74435e62018-05-04 11:58:30 -0400303 private void animateHiddenState(final View v, int state, boolean animate) {
Jason Monkaa573e92017-01-27 17:00:29 -0500304 v.animate().cancel();
305 if (!animate) {
306 v.setAlpha(0f);
Evan Laird74435e62018-05-04 11:58:30 -0400307 v.setVisibility(state);
Jason Monkaa573e92017-01-27 17:00:29 -0500308 return;
309 }
Evan Laird74435e62018-05-04 11:58:30 -0400310
Jason Monkaa573e92017-01-27 17:00:29 -0500311 v.animate()
312 .alpha(0f)
313 .setDuration(160)
314 .setStartDelay(0)
315 .setInterpolator(Interpolators.ALPHA_OUT)
Evan Laird74435e62018-05-04 11:58:30 -0400316 .withEndAction(() -> v.setVisibility(state));
317 }
318
319 /**
320 * Hides a view.
321 */
322 private void animateHide(final View v, boolean animate) {
323 animateHiddenState(v, View.INVISIBLE, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500324 }
325
326 /**
327 * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
328 */
329 private void animateShow(View v, boolean animate) {
330 v.animate().cancel();
331 v.setVisibility(View.VISIBLE);
332 if (!animate) {
333 v.setAlpha(1f);
334 return;
335 }
336 v.animate()
337 .alpha(1f)
Selim Cinek2627d722018-01-19 12:16:49 -0800338 .setDuration(FADE_IN_DURATION)
Jason Monkaa573e92017-01-27 17:00:29 -0500339 .setInterpolator(Interpolators.ALPHA_IN)
Selim Cinek2627d722018-01-19 12:16:49 -0800340 .setStartDelay(FADE_IN_DELAY)
Jason Monkaa573e92017-01-27 17:00:29 -0500341
342 // We need to clean up any pending end action from animateHide if we call
343 // both hide and show in the same frame before the animation actually gets started.
344 // cancel() doesn't really remove the end action.
345 .withEndAction(null);
346
347 // Synchronize the motion with the Keyguard fading if necessary.
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400348 if (mKeyguardStateController.isKeyguardFadingAway()) {
Jason Monkaa573e92017-01-27 17:00:29 -0500349 v.animate()
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400350 .setDuration(mKeyguardStateController.getKeyguardFadingAwayDuration())
Jason Monkaa573e92017-01-27 17:00:29 -0500351 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400352 .setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
Jason Monkaa573e92017-01-27 17:00:29 -0500353 .start();
354 }
355 }
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900356
357 private void initEmergencyCryptkeeperText() {
358 View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
359 if (mNetworkController.hasEmergencyCryptKeeperText()) {
360 if (emergencyViewStub != null) {
361 ((ViewStub) emergencyViewStub).inflate();
362 }
363 mNetworkController.addCallback(mSignalCallback);
364 } else if (emergencyViewStub != null) {
365 ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
366 parent.removeView(emergencyViewStub);
367 }
368 }
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900369
370 private void initOperatorName() {
371 if (getResources().getBoolean(R.bool.config_showOperatorNameInStatusBar)) {
372 ViewStub stub = mStatusBar.findViewById(R.id.operator_name);
373 mOperatorNameFrame = stub.inflate();
374 }
375 }
Lucas Dupin2e43cfc2018-11-12 14:07:18 -0800376
377 @Override
378 public void onStateChanged(int newState) {
379
380 }
381
382 @Override
383 public void onDozingChanged(boolean isDozing) {
Charles Chenf3d295c2018-11-30 18:15:21 +0800384 disable(getContext().getDisplayId(), mDisabled1, mDisabled1, false /* animate */);
Lucas Dupin2e43cfc2018-11-12 14:07:18 -0800385 }
Jason Monkaa573e92017-01-27 17:00:29 -0500386}