blob: f7b7eeb2ad88969dc6cf5bc462b00281d946bcc5 [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;
25import android.view.LayoutInflater;
26import android.view.View;
27import android.view.ViewGroup;
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090028import android.view.ViewStub;
Jason Monkaa573e92017-01-27 17:00:29 -050029import android.widget.LinearLayout;
30
31import com.android.systemui.Dependency;
32import com.android.systemui.Interpolators;
33import com.android.systemui.R;
34import com.android.systemui.SysUiServiceProvider;
35import com.android.systemui.statusbar.CommandQueue;
Jason Monkaa573e92017-01-27 17:00:29 -050036import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
37import com.android.systemui.statusbar.policy.DarkIconDispatcher;
38import com.android.systemui.statusbar.policy.EncryptionHelper;
39import com.android.systemui.statusbar.policy.KeyguardMonitor;
40import com.android.systemui.statusbar.policy.NetworkController;
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090041import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
Jason Monkaa573e92017-01-27 17:00:29 -050042
43/**
44 * Contains the collapsed status bar and handles hiding/showing based on disable flags
45 * and keyguard state. Also manages lifecycle to make sure the views it contains are being
46 * updated by the StatusBarIconController and DarkIconManager while it is attached.
47 */
48public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {
49
50 public static final String TAG = "CollapsedStatusBarFragment";
Jason Monk0a7d9f22017-03-15 11:03:06 -040051 private static final String EXTRA_PANEL_STATE = "panel_state";
Evan Laird937d9fa2018-02-08 10:12:16 -080052 public static final String STATUS_BAR_ICON_MANAGER_TAG = "status_bar_icon_manager";
Selim Cinek2627d722018-01-19 12:16:49 -080053 public static final int FADE_IN_DURATION = 320;
54 public static final int FADE_IN_DELAY = 50;
Jason Monkaa573e92017-01-27 17:00:29 -050055 private PhoneStatusBarView mStatusBar;
56 private KeyguardMonitor mKeyguardMonitor;
57 private NetworkController mNetworkController;
58 private LinearLayout mSystemIconArea;
Evan Laird2cf56822017-12-18 11:22:39 -050059 private View mClockView;
Jason Monkaa573e92017-01-27 17:00:29 -050060 private View mNotificationIconAreaInner;
61 private int mDisabled1;
62 private StatusBar mStatusBarComponent;
63 private DarkIconManager mDarkIconManager;
Kensuke Matsui21d1bf12017-03-14 13:27:20 +090064 private View mOperatorNameFrame;
Jason Monkaa573e92017-01-27 17:00:29 -050065
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090066 private SignalCallback mSignalCallback = new SignalCallback() {
67 @Override
68 public void setIsAirplaneMode(NetworkController.IconState icon) {
69 mStatusBarComponent.recomputeDisableFlags(true /* animate */);
70 }
71 };
72
Jason Monkaa573e92017-01-27 17:00:29 -050073 @Override
74 public void onCreate(@Nullable Bundle savedInstanceState) {
75 super.onCreate(savedInstanceState);
76 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
77 mNetworkController = Dependency.get(NetworkController.class);
78 mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
79 }
80
81 @Override
82 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
83 Bundle savedInstanceState) {
84 return inflater.inflate(R.layout.status_bar, container, false);
85 }
86
87 @Override
88 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
89 super.onViewCreated(view, savedInstanceState);
90 mStatusBar = (PhoneStatusBarView) view;
Jason Monk0a7d9f22017-03-15 11:03:06 -040091 if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
92 mStatusBar.go(savedInstanceState.getInt(EXTRA_PANEL_STATE));
93 }
94 mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
Evan Laird937d9fa2018-02-08 10:12:16 -080095 mDarkIconManager.setShouldLog(true);
Jason Monkaa573e92017-01-27 17:00:29 -050096 Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
Jason Monk0a7d9f22017-03-15 11:03:06 -040097 mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
Evan Laird2cf56822017-12-18 11:22:39 -050098 mClockView = mStatusBar.findViewById(R.id.clock);
Jason Monk60033fc2017-03-24 11:26:35 -040099 showSystemIconArea(false);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400100 showClock(false);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900101 initEmergencyCryptkeeperText();
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900102 initOperatorName();
Jason Monkaa573e92017-01-27 17:00:29 -0500103 }
104
105 @Override
Jason Monk0a7d9f22017-03-15 11:03:06 -0400106 public void onSaveInstanceState(Bundle outState) {
107 super.onSaveInstanceState(outState);
108 outState.putInt(EXTRA_PANEL_STATE, mStatusBar.getState());
109 }
110
111 @Override
Jason Monkaa573e92017-01-27 17:00:29 -0500112 public void onResume() {
113 super.onResume();
114 SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
115 }
116
117 @Override
118 public void onPause() {
119 super.onPause();
120 SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).removeCallbacks(this);
121 }
122
123 @Override
124 public void onDestroyView() {
125 super.onDestroyView();
Jason Monkaa573e92017-01-27 17:00:29 -0500126 Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900127 if (mNetworkController.hasEmergencyCryptKeeperText()) {
128 mNetworkController.removeCallback(mSignalCallback);
129 }
Jason Monkaa573e92017-01-27 17:00:29 -0500130 }
131
132 public void initNotificationIconArea(NotificationIconAreaController
133 notificationIconAreaController) {
Jason Monk0a7d9f22017-03-15 11:03:06 -0400134 ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
Jason Monkaa573e92017-01-27 17:00:29 -0500135 mNotificationIconAreaInner =
136 notificationIconAreaController.getNotificationInnerAreaView();
137 if (mNotificationIconAreaInner.getParent() != null) {
138 ((ViewGroup) mNotificationIconAreaInner.getParent())
139 .removeView(mNotificationIconAreaInner);
140 }
141 notificationIconArea.addView(mNotificationIconAreaInner);
Jason Monk60033fc2017-03-24 11:26:35 -0400142 // Default to showing until we know otherwise.
143 showNotificationIconArea(false);
Jason Monkaa573e92017-01-27 17:00:29 -0500144 }
145
146 @Override
147 public void disable(int state1, int state2, boolean animate) {
148 state1 = adjustDisableFlags(state1);
149 final int old1 = mDisabled1;
150 final int diff1 = state1 ^ old1;
151 mDisabled1 = state1;
Jason Monkd3ee70c2017-08-30 17:05:24 -0400152 if ((diff1 & DISABLE_SYSTEM_INFO) != 0) {
153 if ((state1 & DISABLE_SYSTEM_INFO) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500154 hideSystemIconArea(animate);
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900155 hideOperatorName(animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500156 } else {
157 showSystemIconArea(animate);
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900158 showOperatorName(animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500159 }
160 }
Jason Monkd3ee70c2017-08-30 17:05:24 -0400161 if ((diff1 & DISABLE_NOTIFICATION_ICONS) != 0) {
162 if ((state1 & DISABLE_NOTIFICATION_ICONS) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500163 hideNotificationIconArea(animate);
164 } else {
165 showNotificationIconArea(animate);
166 }
167 }
Evan Lairdc1f231f2018-05-16 19:43:19 -0400168 // The clock may have already been hidden, but we might want to shift its
169 // visibility to GONE from INVISIBLE or vice versa
170 if ((diff1 & DISABLE_CLOCK) != 0 || mClockView.getVisibility() != clockHiddenMode()) {
Evan Laird4b68e2f72018-03-29 18:21:48 -0400171 if ((state1 & DISABLE_CLOCK) != 0) {
172 hideClock(animate);
173 } else {
174 showClock(animate);
175 }
176 }
Jason Monkaa573e92017-01-27 17:00:29 -0500177 }
178
179 protected int adjustDisableFlags(int state) {
180 if (!mStatusBarComponent.isLaunchTransitionFadingAway()
181 && !mKeyguardMonitor.isKeyguardFadingAway()
182 && shouldHideNotificationIcons()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400183 state |= DISABLE_NOTIFICATION_ICONS;
184 state |= DISABLE_SYSTEM_INFO;
Evan Laird4b68e2f72018-03-29 18:21:48 -0400185 state |= DISABLE_CLOCK;
Jason Monkaa573e92017-01-27 17:00:29 -0500186 }
187 if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
188 if (mNetworkController.hasEmergencyCryptKeeperText()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400189 state |= DISABLE_NOTIFICATION_ICONS;
Jason Monkaa573e92017-01-27 17:00:29 -0500190 }
191 if (!mNetworkController.isRadioOn()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400192 state |= DISABLE_SYSTEM_INFO;
Jason Monkaa573e92017-01-27 17:00:29 -0500193 }
194 }
195 return state;
196 }
197
198 private boolean shouldHideNotificationIcons() {
Selim Cinek3a49ba22017-08-10 11:17:39 -0700199 if (!mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded()) {
200 return true;
201 }
202 if (mStatusBarComponent.hideStatusBarIconsForBouncer()) {
203 return true;
204 }
205 return false;
Jason Monkaa573e92017-01-27 17:00:29 -0500206 }
207
208 public void hideSystemIconArea(boolean animate) {
209 animateHide(mSystemIconArea, animate);
210 }
211
212 public void showSystemIconArea(boolean animate) {
213 animateShow(mSystemIconArea, animate);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400214 }
215
216 public void hideClock(boolean animate) {
Evan Lairdc1f231f2018-05-16 19:43:19 -0400217 animateHiddenState(mClockView, clockHiddenMode(), animate);
Evan Laird4b68e2f72018-03-29 18:21:48 -0400218 }
219
220 public void showClock(boolean animate) {
Evan Laird2cf56822017-12-18 11:22:39 -0500221 animateShow(mClockView, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500222 }
223
Evan Lairdc1f231f2018-05-16 19:43:19 -0400224 /**
225 * If panel is expanded/expanding it usually means QS shade is opening, so
226 * don't set the clock GONE otherwise it'll mess up the animation.
227 */
228 private int clockHiddenMode() {
229 if (!mStatusBar.isClosed() && !mKeyguardMonitor.isShowing()) {
230 return View.INVISIBLE;
231 }
232 return View.GONE;
233 }
234
Jason Monkaa573e92017-01-27 17:00:29 -0500235 public void hideNotificationIconArea(boolean animate) {
236 animateHide(mNotificationIconAreaInner, animate);
237 }
238
239 public void showNotificationIconArea(boolean animate) {
240 animateShow(mNotificationIconAreaInner, animate);
241 }
242
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900243 public void hideOperatorName(boolean animate) {
244 if (mOperatorNameFrame != null) {
245 animateHide(mOperatorNameFrame, animate);
246 }
247 }
248
249 public void showOperatorName(boolean animate) {
250 if (mOperatorNameFrame != null) {
251 animateShow(mOperatorNameFrame, animate);
252 }
253 }
254
Jason Monkaa573e92017-01-27 17:00:29 -0500255 /**
Evan Laird74435e62018-05-04 11:58:30 -0400256 * Animate a view to INVISIBLE or GONE
Jason Monkaa573e92017-01-27 17:00:29 -0500257 */
Evan Laird74435e62018-05-04 11:58:30 -0400258 private void animateHiddenState(final View v, int state, boolean animate) {
Jason Monkaa573e92017-01-27 17:00:29 -0500259 v.animate().cancel();
260 if (!animate) {
261 v.setAlpha(0f);
Evan Laird74435e62018-05-04 11:58:30 -0400262 v.setVisibility(state);
Jason Monkaa573e92017-01-27 17:00:29 -0500263 return;
264 }
Evan Laird74435e62018-05-04 11:58:30 -0400265
Jason Monkaa573e92017-01-27 17:00:29 -0500266 v.animate()
267 .alpha(0f)
268 .setDuration(160)
269 .setStartDelay(0)
270 .setInterpolator(Interpolators.ALPHA_OUT)
Evan Laird74435e62018-05-04 11:58:30 -0400271 .withEndAction(() -> v.setVisibility(state));
272 }
273
274 /**
275 * Hides a view.
276 */
277 private void animateHide(final View v, boolean animate) {
278 animateHiddenState(v, View.INVISIBLE, animate);
Jason Monkaa573e92017-01-27 17:00:29 -0500279 }
280
281 /**
282 * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
283 */
284 private void animateShow(View v, boolean animate) {
285 v.animate().cancel();
286 v.setVisibility(View.VISIBLE);
287 if (!animate) {
288 v.setAlpha(1f);
289 return;
290 }
291 v.animate()
292 .alpha(1f)
Selim Cinek2627d722018-01-19 12:16:49 -0800293 .setDuration(FADE_IN_DURATION)
Jason Monkaa573e92017-01-27 17:00:29 -0500294 .setInterpolator(Interpolators.ALPHA_IN)
Selim Cinek2627d722018-01-19 12:16:49 -0800295 .setStartDelay(FADE_IN_DELAY)
Jason Monkaa573e92017-01-27 17:00:29 -0500296
297 // We need to clean up any pending end action from animateHide if we call
298 // both hide and show in the same frame before the animation actually gets started.
299 // cancel() doesn't really remove the end action.
300 .withEndAction(null);
301
302 // Synchronize the motion with the Keyguard fading if necessary.
303 if (mKeyguardMonitor.isKeyguardFadingAway()) {
304 v.animate()
305 .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration())
306 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
307 .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
308 .start();
309 }
310 }
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900311
312 private void initEmergencyCryptkeeperText() {
313 View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
314 if (mNetworkController.hasEmergencyCryptKeeperText()) {
315 if (emergencyViewStub != null) {
316 ((ViewStub) emergencyViewStub).inflate();
317 }
318 mNetworkController.addCallback(mSignalCallback);
319 } else if (emergencyViewStub != null) {
320 ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
321 parent.removeView(emergencyViewStub);
322 }
323 }
Kensuke Matsui21d1bf12017-03-14 13:27:20 +0900324
325 private void initOperatorName() {
326 if (getResources().getBoolean(R.bool.config_showOperatorNameInStatusBar)) {
327 ViewStub stub = mStatusBar.findViewById(R.id.operator_name);
328 mOperatorNameFrame = stub.inflate();
329 }
330 }
Jason Monkaa573e92017-01-27 17:00:29 -0500331}