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 17package com.android.systemui.statusbar.phone; 18 19import android.app.StatusBarManager; 20import android.bluetooth.BluetoothAdapter; 21import android.content.BroadcastReceiver; 22import android.content.Context; 23import android.content.Intent; 24import android.content.IntentFilter; 25import android.location.LocationManager; 26import android.media.AudioManager; 27import android.net.ConnectivityManager; 28import android.net.NetworkInfo; 29import android.net.wifi.WifiManager; 30import android.os.Binder; 31import android.os.Handler; 32import android.os.RemoteException; 33import android.os.storage.StorageManager; 34import android.provider.Settings; 35import android.telephony.PhoneStateListener; 36import android.telephony.ServiceState; 37import android.telephony.SignalStrength; 38import android.telephony.TelephonyManager; 39import android.util.Slog; 40 41import com.android.internal.telephony.IccCard; 42import com.android.internal.telephony.TelephonyIntents; 43import com.android.internal.telephony.cdma.EriInfo; 44import com.android.internal.telephony.cdma.TtyIntent; 45import com.android.server.am.BatteryStatsService; 46import 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 */ 53public 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