Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.systemui.statusbar.phone;
     18 
     19 import android.app.AlarmManager;
     20 import android.app.StatusBarManager;
     21 import android.bluetooth.BluetoothAdapter;
     22 import android.content.BroadcastReceiver;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.content.IntentFilter;
     26 import android.media.AudioManager;
     27 import android.os.Handler;
     28 import android.os.UserHandle;
     29 import android.provider.Settings.Global;
     30 import android.telecom.TelecomManager;
     31 import android.util.Log;
     32 
     33 import com.android.internal.telephony.IccCardConstants;
     34 import com.android.internal.telephony.TelephonyIntents;
     35 import com.android.systemui.R;
     36 import com.android.systemui.statusbar.policy.CastController;
     37 import com.android.systemui.statusbar.policy.CastController.CastDevice;
     38 import com.android.systemui.statusbar.policy.HotspotController;
     39 
     40 /**
     41  * This class contains all of the policy about which icons are installed in the status
     42  * bar at boot time.  It goes through the normal API for icons, even though it probably
     43  * strictly doesn't need to.
     44  */
     45 public class PhoneStatusBarPolicy {
     46     private static final String TAG = "PhoneStatusBarPolicy";
     47     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     48 
     49     private static final boolean SHOW_SYNC_ICON = false;
     50 
     51     private static final String SLOT_SYNC_ACTIVE = "sync_active";
     52     private static final String SLOT_CAST = "cast";
     53     private static final String SLOT_HOTSPOT = "hotspot";
     54     private static final String SLOT_BLUETOOTH = "bluetooth";
     55     private static final String SLOT_TTY = "tty";
     56     private static final String SLOT_ZEN = "zen";
     57     private static final String SLOT_VOLUME = "volume";
     58     private static final String SLOT_CDMA_ERI = "cdma_eri";
     59     private static final String SLOT_ALARM_CLOCK = "alarm_clock";
     60 
     61     private final Context mContext;
     62     private final StatusBarManager mService;
     63     private final Handler mHandler = new Handler();
     64     private final CastController mCast;
     65     private final HotspotController mHotspot;
     66 
     67     // Assume it's all good unless we hear otherwise.  We don't always seem
     68     // to get broadcasts that it *is* there.
     69     IccCardConstants.State mSimState = IccCardConstants.State.READY;
     70 
     71     private boolean mZenVisible;
     72     private boolean mVolumeVisible;
     73 
     74     private int mZen;
     75 
     76     private boolean mBluetoothEnabled = false;
     77 
     78 
     79     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
     80         @Override
     81         public void onReceive(Context context, Intent intent) {
     82             String action = intent.getAction();
     83             if (action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
     84                 updateAlarm();
     85             }
     86             else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
     87                 updateSyncState(intent);
     88             }
     89             else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
     90                     action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
     91                 updateBluetooth();
     92             }
     93             else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
     94                     action.equals(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)) {
     95                 updateVolumeZen();
     96             }
     97             else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
     98                 updateSimState(intent);
     99             }
    100             else if (action.equals(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED)) {
    101                 updateTTY(intent);
    102             }
    103             else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
    104                 updateAlarm();
    105             }
    106         }
    107     };
    108 
    109     public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot) {
    110         mContext = context;
    111         mCast = cast;
    112         mHotspot = hotspot;
    113         mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
    114 
    115         // listen for broadcasts
    116         IntentFilter filter = new IntentFilter();
    117         filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
    118         filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
    119         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
    120         filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
    121         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    122         filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
    123         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
    124         filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
    125         filter.addAction(Intent.ACTION_USER_SWITCHED);
    126         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
    127 
    128         // TTY status
    129         mService.setIcon(SLOT_TTY,  R.drawable.stat_sys_tty_mode, 0, null);
    130         mService.setIconVisibility(SLOT_TTY, false);
    131 
    132         // Cdma Roaming Indicator, ERI
    133         mService.setIcon(SLOT_CDMA_ERI, R.drawable.stat_sys_roaming_cdma_0, 0, null);
    134         mService.setIconVisibility(SLOT_CDMA_ERI, false);
    135 
    136         // bluetooth status
    137         updateBluetooth();
    138 
    139         // Alarm clock
    140         mService.setIcon(SLOT_ALARM_CLOCK, R.drawable.stat_sys_alarm, 0, null);
    141         mService.setIconVisibility(SLOT_ALARM_CLOCK, false);
    142 
    143         // Sync state
    144         mService.setIcon(SLOT_SYNC_ACTIVE, R.drawable.stat_sys_sync, 0, null);
    145         mService.setIconVisibility(SLOT_SYNC_ACTIVE, false);
    146         // "sync_failing" is obsolete: b/1297963
    147 
    148         // zen
    149         mService.setIcon(SLOT_ZEN, R.drawable.stat_sys_zen_important, 0, null);
    150         mService.setIconVisibility(SLOT_ZEN, false);
    151 
    152         // volume
    153         mService.setIcon(SLOT_VOLUME, R.drawable.stat_sys_ringer_vibrate, 0, null);
    154         mService.setIconVisibility(SLOT_VOLUME, false);
    155         updateVolumeZen();
    156 
    157         // cast
    158         mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0, null);
    159         mService.setIconVisibility(SLOT_CAST, false);
    160         mCast.addCallback(mCastCallback);
    161 
    162         // hotspot
    163         mService.setIcon(SLOT_HOTSPOT, R.drawable.stat_sys_hotspot, 0, null);
    164         mService.setIconVisibility(SLOT_HOTSPOT, mHotspot.isHotspotEnabled());
    165         mHotspot.addCallback(mHotspotCallback);
    166     }
    167 
    168     public void setZenMode(int zen) {
    169         mZen = zen;
    170         updateVolumeZen();
    171     }
    172 
    173     private void updateAlarm() {
    174         AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
    175 	boolean alarmSet = alarmManager.getNextAlarmClock(UserHandle.USER_CURRENT) != null;
    176         mService.setIconVisibility(SLOT_ALARM_CLOCK, alarmSet);
    177     }
    178 
    179     private final void updateSyncState(Intent intent) {
    180         if (!SHOW_SYNC_ICON) return;
    181         boolean isActive = intent.getBooleanExtra("active", false);
    182         mService.setIconVisibility(SLOT_SYNC_ACTIVE, isActive);
    183     }
    184 
    185     private final void updateSimState(Intent intent) {
    186         String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
    187         if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
    188             mSimState = IccCardConstants.State.ABSENT;
    189         }
    190         else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
    191             mSimState = IccCardConstants.State.CARD_IO_ERROR;
    192         }
    193         else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
    194             mSimState = IccCardConstants.State.READY;
    195         }
    196         else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
    197             final String lockedReason =
    198                     intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
    199             if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
    200                 mSimState = IccCardConstants.State.PIN_REQUIRED;
    201             }
    202             else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
    203                 mSimState = IccCardConstants.State.PUK_REQUIRED;
    204             }
    205             else {
    206                 mSimState = IccCardConstants.State.NETWORK_LOCKED;
    207             }
    208         } else {
    209             mSimState = IccCardConstants.State.UNKNOWN;
    210         }
    211     }
    212 
    213     private final void updateVolumeZen() {
    214         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
    215 
    216         boolean zenVisible = false;
    217         int zenIconId = 0;
    218         String zenDescription = null;
    219 
    220         boolean volumeVisible = false;
    221         int volumeIconId = 0;
    222         String volumeDescription = null;
    223 
    224         if (mZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
    225             zenVisible = true;
    226             zenIconId = R.drawable.stat_sys_zen_none;
    227             zenDescription = mContext.getString(R.string.zen_no_interruptions);
    228         } else if (mZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
    229             zenVisible = true;
    230             zenIconId = R.drawable.stat_sys_zen_important;
    231             zenDescription = mContext.getString(R.string.zen_important_interruptions);
    232         }
    233 
    234         if (mZen != Global.ZEN_MODE_NO_INTERRUPTIONS &&
    235                 audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
    236             volumeVisible = true;
    237             volumeIconId = R.drawable.stat_sys_ringer_vibrate;
    238             volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
    239         }
    240 
    241         if (zenVisible) {
    242             mService.setIcon(SLOT_ZEN, zenIconId, 0, zenDescription);
    243         }
    244         if (zenVisible != mZenVisible) {
    245             mService.setIconVisibility(SLOT_ZEN, zenVisible);
    246             mZenVisible = zenVisible;
    247         }
    248 
    249         if (volumeVisible) {
    250             mService.setIcon(SLOT_VOLUME, volumeIconId, 0, volumeDescription);
    251         }
    252         if (volumeVisible != mVolumeVisible) {
    253             mService.setIconVisibility(SLOT_VOLUME, volumeVisible);
    254             mVolumeVisible = volumeVisible;
    255         }
    256     }
    257 
    258     private final void updateBluetooth() {
    259         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    260         int iconId = R.drawable.stat_sys_data_bluetooth;
    261         String contentDescription =
    262                 mContext.getString(R.string.accessibility_bluetooth_disconnected);
    263         if (adapter != null) {
    264             mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON);
    265             if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) {
    266                 iconId = R.drawable.stat_sys_data_bluetooth_connected;
    267                 contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
    268             }
    269         } else {
    270             mBluetoothEnabled = false;
    271         }
    272 
    273         mService.setIcon(SLOT_BLUETOOTH, iconId, 0, contentDescription);
    274         mService.setIconVisibility(SLOT_BLUETOOTH, mBluetoothEnabled);
    275     }
    276 
    277     private final void updateTTY(Intent intent) {
    278         int currentTtyMode = intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE,
    279                 TelecomManager.TTY_MODE_OFF);
    280         boolean enabled = currentTtyMode != TelecomManager.TTY_MODE_OFF;
    281 
    282         if (DEBUG) Log.v(TAG, "updateTTY: enabled: " + enabled);
    283 
    284         if (enabled) {
    285             // TTY is on
    286             if (DEBUG) Log.v(TAG, "updateTTY: set TTY on");
    287             mService.setIcon(SLOT_TTY, R.drawable.stat_sys_tty_mode, 0,
    288                     mContext.getString(R.string.accessibility_tty_enabled));
    289             mService.setIconVisibility(SLOT_TTY, true);
    290         } else {
    291             // TTY is off
    292             if (DEBUG) Log.v(TAG, "updateTTY: set TTY off");
    293             mService.setIconVisibility(SLOT_TTY, false);
    294         }
    295     }
    296 
    297     private void updateCast() {
    298         boolean isCasting = false;
    299         for (CastDevice device : mCast.getCastDevices()) {
    300             if (device.state == CastDevice.STATE_CONNECTING
    301                     || device.state == CastDevice.STATE_CONNECTED) {
    302                 isCasting = true;
    303                 break;
    304             }
    305         }
    306         if (DEBUG) Log.v(TAG, "updateCast: isCasting: " + isCasting);
    307         if (isCasting) {
    308             mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0,
    309                     mContext.getString(R.string.accessibility_casting));
    310         }
    311         mService.setIconVisibility(SLOT_CAST, isCasting);
    312     }
    313 
    314     private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() {
    315         @Override
    316         public void onHotspotChanged(boolean enabled) {
    317             mService.setIconVisibility(SLOT_HOTSPOT, enabled);
    318         }
    319     };
    320 
    321     private final CastController.Callback mCastCallback = new CastController.Callback() {
    322         @Override
    323         public void onCastDevicesChanged() {
    324             updateCast();
    325         }
    326     };
    327 }
    328