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.StatusBarManager;
     20 import android.bluetooth.BluetoothAdapter;
     21 import android.content.BroadcastReceiver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.location.LocationManager;
     26 import android.media.AudioManager;
     27 import android.net.ConnectivityManager;
     28 import android.net.NetworkInfo;
     29 import android.net.wifi.WifiManager;
     30 import android.os.Binder;
     31 import android.os.Handler;
     32 import android.os.RemoteException;
     33 import android.os.storage.StorageManager;
     34 import android.provider.Settings;
     35 import android.telephony.PhoneStateListener;
     36 import android.telephony.ServiceState;
     37 import android.telephony.SignalStrength;
     38 import android.telephony.TelephonyManager;
     39 import android.util.Slog;
     40 
     41 import com.android.internal.telephony.IccCard;
     42 import com.android.internal.telephony.TelephonyIntents;
     43 import com.android.internal.telephony.cdma.EriInfo;
     44 import com.android.internal.telephony.cdma.TtyIntent;
     45 import com.android.server.am.BatteryStatsService;
     46 import com.android.systemui.R;
     47 
     48 /**
     49  * This class contains all of the policy about which icons are installed in the status
     50  * bar at boot time.  It goes through the normal API for icons, even though it probably
     51  * strictly doesn't need to.
     52  */
     53 public class PhoneStatusBarPolicy {
     54     private static final String TAG = "PhoneStatusBarPolicy";
     55 
     56     // message codes for the handler
     57     private static final int EVENT_BATTERY_CLOSE = 4;
     58 
     59     private static final int AM_PM_STYLE_NORMAL  = 0;
     60     private static final int AM_PM_STYLE_SMALL   = 1;
     61     private static final int AM_PM_STYLE_GONE    = 2;
     62 
     63     private static final int AM_PM_STYLE = AM_PM_STYLE_GONE;
     64 
     65     private static final int INET_CONDITION_THRESHOLD = 50;
     66 
     67     private static final boolean SHOW_SYNC_ICON = false;
     68 
     69     private final Context mContext;
     70     private final StatusBarManager mService;
     71     private final Handler mHandler = new Handler();
     72 
     73     // storage
     74     private StorageManager mStorageManager;
     75 
     76 
     77     // Assume it's all good unless we hear otherwise.  We don't always seem
     78     // to get broadcasts that it *is* there.
     79     IccCard.State mSimState = IccCard.State.READY;
     80 
     81     // ringer volume
     82     private boolean mVolumeVisible;
     83 
     84     // bluetooth device status
     85     private boolean mBluetoothEnabled = false;
     86 
     87     // wifi
     88     private static final int[][] sWifiSignalImages = {
     89             { R.drawable.stat_sys_wifi_signal_1,
     90               R.drawable.stat_sys_wifi_signal_2,
     91               R.drawable.stat_sys_wifi_signal_3,
     92               R.drawable.stat_sys_wifi_signal_4 },
     93             { R.drawable.stat_sys_wifi_signal_1_fully,
     94               R.drawable.stat_sys_wifi_signal_2_fully,
     95               R.drawable.stat_sys_wifi_signal_3_fully,
     96               R.drawable.stat_sys_wifi_signal_4_fully }
     97         };
     98     private static final int sWifiTemporarilyNotConnectedImage =
     99             R.drawable.stat_sys_wifi_signal_0;
    100 
    101     private int mLastWifiSignalLevel = -1;
    102     private boolean mIsWifiConnected = false;
    103 
    104     // state of inet connection - 0 not connected, 100 connected
    105     private int mInetCondition = 0;
    106 
    107     // sync state
    108     // If sync is active the SyncActive icon is displayed. If sync is not active but
    109     // sync is failing the SyncFailing icon is displayed. Otherwise neither are displayed.
    110 
    111     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
    112         @Override
    113         public void onReceive(Context context, Intent intent) {
    114             String action = intent.getAction();
    115             if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
    116                 updateAlarm(intent);
    117             }
    118             else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
    119                 updateSyncState(intent);
    120             }
    121             else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
    122                     action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
    123                 updateBluetooth(intent);
    124             }
    125             else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
    126                 updateVolume();
    127             }
    128             else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
    129                 updateSimState(intent);
    130             }
    131             else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
    132                 updateTTY(intent);
    133             }
    134         }
    135     };
    136 
    137     public PhoneStatusBarPolicy(Context context) {
    138         mContext = context;
    139         mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
    140 
    141         // listen for broadcasts
    142         IntentFilter filter = new IntentFilter();
    143         filter.addAction(Intent.ACTION_ALARM_CHANGED);
    144         filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
    145         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
    146         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    147         filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
    148         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
    149         filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
    150         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
    151 
    152         // storage
    153         mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
    154         mStorageManager.registerListener(
    155                 new com.android.systemui.usb.StorageNotification(context));
    156 
    157         // TTY status
    158         mService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0, null);
    159         mService.setIconVisibility("tty", false);
    160 
    161         // Cdma Roaming Indicator, ERI
    162         mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null);
    163         mService.setIconVisibility("cdma_eri", false);
    164 
    165         // bluetooth status
    166         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    167         int bluetoothIcon = R.drawable.stat_sys_data_bluetooth;
    168         if (adapter != null) {
    169             mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON);
    170             if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) {
    171                 bluetoothIcon = R.drawable.stat_sys_data_bluetooth_connected;
    172             }
    173         }
    174         mService.setIcon("bluetooth", bluetoothIcon, 0, null);
    175         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
    176 
    177         // Alarm clock
    178         mService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null);
    179         mService.setIconVisibility("alarm_clock", false);
    180 
    181         // Sync state
    182         mService.setIcon("sync_active", R.drawable.stat_sys_sync, 0, null);
    183         mService.setIcon("sync_failing", R.drawable.stat_sys_sync_error, 0, null);
    184         mService.setIconVisibility("sync_active", false);
    185         mService.setIconVisibility("sync_failing", false);
    186 
    187         // volume
    188         mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null);
    189         mService.setIconVisibility("volume", false);
    190         updateVolume();
    191     }
    192 
    193     private final void updateAlarm(Intent intent) {
    194         boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
    195         mService.setIconVisibility("alarm_clock", alarmSet);
    196     }
    197 
    198     private final void updateSyncState(Intent intent) {
    199         if (!SHOW_SYNC_ICON) return;
    200         boolean isActive = intent.getBooleanExtra("active", false);
    201         boolean isFailing = intent.getBooleanExtra("failing", false);
    202         mService.setIconVisibility("sync_active", isActive);
    203         // Don't display sync failing icon: BUG 1297963 Set sync error timeout to "never"
    204         //mService.setIconVisibility("sync_failing", isFailing && !isActive);
    205     }
    206 
    207     private final void updateSimState(Intent intent) {
    208         String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
    209         if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
    210             mSimState = IccCard.State.ABSENT;
    211         }
    212         else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
    213             mSimState = IccCard.State.READY;
    214         }
    215         else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
    216             final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
    217             if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
    218                 mSimState = IccCard.State.PIN_REQUIRED;
    219             }
    220             else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
    221                 mSimState = IccCard.State.PUK_REQUIRED;
    222             }
    223             else {
    224                 mSimState = IccCard.State.NETWORK_LOCKED;
    225             }
    226         } else {
    227             mSimState = IccCard.State.UNKNOWN;
    228         }
    229     }
    230 
    231     private final void updateVolume() {
    232         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
    233         final int ringerMode = audioManager.getRingerMode();
    234         final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
    235                 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
    236 
    237         final int iconId;
    238         String contentDescription = null;
    239         if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
    240             iconId = R.drawable.stat_sys_ringer_vibrate;
    241             contentDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
    242         } else {
    243             iconId =  R.drawable.stat_sys_ringer_silent;
    244             contentDescription = mContext.getString(R.string.accessibility_ringer_silent);
    245         }
    246 
    247         if (visible) {
    248             mService.setIcon("volume", iconId, 0, contentDescription);
    249         }
    250         if (visible != mVolumeVisible) {
    251             mService.setIconVisibility("volume", visible);
    252             mVolumeVisible = visible;
    253         }
    254     }
    255 
    256     private final void updateBluetooth(Intent intent) {
    257         int iconId = R.drawable.stat_sys_data_bluetooth;
    258         String contentDescription = null;
    259         String action = intent.getAction();
    260         if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
    261             int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
    262             mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
    263         } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
    264             int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
    265                 BluetoothAdapter.STATE_DISCONNECTED);
    266             if (state == BluetoothAdapter.STATE_CONNECTED) {
    267                 iconId = R.drawable.stat_sys_data_bluetooth_connected;
    268                 contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
    269             } else {
    270                 contentDescription = mContext.getString(
    271                         R.string.accessibility_bluetooth_disconnected);
    272             }
    273         } else {
    274             return;
    275         }
    276 
    277         mService.setIcon("bluetooth", iconId, 0, contentDescription);
    278         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
    279     }
    280 
    281     private final void updateTTY(Intent intent) {
    282         final String action = intent.getAction();
    283         final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
    284 
    285         if (false) Slog.v(TAG, "updateTTY: enabled: " + enabled);
    286 
    287         if (enabled) {
    288             // TTY is on
    289             if (false) Slog.v(TAG, "updateTTY: set TTY on");
    290             mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0,
    291                     mContext.getString(R.string.accessibility_tty_enabled));
    292             mService.setIconVisibility("tty", true);
    293         } else {
    294             // TTY is off
    295             if (false) Slog.v(TAG, "updateTTY: set TTY off");
    296             mService.setIconVisibility("tty", false);
    297         }
    298     }
    299 }
    300