blob: a781be69c93e64c15f74e6109696a4432b4cd4e6 [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;
23import android.app.StatusBarManager;
24import android.os.Bundle;
felkachang08579552018-05-24 15:38:04 +080025import android.os.Parcelable;
26import android.util.SparseArray;
Jason Monkaa573e92017-01-27 17:00:29 -050027import android.view.LayoutInflater;
28import android.view.View;
29import android.view.ViewGroup;
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090030import android.view.ViewStub;
Jason Monkaa573e92017-01-27 17:00:29 -050031import android.widget.LinearLayout;
32
33import com.android.systemui.Dependency;
34import com.android.systemui.Interpolators;
35import com.android.systemui.R;
36import com.android.systemui.SysUiServiceProvider;
37import com.android.systemui.statusbar.CommandQueue;
Jason Monkaa573e92017-01-27 17:00:29 -050038import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
39import com.android.systemui.statusbar.policy.DarkIconDispatcher;
40import com.android.systemui.statusbar.policy.EncryptionHelper;
41import com.android.systemui.statusbar.policy.KeyguardMonitor;
42import com.android.systemui.statusbar.policy.NetworkController;
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090043import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
Jason Monkaa573e92017-01-27 17:00:29 -050044
45/**
46 * Contains the collapsed status bar and handles hiding/showing based on disable flags
47 * and keyguard state. Also manages lifecycle to make sure the views it contains are being
48 * updated by the StatusBarIconController and DarkIconManager while it is attached.
49 */
50public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {
51
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;
58 private KeyguardMonitor mKeyguardMonitor;
59 private NetworkController mNetworkController;
60 private LinearLayout mSystemIconArea;
Evan Laird2cf56822017-12-18 11:22:39 -050061 private View mClockView;
Jason Monkaa573e92017-01-27 17:00:29 -050062 private View mNotificationIconAreaInner;
63 private int mDisabled1;
64 private StatusBar mStatusBarComponent;
65 private DarkIconManager mDarkIconManager;
Kensuke Matsui21d1bf12017-03-14 13:27:20 +090066 private View mOperatorNameFrame;
Jason Monkaa573e92017-01-27 17:00:29 -050067
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090068 private SignalCallback mSignalCallback = new SignalCallback() {
69 @Override
70 public void setIsAirplaneMode(NetworkController.IconState icon) {
71 mStatusBarComponent.recomputeDisableFlags(true /* animate */);
72 }
73 };
74
Jason Monkaa573e92017-01-27 17:00:29 -050075 @Override
76 public void onCreate(@Nullable Bundle savedInstanceState) {
77 super.onCreate(savedInstanceState);
78 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
79 mNetworkController = Dependency.get(NetworkController.class);
80 mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
81 }
82
83 @Override
84 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
85 Bundle savedInstanceState) {
86 return inflater.inflate(R.layout.status_bar, container, false);
87 }
88
89 @Override
90 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
91 super.onViewCreated(view, savedInstanceState);
92 mStatusBar = (PhoneStatusBarView) view;
Jason Monk0a7d9f22017-03-15 11:03:06 -040093 if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
felkachang08579552018-05-24 15:38:04 +080094 mStatusBar.restoreHierarchyState(
95 savedInstanceState.getSparseParcelableArray(EXTRA_PANEL_STATE));
Jason Monk0a7d9f22017-03-15 11:03:06 -040096 }
97 mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
Evan Laird937d9fa2018-02-08 10:12:16 -080098 mDarkIconManager.setShouldLog(true);
Jason Monkaa573e92017-01-27 17:00:29 -050099 Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
Jason Monk0a7d9f22017-03-15 11:03:06 -0400100 mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
Evan Laird2cf56822017-12-18 11:22:39 -0500101 mClockView = mStatusBar.findViewById(R.id.clock);
Jason Monk60033fc2017-03-24 11:26:35 -0400102 showSystemIconArea(false);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400103 showClock(false);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900104 initEmergencyCryptkeeperText();
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900105 initOperatorName();
Jason Monkaa573e92017-01-27 17:00:29 -0500106 }
107
108 @Override
Jason Monk0a7d9f22017-03-15 11:03:06 -0400109 public void onSaveInstanceState(Bundle outState) {
110 super.onSaveInstanceState(outState);
felkachang08579552018-05-24 15:38:04 +0800111 SparseArray<Parcelable> states = new SparseArray<>();
112 mStatusBar.saveHierarchyState(states);
113 outState.putSparseParcelableArray(EXTRA_PANEL_STATE, states);
Jason Monk0a7d9f22017-03-15 11:03:06 -0400114 }
115
116 @Override
Jason Monkaa573e92017-01-27 17:00:29 -0500117 public void onResume() {
118 super.onResume();
119 SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
120 }
121
122 @Override
123 public void onPause() {
124 super.onPause();
125 SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).removeCallbacks(this);
126 }
127
128 @Override
129 public void onDestroyView() {
130 super.onDestroyView();
Jason Monkaa573e92017-01-27 17:00:29 -0500131 Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900132 if (mNetworkController.hasEmergencyCryptKeeperText()) {
133 mNetworkController.removeCallback(mSignalCallback);
134 }
Jason Monkaa573e92017-01-27 17:00:29 -0500135 }
136
137 public void initNotificationIconArea(NotificationIconAreaController
138 notificationIconAreaController) {
Jason Monk0a7d9f22017-03-15 11:03:06 -0400139 ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
Jason Monkaa573e92017-01-27 17:00:29 -0500140 mNotificationIconAreaInner =
141 notificationIconAreaController.getNotificationInnerAreaView();
142 if (mNotificationIconAreaInner.getParent() != null) {
143 ((ViewGroup) mNotificationIconAreaInner.getParent())
144 .removeView(mNotificationIconAreaInner);
145 }
146 notificationIconArea.addView(mNotificationIconAreaInner);
Jason Monk60033fc2017-03-24 11:26:35 -0400147 // Default to showing until we know otherwise.
148 showNotificationIconArea(false);
Jason Monkaa573e92017-01-27 17:00:29 -0500149 }
150
151 @Override
152 public void disable(int state1, int state2, boolean animate) {
153 state1 = adjustDisableFlags(state1);
154 final int old1 = mDisabled1;
155 final int diff1 = state1 ^ old1;
156 mDisabled1 = state1;
Jason Monkd3ee70c2017-08-30 17:05:24 -0400157 if ((diff1 & DISABLE_SYSTEM_INFO) != 0) {
158 if ((state1 & DISABLE_SYSTEM_INFO) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500159 hideSystemIconArea(animate);
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900160 hideOperatorName(animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500161 } else {
162 showSystemIconArea(animate);
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900163 showOperatorName(animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500164 }
165 }
Jason Monkd3ee70c2017-08-30 17:05:24 -0400166 if ((diff1 & DISABLE_NOTIFICATION_ICONS) != 0) {
167 if ((state1 & DISABLE_NOTIFICATION_ICONS) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500168 hideNotificationIconArea(animate);
169 } else {
170 showNotificationIconArea(animate);
171 }
172 }
Evan Lairdc1f231f2018-05-16 19:43:19 -0400173 // The clock may have already been hidden, but we might want to shift its
174 // visibility to GONE from INVISIBLE or vice versa
175 if ((diff1 & DISABLE_CLOCK) != 0 || mClockView.getVisibility() != clockHiddenMode()) {
Evan Laird4b68e2f72018-03-29 18:21:48 -0400176 if ((state1 & DISABLE_CLOCK) != 0) {
177 hideClock(animate);
178 } else {
179 showClock(animate);
180 }
181 }
Jason Monkaa573e92017-01-27 17:00:29 -0500182 }
183
184 protected int adjustDisableFlags(int state) {
185 if (!mStatusBarComponent.isLaunchTransitionFadingAway()
186 && !mKeyguardMonitor.isKeyguardFadingAway()
187 && shouldHideNotificationIcons()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400188 state |= DISABLE_NOTIFICATION_ICONS;
189 state |= DISABLE_SYSTEM_INFO;
Evan Laird4b68e2f72018-03-29 18:21:48 -0400190 state |= DISABLE_CLOCK;
Jason Monkaa573e92017-01-27 17:00:29 -0500191 }
felkachange61f95b2018-06-29 15:34:28 +0800192
193 // In landscape, the heads up show but shouldHideNotificationIcons() return false
194 // because the visual icon is in notification icon area rather than heads up's space.
195 // whether the notification icon show or not, clock should hide when heads up show.
196 if (mStatusBarComponent.isHeadsUpShouldBeVisible()) {
197 state |= DISABLE_CLOCK;
198 }
199
Jason Monkaa573e92017-01-27 17:00:29 -0500200 if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
201 if (mNetworkController.hasEmergencyCryptKeeperText()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400202 state |= DISABLE_NOTIFICATION_ICONS;
Jason Monkaa573e92017-01-27 17:00:29 -0500203 }
204 if (!mNetworkController.isRadioOn()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400205 state |= DISABLE_SYSTEM_INFO;
Jason Monkaa573e92017-01-27 17:00:29 -0500206 }
207 }
208 return state;
209 }
210
211 private boolean shouldHideNotificationIcons() {
Selim Cinek3a49ba22017-08-10 11:17:39 -0700212 if (!mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded()) {
213 return true;
214 }
215 if (mStatusBarComponent.hideStatusBarIconsForBouncer()) {
216 return true;
217 }
218 return false;
Jason Monkaa573e92017-01-27 17:00:29 -0500219 }
220
221 public void hideSystemIconArea(boolean animate) {
222 animateHide(mSystemIconArea, animate);
223 }
224
225 public void showSystemIconArea(boolean animate) {
226 animateShow(mSystemIconArea, animate);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400227 }
228
229 public void hideClock(boolean animate) {
Evan Lairdc1f231f2018-05-16 19:43:19 -0400230 animateHiddenState(mClockView, clockHiddenMode(), animate);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400231 }
232
233 public void showClock(boolean animate) {
Evan Laird2cf56822017-12-18 11:22:39 -0500234 animateShow(mClockView, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500235 }
236
Evan Lairdc1f231f2018-05-16 19:43:19 -0400237 /**
238 * If panel is expanded/expanding it usually means QS shade is opening, so
239 * don't set the clock GONE otherwise it'll mess up the animation.
240 */
241 private int clockHiddenMode() {
242 if (!mStatusBar.isClosed() && !mKeyguardMonitor.isShowing()) {
243 return View.INVISIBLE;
244 }
245 return View.GONE;
246 }
247
Jason Monkaa573e92017-01-27 17:00:29 -0500248 public void hideNotificationIconArea(boolean animate) {
249 animateHide(mNotificationIconAreaInner, animate);
250 }
251
252 public void showNotificationIconArea(boolean animate) {
253 animateShow(mNotificationIconAreaInner, animate);
254 }
255
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900256 public void hideOperatorName(boolean animate) {
257 if (mOperatorNameFrame != null) {
258 animateHide(mOperatorNameFrame, animate);
259 }
260 }
261
262 public void showOperatorName(boolean animate) {
263 if (mOperatorNameFrame != null) {
264 animateShow(mOperatorNameFrame, animate);
265 }
266 }
267
Jason Monkaa573e92017-01-27 17:00:29 -0500268 /**
Evan Laird74435e62018-05-04 11:58:30 -0400269 * Animate a view to INVISIBLE or GONE
Jason Monkaa573e92017-01-27 17:00:29 -0500270 */
Evan Laird74435e62018-05-04 11:58:30 -0400271 private void animateHiddenState(final View v, int state, boolean animate) {
Jason Monkaa573e92017-01-27 17:00:29 -0500272 v.animate().cancel();
273 if (!animate) {
274 v.setAlpha(0f);
Evan Laird74435e62018-05-04 11:58:30 -0400275 v.setVisibility(state);
Jason Monkaa573e92017-01-27 17:00:29 -0500276 return;
277 }
Evan Laird74435e62018-05-04 11:58:30 -0400278
Jason Monkaa573e92017-01-27 17:00:29 -0500279 v.animate()
280 .alpha(0f)
281 .setDuration(160)
282 .setStartDelay(0)
283 .setInterpolator(Interpolators.ALPHA_OUT)
Evan Laird74435e62018-05-04 11:58:30 -0400284 .withEndAction(() -> v.setVisibility(state));
285 }
286
287 /**
288 * Hides a view.
289 */
290 private void animateHide(final View v, boolean animate) {
291 animateHiddenState(v, View.INVISIBLE, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500292 }
293
294 /**
295 * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
296 */
297 private void animateShow(View v, boolean animate) {
298 v.animate().cancel();
299 v.setVisibility(View.VISIBLE);
300 if (!animate) {
301 v.setAlpha(1f);
302 return;
303 }
304 v.animate()
305 .alpha(1f)
Selim Cinek2627d722018-01-19 12:16:49 -0800306 .setDuration(FADE_IN_DURATION)
Jason Monkaa573e92017-01-27 17:00:29 -0500307 .setInterpolator(Interpolators.ALPHA_IN)
Selim Cinek2627d722018-01-19 12:16:49 -0800308 .setStartDelay(FADE_IN_DELAY)
Jason Monkaa573e92017-01-27 17:00:29 -0500309
310 // We need to clean up any pending end action from animateHide if we call
311 // both hide and show in the same frame before the animation actually gets started.
312 // cancel() doesn't really remove the end action.
313 .withEndAction(null);
314
315 // Synchronize the motion with the Keyguard fading if necessary.
316 if (mKeyguardMonitor.isKeyguardFadingAway()) {
317 v.animate()
318 .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration())
319 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
320 .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
321 .start();
322 }
323 }
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900324
325 private void initEmergencyCryptkeeperText() {
326 View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
327 if (mNetworkController.hasEmergencyCryptKeeperText()) {
328 if (emergencyViewStub != null) {
329 ((ViewStub) emergencyViewStub).inflate();
330 }
331 mNetworkController.addCallback(mSignalCallback);
332 } else if (emergencyViewStub != null) {
333 ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
334 parent.removeView(emergencyViewStub);
335 }
336 }
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900337
338 private void initOperatorName() {
339 if (getResources().getBoolean(R.bool.config_showOperatorNameInStatusBar)) {
340 ViewStub stub = mStatusBar.findViewById(R.id.operator_name);
341 mOperatorNameFrame = stub.inflate();
342 }
343 }
Jason Monkaa573e92017-01-27 17:00:29 -0500344}