1 /*
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 
15 package com.android.systemui.statusbar.phone.fragment;
16 
17 import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
18 import static android.app.StatusBarManager.DISABLE_CLOCK;
19 import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS;
20 import static android.app.StatusBarManager.DISABLE_ONGOING_CALL_CHIP;
21 import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
22 
23 import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_IN;
24 import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_OUT;
25 import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.IDLE;
26 import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.SHOWING_PERSISTENT_DOT;
27 
28 import android.animation.ValueAnimator;
29 import android.annotation.NonNull;
30 import android.annotation.Nullable;
31 import android.app.Fragment;
32 import android.os.Bundle;
33 import android.os.Parcelable;
34 import android.util.SparseArray;
35 import android.view.LayoutInflater;
36 import android.view.View;
37 import android.view.ViewGroup;
38 import android.view.ViewStub;
39 import android.widget.LinearLayout;
40 
41 import com.android.systemui.R;
42 import com.android.systemui.animation.Interpolators;
43 import com.android.systemui.flags.FeatureFlags;
44 import com.android.systemui.plugins.statusbar.StatusBarStateController;
45 import com.android.systemui.statusbar.CommandQueue;
46 import com.android.systemui.statusbar.DisableFlagsLogger.DisableState;
47 import com.android.systemui.statusbar.OperatorNameView;
48 import com.android.systemui.statusbar.OperatorNameViewController;
49 import com.android.systemui.statusbar.StatusBarState;
50 import com.android.systemui.statusbar.connectivity.IconState;
51 import com.android.systemui.statusbar.connectivity.NetworkController;
52 import com.android.systemui.statusbar.connectivity.SignalCallback;
53 import com.android.systemui.statusbar.events.SystemStatusAnimationCallback;
54 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
55 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
56 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
57 import com.android.systemui.statusbar.phone.PhoneStatusBarView;
58 import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
59 import com.android.systemui.statusbar.phone.StatusBarIconController;
60 import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
61 import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
62 import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
63 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
64 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener;
65 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
66 import com.android.systemui.statusbar.policy.EncryptionHelper;
67 import com.android.systemui.statusbar.policy.KeyguardStateController;
68 
69 import org.jetbrains.annotations.NotNull;
70 
71 import java.util.ArrayList;
72 import java.util.List;
73 
74 import javax.inject.Inject;
75 
76 /**
77  * Contains the collapsed status bar and handles hiding/showing based on disable flags
78  * and keyguard state. Also manages lifecycle to make sure the views it contains are being
79  * updated by the StatusBarIconController and DarkIconManager while it is attached.
80  */
81 public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks,
82         StatusBarStateController.StateListener,
83         SystemStatusAnimationCallback {
84 
85     public static final String TAG = "CollapsedStatusBarFragment";
86     private static final String EXTRA_PANEL_STATE = "panel_state";
87     public static final String STATUS_BAR_ICON_MANAGER_TAG = "status_bar_icon_manager";
88     public static final int FADE_IN_DURATION = 320;
89     public static final int FADE_IN_DELAY = 50;
90     private StatusBarFragmentComponent mStatusBarFragmentComponent;
91     private PhoneStatusBarView mStatusBar;
92     private final StatusBarStateController mStatusBarStateController;
93     private final KeyguardStateController mKeyguardStateController;
94     private final NotificationPanelViewController mNotificationPanelViewController;
95     private final NetworkController mNetworkController;
96     private LinearLayout mSystemIconArea;
97     private View mClockView;
98     private View mOngoingCallChip;
99     private View mNotificationIconAreaInner;
100     private View mCenteredIconArea;
101     private int mDisabled1;
102     private int mDisabled2;
103     private DarkIconManager mDarkIconManager;
104     private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory;
105     private final CommandQueue mCommandQueue;
106     private final CollapsedStatusBarFragmentLogger mCollapsedStatusBarFragmentLogger;
107     private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
108     private final OngoingCallController mOngoingCallController;
109     private final SystemStatusAnimationScheduler mAnimationScheduler;
110     private final StatusBarLocationPublisher mLocationPublisher;
111     private final FeatureFlags mFeatureFlags;
112     private final NotificationIconAreaController mNotificationIconAreaController;
113     private final PanelExpansionStateManager mPanelExpansionStateManager;
114     private final StatusBarIconController mStatusBarIconController;
115     private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
116 
117     private List<String> mBlockedIcons = new ArrayList<>();
118 
119     private SignalCallback mSignalCallback = new SignalCallback() {
120         @Override
121         public void setIsAirplaneMode(@NonNull IconState icon) {
122             mCommandQueue.recomputeDisableFlags(getContext().getDisplayId(), true /* animate */);
123         }
124     };
125 
126     private final OngoingCallListener mOngoingCallListener = new OngoingCallListener() {
127         @Override
128         public void onOngoingCallStateChanged(boolean animate) {
129             disable(getContext().getDisplayId(), mDisabled1, mDisabled2, animate);
130         }
131     };
132     private OperatorNameViewController mOperatorNameViewController;
133 
134     @Inject
CollapsedStatusBarFragment( StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, OngoingCallController ongoingCallController, SystemStatusAnimationScheduler animationScheduler, StatusBarLocationPublisher locationPublisher, NotificationIconAreaController notificationIconAreaController, PanelExpansionStateManager panelExpansionStateManager, FeatureFlags featureFlags, StatusBarIconController statusBarIconController, StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, KeyguardStateController keyguardStateController, NotificationPanelViewController notificationPanelViewController, NetworkController networkController, StatusBarStateController statusBarStateController, CommandQueue commandQueue, CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, OperatorNameViewController.Factory operatorNameViewControllerFactory )135     public CollapsedStatusBarFragment(
136             StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
137             OngoingCallController ongoingCallController,
138             SystemStatusAnimationScheduler animationScheduler,
139             StatusBarLocationPublisher locationPublisher,
140             NotificationIconAreaController notificationIconAreaController,
141             PanelExpansionStateManager panelExpansionStateManager,
142             FeatureFlags featureFlags,
143             StatusBarIconController statusBarIconController,
144             StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
145             KeyguardStateController keyguardStateController,
146             NotificationPanelViewController notificationPanelViewController,
147             NetworkController networkController,
148             StatusBarStateController statusBarStateController,
149             CommandQueue commandQueue,
150             CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
151             OperatorNameViewController.Factory operatorNameViewControllerFactory
152     ) {
153         mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory;
154         mOngoingCallController = ongoingCallController;
155         mAnimationScheduler = animationScheduler;
156         mLocationPublisher = locationPublisher;
157         mNotificationIconAreaController = notificationIconAreaController;
158         mPanelExpansionStateManager = panelExpansionStateManager;
159         mFeatureFlags = featureFlags;
160         mStatusBarIconController = statusBarIconController;
161         mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
162         mKeyguardStateController = keyguardStateController;
163         mNotificationPanelViewController = notificationPanelViewController;
164         mNetworkController = networkController;
165         mStatusBarStateController = statusBarStateController;
166         mCommandQueue = commandQueue;
167         mCollapsedStatusBarFragmentLogger = collapsedStatusBarFragmentLogger;
168         mOperatorNameViewControllerFactory = operatorNameViewControllerFactory;
169     }
170 
171     @Override
onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState)172     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
173             Bundle savedInstanceState) {
174         return inflater.inflate(R.layout.status_bar, container, false);
175     }
176 
177     @Override
onViewCreated(View view, @Nullable Bundle savedInstanceState)178     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
179         super.onViewCreated(view, savedInstanceState);
180         mStatusBarFragmentComponent = mStatusBarFragmentComponentFactory.create(this);
181         mStatusBarFragmentComponent.init();
182 
183         mStatusBar = (PhoneStatusBarView) view;
184         View contents = mStatusBar.findViewById(R.id.status_bar_contents);
185         contents.addOnLayoutChangeListener(mStatusBarLayoutListener);
186         updateStatusBarLocation(contents.getLeft(), contents.getRight());
187         if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
188             mStatusBar.restoreHierarchyState(
189                     savedInstanceState.getSparseParcelableArray(EXTRA_PANEL_STATE));
190         }
191         mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons), mFeatureFlags);
192         mDarkIconManager.setShouldLog(true);
193         mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_volume));
194         mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
195         mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
196         mDarkIconManager.setBlockList(mBlockedIcons);
197         mStatusBarIconController.addIconGroup(mDarkIconManager);
198         mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
199         mClockView = mStatusBar.findViewById(R.id.clock);
200         mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip);
201         showSystemIconArea(false);
202         showClock(false);
203         initEmergencyCryptkeeperText();
204         initOperatorName();
205         initNotificationIconArea();
206         mAnimationScheduler.addCallback(this);
207     }
208 
209     @Override
onSaveInstanceState(Bundle outState)210     public void onSaveInstanceState(Bundle outState) {
211         super.onSaveInstanceState(outState);
212         SparseArray<Parcelable> states = new SparseArray<>();
213         mStatusBar.saveHierarchyState(states);
214         outState.putSparseParcelableArray(EXTRA_PANEL_STATE, states);
215     }
216 
217     @Override
onResume()218     public void onResume() {
219         super.onResume();
220         mCommandQueue.addCallback(this);
221         mStatusBarStateController.addCallback(this);
222         initOngoingCallChip();
223     }
224 
225     @Override
onPause()226     public void onPause() {
227         super.onPause();
228         mCommandQueue.removeCallback(this);
229         mStatusBarStateController.removeCallback(this);
230         mOngoingCallController.removeCallback(mOngoingCallListener);
231     }
232 
233     @Override
onDestroyView()234     public void onDestroyView() {
235         super.onDestroyView();
236         mStatusBarIconController.removeIconGroup(mDarkIconManager);
237         mAnimationScheduler.removeCallback(this);
238         if (mNetworkController.hasEmergencyCryptKeeperText()) {
239             mNetworkController.removeCallback(mSignalCallback);
240         }
241     }
242 
243     /** Initializes views related to the notification icon area. */
initNotificationIconArea()244     public void initNotificationIconArea() {
245         ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
246         mNotificationIconAreaInner =
247                 mNotificationIconAreaController.getNotificationInnerAreaView();
248         if (mNotificationIconAreaInner.getParent() != null) {
249             ((ViewGroup) mNotificationIconAreaInner.getParent())
250                     .removeView(mNotificationIconAreaInner);
251         }
252         notificationIconArea.addView(mNotificationIconAreaInner);
253 
254         ViewGroup statusBarCenteredIconArea = mStatusBar.findViewById(R.id.centered_icon_area);
255         mCenteredIconArea = mNotificationIconAreaController.getCenteredNotificationAreaView();
256         if (mCenteredIconArea.getParent() != null) {
257             ((ViewGroup) mCenteredIconArea.getParent())
258                     .removeView(mCenteredIconArea);
259         }
260         statusBarCenteredIconArea.addView(mCenteredIconArea);
261 
262         // #disable should have already been called, so use the disable values to set visibility.
263         updateNotificationIconAreaAndCallChip(mDisabled1, false);
264     }
265 
266     /**
267      * Returns the dagger component for this fragment.
268      *
269      * TODO(b/205609837): Eventually, the dagger component should encapsulate all status bar
270      *   fragment functionality and we won't need to expose it here anymore.
271      */
272     @Nullable
getStatusBarFragmentComponent()273     public StatusBarFragmentComponent getStatusBarFragmentComponent() {
274         return mStatusBarFragmentComponent;
275     }
276 
277     @Override
disable(int displayId, int state1, int state2, boolean animate)278     public void disable(int displayId, int state1, int state2, boolean animate) {
279         if (displayId != getContext().getDisplayId()) {
280             return;
281         }
282 
283         int state1BeforeAdjustment = state1;
284         state1 = adjustDisableFlags(state1);
285 
286         mCollapsedStatusBarFragmentLogger.logDisableFlagChange(
287                 /* new= */ new DisableState(state1BeforeAdjustment, state2),
288                 /* newAfterLocalModification= */ new DisableState(state1, state2));
289 
290         final int old1 = mDisabled1;
291         final int diff1 = state1 ^ old1;
292         final int old2 = mDisabled2;
293         final int diff2 = state2 ^ old2;
294         mDisabled1 = state1;
295         mDisabled2 = state2;
296         if ((diff1 & DISABLE_SYSTEM_INFO) != 0 || ((diff2 & DISABLE2_SYSTEM_ICONS) != 0)) {
297             if ((state1 & DISABLE_SYSTEM_INFO) != 0 || ((state2 & DISABLE2_SYSTEM_ICONS) != 0)) {
298                 hideSystemIconArea(animate);
299                 hideOperatorName(animate);
300             } else {
301                 showSystemIconArea(animate);
302                 showOperatorName(animate);
303             }
304         }
305 
306         // The ongoing call chip and notification icon visibilities are intertwined, so update both
307         // if either change.
308         if (((diff1 & DISABLE_ONGOING_CALL_CHIP) != 0)
309                 || ((diff1 & DISABLE_NOTIFICATION_ICONS) != 0)) {
310             updateNotificationIconAreaAndCallChip(state1, animate);
311         }
312 
313         // The clock may have already been hidden, but we might want to shift its
314         // visibility to GONE from INVISIBLE or vice versa
315         if ((diff1 & DISABLE_CLOCK) != 0 || mClockView.getVisibility() != clockHiddenMode()) {
316             if ((state1 & DISABLE_CLOCK) != 0) {
317                 hideClock(animate);
318             } else {
319                 showClock(animate);
320             }
321         }
322     }
323 
adjustDisableFlags(int state)324     protected int adjustDisableFlags(int state) {
325         boolean headsUpVisible =
326                 mStatusBarFragmentComponent.getHeadsUpAppearanceController().shouldBeVisible();
327         if (headsUpVisible) {
328             state |= DISABLE_CLOCK;
329         }
330 
331         if (!mKeyguardStateController.isLaunchTransitionFadingAway()
332                 && !mKeyguardStateController.isKeyguardFadingAway()
333                 && shouldHideNotificationIcons()
334                 && !(mStatusBarStateController.getState() == StatusBarState.KEYGUARD
335                         && headsUpVisible)) {
336             state |= DISABLE_NOTIFICATION_ICONS;
337             state |= DISABLE_SYSTEM_INFO;
338             state |= DISABLE_CLOCK;
339         }
340 
341 
342         if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
343             if (mNetworkController.hasEmergencyCryptKeeperText()) {
344                 state |= DISABLE_NOTIFICATION_ICONS;
345             }
346             if (!mNetworkController.isRadioOn()) {
347                 state |= DISABLE_SYSTEM_INFO;
348             }
349         }
350 
351         // The shelf will be hidden when dozing with a custom clock, we must show notification
352         // icons in this occasion.
353         if (mStatusBarStateController.isDozing()
354                 && mNotificationPanelViewController.hasCustomClock()) {
355             state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
356         }
357 
358         if (mOngoingCallController.hasOngoingCall()) {
359             state &= ~DISABLE_ONGOING_CALL_CHIP;
360         } else {
361             state |= DISABLE_ONGOING_CALL_CHIP;
362         }
363 
364         return state;
365     }
366 
367     /**
368      * Updates the visibility of the notification icon area and ongoing call chip based on disabled1
369      * state.
370      */
updateNotificationIconAreaAndCallChip(int state1, boolean animate)371     private void updateNotificationIconAreaAndCallChip(int state1, boolean animate) {
372         boolean disableNotifications = (state1 & DISABLE_NOTIFICATION_ICONS) != 0;
373         boolean hasOngoingCall = (state1 & DISABLE_ONGOING_CALL_CHIP) == 0;
374 
375         // Hide notifications if the disable flag is set or we have an ongoing call.
376         if (disableNotifications || hasOngoingCall) {
377             hideNotificationIconArea(animate);
378         } else {
379             showNotificationIconArea(animate);
380         }
381 
382         // Show the ongoing call chip only if there is an ongoing call *and* notification icons
383         // are allowed. (The ongoing call chip occupies the same area as the notification icons,
384         // so if the icons are disabled then the call chip should be, too.)
385         boolean showOngoingCallChip = hasOngoingCall && !disableNotifications;
386         if (showOngoingCallChip) {
387             showOngoingCallChip(animate);
388         } else {
389             hideOngoingCallChip(animate);
390         }
391         mOngoingCallController.notifyChipVisibilityChanged(showOngoingCallChip);
392     }
393 
shouldHideNotificationIcons()394     private boolean shouldHideNotificationIcons() {
395         if (!mPanelExpansionStateManager.isClosed()
396                 && mNotificationPanelViewController.hideStatusBarIconsWhenExpanded()) {
397             return true;
398         }
399         return mStatusBarHideIconsForBouncerManager.getShouldHideStatusBarIconsForBouncer();
400     }
401 
hideSystemIconArea(boolean animate)402     private void hideSystemIconArea(boolean animate) {
403         animateHide(mSystemIconArea, animate);
404     }
405 
showSystemIconArea(boolean animate)406     private void showSystemIconArea(boolean animate) {
407         // Only show the system icon area if we are not currently animating
408         int state = mAnimationScheduler.getAnimationState();
409         if (state == IDLE || state == SHOWING_PERSISTENT_DOT) {
410             animateShow(mSystemIconArea, animate);
411         }
412     }
413 
hideClock(boolean animate)414     private void hideClock(boolean animate) {
415         animateHiddenState(mClockView, clockHiddenMode(), animate);
416     }
417 
showClock(boolean animate)418     private void showClock(boolean animate) {
419         animateShow(mClockView, animate);
420     }
421 
422     /** Hides the ongoing call chip. */
hideOngoingCallChip(boolean animate)423     public void hideOngoingCallChip(boolean animate) {
424         animateHiddenState(mOngoingCallChip, View.GONE, animate);
425     }
426 
427     /** Displays the ongoing call chip. */
showOngoingCallChip(boolean animate)428     public void showOngoingCallChip(boolean animate) {
429         animateShow(mOngoingCallChip, animate);
430     }
431 
432     /**
433      * If panel is expanded/expanding it usually means QS shade is opening, so
434      * don't set the clock GONE otherwise it'll mess up the animation.
435      */
clockHiddenMode()436     private int clockHiddenMode() {
437         if (!mPanelExpansionStateManager.isClosed() && !mKeyguardStateController.isShowing()
438                 && !mStatusBarStateController.isDozing()) {
439             return View.INVISIBLE;
440         }
441         return View.GONE;
442     }
443 
hideNotificationIconArea(boolean animate)444     public void hideNotificationIconArea(boolean animate) {
445         animateHide(mNotificationIconAreaInner, animate);
446         animateHide(mCenteredIconArea, animate);
447     }
448 
showNotificationIconArea(boolean animate)449     public void showNotificationIconArea(boolean animate) {
450         animateShow(mNotificationIconAreaInner, animate);
451         animateShow(mCenteredIconArea, animate);
452     }
453 
hideOperatorName(boolean animate)454     public void hideOperatorName(boolean animate) {
455         if (mOperatorNameViewController != null) {
456             animateHide(mOperatorNameViewController.getView(), animate);
457         }
458     }
459 
showOperatorName(boolean animate)460     public void showOperatorName(boolean animate) {
461         if (mOperatorNameViewController != null) {
462             animateShow(mOperatorNameViewController.getView(), animate);
463         }
464     }
465 
466     /**
467      * Animate a view to INVISIBLE or GONE
468      */
animateHiddenState(final View v, int state, boolean animate)469     private void animateHiddenState(final View v, int state, boolean animate) {
470         v.animate().cancel();
471         if (!animate) {
472             v.setAlpha(0f);
473             v.setVisibility(state);
474             return;
475         }
476 
477         v.animate()
478                 .alpha(0f)
479                 .setDuration(160)
480                 .setStartDelay(0)
481                 .setInterpolator(Interpolators.ALPHA_OUT)
482                 .withEndAction(() -> v.setVisibility(state));
483     }
484 
485     /**
486      * Hides a view.
487      */
animateHide(final View v, boolean animate)488     private void animateHide(final View v, boolean animate) {
489         animateHiddenState(v, View.INVISIBLE, animate);
490     }
491 
492     /**
493      * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
494      */
animateShow(View v, boolean animate)495     private void animateShow(View v, boolean animate) {
496         v.animate().cancel();
497         v.setVisibility(View.VISIBLE);
498         if (!animate) {
499             v.setAlpha(1f);
500             return;
501         }
502         v.animate()
503                 .alpha(1f)
504                 .setDuration(FADE_IN_DURATION)
505                 .setInterpolator(Interpolators.ALPHA_IN)
506                 .setStartDelay(FADE_IN_DELAY)
507 
508                 // We need to clean up any pending end action from animateHide if we call
509                 // both hide and show in the same frame before the animation actually gets started.
510                 // cancel() doesn't really remove the end action.
511                 .withEndAction(null);
512 
513         // Synchronize the motion with the Keyguard fading if necessary.
514         if (mKeyguardStateController.isKeyguardFadingAway()) {
515             v.animate()
516                     .setDuration(mKeyguardStateController.getKeyguardFadingAwayDuration())
517                     .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
518                     .setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
519                     .start();
520         }
521     }
522 
initEmergencyCryptkeeperText()523     private void initEmergencyCryptkeeperText() {
524         View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
525         if (mNetworkController.hasEmergencyCryptKeeperText()) {
526             if (emergencyViewStub != null) {
527                 ((ViewStub) emergencyViewStub).inflate();
528             }
529             mNetworkController.addCallback(mSignalCallback);
530         } else if (emergencyViewStub != null) {
531             ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
532             parent.removeView(emergencyViewStub);
533         }
534     }
535 
initOperatorName()536     private void initOperatorName() {
537         if (getResources().getBoolean(R.bool.config_showOperatorNameInStatusBar)) {
538             ViewStub stub = mStatusBar.findViewById(R.id.operator_name);
539             mOperatorNameViewController =
540                     mOperatorNameViewControllerFactory.create((OperatorNameView) stub.inflate());
541             mOperatorNameViewController.init();
542         }
543     }
544 
initOngoingCallChip()545     private void initOngoingCallChip() {
546         mOngoingCallController.addCallback(mOngoingCallListener);
547         mOngoingCallController.setChipView(mOngoingCallChip);
548     }
549 
550     @Override
onStateChanged(int newState)551     public void onStateChanged(int newState) { }
552 
553     @Override
onDozingChanged(boolean isDozing)554     public void onDozingChanged(boolean isDozing) {
555         disable(getContext().getDisplayId(), mDisabled1, mDisabled2, false /* animate */);
556     }
557 
558     @Override
onSystemChromeAnimationStart()559     public void onSystemChromeAnimationStart() {
560         if (mAnimationScheduler.getAnimationState() == ANIMATING_OUT
561                 && !isSystemIconAreaDisabled()) {
562             mSystemIconArea.setVisibility(View.VISIBLE);
563             mSystemIconArea.setAlpha(0f);
564         }
565     }
566 
567     @Override
onSystemChromeAnimationEnd()568     public void onSystemChromeAnimationEnd() {
569         // Make sure the system icons are out of the way
570         if (mAnimationScheduler.getAnimationState() == ANIMATING_IN) {
571             mSystemIconArea.setVisibility(View.INVISIBLE);
572             mSystemIconArea.setAlpha(0f);
573         } else {
574             if (isSystemIconAreaDisabled()) {
575                 // don't unhide
576                 return;
577             }
578 
579             mSystemIconArea.setAlpha(1f);
580             mSystemIconArea.setVisibility(View.VISIBLE);
581         }
582     }
583 
584     @Override
onSystemChromeAnimationUpdate(@otNull ValueAnimator animator)585     public void onSystemChromeAnimationUpdate(@NotNull ValueAnimator animator) {
586         mSystemIconArea.setAlpha((float) animator.getAnimatedValue());
587     }
588 
isSystemIconAreaDisabled()589     private boolean isSystemIconAreaDisabled() {
590         return (mDisabled1 & DISABLE_SYSTEM_INFO) != 0 || (mDisabled2 & DISABLE2_SYSTEM_ICONS) != 0;
591     }
592 
updateStatusBarLocation(int left, int right)593     private void updateStatusBarLocation(int left, int right) {
594         int leftMargin = left - mStatusBar.getLeft();
595         int rightMargin = mStatusBar.getRight() - right;
596 
597         mLocationPublisher.updateStatusBarMargin(leftMargin, rightMargin);
598     }
599 
600     // Listen for view end changes of PhoneStatusBarView and publish that to the privacy dot
601     private View.OnLayoutChangeListener mStatusBarLayoutListener =
602             (view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
603                 if (left != oldLeft || right != oldRight) {
604                     updateStatusBarLocation(left, right);
605                 }
606             };
607 }
608