blob: 2c3f452e827462954b9df924b20f9700c0aa38a2 [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
Jason Monkd3ee70c2017-08-30 17:05:24 -040017import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS;
18import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
19
Jason Monkaa573e92017-01-27 17:00:29 -050020import static com.android.systemui.statusbar.phone.StatusBar.reinflateSignalCluster;
21
22import android.annotation.Nullable;
23import android.app.Fragment;
24import android.app.StatusBarManager;
25import android.os.Bundle;
26import 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;
36import com.android.systemui.statusbar.CommandQueue;
37import com.android.systemui.statusbar.SignalClusterView;
38import 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";
Jason Monkaa573e92017-01-27 17:00:29 -050054 private PhoneStatusBarView mStatusBar;
55 private KeyguardMonitor mKeyguardMonitor;
56 private NetworkController mNetworkController;
57 private LinearLayout mSystemIconArea;
58 private View mNotificationIconAreaInner;
59 private int mDisabled1;
60 private StatusBar mStatusBarComponent;
61 private DarkIconManager mDarkIconManager;
62 private SignalClusterView mSignalClusterView;
63
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090064 private SignalCallback mSignalCallback = new SignalCallback() {
65 @Override
66 public void setIsAirplaneMode(NetworkController.IconState icon) {
67 mStatusBarComponent.recomputeDisableFlags(true /* animate */);
68 }
69 };
70
Jason Monkaa573e92017-01-27 17:00:29 -050071 @Override
72 public void onCreate(@Nullable Bundle savedInstanceState) {
73 super.onCreate(savedInstanceState);
74 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
75 mNetworkController = Dependency.get(NetworkController.class);
76 mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
77 }
78
79 @Override
80 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
81 Bundle savedInstanceState) {
82 return inflater.inflate(R.layout.status_bar, container, false);
83 }
84
85 @Override
86 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
87 super.onViewCreated(view, savedInstanceState);
88 mStatusBar = (PhoneStatusBarView) view;
Jason Monk0a7d9f22017-03-15 11:03:06 -040089 if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
90 mStatusBar.go(savedInstanceState.getInt(EXTRA_PANEL_STATE));
91 }
92 mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
Jason Monkaa573e92017-01-27 17:00:29 -050093 Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
Jason Monk0a7d9f22017-03-15 11:03:06 -040094 mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
Jason Monkd60a72f2017-04-21 10:10:35 -040095 mSignalClusterView = mStatusBar.findViewById(R.id.signal_cluster);
Jason Monkaa573e92017-01-27 17:00:29 -050096 Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSignalClusterView);
Jason Monk60033fc2017-03-24 11:26:35 -040097 // Default to showing until we know otherwise.
98 showSystemIconArea(false);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +090099 initEmergencyCryptkeeperText();
Jason Monkaa573e92017-01-27 17:00:29 -0500100 }
101
102 @Override
Jason Monk0a7d9f22017-03-15 11:03:06 -0400103 public void onSaveInstanceState(Bundle outState) {
104 super.onSaveInstanceState(outState);
105 outState.putInt(EXTRA_PANEL_STATE, mStatusBar.getState());
106 }
107
108 @Override
Jason Monkaa573e92017-01-27 17:00:29 -0500109 public void onResume() {
110 super.onResume();
111 SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
112 }
113
114 @Override
115 public void onPause() {
116 super.onPause();
117 SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).removeCallbacks(this);
118 }
119
120 @Override
121 public void onDestroyView() {
122 super.onDestroyView();
123 Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mSignalClusterView);
124 Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900125 if (mNetworkController.hasEmergencyCryptKeeperText()) {
126 mNetworkController.removeCallback(mSignalCallback);
127 }
Jason Monkaa573e92017-01-27 17:00:29 -0500128 }
129
130 public void initNotificationIconArea(NotificationIconAreaController
131 notificationIconAreaController) {
Jason Monk0a7d9f22017-03-15 11:03:06 -0400132 ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
Jason Monkaa573e92017-01-27 17:00:29 -0500133 mNotificationIconAreaInner =
134 notificationIconAreaController.getNotificationInnerAreaView();
135 if (mNotificationIconAreaInner.getParent() != null) {
136 ((ViewGroup) mNotificationIconAreaInner.getParent())
137 .removeView(mNotificationIconAreaInner);
138 }
139 notificationIconArea.addView(mNotificationIconAreaInner);
Jason Monk60033fc2017-03-24 11:26:35 -0400140 // Default to showing until we know otherwise.
141 showNotificationIconArea(false);
Jason Monkaa573e92017-01-27 17:00:29 -0500142 }
143
144 @Override
145 public void disable(int state1, int state2, boolean animate) {
146 state1 = adjustDisableFlags(state1);
147 final int old1 = mDisabled1;
148 final int diff1 = state1 ^ old1;
149 mDisabled1 = state1;
Jason Monkd3ee70c2017-08-30 17:05:24 -0400150 if ((diff1 & DISABLE_SYSTEM_INFO) != 0) {
151 if ((state1 & DISABLE_SYSTEM_INFO) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500152 hideSystemIconArea(animate);
153 } else {
154 showSystemIconArea(animate);
155 }
156 }
Jason Monkd3ee70c2017-08-30 17:05:24 -0400157 if ((diff1 & DISABLE_NOTIFICATION_ICONS) != 0) {
158 if ((state1 & DISABLE_NOTIFICATION_ICONS) != 0) {
Jason Monkaa573e92017-01-27 17:00:29 -0500159 hideNotificationIconArea(animate);
160 } else {
161 showNotificationIconArea(animate);
162 }
163 }
164 }
165
166 protected int adjustDisableFlags(int state) {
167 if (!mStatusBarComponent.isLaunchTransitionFadingAway()
168 && !mKeyguardMonitor.isKeyguardFadingAway()
169 && shouldHideNotificationIcons()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400170 state |= DISABLE_NOTIFICATION_ICONS;
171 state |= DISABLE_SYSTEM_INFO;
Jason Monkaa573e92017-01-27 17:00:29 -0500172 }
173 if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
174 if (mNetworkController.hasEmergencyCryptKeeperText()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400175 state |= DISABLE_NOTIFICATION_ICONS;
Jason Monkaa573e92017-01-27 17:00:29 -0500176 }
177 if (!mNetworkController.isRadioOn()) {
Jason Monkd3ee70c2017-08-30 17:05:24 -0400178 state |= DISABLE_SYSTEM_INFO;
Jason Monkaa573e92017-01-27 17:00:29 -0500179 }
180 }
181 return state;
182 }
183
184 private boolean shouldHideNotificationIcons() {
Selim Cinek3a49ba22017-08-10 11:17:39 -0700185 if (!mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded()) {
186 return true;
187 }
188 if (mStatusBarComponent.hideStatusBarIconsForBouncer()) {
189 return true;
190 }
191 return false;
Jason Monkaa573e92017-01-27 17:00:29 -0500192 }
193
194 public void hideSystemIconArea(boolean animate) {
195 animateHide(mSystemIconArea, animate);
196 }
197
198 public void showSystemIconArea(boolean animate) {
199 animateShow(mSystemIconArea, animate);
200 }
201
202 public void hideNotificationIconArea(boolean animate) {
203 animateHide(mNotificationIconAreaInner, animate);
204 }
205
206 public void showNotificationIconArea(boolean animate) {
207 animateShow(mNotificationIconAreaInner, animate);
208 }
209
210 /**
211 * Hides a view.
212 */
213 private void animateHide(final View v, boolean animate) {
214 v.animate().cancel();
215 if (!animate) {
216 v.setAlpha(0f);
217 v.setVisibility(View.INVISIBLE);
218 return;
219 }
220 v.animate()
221 .alpha(0f)
222 .setDuration(160)
223 .setStartDelay(0)
224 .setInterpolator(Interpolators.ALPHA_OUT)
225 .withEndAction(() -> v.setVisibility(View.INVISIBLE));
226 }
227
228 /**
229 * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
230 */
231 private void animateShow(View v, boolean animate) {
232 v.animate().cancel();
233 v.setVisibility(View.VISIBLE);
234 if (!animate) {
235 v.setAlpha(1f);
236 return;
237 }
238 v.animate()
239 .alpha(1f)
240 .setDuration(320)
241 .setInterpolator(Interpolators.ALPHA_IN)
242 .setStartDelay(50)
243
244 // We need to clean up any pending end action from animateHide if we call
245 // both hide and show in the same frame before the animation actually gets started.
246 // cancel() doesn't really remove the end action.
247 .withEndAction(null);
248
249 // Synchronize the motion with the Keyguard fading if necessary.
250 if (mKeyguardMonitor.isKeyguardFadingAway()) {
251 v.animate()
252 .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration())
253 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
254 .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
255 .start();
256 }
257 }
Yoshinori Hirano2696aa32017-04-10 20:33:49 +0900258
259 private void initEmergencyCryptkeeperText() {
260 View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
261 if (mNetworkController.hasEmergencyCryptKeeperText()) {
262 if (emergencyViewStub != null) {
263 ((ViewStub) emergencyViewStub).inflate();
264 }
265 mNetworkController.addCallback(mSignalCallback);
266 } else if (emergencyViewStub != null) {
267 ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
268 parent.removeView(emergencyViewStub);
269 }
270 }
Jason Monkaa573e92017-01-27 17:00:29 -0500271}