blob: b90897bd43fbda174410ae66ad89e31521b14ed3 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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.server.status;
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019import android.app.AlertDialog;
20import android.bluetooth.BluetoothA2dp;
Nick Pellybd022f42009-08-14 18:33:38 -070021import android.bluetooth.BluetoothAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.bluetooth.BluetoothHeadset;
Jiafa Liu3f416732009-07-02 16:36:02 +080023import android.bluetooth.BluetoothPbap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.BroadcastReceiver;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050025import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.content.Context;
27import android.content.DialogInterface;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.res.TypedArray;
31import android.graphics.PixelFormat;
Daniel Sandler2c195f72010-05-21 15:42:06 -040032import android.graphics.Typeface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.graphics.drawable.Drawable;
Mike Lockwood00b74272010-03-26 10:41:48 -040034import android.location.LocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.media.AudioManager;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050036import android.media.Ringtone;
37import android.media.RingtoneManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.net.NetworkInfo;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050039import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.net.wifi.WifiManager;
Dianne Hackborn4840e142009-03-24 22:40:29 -070041import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.os.Message;
Dianne Hackborn4840e142009-03-24 22:40:29 -070044import android.os.RemoteException;
San Mehat4154c072010-02-09 18:37:54 -080045import android.os.storage.StorageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.provider.Settings;
47import android.telephony.PhoneStateListener;
48import android.telephony.ServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -070049import android.telephony.SignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.telephony.TelephonyManager;
51import android.text.format.DateFormat;
Daniel Sandler2c195f72010-05-21 15:42:06 -040052import android.text.style.CharacterStyle;
Eric Fischer36e136c2010-01-14 17:42:48 -080053import android.text.style.RelativeSizeSpan;
Daniel Sandler2c195f72010-05-21 15:42:06 -040054import android.text.style.ForegroundColorSpan;
55import android.text.style.StyleSpan;
Eric Fischer36e136c2010-01-14 17:42:48 -080056import android.text.Spannable;
57import android.text.SpannableStringBuilder;
Joe Onorato8a9b2202010-02-26 18:56:32 -080058import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.view.View;
60import android.view.ViewGroup;
61import android.view.WindowManager;
62import android.view.WindowManagerImpl;
63import android.widget.ImageView;
64import android.widget.LinearLayout;
65import android.widget.TextView;
66
Wink Saville04e71b32009-04-02 11:00:54 -070067import com.android.internal.R;
68import com.android.internal.app.IBatteryStats;
Wink Saville04e71b32009-04-02 11:00:54 -070069import com.android.internal.telephony.IccCard;
70import com.android.internal.telephony.TelephonyIntents;
Wink Savillee9b06d72009-05-18 21:47:50 -070071import com.android.internal.telephony.cdma.EriInfo;
Wink Saville04e71b32009-04-02 11:00:54 -070072import com.android.internal.telephony.cdma.TtyIntent;
73import com.android.server.am.BatteryStatsService;
74
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075/**
76 * This class contains all of the policy about which icons are installed in the status
77 * bar at boot time. In reality, it should go into the android.policy package, but
78 * putting it here is the first step from extracting it.
79 */
80public class StatusBarPolicy {
81 private static final String TAG = "StatusBarPolicy";
82
83 private static StatusBarPolicy sInstance;
84
85 // message codes for the handler
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 private static final int EVENT_BATTERY_CLOSE = 4;
87
Daniel Sandler2c195f72010-05-21 15:42:06 -040088 private static final int AM_PM_STYLE_NORMAL = 0;
89 private static final int AM_PM_STYLE_SMALL = 1;
90 private static final int AM_PM_STYLE_GONE = 2;
91
92 private static final int AM_PM_STYLE = AM_PM_STYLE_GONE;
93
Dianne Hackborn4840e142009-03-24 22:40:29 -070094 private final Context mContext;
Joe Onorato089de882010-04-12 08:18:45 -070095 private final StatusBarManagerService mService;
Dianne Hackborn4840e142009-03-24 22:40:29 -070096 private final Handler mHandler = new StatusBarHandler();
97 private final IBatteryStats mBatteryStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098
San Mehat4154c072010-02-09 18:37:54 -080099 // storage
100 private StorageManager mStorageManager;
101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 // battery
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 private boolean mBatteryFirst = true;
104 private boolean mBatteryPlugged;
105 private int mBatteryLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 private AlertDialog mLowBatteryDialog;
107 private TextView mBatteryLevelTextView;
108 private View mBatteryView;
109 private int mBatteryViewSequence;
110 private boolean mBatteryShowLowOnEndCall = false;
111 private static final boolean SHOW_LOW_BATTERY_WARNING = true;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500112 private static final boolean SHOW_BATTERY_WARNINGS_IN_CALL = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113
114 // phone
115 private TelephonyManager mPhone;
Joe Onorato0cbda992010-05-02 16:28:15 -0700116 private int mPhoneSignalIconId;
Wink Saville04e71b32009-04-02 11:00:54 -0700117
118 //***** Signal strength icons
Wink Saville04e71b32009-04-02 11:00:54 -0700119 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 private static final int[] sSignalImages = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700121 com.android.internal.R.drawable.stat_sys_signal_0,
122 com.android.internal.R.drawable.stat_sys_signal_1,
123 com.android.internal.R.drawable.stat_sys_signal_2,
124 com.android.internal.R.drawable.stat_sys_signal_3,
125 com.android.internal.R.drawable.stat_sys_signal_4
126 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 private static final int[] sSignalImages_r = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700128 com.android.internal.R.drawable.stat_sys_r_signal_0,
129 com.android.internal.R.drawable.stat_sys_r_signal_1,
130 com.android.internal.R.drawable.stat_sys_r_signal_2,
131 com.android.internal.R.drawable.stat_sys_r_signal_3,
132 com.android.internal.R.drawable.stat_sys_r_signal_4
133 };
Wink Savillee9b06d72009-05-18 21:47:50 -0700134 private static final int[] sRoamingIndicatorImages_cdma = new int[] {
135 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
136 // 1 is Standard Roaming Indicator OFF
137 // TODO T: image never used, remove and put 0 instead?
138 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
139
140 // 2 is Standard Roaming Indicator FLASHING
141 // TODO T: image never used, remove and put 0 instead?
142 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
143
144 // 3-12 Standard ERI
145 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //3
146 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
147 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
148 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
149 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
150 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
151 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
152 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
153 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
154 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
155
156 // 13-63 Reserved for Standard ERI
157 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //13
158 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
159 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
160 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
161 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
162 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
163 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
164 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
165 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
166 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
167 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
168 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
169 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
170 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
171 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
172 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
173 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
174 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
175 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
176 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
177 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
178 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
179 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
180 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
181 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
182 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
183 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
184 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
185 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
186 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
187 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
188 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
189 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
190 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
191 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
192 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
193 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
194 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
195 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
196 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
197 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
198 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
199 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
200 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
201 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
202 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
203 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
204 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
205 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
206 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
207 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
208
209 // 64-127 Reserved for Non Standard (Operator Specific) ERI
210 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //64
211 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
212 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
213 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
214 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
215 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
216 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
217 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
218 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
219 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
220 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
221 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
222 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
223 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
224 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
225 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
226 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
227 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
228 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
229 com.android.internal.R.drawable.stat_sys_roaming_cdma_0 //83
230
231 // 128-255 Reserved
Wink Saville04e71b32009-04-02 11:00:54 -0700232 };
Wink Saville04e71b32009-04-02 11:00:54 -0700233
234 //***** Data connection icons
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 private int[] mDataIconList = sDataNetType_g;
Wink Saville04e71b32009-04-02 11:00:54 -0700236 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 private static final int[] sDataNetType_g = new int[] {
238 com.android.internal.R.drawable.stat_sys_data_connected_g,
239 com.android.internal.R.drawable.stat_sys_data_in_g,
240 com.android.internal.R.drawable.stat_sys_data_out_g,
241 com.android.internal.R.drawable.stat_sys_data_inandout_g,
242 };
243 private static final int[] sDataNetType_3g = new int[] {
244 com.android.internal.R.drawable.stat_sys_data_connected_3g,
245 com.android.internal.R.drawable.stat_sys_data_in_3g,
246 com.android.internal.R.drawable.stat_sys_data_out_3g,
247 com.android.internal.R.drawable.stat_sys_data_inandout_3g,
248 };
249 private static final int[] sDataNetType_e = new int[] {
250 com.android.internal.R.drawable.stat_sys_data_connected_e,
251 com.android.internal.R.drawable.stat_sys_data_in_e,
252 com.android.internal.R.drawable.stat_sys_data_out_e,
253 com.android.internal.R.drawable.stat_sys_data_inandout_e,
254 };
Li Zheebe66342009-08-14 19:22:16 +0800255 //3.5G
256 private static final int[] sDataNetType_h = new int[] {
257 com.android.internal.R.drawable.stat_sys_data_connected_h,
258 com.android.internal.R.drawable.stat_sys_data_in_h,
259 com.android.internal.R.drawable.stat_sys_data_out_h,
260 com.android.internal.R.drawable.stat_sys_data_inandout_h,
261 };
262
Wink Saville04e71b32009-04-02 11:00:54 -0700263 //CDMA
johnwang9f87cb22009-08-25 15:25:37 -0700264 // Use 3G icons for EVDO data and 1x icons for 1XRTT data
265 private static final int[] sDataNetType_1x = new int[] {
266 com.android.internal.R.drawable.stat_sys_data_connected_1x,
267 com.android.internal.R.drawable.stat_sys_data_in_1x,
268 com.android.internal.R.drawable.stat_sys_data_out_1x,
269 com.android.internal.R.drawable.stat_sys_data_inandout_1x,
Wink Saville04e71b32009-04-02 11:00:54 -0700270 };
271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 // Assume it's all good unless we hear otherwise. We don't always seem
273 // to get broadcasts that it *is* there.
Wink Saville04e71b32009-04-02 11:00:54 -0700274 IccCard.State mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
276 int mDataState = TelephonyManager.DATA_DISCONNECTED;
277 int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
278 ServiceState mServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -0700279 SignalStrength mSignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280
281 // data connection
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 private boolean mDataIconVisible;
John Wang33e21fc2009-10-08 10:35:27 -0700283 private boolean mHspaDataDistinguishable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
285 // ringer volume
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 private boolean mVolumeVisible;
Wink Saville04e71b32009-04-02 11:00:54 -0700287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 // bluetooth device status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 private int mBluetoothHeadsetState;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800290 private boolean mBluetoothA2dpConnected;
Jiafa Liu3f416732009-07-02 16:36:02 +0800291 private int mBluetoothPbapState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 private boolean mBluetoothEnabled;
293
294 // wifi
295 private static final int[] sWifiSignalImages = new int[] {
296 com.android.internal.R.drawable.stat_sys_wifi_signal_1,
297 com.android.internal.R.drawable.stat_sys_wifi_signal_2,
298 com.android.internal.R.drawable.stat_sys_wifi_signal_3,
299 com.android.internal.R.drawable.stat_sys_wifi_signal_4,
300 };
301 private static final int sWifiTemporarilyNotConnectedImage =
302 com.android.internal.R.drawable.stat_sys_wifi_signal_0;
303
304 private int mLastWifiSignalLevel = -1;
305 private boolean mIsWifiConnected = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306
307 // sync state
308 // If sync is active the SyncActive icon is displayed. If sync is not active but
309 // sync is failing the SyncFailing icon is displayed. Otherwise neither are displayed.
Wink Savillee9b06d72009-05-18 21:47:50 -0700310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
312 @Override
313 public void onReceive(Context context, Intent intent) {
314 String action = intent.getAction();
Joe Onorato263700d2010-05-14 11:54:53 -0700315 if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700316 updateBattery(intent);
317 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 else if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
319 updateAlarm(intent);
320 }
321 else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
322 updateSyncState(intent);
323 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200324 else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
325 onBatteryLow(intent);
326 }
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400327 else if (action.equals(Intent.ACTION_BATTERY_OKAY)
328 || action.equals(Intent.ACTION_POWER_CONNECTED)) {
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700329 onBatteryOkay(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 }
Nick Pellyde893f52009-09-08 13:15:33 -0700331 else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
Nick Pelly005b2282009-09-10 10:21:56 -0700332 action.equals(BluetoothHeadset.ACTION_STATE_CHANGED) ||
333 action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED) ||
Jiafa Liu3f416732009-07-02 16:36:02 +0800334 action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 updateBluetooth(intent);
336 }
337 else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
338 action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) ||
339 action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
340 updateWifi(intent);
341 }
Mike Lockwood00b74272010-03-26 10:41:48 -0400342 else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) ||
343 action.equals(LocationManager.GPS_FIX_CHANGE_ACTION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 updateGps(intent);
345 }
346 else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
347 action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
348 updateVolume();
349 }
350 else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
351 updateSimState(intent);
352 }
Wink Saville04e71b32009-04-02 11:00:54 -0700353 else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
354 updateTTY(intent);
355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 }
357 };
358
Joe Onorato089de882010-04-12 08:18:45 -0700359 private StatusBarPolicy(Context context, StatusBarManagerService service) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360 mContext = context;
361 mService = service;
Wink Savillee9b06d72009-05-18 21:47:50 -0700362 mSignalStrength = new SignalStrength();
Dianne Hackborn4840e142009-03-24 22:40:29 -0700363 mBatteryStats = BatteryStatsService.getService();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364
San Mehat4154c072010-02-09 18:37:54 -0800365 // storage
366 mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
367 mStorageManager.registerListener(
368 new com.android.server.status.StorageNotification(context));
369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 // battery
Joe Onorato0cbda992010-05-02 16:28:15 -0700371 service.setIcon("battery",
372 null, com.android.internal.R.drawable.stat_sys_battery_unknown, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373
374 // phone_signal
375 mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Joe Onorato0cbda992010-05-02 16:28:15 -0700376 mPhoneSignalIconId = com.android.internal.R.drawable.stat_sys_signal_null;
377 service.setIcon("phone_signal", null, mPhoneSignalIconId, 0);
Wink Savillee9b06d72009-05-18 21:47:50 -0700378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 // register for phone state notifications.
380 ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
381 .listen(mPhoneStateListener,
382 PhoneStateListener.LISTEN_SERVICE_STATE
Wink Savillee9b06d72009-05-18 21:47:50 -0700383 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 | PhoneStateListener.LISTEN_CALL_STATE
385 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
386 | PhoneStateListener.LISTEN_DATA_ACTIVITY);
387
388 // data_connection
Joe Onorato0cbda992010-05-02 16:28:15 -0700389 service.setIcon("data_connection",
390 null, com.android.internal.R.drawable.stat_sys_data_connected_g, 0);
391 service.setIconVisibility("data_connection", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392
393 // wifi
Joe Onorato0cbda992010-05-02 16:28:15 -0700394 service.setIcon("wifi", null, sWifiSignalImages[0], 0);
395 service.setIconVisibility("wifi", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 // wifi will get updated by the sticky intents
Wink Saville04e71b32009-04-02 11:00:54 -0700397
398 // TTY status
Joe Onorato0cbda992010-05-02 16:28:15 -0700399 service.setIcon("tty", null, com.android.internal.R.drawable.stat_sys_tty_mode, 0);
400 service.setIconVisibility("tty", false);
Wink Saville04e71b32009-04-02 11:00:54 -0700401
Wink Savillee9b06d72009-05-18 21:47:50 -0700402 // Cdma Roaming Indicator, ERI
Joe Onorato0cbda992010-05-02 16:28:15 -0700403 service.setIcon("cdma_eri",
404 null, com.android.internal.R.drawable.stat_sys_roaming_cdma_0, 0);
405 service.setIconVisibility("cdma_eri", false);
Wink Savillee9b06d72009-05-18 21:47:50 -0700406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 // bluetooth status
Joe Onorato0cbda992010-05-02 16:28:15 -0700408 service.setIcon("bluetooth",
409 null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200410 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Nick Pellybd022f42009-08-14 18:33:38 -0700411 if (adapter != null) {
412 mBluetoothEnabled = adapter.isEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 } else {
414 mBluetoothEnabled = false;
415 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800416 mBluetoothA2dpConnected = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 mBluetoothHeadsetState = BluetoothHeadset.STATE_DISCONNECTED;
Jiafa Liu3f416732009-07-02 16:36:02 +0800418 mBluetoothPbapState = BluetoothPbap.STATE_DISCONNECTED;
Joe Onorato0cbda992010-05-02 16:28:15 -0700419 mService.setIconVisibility("bluetooth", mBluetoothEnabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420
421 // Gps status
Joe Onorato0cbda992010-05-02 16:28:15 -0700422 service.setIcon("gps",
423 null, com.android.internal.R.drawable.stat_sys_gps_acquiring_anim, 0);
424 service.setIconVisibility("gps", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425
426 // Alarm clock
Joe Onorato0cbda992010-05-02 16:28:15 -0700427 service.setIcon("alarm_clock", null, com.android.internal.R.drawable.stat_notify_alarm, 0);
428 service.setIconVisibility("alarm_clock", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429
430 // Sync state
Joe Onorato0cbda992010-05-02 16:28:15 -0700431 service.setIcon("sync_active", null, R.drawable.stat_notify_sync_anim0, 0);
432 service.setIcon("sync_failing", null, R.drawable.stat_notify_sync_error, 0);
433 service.setIconVisibility("sync_active", false);
434 service.setIconVisibility("sync_failing", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435
436 // volume
Joe Onorato0cbda992010-05-02 16:28:15 -0700437 service.setIcon("volume", null, com.android.internal.R.drawable.stat_sys_ringer_silent, 0);
438 service.setIconVisibility("volume", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 updateVolume();
johnwang347c5a22009-08-24 22:11:11 -0700440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 IntentFilter filter = new IntentFilter();
442
443 // Register for Intent broadcasts for...
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Mihai Predaa82842f2009-04-29 15:05:56 +0200445 filter.addAction(Intent.ACTION_BATTERY_LOW);
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700446 filter.addAction(Intent.ACTION_BATTERY_OKAY);
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400447 filter.addAction(Intent.ACTION_POWER_CONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 filter.addAction(Intent.ACTION_ALARM_CHANGED);
449 filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
450 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
451 filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
Nick Pellyde893f52009-09-08 13:15:33 -0700452 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Nick Pelly005b2282009-09-10 10:21:56 -0700453 filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
454 filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
Jiafa Liu3f416732009-07-02 16:36:02 +0800455 filter.addAction(BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
457 filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
458 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
459 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
Mike Lockwood00b74272010-03-26 10:41:48 -0400460 filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION);
461 filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Wink Saville04e71b32009-04-02 11:00:54 -0700463 filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
John Wang33e21fc2009-10-08 10:35:27 -0700465
466 // load config to determine if to distinguish Hspa data icon
467 try {
468 mHspaDataDistinguishable = mContext.getResources().getBoolean(
469 com.android.internal.R.bool.config_hspa_data_distinguishable);
470 } catch (Exception e) {
471 mHspaDataDistinguishable = false;
472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 }
474
Joe Onorato089de882010-04-12 08:18:45 -0700475 public static void installIcons(Context context, StatusBarManagerService service) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 sInstance = new StatusBarPolicy(context, service);
477 }
478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 private final void updateAlarm(Intent intent) {
480 boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
Joe Onorato0cbda992010-05-02 16:28:15 -0700481 mService.setIconVisibility("alarm_clock", alarmSet);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 }
483
484 private final void updateSyncState(Intent intent) {
485 boolean isActive = intent.getBooleanExtra("active", false);
486 boolean isFailing = intent.getBooleanExtra("failing", false);
Joe Onorato0cbda992010-05-02 16:28:15 -0700487 mService.setIconVisibility("sync_active", isActive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488 // Don't display sync failing icon: BUG 1297963 Set sync error timeout to "never"
Joe Onorato0cbda992010-05-02 16:28:15 -0700489 //mService.setIconVisibility("sync_failing", isFailing && !isActive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 }
491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 private final void updateBattery(Intent intent) {
Joe Onorato0cbda992010-05-02 16:28:15 -0700493 final int id = intent.getIntExtra("icon-small", 0);
494 int level = intent.getIntExtra("level", 0);
495 mService.setIcon("battery", null, id, level);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496
497 boolean plugged = intent.getIntExtra("plugged", 0) != 0;
Joe Onorato0cbda992010-05-02 16:28:15 -0700498 level = intent.getIntExtra("level", -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800500 Slog.d(TAG, "updateBattery level=" + level
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 + " plugged=" + plugged
502 + " mBatteryPlugged=" + mBatteryPlugged
503 + " mBatteryLevel=" + mBatteryLevel
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 + " mBatteryFirst=" + mBatteryFirst);
505 }
506
507 boolean oldPlugged = mBatteryPlugged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508
509 mBatteryPlugged = plugged;
510 mBatteryLevel = level;
511
512 if (mBatteryFirst) {
513 mBatteryFirst = false;
514 }
515 /*
516 * No longer showing the battery view because it draws attention away
517 * from the USB storage notification. We could still show it when
518 * connected to a brick, but that could lead to the user into thinking
519 * the device does not charge when plugged into USB (since he/she would
520 * not see the same battery screen on USB as he sees on brick).
521 */
522 /* else {
523 if (plugged && !oldPlugged) {
524 showBatteryView();
525 }
526 }
527 */
528 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800529 Slog.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532
Mihai Predaa82842f2009-04-29 15:05:56 +0200533 private void onBatteryLow(Intent intent) {
534 if (SHOW_LOW_BATTERY_WARNING) {
535 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800536 Slog.d(TAG, "mPhoneState=" + mPhoneState
Mihai Predaa82842f2009-04-29 15:05:56 +0200537 + " mLowBatteryDialog=" + mLowBatteryDialog
538 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200540
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500541 if (SHOW_BATTERY_WARNINGS_IN_CALL || mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
Mihai Predaa82842f2009-04-29 15:05:56 +0200542 showLowBatteryWarning();
543 } else {
544 mBatteryShowLowOnEndCall = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 }
546 }
547 }
548
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700549 private void onBatteryOkay(Intent intent) {
550 if (mLowBatteryDialog != null
551 && SHOW_LOW_BATTERY_WARNING) {
552 mLowBatteryDialog.dismiss();
553 mBatteryShowLowOnEndCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 }
555 }
556
johnwang347c5a22009-08-24 22:11:11 -0700557 private void showBatteryView() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 closeLastBatteryView();
559 if (mLowBatteryDialog != null) {
560 mLowBatteryDialog.dismiss();
561 }
562
563 int level = mBatteryLevel;
564
565 View v = View.inflate(mContext, com.android.internal.R.layout.battery_status, null);
566 mBatteryView = v;
567 int pixelFormat = PixelFormat.TRANSLUCENT;
568 Drawable bg = v.getBackground();
569 if (bg != null) {
570 pixelFormat = bg.getOpacity();
571 }
572
Dianne Hackborn568cae52009-10-07 16:13:39 -0700573 int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
574 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
575 | WindowManager.LayoutParams.FLAG_DIM_BEHIND;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800576
Dianne Hackborn568cae52009-10-07 16:13:39 -0700577 if (!mContext.getResources().getBoolean(
578 com.android.internal.R.bool.config_sf_slowBlur)) {
579 flags |= WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
580 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
583 ViewGroup.LayoutParams.WRAP_CONTENT,
584 ViewGroup.LayoutParams.WRAP_CONTENT,
585 WindowManager.LayoutParams.TYPE_TOAST,
Dianne Hackborn568cae52009-10-07 16:13:39 -0700586 flags, pixelFormat);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587
588 // Get the dim amount from the theme
589 TypedArray a = mContext.obtainStyledAttributes(
590 com.android.internal.R.styleable.Theme);
591 lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
592 a.recycle();
Wink Saville04e71b32009-04-02 11:00:54 -0700593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 lp.setTitle("Battery");
595
596 TextView levelTextView = (TextView)v.findViewById(com.android.internal.R.id.level_percent);
597 levelTextView.setText(mContext.getString(
598 com.android.internal.R.string.battery_status_text_percent_format, level));
599
600 setBatteryLevel(v, com.android.internal.R.id.spacer, 100-level, 0, 0);
601 setBatteryLevel(v, com.android.internal.R.id.level, level,
602 com.android.internal.R.drawable.battery_charge_fill, level);
603
604 WindowManagerImpl.getDefault().addView(v, lp);
605
606 scheduleCloseBatteryView();
607 }
608
609 private void setBatteryLevel(View parent, int id, int height, int background, int level) {
610 ImageView v = (ImageView)parent.findViewById(id);
611 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)v.getLayoutParams();
612 lp.weight = height;
613 if (background != 0) {
614 v.setBackgroundResource(background);
615 Drawable bkg = v.getBackground();
616 bkg.setLevel(level);
617 }
618 }
619
620 private void showLowBatteryWarning() {
621 closeLastBatteryView();
622
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400623 // Show exact battery level.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 CharSequence levelText = mContext.getString(
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400625 com.android.internal.R.string.battery_low_percent_format, mBatteryLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626
627 if (mBatteryLevelTextView != null) {
628 mBatteryLevelTextView.setText(levelText);
629 } else {
630 View v = View.inflate(mContext, com.android.internal.R.layout.battery_low, null);
631 mBatteryLevelTextView=(TextView)v.findViewById(com.android.internal.R.id.level_percent);
632
633 mBatteryLevelTextView.setText(levelText);
634
635 AlertDialog.Builder b = new AlertDialog.Builder(mContext);
636 b.setCancelable(true);
637 b.setTitle(com.android.internal.R.string.battery_low_title);
638 b.setView(v);
639 b.setIcon(android.R.drawable.ic_dialog_alert);
640 b.setPositiveButton(android.R.string.ok, null);
johnwang347c5a22009-08-24 22:11:11 -0700641
Dianne Hackborn3d74bb42009-06-19 10:35:21 -0700642 final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
643 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
644 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
645 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
646 | Intent.FLAG_ACTIVITY_NO_HISTORY);
647 if (intent.resolveActivity(mContext.getPackageManager()) != null) {
648 b.setNegativeButton(com.android.internal.R.string.battery_low_why,
649 new DialogInterface.OnClickListener() {
650 public void onClick(DialogInterface dialog, int which) {
651 mContext.startActivity(intent);
652 if (mLowBatteryDialog != null) {
653 mLowBatteryDialog.dismiss();
654 }
655 }
656 });
657 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658
659 AlertDialog d = b.create();
660 d.setOnDismissListener(mLowBatteryListener);
661 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
662 d.show();
663 mLowBatteryDialog = d;
664 }
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500665
666 final ContentResolver cr = mContext.getContentResolver();
667 if (Settings.System.getInt(cr,
John Wang56c2d2f2010-04-07 08:57:17 -0700668 Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500669 {
670 final String soundPath = Settings.System.getString(cr,
671 Settings.System.LOW_BATTERY_SOUND);
672 if (soundPath != null) {
673 final Uri soundUri = Uri.parse("file://" + soundPath);
674 if (soundUri != null) {
675 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
Daniel Sandlerec2c88d2010-02-20 01:04:57 -0500676 if (sfx != null) {
677 sfx.setStreamType(AudioManager.STREAM_SYSTEM);
678 sfx.play();
679 }
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500680 }
681 }
682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 }
684
685 private final void updateCallState(int state) {
686 mPhoneState = state;
687 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800688 Slog.d(TAG, "mPhoneState=" + mPhoneState
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 + " mLowBatteryDialog=" + mLowBatteryDialog
690 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
691 }
692 if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
693 if (mBatteryShowLowOnEndCall) {
694 if (!mBatteryPlugged) {
695 showLowBatteryWarning();
696 }
697 mBatteryShowLowOnEndCall = false;
698 }
699 } else {
700 if (mLowBatteryDialog != null) {
701 mLowBatteryDialog.dismiss();
702 mBatteryShowLowOnEndCall = true;
703 }
704 }
705 }
706
707 private DialogInterface.OnDismissListener mLowBatteryListener
708 = new DialogInterface.OnDismissListener() {
709 public void onDismiss(DialogInterface dialog) {
710 mLowBatteryDialog = null;
711 mBatteryLevelTextView = null;
712 }
713 };
714
715 private void scheduleCloseBatteryView() {
716 Message m = mHandler.obtainMessage(EVENT_BATTERY_CLOSE);
717 m.arg1 = (++mBatteryViewSequence);
718 mHandler.sendMessageDelayed(m, 3000);
719 }
720
721 private void closeLastBatteryView() {
722 if (mBatteryView != null) {
723 //mBatteryView.debug();
724 WindowManagerImpl.getDefault().removeView(mBatteryView);
725 mBatteryView = null;
726 }
727 }
728
729 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
730 @Override
Wink Savillee9b06d72009-05-18 21:47:50 -0700731 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
732 mSignalStrength = signalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 updateSignalStrength();
734 }
735
736 @Override
737 public void onServiceStateChanged(ServiceState state) {
738 mServiceState = state;
739 updateSignalStrength();
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700740 updateCdmaRoamingIcon(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 updateDataIcon();
742 }
743
744 @Override
745 public void onCallStateChanged(int state, String incomingNumber) {
746 updateCallState(state);
johnwang347c5a22009-08-24 22:11:11 -0700747 // In cdma, if a voice call is made, RSSI should switch to 1x.
748 if (isCdma()) {
749 updateSignalStrength();
750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751 }
752
753 @Override
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700754 public void onDataConnectionStateChanged(int state, int networkType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 mDataState = state;
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700756 updateDataNetType(networkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 updateDataIcon();
758 }
759
760 @Override
761 public void onDataActivity(int direction) {
762 mDataActivity = direction;
763 updateDataIcon();
764 }
765 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766
767 private final void updateSimState(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -0700768 String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
769 if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
770 mSimState = IccCard.State.ABSENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 }
Wink Saville04e71b32009-04-02 11:00:54 -0700772 else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
773 mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 }
Wink Saville04e71b32009-04-02 11:00:54 -0700775 else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
776 final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
777 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
778 mSimState = IccCard.State.PIN_REQUIRED;
johnwang347c5a22009-08-24 22:11:11 -0700779 }
Wink Saville04e71b32009-04-02 11:00:54 -0700780 else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
781 mSimState = IccCard.State.PUK_REQUIRED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 }
783 else {
Wink Saville04e71b32009-04-02 11:00:54 -0700784 mSimState = IccCard.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 }
786 } else {
Wink Saville04e71b32009-04-02 11:00:54 -0700787 mSimState = IccCard.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 }
789 updateDataIcon();
790 }
791
Wink Savillee9b06d72009-05-18 21:47:50 -0700792 private boolean isCdma() {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700793 return (mSignalStrength != null) && !mSignalStrength.isGsm();
Wink Savillee9b06d72009-05-18 21:47:50 -0700794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795
johnwang347c5a22009-08-24 22:11:11 -0700796 private boolean isEvdo() {
797 return ( (mServiceState != null)
798 && ((mServiceState.getRadioTechnology()
799 == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
800 || (mServiceState.getRadioTechnology()
Naveen Kalla0a5174a2010-04-21 14:48:03 -0700801 == ServiceState.RADIO_TECHNOLOGY_EVDO_A)
802 || (mServiceState.getRadioTechnology()
803 == ServiceState.RADIO_TECHNOLOGY_EVDO_B)));
johnwang347c5a22009-08-24 22:11:11 -0700804 }
805
Wink Savillee9b06d72009-05-18 21:47:50 -0700806 private boolean hasService() {
807 if (mServiceState != null) {
808 switch (mServiceState.getState()) {
809 case ServiceState.STATE_OUT_OF_SERVICE:
810 case ServiceState.STATE_POWER_OFF:
811 return false;
812 default:
813 return true;
814 }
815 } else {
816 return false;
817 }
818 }
819
820 private final void updateSignalStrength() {
821 int iconLevel = -1;
Wink Savillee9b06d72009-05-18 21:47:50 -0700822 int[] iconList;
Wink Savillee9b06d72009-05-18 21:47:50 -0700823
John Wang56c2d2f2010-04-07 08:57:17 -0700824 // Display signal strength while in "emergency calls only" mode
825 if (!hasService() && !mServiceState.isEmergencyOnly()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800826 //Slog.d(TAG, "updateSignalStrength: no service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 if (Settings.System.getInt(mContext.getContentResolver(),
828 Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
Joe Onorato0cbda992010-05-02 16:28:15 -0700829 mPhoneSignalIconId = com.android.internal.R.drawable.stat_sys_signal_flightmode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 } else {
Joe Onorato0cbda992010-05-02 16:28:15 -0700831 mPhoneSignalIconId = com.android.internal.R.drawable.stat_sys_signal_null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 }
Joe Onorato0cbda992010-05-02 16:28:15 -0700833 mService.setIcon("phone_signal", null, mPhoneSignalIconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 return;
835 }
836
Wink Savillee9b06d72009-05-18 21:47:50 -0700837 if (!isCdma()) {
838 int asu = mSignalStrength.getGsmSignalStrength();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839
Wink Savillee9b06d72009-05-18 21:47:50 -0700840 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
841 // asu = 0 (-113dB or less) is very weak
842 // signal, its better to show 0 bars to the user in such cases.
843 // asu = 99 is a special case, where the signal strength is unknown.
jshee63e472010-03-18 11:14:42 -0700844 if (asu <= 2 || asu == 99) iconLevel = 0;
845 else if (asu >= 12) iconLevel = 4;
Wink Savillee9b06d72009-05-18 21:47:50 -0700846 else if (asu >= 8) iconLevel = 3;
jshee63e472010-03-18 11:14:42 -0700847 else if (asu >= 5) iconLevel = 2;
Wink Savillee9b06d72009-05-18 21:47:50 -0700848 else iconLevel = 1;
849
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700850 // Though mPhone is a Manager, this call is not an IPC
Wink Savillee9b06d72009-05-18 21:47:50 -0700851 if (mPhone.isNetworkRoaming()) {
852 iconList = sSignalImages_r;
853 } else {
854 iconList = sSignalImages;
Wink Saville04e71b32009-04-02 11:00:54 -0700855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 } else {
johnwang347c5a22009-08-24 22:11:11 -0700857 iconList = this.sSignalImages;
Wink Savillee9b06d72009-05-18 21:47:50 -0700858
johnwang347c5a22009-08-24 22:11:11 -0700859 // If 3G(EV) and 1x network are available than 3G should be
860 // displayed, displayed RSSI should be from the EV side.
861 // If a voice call is made then RSSI should switch to 1x.
862 if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
863 iconLevel = getEvdoLevel();
864 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800865 Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level=" + getCdmaLevel());
johnwang347c5a22009-08-24 22:11:11 -0700866 }
867 } else {
868 iconLevel = getCdmaLevel();
869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 }
Joe Onorato0cbda992010-05-02 16:28:15 -0700871 mPhoneSignalIconId = iconList[iconLevel];
872 mService.setIcon("phone_signal", null, mPhoneSignalIconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 }
874
johnwang347c5a22009-08-24 22:11:11 -0700875 private int getCdmaLevel() {
876 final int cdmaDbm = mSignalStrength.getCdmaDbm();
877 final int cdmaEcio = mSignalStrength.getCdmaEcio();
878 int levelDbm = 0;
879 int levelEcio = 0;
880
881 if (cdmaDbm >= -75) levelDbm = 4;
882 else if (cdmaDbm >= -85) levelDbm = 3;
883 else if (cdmaDbm >= -95) levelDbm = 2;
884 else if (cdmaDbm >= -100) levelDbm = 1;
885 else levelDbm = 0;
886
887 // Ec/Io are in dB*10
888 if (cdmaEcio >= -90) levelEcio = 4;
889 else if (cdmaEcio >= -110) levelEcio = 3;
890 else if (cdmaEcio >= -130) levelEcio = 2;
891 else if (cdmaEcio >= -150) levelEcio = 1;
892 else levelEcio = 0;
893
894 return (levelDbm < levelEcio) ? levelDbm : levelEcio;
895 }
896
897 private int getEvdoLevel() {
898 int evdoDbm = mSignalStrength.getEvdoDbm();
899 int evdoSnr = mSignalStrength.getEvdoSnr();
900 int levelEvdoDbm = 0;
901 int levelEvdoSnr = 0;
902
903 if (evdoDbm >= -65) levelEvdoDbm = 4;
904 else if (evdoDbm >= -75) levelEvdoDbm = 3;
905 else if (evdoDbm >= -90) levelEvdoDbm = 2;
906 else if (evdoDbm >= -105) levelEvdoDbm = 1;
907 else levelEvdoDbm = 0;
908
John Michelau1336a562009-09-28 10:41:02 -0500909 if (evdoSnr >= 7) levelEvdoSnr = 4;
910 else if (evdoSnr >= 5) levelEvdoSnr = 3;
911 else if (evdoSnr >= 3) levelEvdoSnr = 2;
912 else if (evdoSnr >= 1) levelEvdoSnr = 1;
johnwang347c5a22009-08-24 22:11:11 -0700913 else levelEvdoSnr = 0;
914
915 return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
916 }
917
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700918 private final void updateDataNetType(int net) {
Wink Saville04e71b32009-04-02 11:00:54 -0700919 switch (net) {
Wink Saville04e71b32009-04-02 11:00:54 -0700920 case TelephonyManager.NETWORK_TYPE_EDGE:
921 mDataIconList = sDataNetType_e;
922 break;
923 case TelephonyManager.NETWORK_TYPE_UMTS:
924 mDataIconList = sDataNetType_3g;
925 break;
Li Zheebe66342009-08-14 19:22:16 +0800926 case TelephonyManager.NETWORK_TYPE_HSDPA:
927 case TelephonyManager.NETWORK_TYPE_HSUPA:
928 case TelephonyManager.NETWORK_TYPE_HSPA:
John Wang33e21fc2009-10-08 10:35:27 -0700929 if (mHspaDataDistinguishable) {
930 mDataIconList = sDataNetType_h;
931 } else {
932 mDataIconList = sDataNetType_3g;
933 }
Li Zheebe66342009-08-14 19:22:16 +0800934 break;
Wink Saville04e71b32009-04-02 11:00:54 -0700935 case TelephonyManager.NETWORK_TYPE_CDMA:
936 // display 1xRTT for IS95A/B
johnwang9f87cb22009-08-25 15:25:37 -0700937 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -0700938 break;
939 case TelephonyManager.NETWORK_TYPE_1xRTT:
johnwang9f87cb22009-08-25 15:25:37 -0700940 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -0700941 break;
942 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
943 case TelephonyManager.NETWORK_TYPE_EVDO_A:
Naveen Kalla0a5174a2010-04-21 14:48:03 -0700944 case TelephonyManager.NETWORK_TYPE_EVDO_B:
johnwang9f87cb22009-08-25 15:25:37 -0700945 mDataIconList = sDataNetType_3g;
Wink Saville04e71b32009-04-02 11:00:54 -0700946 break;
947 default:
948 mDataIconList = sDataNetType_g;
949 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 }
951 }
952
953 private final void updateDataIcon() {
954 int iconId;
955 boolean visible = true;
956
Wink Savillee9b06d72009-05-18 21:47:50 -0700957 if (!isCdma()) {
958 // GSM case, we have to check also the sim state
959 if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
960 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
961 switch (mDataActivity) {
962 case TelephonyManager.DATA_ACTIVITY_IN:
963 iconId = mDataIconList[1];
964 break;
965 case TelephonyManager.DATA_ACTIVITY_OUT:
966 iconId = mDataIconList[2];
967 break;
968 case TelephonyManager.DATA_ACTIVITY_INOUT:
969 iconId = mDataIconList[3];
970 break;
971 default:
972 iconId = mDataIconList[0];
973 break;
974 }
Joe Onorato0cbda992010-05-02 16:28:15 -0700975 mService.setIcon("data_connection", null, iconId, 0);
Wink Savillee9b06d72009-05-18 21:47:50 -0700976 } else {
977 visible = false;
978 }
979 } else {
Joe Onorato0cbda992010-05-02 16:28:15 -0700980 iconId = com.android.internal.R.drawable.stat_sys_no_sim;
981 mService.setIcon("data_connection", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700983 } else {
984 // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
985 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 switch (mDataActivity) {
987 case TelephonyManager.DATA_ACTIVITY_IN:
Wink Savillee9b06d72009-05-18 21:47:50 -0700988 iconId = mDataIconList[1];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 break;
990 case TelephonyManager.DATA_ACTIVITY_OUT:
Wink Savillee9b06d72009-05-18 21:47:50 -0700991 iconId = mDataIconList[2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 break;
993 case TelephonyManager.DATA_ACTIVITY_INOUT:
Wink Savillee9b06d72009-05-18 21:47:50 -0700994 iconId = mDataIconList[3];
995 break;
996 case TelephonyManager.DATA_ACTIVITY_DORMANT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 default:
Wink Savillee9b06d72009-05-18 21:47:50 -0700998 iconId = mDataIconList[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 break;
1000 }
Joe Onorato0cbda992010-05-02 16:28:15 -07001001 mService.setIcon("data_connection", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 } else {
1003 visible = false;
1004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001006
Dianne Hackborn4840e142009-03-24 22:40:29 -07001007 long ident = Binder.clearCallingIdentity();
1008 try {
Wink Saville04e71b32009-04-02 11:00:54 -07001009 mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
Dianne Hackborn4840e142009-03-24 22:40:29 -07001010 } catch (RemoteException e) {
1011 } finally {
1012 Binder.restoreCallingIdentity(ident);
1013 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 if (mDataIconVisible != visible) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001016 mService.setIconVisibility("data_connection", visible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 mDataIconVisible = visible;
1018 }
1019 }
1020
1021 private final void updateVolume() {
1022 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1023 final int ringerMode = audioManager.getRingerMode();
1024 final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
Wink Savillee9b06d72009-05-18 21:47:50 -07001025 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
1027 ? com.android.internal.R.drawable.stat_sys_ringer_vibrate
1028 : com.android.internal.R.drawable.stat_sys_ringer_silent;
1029
1030 if (visible) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001031 mService.setIcon("volume", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 }
1033 if (visible != mVolumeVisible) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001034 mService.setIconVisibility("volume", visible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 mVolumeVisible = visible;
1036 }
1037 }
1038
1039 private final void updateBluetooth(Intent intent) {
1040 int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 String action = intent.getAction();
Nick Pellyde893f52009-09-08 13:15:33 -07001042 if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
Nick Pellyb24e11b2009-09-08 17:40:43 -07001043 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
Nick Pellyde893f52009-09-08 13:15:33 -07001044 mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
Nick Pelly005b2282009-09-10 10:21:56 -07001045 } else if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
1046 mBluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 BluetoothHeadset.STATE_ERROR);
Nick Pelly005b2282009-09-10 10:21:56 -07001048 } else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) {
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001049 BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
1050 if (a2dp.getConnectedSinks().size() != 0) {
1051 mBluetoothA2dpConnected = true;
1052 } else {
1053 mBluetoothA2dpConnected = false;
1054 }
Jiafa Liu3f416732009-07-02 16:36:02 +08001055 } else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
1056 mBluetoothPbapState = intent.getIntExtra(BluetoothPbap.PBAP_STATE,
1057 BluetoothPbap.STATE_DISCONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 } else {
1059 return;
1060 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001061
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001062 if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED || mBluetoothA2dpConnected ||
Jiafa Liu3f416732009-07-02 16:36:02 +08001063 mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
1065 }
1066
Joe Onorato0cbda992010-05-02 16:28:15 -07001067 mService.setIcon("bluetooth", null, iconId, 0);
1068 mService.setIconVisibility("bluetooth", mBluetoothEnabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 }
1070
1071 private final void updateWifi(Intent intent) {
1072 final String action = intent.getAction();
1073 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
1076 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
Wink Savillee9b06d72009-05-18 21:47:50 -07001077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078 if (!enabled) {
1079 // If disabled, hide the icon. (We show icon when connected.)
Joe Onorato0cbda992010-05-02 16:28:15 -07001080 mService.setIconVisibility("wifi", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
1084 final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
1085 false);
1086 if (!enabled) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001087 mService.setIconVisibility("wifi", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 }
1089 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
1090
Wink Savillee9b06d72009-05-18 21:47:50 -07001091 final NetworkInfo networkInfo = (NetworkInfo)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
Wink Savillee9b06d72009-05-18 21:47:50 -07001093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 int iconId;
1095 if (networkInfo != null && networkInfo.isConnected()) {
1096 mIsWifiConnected = true;
1097 if (mLastWifiSignalLevel == -1) {
1098 iconId = sWifiSignalImages[0];
1099 } else {
1100 iconId = sWifiSignalImages[mLastWifiSignalLevel];
1101 }
Wink Saville04e71b32009-04-02 11:00:54 -07001102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 // Show the icon since wi-fi is connected
Joe Onorato0cbda992010-05-02 16:28:15 -07001104 mService.setIconVisibility("wifi", true);
Wink Saville04e71b32009-04-02 11:00:54 -07001105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 } else {
1107 mLastWifiSignalLevel = -1;
1108 mIsWifiConnected = false;
1109 iconId = sWifiSignalImages[0];
1110
1111 // Hide the icon since we're not connected
Joe Onorato0cbda992010-05-02 16:28:15 -07001112 mService.setIconVisibility("wifi", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 }
1114
Joe Onorato0cbda992010-05-02 16:28:15 -07001115 mService.setIcon("wifi", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001117 int iconId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
1119 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
1120 sWifiSignalImages.length);
1121 if (newSignalLevel != mLastWifiSignalLevel) {
1122 mLastWifiSignalLevel = newSignalLevel;
1123 if (mIsWifiConnected) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001124 iconId = sWifiSignalImages[newSignalLevel];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 } else {
Joe Onorato0cbda992010-05-02 16:28:15 -07001126 iconId = sWifiTemporarilyNotConnectedImage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 }
Joe Onorato0cbda992010-05-02 16:28:15 -07001128 mService.setIcon("wifi", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 }
1130 }
1131 }
1132
1133 private final void updateGps(Intent intent) {
1134 final String action = intent.getAction();
Mike Lockwood00b74272010-03-26 10:41:48 -04001135 final boolean enabled = intent.getBooleanExtra(LocationManager.EXTRA_GPS_ENABLED, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136
Mike Lockwood00b74272010-03-26 10:41:48 -04001137 if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 // GPS is getting fixes
Joe Onorato0cbda992010-05-02 16:28:15 -07001139 mService.setIcon("gps", null, com.android.internal.R.drawable.stat_sys_gps_on, 0);
1140 mService.setIconVisibility("gps", true);
Mike Lockwood00b74272010-03-26 10:41:48 -04001141 } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 // GPS is off
Joe Onorato0cbda992010-05-02 16:28:15 -07001143 mService.setIconVisibility("gps", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 } else {
1145 // GPS is on, but not receiving fixes
Joe Onorato0cbda992010-05-02 16:28:15 -07001146 mService.setIcon("gps",
1147 null, com.android.internal.R.drawable.stat_sys_gps_acquiring_anim, 0);
1148 mService.setIconVisibility("gps", true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 }
1150 }
1151
Wink Savillee9b06d72009-05-18 21:47:50 -07001152 private final void updateTTY(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -07001153 final String action = intent.getAction();
1154 final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
1155
Joe Onorato8a9b2202010-02-26 18:56:32 -08001156 if (false) Slog.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -07001157
1158 if (enabled) {
1159 // TTY is on
Joe Onorato8a9b2202010-02-26 18:56:32 -08001160 if (false) Slog.v(TAG, "updateTTY: set TTY on");
Joe Onorato0cbda992010-05-02 16:28:15 -07001161 mService.setIcon("tty", null, com.android.internal.R.drawable.stat_sys_tty_mode, 0);
1162 mService.setIconVisibility("tty", true);
Wink Saville04e71b32009-04-02 11:00:54 -07001163 } else {
1164 // TTY is off
Joe Onorato8a9b2202010-02-26 18:56:32 -08001165 if (false) Slog.v(TAG, "updateTTY: set TTY off");
Joe Onorato0cbda992010-05-02 16:28:15 -07001166 mService.setIconVisibility("tty", false);
Wink Saville04e71b32009-04-02 11:00:54 -07001167 }
1168 }
1169
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001170 private final void updateCdmaRoamingIcon(ServiceState state) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001171 if (!hasService()) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001172 mService.setIconVisibility("cdma_eri", false);
Wink Savillef3152382009-06-01 14:39:20 -07001173 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001174 }
1175
1176 if (!isCdma()) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001177 mService.setIconVisibility("cdma_eri", false);
Wink Savillef3152382009-06-01 14:39:20 -07001178 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001179 }
1180
1181 int[] iconList = sRoamingIndicatorImages_cdma;
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001182 int iconIndex = state.getCdmaEriIconIndex();
1183 int iconMode = state.getCdmaEriIconMode();
Wink Savillee9b06d72009-05-18 21:47:50 -07001184
1185 if (iconIndex == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001186 Slog.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001187 return;
1188 }
1189
1190 if (iconMode == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001191 Slog.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001192 return;
1193 }
1194
1195 if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001196 if (false) Slog.v(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
Joe Onorato0cbda992010-05-02 16:28:15 -07001197 mService.setIconVisibility("cdma_eri", false);
Wink Savillee9b06d72009-05-18 21:47:50 -07001198 return;
1199 }
1200
1201 switch (iconMode) {
1202 case EriInfo.ROAMING_ICON_MODE_NORMAL:
Joe Onorato0cbda992010-05-02 16:28:15 -07001203 mService.setIcon("cdma_eri", null, iconList[iconIndex], 0);
1204 mService.setIconVisibility("cdma_eri", true);
Wink Savillee9b06d72009-05-18 21:47:50 -07001205 break;
1206 case EriInfo.ROAMING_ICON_MODE_FLASH:
Joe Onorato0cbda992010-05-02 16:28:15 -07001207 mService.setIcon("cdma_eri",
1208 null, com.android.internal.R.drawable.stat_sys_roaming_cdma_flash, 0);
1209 mService.setIconVisibility("cdma_eri", true);
Wink Savillee9b06d72009-05-18 21:47:50 -07001210 break;
1211
1212 }
Joe Onorato0cbda992010-05-02 16:28:15 -07001213 mService.setIcon("phone_signal", null, mPhoneSignalIconId, 0);
Wink Savillee9b06d72009-05-18 21:47:50 -07001214 }
1215
1216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 private class StatusBarHandler extends Handler {
1218 @Override
1219 public void handleMessage(Message msg) {
1220 switch (msg.what) {
1221 case EVENT_BATTERY_CLOSE:
1222 if (msg.arg1 == mBatteryViewSequence) {
1223 closeLastBatteryView();
1224 }
1225 break;
1226 }
1227 }
1228 }
1229}