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.IccCardConstants;
     43 import com.android.internal.telephony.TelephonyIntents;
     44 import com.android.internal.telephony.cdma.EriInfo;
     45 import com.android.internal.telephony.cdma.TtyIntent;
     46 import com.android.server.am.BatteryStatsService;
     47 import com.android.systemui.R;
     48 
     49 /**
     50  * This class contains all of the policy about which icons are installed in the status
     51  * bar at boot time.  It goes through the normal API for icons, even though it probably
     52  * strictly doesn't need to.
     53  */
     54 public class PhoneStatusBarPolicy {
     55     private static final String TAG = "PhoneStatusBarPolicy";
     56 
     57     // message codes for the handler
     58     private static final int EVENT_BATTERY_CLOSE = 4;
     59 
     60     private static final int AM_PM_STYLE_NORMAL  = 0;
     61     private static final int AM_PM_STYLE_SMALL   = 1;
     62     private static final int AM_PM_STYLE_GONE    = 2;
     63 
     64     private static final int AM_PM_STYLE = AM_PM_STYLE_GONE;
     65 
     66     private static final int INET_CONDITION_THRESHOLD = 50;
     67 
     68     private static final boolean SHOW_SYNC_ICON = false;
     69 
     70     private final Context mContext;
     71     private final StatusBarManager mService;
     72     private final Handler mHandler = new Handler();
     73 
     74     // storage
     75     private StorageManager mStorageManager;
     76 
     77 
     78     // Assume it's all good unless we hear otherwise.  We don't always seem
     79     // to get broadcasts that it *is* there.
     80     IccCardConstants.State mSimState = IccCardConstants.State.READY;
     81 
     82     // ringer volume
     83     private boolean mVolumeVisible;
     84 
     85     // bluetooth device status
     86     private boolean mBluetoothEnabled = false;
     87 
     88     // wifi
     89     private static final int[][] sWifiSignalImages = {
     90             { R.drawable.stat_sys_wifi_signal_1,
     91               R.drawable.stat_sys_wifi_signal_2,
     92               R.drawable.stat_sys_wifi_signal_3,
     93               R.drawable.stat_sys_wifi_signal_4 },
     94             { R.drawable.stat_sys_wifi_signal_1_fully,
     95               R.drawable.stat_sys_wifi_signal_2_fully,
     96               R.drawable.stat_sys_wifi_signal_3_fully,
     97               R.drawable.stat_sys_wifi_signal_4_fully }
     98         };
     99     private static final int sWifiTemporarilyNotConnectedImage =
    100             R.drawable.stat_sys_wifi_signal_0;
    101 
    102     private int mLastWifiSignalLevel = -1;
    103     private boolean mIsWifiConnected = false;
    104 
    105     // state of inet connection - 0 not connected, 100 connected
    106     private int mInetCondition = 0;
    107 
    108     // sync state
    109     // If sync is active the SyncActive icon is displayed. If sync is not active but
    110     // sync is failing the SyncFailing icon is displayed. Otherwise neither are displayed.
    111 
    112     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
    113         @Override
    114         public void onReceive(Context context, Intent intent) {
    115             String action = intent.getAction();
    116             if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
    117                 updateAlarm(intent);
    118             }
    119             else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
    120                 updateSyncState(intent);
    121             }
    122             else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
    123                     action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
    124                 updateBluetooth(intent);
    125             }
    126             else if (action.equals(AudioManager.RINGER_MODE_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(BluetoothAdapter.ACTION_STATE_CHANGED);
    148         filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
    149         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
    150         filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
    151         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
    152 
    153         // storage
    154         mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
    155         mStorageManager.registerListener(
    156                 new com.android.systemui.usb.StorageNotification(context));
    157 
    158         // TTY status
    159         mService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0, null);
    160         mService.setIconVisibility("tty", false);
    161 
    162         // Cdma Roaming Indicator, ERI
    163         mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null);
    164         mService.setIconVisibility("cdma_eri", false);
    165 
    166         // bluetooth status
    167         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    168         int bluetoothIcon = R.drawable.stat_sys_data_bluetooth;
    169         if (adapter != null) {
    170             mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON);
    171             if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) {
    172                 bluetoothIcon = R.drawable.stat_sys_data_bluetooth_connected;
    173             }
    174         }
    175         mService.setIcon("bluetooth", bluetoothIcon, 0, null);
    176         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
    177 
    178         // Alarm clock
    179         mService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null);
    180         mService.setIconVisibility("alarm_clock", false);
    181 
    182         // Sync state
    183         mService.setIcon("sync_active", R.drawable.stat_sys_sync, 0, null);
    184         mService.setIcon("sync_failing", R.drawable.stat_sys_sync_error, 0, null);
    185         mService.setIconVisibility("sync_active", false);
    186         mService.setIconVisibility("sync_failing", false);
    187 
    188         // volume
    189         mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null);
    190         mService.setIconVisibility("volume", false);
    191         updateVolume();
    192     }
    193 
    194     private final void updateAlarm(Intent intent) {
    195         boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
    196         mService.setIconVisibility("alarm_clock", alarmSet);
    197     }
    198 
    199     private final void updateSyncState(Intent intent) {
    200         if (!SHOW_SYNC_ICON) return;
    201         boolean isActive = intent.getBooleanExtra("active", false);
    202         boolean isFailing = intent.getBooleanExtra("failing", false);
    203         mService.setIconVisibility("sync_active", isActive);
    204         // Don't display sync failing icon: BUG 1297963 Set sync error timeout to "never"
    205         //mService.setIconVisibility("sync_failing", isFailing && !isActive);
    206     }
    207 
    208     private final void updateSimState(Intent intent) {
    209         String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
    210         if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
    211             mSimState = IccCardConstants.State.ABSENT;
    212         }
    213         else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
    214             mSimState = IccCardConstants.State.READY;
    215         }
    216         else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
    217             final String lockedReason =
    218                     intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
    219             if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
    220                 mSimState = IccCardConstants.State.PIN_REQUIRED;
    221             }
    222             else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
    223                 mSimState = IccCardConstants.State.PUK_REQUIRED;
    224             }
    225             else {
    226                 mSimState = IccCardConstants.State.NETWORK_LOCKED;
    227             }
    228         } else {
    229             mSimState = IccCardConstants.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 (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
    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