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                     action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
    127                 updateVolume();
    128             }
    129             else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
    130                 updateSimState(intent);
    131             }
    132             else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
    133                 updateTTY(intent);
    134             }
    135         }
    136     };
    137 
    138     public PhoneStatusBarPolicy(Context context) {
    139         mContext = context;
    140         mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
    141 
    142         // listen for broadcasts
    143         IntentFilter filter = new IntentFilter();
    144         filter.addAction(Intent.ACTION_ALARM_CHANGED);
    145         filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
    146         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
    147         filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
    148         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    149         filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
    150         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
    151         filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
    152         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
    153 
    154         // storage
    155         mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
    156         mStorageManager.registerListener(
    157                 new com.android.systemui.usb.StorageNotification(context));
    158 
    159         // TTY status
    160         mService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0, null);
    161         mService.setIconVisibility("tty", false);
    162 
    163         // Cdma Roaming Indicator, ERI
    164         mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null);
    165         mService.setIconVisibility("cdma_eri", false);
    166 
    167         // bluetooth status
    168         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    169         int bluetoothIcon = R.drawable.stat_sys_data_bluetooth;
    170         if (adapter != null) {
    171             mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON);
    172             if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) {
    173                 bluetoothIcon = R.drawable.stat_sys_data_bluetooth_connected;
    174             }
    175         }
    176         mService.setIcon("bluetooth", bluetoothIcon, 0, null);
    177         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
    178 
    179         // Alarm clock
    180         mService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null);
    181         mService.setIconVisibility("alarm_clock", false);
    182 
    183         // Sync state
    184         mService.setIcon("sync_active", R.drawable.stat_sys_sync, 0, null);
    185         mService.setIcon("sync_failing", R.drawable.stat_sys_sync_error, 0, null);
    186         mService.setIconVisibility("sync_active", false);
    187         mService.setIconVisibility("sync_failing", false);
    188 
    189         // volume
    190         mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null);
    191         mService.setIconVisibility("volume", false);
    192         updateVolume();
    193     }
    194 
    195     private final void updateAlarm(Intent intent) {
    196         boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
    197         mService.setIconVisibility("alarm_clock", alarmSet);
    198     }
    199 
    200     private final void updateSyncState(Intent intent) {
    201         if (!SHOW_SYNC_ICON) return;
    202         boolean isActive = intent.getBooleanExtra("active", false);
    203         boolean isFailing = intent.getBooleanExtra("failing", false);
    204         mService.setIconVisibility("sync_active", isActive);
    205         // Don't display sync failing icon: BUG 1297963 Set sync error timeout to "never"
    206         //mService.setIconVisibility("sync_failing", isFailing && !isActive);
    207     }
    208 
    209     private final void updateSimState(Intent intent) {
    210         String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
    211         if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
    212             mSimState = IccCard.State.ABSENT;
    213         }
    214         else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
    215             mSimState = IccCard.State.READY;
    216         }
    217         else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
    218             final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
    219             if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
    220                 mSimState = IccCard.State.PIN_REQUIRED;
    221             }
    222             else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
    223                 mSimState = IccCard.State.PUK_REQUIRED;
    224             }
    225             else {
    226                 mSimState = IccCard.State.NETWORK_LOCKED;
    227             }
    228         } else {
    229             mSimState = IccCard.State.UNKNOWN;
    230         }
    231     }
    232 
    233     private final void updateVolume() {
    234         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
    235         final int ringerMode = audioManager.getRingerMode();
    236         final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
    237                 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
    238 
    239         final int iconId;
    240         String contentDescription = null;
    241         if (audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) {
    242             iconId = R.drawable.stat_sys_ringer_vibrate;
    243             contentDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
    244         } else {
    245             iconId =  R.drawable.stat_sys_ringer_silent;
    246             contentDescription = mContext.getString(R.string.accessibility_ringer_silent);
    247         }
    248 
    249         if (visible) {
    250             mService.setIcon("volume", iconId, 0, contentDescription);
    251         }
    252         if (visible != mVolumeVisible) {
    253             mService.setIconVisibility("volume", visible);
    254             mVolumeVisible = visible;
    255         }
    256     }
    257 
    258     private final void updateBluetooth(Intent intent) {
    259         int iconId = R.drawable.stat_sys_data_bluetooth;
    260         String contentDescription = null;
    261         String action = intent.getAction();
    262         if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
    263             int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
    264             mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
    265         } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
    266             int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
    267                 BluetoothAdapter.STATE_DISCONNECTED);
    268             if (state == BluetoothAdapter.STATE_CONNECTED) {
    269                 iconId = R.drawable.stat_sys_data_bluetooth_connected;
    270                 contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
    271             } else {
    272                 contentDescription = mContext.getString(
    273                         R.string.accessibility_bluetooth_disconnected);
    274             }
    275         } else {
    276             return;
    277         }
    278 
    279         mService.setIcon("bluetooth", iconId, 0, contentDescription);
    280         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
    281     }
    282 
    283     private final void updateTTY(Intent intent) {
    284         final String action = intent.getAction();
    285         final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
    286 
    287         if (false) Slog.v(TAG, "updateTTY: enabled: " + enabled);
    288 
    289         if (enabled) {
    290             // TTY is on
    291             if (false) Slog.v(TAG, "updateTTY: set TTY on");
    292             mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0,
    293                     mContext.getString(R.string.accessibility_tty_enabled));
    294             mService.setIconVisibility("tty", true);
    295         } else {
    296             // TTY is off
    297             if (false) Slog.v(TAG, "updateTTY: set TTY off");
    298             mService.setIconVisibility("tty", false);
    299         }
    300     }
    301 }
    302