Home | History | Annotate | Download | only in phone
      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;
     16 
     17 import static com.android.systemui.statusbar.phone.StatusBar.reinflateSignalCluster;
     18 
     19 import android.annotation.Nullable;
     20 import android.app.Fragment;
     21 import android.app.StatusBarManager;
     22 import android.os.Bundle;
     23 import android.view.LayoutInflater;
     24 import android.view.View;
     25 import android.view.ViewGroup;
     26 import android.view.ViewStub;
     27 import android.widget.LinearLayout;
     28 
     29 import com.android.systemui.Dependency;
     30 import com.android.systemui.Interpolators;
     31 import com.android.systemui.R;
     32 import com.android.systemui.SysUiServiceProvider;
     33 import com.android.systemui.statusbar.CommandQueue;
     34 import com.android.systemui.statusbar.SignalClusterView;
     35 import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
     36 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
     37 import com.android.systemui.statusbar.policy.EncryptionHelper;
     38 import com.android.systemui.statusbar.policy.KeyguardMonitor;
     39 import com.android.systemui.statusbar.policy.NetworkController;
     40 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
     41 
     42 /**
     43  * Contains the collapsed status bar and handles hiding/showing based on disable flags
     44  * and keyguard state. Also manages lifecycle to make sure the views it contains are being
     45  * updated by the StatusBarIconController and DarkIconManager while it is attached.
     46  */
     47 public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {
     48 
     49     public static final String TAG = "CollapsedStatusBarFragment";
     50     private static final String EXTRA_PANEL_STATE = "panel_state";
     51     private PhoneStatusBarView mStatusBar;
     52     private KeyguardMonitor mKeyguardMonitor;
     53     private NetworkController mNetworkController;
     54     private LinearLayout mSystemIconArea;
     55     private View mNotificationIconAreaInner;
     56     private int mDisabled1;
     57     private StatusBar mStatusBarComponent;
     58     private DarkIconManager mDarkIconManager;
     59     private SignalClusterView mSignalClusterView;
     60 
     61     private SignalCallback mSignalCallback = new SignalCallback() {
     62         @Override
     63         public void setIsAirplaneMode(NetworkController.IconState icon) {
     64             mStatusBarComponent.recomputeDisableFlags(true /* animate */);
     65         }
     66     };
     67 
     68     @Override
     69     public void onCreate(@Nullable Bundle savedInstanceState) {
     70         super.onCreate(savedInstanceState);
     71         mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
     72         mNetworkController = Dependency.get(NetworkController.class);
     73         mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
     74     }
     75 
     76     @Override
     77     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
     78             Bundle savedInstanceState) {
     79         return inflater.inflate(R.layout.status_bar, container, false);
     80     }
     81 
     82     @Override
     83     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
     84         super.onViewCreated(view, savedInstanceState);
     85         mStatusBar = (PhoneStatusBarView) view;
     86         if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
     87             mStatusBar.go(savedInstanceState.getInt(EXTRA_PANEL_STATE));
     88         }
     89         mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
     90         Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
     91         mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
     92         mSignalClusterView = mStatusBar.findViewById(R.id.signal_cluster);
     93         Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSignalClusterView);
     94         // Default to showing until we know otherwise.
     95         showSystemIconArea(false);
     96         initEmergencyCryptkeeperText();
     97     }
     98 
     99     @Override
    100     public void onSaveInstanceState(Bundle outState) {
    101         super.onSaveInstanceState(outState);
    102         outState.putInt(EXTRA_PANEL_STATE, mStatusBar.getState());
    103     }
    104 
    105     @Override
    106     public void onResume() {
    107         super.onResume();
    108         SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
    109     }
    110 
    111     @Override
    112     public void onPause() {
    113         super.onPause();
    114         SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).removeCallbacks(this);
    115     }
    116 
    117     @Override
    118     public void onDestroyView() {
    119         super.onDestroyView();
    120         Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mSignalClusterView);
    121         Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
    122         if (mNetworkController.hasEmergencyCryptKeeperText()) {
    123             mNetworkController.removeCallback(mSignalCallback);
    124         }
    125     }
    126 
    127     public void initNotificationIconArea(NotificationIconAreaController
    128             notificationIconAreaController) {
    129         ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
    130         mNotificationIconAreaInner =
    131                 notificationIconAreaController.getNotificationInnerAreaView();
    132         if (mNotificationIconAreaInner.getParent() != null) {
    133             ((ViewGroup) mNotificationIconAreaInner.getParent())
    134                     .removeView(mNotificationIconAreaInner);
    135         }
    136         notificationIconArea.addView(mNotificationIconAreaInner);
    137         // Default to showing until we know otherwise.
    138         showNotificationIconArea(false);
    139     }
    140 
    141     @Override
    142     public void disable(int state1, int state2, boolean animate) {
    143         state1 = adjustDisableFlags(state1);
    144         final int old1 = mDisabled1;
    145         final int diff1 = state1 ^ old1;
    146         mDisabled1 = state1;
    147         if ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
    148             if ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
    149                 hideSystemIconArea(animate);
    150             } else {
    151                 showSystemIconArea(animate);
    152             }
    153         }
    154         if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
    155             if ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
    156                 hideNotificationIconArea(animate);
    157             } else {
    158                 showNotificationIconArea(animate);
    159             }
    160         }
    161     }
    162 
    163     protected int adjustDisableFlags(int state) {
    164         if (!mStatusBarComponent.isLaunchTransitionFadingAway()
    165                 && !mKeyguardMonitor.isKeyguardFadingAway()
    166                 && shouldHideNotificationIcons()) {
    167             state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
    168             state |= StatusBarManager.DISABLE_SYSTEM_INFO;
    169         }
    170         if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
    171             if (mNetworkController.hasEmergencyCryptKeeperText()) {
    172                 state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
    173             }
    174             if (!mNetworkController.isRadioOn()) {
    175                 state |= StatusBarManager.DISABLE_SYSTEM_INFO;
    176             }
    177         }
    178         return state;
    179     }
    180 
    181     private boolean shouldHideNotificationIcons() {
    182         return !mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded();
    183     }
    184 
    185     public void hideSystemIconArea(boolean animate) {
    186         animateHide(mSystemIconArea, animate);
    187     }
    188 
    189     public void showSystemIconArea(boolean animate) {
    190         animateShow(mSystemIconArea, animate);
    191     }
    192 
    193     public void hideNotificationIconArea(boolean animate) {
    194         animateHide(mNotificationIconAreaInner, animate);
    195     }
    196 
    197     public void showNotificationIconArea(boolean animate) {
    198         animateShow(mNotificationIconAreaInner, animate);
    199     }
    200 
    201     /**
    202      * Hides a view.
    203      */
    204     private void animateHide(final View v, boolean animate) {
    205         v.animate().cancel();
    206         if (!animate) {
    207             v.setAlpha(0f);
    208             v.setVisibility(View.INVISIBLE);
    209             return;
    210         }
    211         v.animate()
    212                 .alpha(0f)
    213                 .setDuration(160)
    214                 .setStartDelay(0)
    215                 .setInterpolator(Interpolators.ALPHA_OUT)
    216                 .withEndAction(() -> v.setVisibility(View.INVISIBLE));
    217     }
    218 
    219     /**
    220      * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
    221      */
    222     private void animateShow(View v, boolean animate) {
    223         v.animate().cancel();
    224         v.setVisibility(View.VISIBLE);
    225         if (!animate) {
    226             v.setAlpha(1f);
    227             return;
    228         }
    229         v.animate()
    230                 .alpha(1f)
    231                 .setDuration(320)
    232                 .setInterpolator(Interpolators.ALPHA_IN)
    233                 .setStartDelay(50)
    234 
    235                 // We need to clean up any pending end action from animateHide if we call
    236                 // both hide and show in the same frame before the animation actually gets started.
    237                 // cancel() doesn't really remove the end action.
    238                 .withEndAction(null);
    239 
    240         // Synchronize the motion with the Keyguard fading if necessary.
    241         if (mKeyguardMonitor.isKeyguardFadingAway()) {
    242             v.animate()
    243                     .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration())
    244                     .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
    245                     .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
    246                     .start();
    247         }
    248     }
    249 
    250     private void initEmergencyCryptkeeperText() {
    251         View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
    252         if (mNetworkController.hasEmergencyCryptKeeperText()) {
    253             if (emergencyViewStub != null) {
    254                 ((ViewStub) emergencyViewStub).inflate();
    255             }
    256             mNetworkController.addCallback(mSignalCallback);
    257         } else if (emergencyViewStub != null) {
    258             ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
    259             parent.removeView(emergencyViewStub);
    260         }
    261     }
    262 }
    263