blob: 58f457ed6e3ace5fbbf0c228fcd3987f4904c3e2 [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;
35import com.android.systemui.SysUiServiceProvider;
Beverly8fdb5332019-02-04 14:29:49 -050036import com.android.systemui.plugins.statusbar.StatusBarStateController;
Jason Monkaa573e92017-01-27 17:00:29 -050037import com.android.systemui.statusbar.CommandQueue;
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;
40import com.android.systemui.statusbar.policy.KeyguardMonitor;
41import 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;
Jason Monkaa573e92017-01-27 17:00:29 -050059 private KeyguardMonitor mKeyguardMonitor;
60 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);
81 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
82 mNetworkController = Dependency.get(NetworkController.class);
Lucas Dupin23a8d3b2018-10-08 20:57:35 -070083 mStatusBarStateController = Dependency.get(StatusBarStateController.class);
Jason Monkaa573e92017-01-27 17:00:29 -050084 mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
Jason Monk297c04e2018-08-23 17:16:59 -040085 mCommandQueue = SysUiServiceProvider.getComponent(getContext(), 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 }
102 mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
Evan Laird937d9fa2018-02-08 10:12:16 -0800103 mDarkIconManager.setShouldLog(true);
Jason Monkaa573e92017-01-27 17:00:29 -0500104 Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
Jason Monk0a7d9f22017-03-15 11:03:06 -0400105 mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
Evan Laird2cf56822017-12-18 11:22:39 -0500106 mClockView = mStatusBar.findViewById(R.id.clock);
Jason Monk60033fc2017-03-24 11:26:35 -0400107 showSystemIconArea(false);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400108 showClock(false);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900109 initEmergencyCryptkeeperText();
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900110 initOperatorName();
Jason Monkaa573e92017-01-27 17:00:29 -0500111 }
112
113 @Override
Jason Monk0a7d9f22017-03-15 11:03:06 -0400114 public void onSaveInstanceState(Bundle outState) {
115 super.onSaveInstanceState(outState);
felkachange6c03a02018-05-24 15:38:04 +0800116 SparseArray<Parcelable> states = new SparseArray<>();
117 mStatusBar.saveHierarchyState(states);
118 outState.putSparseParcelableArray(EXTRA_PANEL_STATE, states);
Jason Monk0a7d9f22017-03-15 11:03:06 -0400119 }
120
121 @Override
Jason Monkaa573e92017-01-27 17:00:29 -0500122 public void onResume() {
123 super.onResume();
Jason Monkd7c98552018-12-04 11:14:50 -0500124 mCommandQueue.addCallback(this);
Jason Monkaf08c152018-12-04 11:12:39 -0500125 mStatusBarStateController.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500126 }
127
128 @Override
129 public void onPause() {
130 super.onPause();
Jason Monkd7c98552018-12-04 11:14:50 -0500131 mCommandQueue.removeCallback(this);
Jason Monkaf08c152018-12-04 11:12:39 -0500132 mStatusBarStateController.removeCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500133 }
134
135 @Override
136 public void onDestroyView() {
137 super.onDestroyView();
Jason Monkaa573e92017-01-27 17:00:29 -0500138 Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900139 if (mNetworkController.hasEmergencyCryptKeeperText()) {
140 mNetworkController.removeCallback(mSignalCallback);
141 }
Jason Monkaa573e92017-01-27 17:00:29 -0500142 }
143
144 public void initNotificationIconArea(NotificationIconAreaController
145 notificationIconAreaController) {
Jason Monk0a7d9f22017-03-15 11:03:06 -0400146 ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
Jason Monkaa573e92017-01-27 17:00:29 -0500147 mNotificationIconAreaInner =
148 notificationIconAreaController.getNotificationInnerAreaView();
149 if (mNotificationIconAreaInner.getParent() != null) {
150 ((ViewGroup) mNotificationIconAreaInner.getParent())
151 .removeView(mNotificationIconAreaInner);
152 }
153 notificationIconArea.addView(mNotificationIconAreaInner);
Beverly40770652019-02-15 15:49:49 -0500154
155 ViewGroup statusBarCenteredIconArea = mStatusBar.findViewById(R.id.centered_icon_area);
156 mCenteredIconArea = notificationIconAreaController.getCenteredNotificationAreaView();
157 if (mCenteredIconArea.getParent() != null) {
158 ((ViewGroup) mCenteredIconArea.getParent())
159 .removeView(mCenteredIconArea);
160 }
161 statusBarCenteredIconArea.addView(mCenteredIconArea);
162
Jason Monk60033fc2017-03-24 11:26:35 -0400163 // Default to showing until we know otherwise.
164 showNotificationIconArea(false);
Jason Monkaa573e92017-01-27 17:00:29 -0500165 }
166
167 @Override
Charles Chenf3d295c2018-11-30 18:15:21 +0800168 public void disable(int displayId, int state1, int state2, boolean animate) {
169 if (displayId != getContext().getDisplayId()) {
170 return;
171 }
Jason Monkaa573e92017-01-27 17:00:29 -0500172 state1 = adjustDisableFlags(state1);
173 final int old1 = mDisabled1;
174 final int diff1 = state1 ^ old1;
175 mDisabled1 = state1;
Jason Monkd3ee70c2017-08-30 17:05:24 -0400176 if ((diff1 & DISABLE_SYSTEM_INFO) != 0) {
177 if ((state1 & DISABLE_SYSTEM_INFO) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500178 hideSystemIconArea(animate);
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900179 hideOperatorName(animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500180 } else {
181 showSystemIconArea(animate);
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900182 showOperatorName(animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500183 }
184 }
Jason Monkd3ee70c2017-08-30 17:05:24 -0400185 if ((diff1 & DISABLE_NOTIFICATION_ICONS) != 0) {
186 if ((state1 & DISABLE_NOTIFICATION_ICONS) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500187 hideNotificationIconArea(animate);
188 } else {
189 showNotificationIconArea(animate);
190 }
191 }
Evan Lairdc1f231f2018-05-16 19:43:19 -0400192 // The clock may have already been hidden, but we might want to shift its
193 // visibility to GONE from INVISIBLE or vice versa
194 if ((diff1 & DISABLE_CLOCK) != 0 || mClockView.getVisibility() != clockHiddenMode()) {
Evan Laird4b68e2f72018-03-29 18:21:48 -0400195 if ((state1 & DISABLE_CLOCK) != 0) {
196 hideClock(animate);
197 } else {
198 showClock(animate);
199 }
200 }
Jason Monkaa573e92017-01-27 17:00:29 -0500201 }
202
203 protected int adjustDisableFlags(int state) {
Lucas Dupin28faa492019-02-14 19:06:05 -0800204 if (!mKeyguardMonitor.isLaunchTransitionFadingAway()
Jason Monkaa573e92017-01-27 17:00:29 -0500205 && !mKeyguardMonitor.isKeyguardFadingAway()
206 && shouldHideNotificationIcons()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400207 state |= DISABLE_NOTIFICATION_ICONS;
208 state |= DISABLE_SYSTEM_INFO;
Evan Laird4b68e2f72018-03-29 18:21:48 -0400209 state |= DISABLE_CLOCK;
Jason Monkaa573e92017-01-27 17:00:29 -0500210 }
felkachangca4eee82018-06-29 15:34:28 +0800211
212 // In landscape, the heads up show but shouldHideNotificationIcons() return false
213 // because the visual icon is in notification icon area rather than heads up's space.
214 // whether the notification icon show or not, clock should hide when heads up show.
215 if (mStatusBarComponent.isHeadsUpShouldBeVisible()) {
216 state |= DISABLE_CLOCK;
217 }
218
Jason Monkaa573e92017-01-27 17:00:29 -0500219 if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
220 if (mNetworkController.hasEmergencyCryptKeeperText()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400221 state |= DISABLE_NOTIFICATION_ICONS;
Jason Monkaa573e92017-01-27 17:00:29 -0500222 }
223 if (!mNetworkController.isRadioOn()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400224 state |= DISABLE_SYSTEM_INFO;
Jason Monkaa573e92017-01-27 17:00:29 -0500225 }
226 }
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700227
Lucas Dupin7fc9dc12019-01-03 09:19:43 -0800228 // The shelf will be hidden when dozing with a custom clock, we must show notification
229 // icons in this occasion.
230 if (mStatusBarStateController.isDozing()
231 && mStatusBarComponent.getPanel().hasCustomClock()) {
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700232 state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700233 }
234
Jason Monkaa573e92017-01-27 17:00:29 -0500235 return state;
236 }
237
238 private boolean shouldHideNotificationIcons() {
Selim Cinek3a49ba22017-08-10 11:17:39 -0700239 if (!mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded()) {
240 return true;
241 }
242 if (mStatusBarComponent.hideStatusBarIconsForBouncer()) {
243 return true;
244 }
245 return false;
Jason Monkaa573e92017-01-27 17:00:29 -0500246 }
247
248 public void hideSystemIconArea(boolean animate) {
249 animateHide(mSystemIconArea, animate);
250 }
251
252 public void showSystemIconArea(boolean animate) {
253 animateShow(mSystemIconArea, animate);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400254 }
255
256 public void hideClock(boolean animate) {
Evan Lairdc1f231f2018-05-16 19:43:19 -0400257 animateHiddenState(mClockView, clockHiddenMode(), animate);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400258 }
259
260 public void showClock(boolean animate) {
Evan Laird2cf56822017-12-18 11:22:39 -0500261 animateShow(mClockView, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500262 }
263
Evan Lairdc1f231f2018-05-16 19:43:19 -0400264 /**
265 * If panel is expanded/expanding it usually means QS shade is opening, so
266 * don't set the clock GONE otherwise it'll mess up the animation.
267 */
268 private int clockHiddenMode() {
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700269 if (!mStatusBar.isClosed() && !mKeyguardMonitor.isShowing()
270 && !mStatusBarStateController.isDozing()) {
Evan Lairdc1f231f2018-05-16 19:43:19 -0400271 return View.INVISIBLE;
272 }
273 return View.GONE;
274 }
275
Jason Monkaa573e92017-01-27 17:00:29 -0500276 public void hideNotificationIconArea(boolean animate) {
277 animateHide(mNotificationIconAreaInner, animate);
Beverly40770652019-02-15 15:49:49 -0500278 animateHide(mCenteredIconArea, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500279 }
280
281 public void showNotificationIconArea(boolean animate) {
282 animateShow(mNotificationIconAreaInner, animate);
Beverly40770652019-02-15 15:49:49 -0500283 animateShow(mCenteredIconArea, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500284 }
285
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900286 public void hideOperatorName(boolean animate) {
287 if (mOperatorNameFrame != null) {
288 animateHide(mOperatorNameFrame, animate);
289 }
290 }
291
292 public void showOperatorName(boolean animate) {
293 if (mOperatorNameFrame != null) {
294 animateShow(mOperatorNameFrame, animate);
295 }
296 }
297
Jason Monkaa573e92017-01-27 17:00:29 -0500298 /**
Evan Laird74435e62018-05-04 11:58:30 -0400299 * Animate a view to INVISIBLE or GONE
Jason Monkaa573e92017-01-27 17:00:29 -0500300 */
Evan Laird74435e62018-05-04 11:58:30 -0400301 private void animateHiddenState(final View v, int state, boolean animate) {
Jason Monkaa573e92017-01-27 17:00:29 -0500302 v.animate().cancel();
303 if (!animate) {
304 v.setAlpha(0f);
Evan Laird74435e62018-05-04 11:58:30 -0400305 v.setVisibility(state);
Jason Monkaa573e92017-01-27 17:00:29 -0500306 return;
307 }
Evan Laird74435e62018-05-04 11:58:30 -0400308
Jason Monkaa573e92017-01-27 17:00:29 -0500309 v.animate()
310 .alpha(0f)
311 .setDuration(160)
312 .setStartDelay(0)
313 .setInterpolator(Interpolators.ALPHA_OUT)
Evan Laird74435e62018-05-04 11:58:30 -0400314 .withEndAction(() -> v.setVisibility(state));
315 }
316
317 /**
318 * Hides a view.
319 */
320 private void animateHide(final View v, boolean animate) {
321 animateHiddenState(v, View.INVISIBLE, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500322 }
323
324 /**
325 * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
326 */
327 private void animateShow(View v, boolean animate) {
328 v.animate().cancel();
329 v.setVisibility(View.VISIBLE);
330 if (!animate) {
331 v.setAlpha(1f);
332 return;
333 }
334 v.animate()
335 .alpha(1f)
Selim Cinek2627d722018-01-19 12:16:49 -0800336 .setDuration(FADE_IN_DURATION)
Jason Monkaa573e92017-01-27 17:00:29 -0500337 .setInterpolator(Interpolators.ALPHA_IN)
Selim Cinek2627d722018-01-19 12:16:49 -0800338 .setStartDelay(FADE_IN_DELAY)
Jason Monkaa573e92017-01-27 17:00:29 -0500339
340 // We need to clean up any pending end action from animateHide if we call
341 // both hide and show in the same frame before the animation actually gets started.
342 // cancel() doesn't really remove the end action.
343 .withEndAction(null);
344
345 // Synchronize the motion with the Keyguard fading if necessary.
346 if (mKeyguardMonitor.isKeyguardFadingAway()) {
347 v.animate()
348 .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration())
349 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
350 .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
351 .start();
352 }
353 }
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900354
355 private void initEmergencyCryptkeeperText() {
356 View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
357 if (mNetworkController.hasEmergencyCryptKeeperText()) {
358 if (emergencyViewStub != null) {
359 ((ViewStub) emergencyViewStub).inflate();
360 }
361 mNetworkController.addCallback(mSignalCallback);
362 } else if (emergencyViewStub != null) {
363 ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
364 parent.removeView(emergencyViewStub);
365 }
366 }
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900367
368 private void initOperatorName() {
369 if (getResources().getBoolean(R.bool.config_showOperatorNameInStatusBar)) {
370 ViewStub stub = mStatusBar.findViewById(R.id.operator_name);
371 mOperatorNameFrame = stub.inflate();
372 }
373 }
Lucas Dupin2e43cfc2018-11-12 14:07:18 -0800374
375 @Override
376 public void onStateChanged(int newState) {
377
378 }
379
380 @Override
381 public void onDozingChanged(boolean isDozing) {
Charles Chenf3d295c2018-11-30 18:15:21 +0800382 disable(getContext().getDisplayId(), mDisabled1, mDisabled1, false /* animate */);
Lucas Dupin2e43cfc2018-11-12 14:07:18 -0800383 }
Jason Monkaa573e92017-01-27 17:00:29 -0500384}