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