blob: 55840e27214425cdefcd1a243afcaff0637b8798 [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;
32import android.graphics.drawable.Drawable;
33import android.media.AudioManager;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050034import android.media.Ringtone;
35import android.media.RingtoneManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.net.NetworkInfo;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050037import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.net.wifi.WifiManager;
Dianne Hackborn4840e142009-03-24 22:40:29 -070039import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.Handler;
41import android.os.IBinder;
42import android.os.Message;
Dianne Hackborn4840e142009-03-24 22:40:29 -070043import android.os.RemoteException;
San Mehat4154c072010-02-09 18:37:54 -080044import android.os.storage.StorageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.provider.Settings;
46import android.telephony.PhoneStateListener;
47import android.telephony.ServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -070048import android.telephony.SignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.telephony.TelephonyManager;
50import android.text.format.DateFormat;
Eric Fischer36e136c2010-01-14 17:42:48 -080051import android.text.style.RelativeSizeSpan;
52import android.text.Spannable;
53import android.text.SpannableStringBuilder;
Joe Onorato8a9b2202010-02-26 18:56:32 -080054import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.view.View;
56import android.view.ViewGroup;
57import android.view.WindowManager;
58import android.view.WindowManagerImpl;
59import android.widget.ImageView;
60import android.widget.LinearLayout;
61import android.widget.TextView;
62
Wink Saville04e71b32009-04-02 11:00:54 -070063import com.android.internal.R;
64import com.android.internal.app.IBatteryStats;
65import com.android.internal.location.GpsLocationProvider;
66import com.android.internal.telephony.IccCard;
67import com.android.internal.telephony.TelephonyIntents;
Wink Savillee9b06d72009-05-18 21:47:50 -070068import com.android.internal.telephony.cdma.EriInfo;
Wink Saville04e71b32009-04-02 11:00:54 -070069import com.android.internal.telephony.cdma.TtyIntent;
70import com.android.server.am.BatteryStatsService;
71
Eric Fischer36e136c2010-01-14 17:42:48 -080072import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import java.util.Calendar;
74import java.util.TimeZone;
75
76/**
77 * This class contains all of the policy about which icons are installed in the status
78 * bar at boot time. In reality, it should go into the android.policy package, but
79 * putting it here is the first step from extracting it.
80 */
81public class StatusBarPolicy {
82 private static final String TAG = "StatusBarPolicy";
83
84 private static StatusBarPolicy sInstance;
85
86 // message codes for the handler
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 private static final int EVENT_BATTERY_CLOSE = 4;
88
Dianne Hackborn4840e142009-03-24 22:40:29 -070089 private final Context mContext;
90 private final StatusBarService mService;
91 private final Handler mHandler = new StatusBarHandler();
92 private final IBatteryStats mBatteryStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093
94 // clock
95 private Calendar mCalendar;
Joe Onorato63ce8e82010-01-17 19:06:51 -050096 private String mClockFormatString;
97 private SimpleDateFormat mClockFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098 private IBinder mClockIcon;
99 private IconData mClockData;
100
San Mehat4154c072010-02-09 18:37:54 -0800101 // storage
102 private StorageManager mStorageManager;
103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 // battery
105 private IBinder mBatteryIcon;
106 private IconData mBatteryData;
107 private boolean mBatteryFirst = true;
108 private boolean mBatteryPlugged;
109 private int mBatteryLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 private AlertDialog mLowBatteryDialog;
111 private TextView mBatteryLevelTextView;
112 private View mBatteryView;
113 private int mBatteryViewSequence;
114 private boolean mBatteryShowLowOnEndCall = false;
115 private static final boolean SHOW_LOW_BATTERY_WARNING = true;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500116 private static final boolean SHOW_BATTERY_WARNINGS_IN_CALL = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117
118 // phone
119 private TelephonyManager mPhone;
120 private IBinder mPhoneIcon;
Wink Saville04e71b32009-04-02 11:00:54 -0700121
122 //***** Signal strength icons
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 private IconData mPhoneData;
Wink Saville04e71b32009-04-02 11:00:54 -0700124 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 private static final int[] sSignalImages = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700126 com.android.internal.R.drawable.stat_sys_signal_0,
127 com.android.internal.R.drawable.stat_sys_signal_1,
128 com.android.internal.R.drawable.stat_sys_signal_2,
129 com.android.internal.R.drawable.stat_sys_signal_3,
130 com.android.internal.R.drawable.stat_sys_signal_4
131 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 private static final int[] sSignalImages_r = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700133 com.android.internal.R.drawable.stat_sys_r_signal_0,
134 com.android.internal.R.drawable.stat_sys_r_signal_1,
135 com.android.internal.R.drawable.stat_sys_r_signal_2,
136 com.android.internal.R.drawable.stat_sys_r_signal_3,
137 com.android.internal.R.drawable.stat_sys_r_signal_4
138 };
Wink Savillee9b06d72009-05-18 21:47:50 -0700139 private static final int[] sRoamingIndicatorImages_cdma = new int[] {
140 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
141 // 1 is Standard Roaming Indicator OFF
142 // TODO T: image never used, remove and put 0 instead?
143 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
144
145 // 2 is Standard Roaming Indicator FLASHING
146 // TODO T: image never used, remove and put 0 instead?
147 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
148
149 // 3-12 Standard ERI
150 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //3
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 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
156 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
157 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
158 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
159 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
160
161 // 13-63 Reserved for Standard ERI
162 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //13
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 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
209 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
210 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
211 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
212 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
213
214 // 64-127 Reserved for Non Standard (Operator Specific) ERI
215 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //64
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,
230 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
231 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
232 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
233 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
234 com.android.internal.R.drawable.stat_sys_roaming_cdma_0 //83
235
236 // 128-255 Reserved
Wink Saville04e71b32009-04-02 11:00:54 -0700237 };
Wink Saville04e71b32009-04-02 11:00:54 -0700238
239 //***** Data connection icons
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 private int[] mDataIconList = sDataNetType_g;
Wink Saville04e71b32009-04-02 11:00:54 -0700241 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 private static final int[] sDataNetType_g = new int[] {
243 com.android.internal.R.drawable.stat_sys_data_connected_g,
244 com.android.internal.R.drawable.stat_sys_data_in_g,
245 com.android.internal.R.drawable.stat_sys_data_out_g,
246 com.android.internal.R.drawable.stat_sys_data_inandout_g,
247 };
248 private static final int[] sDataNetType_3g = new int[] {
249 com.android.internal.R.drawable.stat_sys_data_connected_3g,
250 com.android.internal.R.drawable.stat_sys_data_in_3g,
251 com.android.internal.R.drawable.stat_sys_data_out_3g,
252 com.android.internal.R.drawable.stat_sys_data_inandout_3g,
253 };
254 private static final int[] sDataNetType_e = new int[] {
255 com.android.internal.R.drawable.stat_sys_data_connected_e,
256 com.android.internal.R.drawable.stat_sys_data_in_e,
257 com.android.internal.R.drawable.stat_sys_data_out_e,
258 com.android.internal.R.drawable.stat_sys_data_inandout_e,
259 };
Li Zheebe66342009-08-14 19:22:16 +0800260 //3.5G
261 private static final int[] sDataNetType_h = new int[] {
262 com.android.internal.R.drawable.stat_sys_data_connected_h,
263 com.android.internal.R.drawable.stat_sys_data_in_h,
264 com.android.internal.R.drawable.stat_sys_data_out_h,
265 com.android.internal.R.drawable.stat_sys_data_inandout_h,
266 };
267
Wink Saville04e71b32009-04-02 11:00:54 -0700268 //CDMA
johnwang9f87cb22009-08-25 15:25:37 -0700269 // Use 3G icons for EVDO data and 1x icons for 1XRTT data
270 private static final int[] sDataNetType_1x = new int[] {
271 com.android.internal.R.drawable.stat_sys_data_connected_1x,
272 com.android.internal.R.drawable.stat_sys_data_in_1x,
273 com.android.internal.R.drawable.stat_sys_data_out_1x,
274 com.android.internal.R.drawable.stat_sys_data_inandout_1x,
Wink Saville04e71b32009-04-02 11:00:54 -0700275 };
276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 // Assume it's all good unless we hear otherwise. We don't always seem
278 // to get broadcasts that it *is* there.
Wink Saville04e71b32009-04-02 11:00:54 -0700279 IccCard.State mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
281 int mDataState = TelephonyManager.DATA_DISCONNECTED;
282 int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
283 ServiceState mServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -0700284 SignalStrength mSignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
286 // data connection
287 private IBinder mDataIcon;
288 private IconData mDataData;
289 private boolean mDataIconVisible;
John Wang33e21fc2009-10-08 10:35:27 -0700290 private boolean mHspaDataDistinguishable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
292 // ringer volume
293 private IBinder mVolumeIcon;
294 private IconData mVolumeData;
295 private boolean mVolumeVisible;
Wink Saville04e71b32009-04-02 11:00:54 -0700296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 // bluetooth device status
298 private IBinder mBluetoothIcon;
299 private IconData mBluetoothData;
300 private int mBluetoothHeadsetState;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800301 private boolean mBluetoothA2dpConnected;
Jiafa Liu3f416732009-07-02 16:36:02 +0800302 private int mBluetoothPbapState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 private boolean mBluetoothEnabled;
304
305 // wifi
306 private static final int[] sWifiSignalImages = new int[] {
307 com.android.internal.R.drawable.stat_sys_wifi_signal_1,
308 com.android.internal.R.drawable.stat_sys_wifi_signal_2,
309 com.android.internal.R.drawable.stat_sys_wifi_signal_3,
310 com.android.internal.R.drawable.stat_sys_wifi_signal_4,
311 };
312 private static final int sWifiTemporarilyNotConnectedImage =
313 com.android.internal.R.drawable.stat_sys_wifi_signal_0;
314
315 private int mLastWifiSignalLevel = -1;
316 private boolean mIsWifiConnected = false;
317 private IBinder mWifiIcon;
318 private IconData mWifiData;
319
320 // gps
321 private IBinder mGpsIcon;
322 private IconData mGpsEnabledIconData;
323 private IconData mGpsFixIconData;
324
325 // alarm clock
326 // Icon lit when clock is set
327 private IBinder mAlarmClockIcon;
328 private IconData mAlarmClockIconData;
329
330 // sync state
331 // If sync is active the SyncActive icon is displayed. If sync is not active but
332 // sync is failing the SyncFailing icon is displayed. Otherwise neither are displayed.
333 private IBinder mSyncActiveIcon;
334 private IBinder mSyncFailingIcon;
335
Wink Saville04e71b32009-04-02 11:00:54 -0700336 // TTY mode
337 // Icon lit when TTY mode is enabled
338 private IBinder mTTYModeIcon;
339 private IconData mTTYModeEnableIconData;
340
Wink Savillee9b06d72009-05-18 21:47:50 -0700341 // Cdma Roaming Indicator, ERI
342 private IBinder mCdmaRoamingIndicatorIcon;
343 private IconData mCdmaRoamingIndicatorIconData;
344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
346 @Override
347 public void onReceive(Context context, Intent intent) {
348 String action = intent.getAction();
349 if (action.equals(Intent.ACTION_TIME_TICK)) {
350 updateClock();
351 }
352 else if (action.equals(Intent.ACTION_TIME_CHANGED)) {
353 updateClock();
354 }
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700355 else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
356 updateBattery(intent);
357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
359 updateClock();
360 }
361 else if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
362 String tz = intent.getStringExtra("time-zone");
363 mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz));
364 updateClock();
365 }
366 else if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
367 updateAlarm(intent);
368 }
369 else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
370 updateSyncState(intent);
371 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200372 else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
373 onBatteryLow(intent);
374 }
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400375 else if (action.equals(Intent.ACTION_BATTERY_OKAY)
376 || action.equals(Intent.ACTION_POWER_CONNECTED)) {
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700377 onBatteryOkay(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 }
Nick Pellyde893f52009-09-08 13:15:33 -0700379 else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
Nick Pelly005b2282009-09-10 10:21:56 -0700380 action.equals(BluetoothHeadset.ACTION_STATE_CHANGED) ||
381 action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED) ||
Jiafa Liu3f416732009-07-02 16:36:02 +0800382 action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 updateBluetooth(intent);
384 }
385 else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
386 action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) ||
387 action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
388 updateWifi(intent);
389 }
390 else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) ||
391 action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION)) {
392 updateGps(intent);
393 }
394 else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
395 action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
396 updateVolume();
397 }
398 else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
399 updateSimState(intent);
400 }
Wink Saville04e71b32009-04-02 11:00:54 -0700401 else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
402 updateTTY(intent);
403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 }
405 };
406
407 private StatusBarPolicy(Context context, StatusBarService service) {
408 mContext = context;
409 mService = service;
Wink Savillee9b06d72009-05-18 21:47:50 -0700410 mSignalStrength = new SignalStrength();
Dianne Hackborn4840e142009-03-24 22:40:29 -0700411 mBatteryStats = BatteryStatsService.getService();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412
413 // clock
414 mCalendar = Calendar.getInstance(TimeZone.getDefault());
415 mClockData = IconData.makeText("clock", "");
416 mClockIcon = service.addIcon(mClockData, null);
417 updateClock();
418
San Mehat4154c072010-02-09 18:37:54 -0800419 // storage
420 mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
421 mStorageManager.registerListener(
422 new com.android.server.status.StorageNotification(context));
423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 // battery
425 mBatteryData = IconData.makeIcon("battery",
426 null, com.android.internal.R.drawable.stat_sys_battery_unknown, 0, 0);
427 mBatteryIcon = service.addIcon(mBatteryData, null);
428
429 // phone_signal
430 mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Wink Savillee9b06d72009-05-18 21:47:50 -0700431 mPhoneData = IconData.makeIcon("phone_signal",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
433 mPhoneIcon = service.addIcon(mPhoneData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -0700434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 // register for phone state notifications.
436 ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
437 .listen(mPhoneStateListener,
438 PhoneStateListener.LISTEN_SERVICE_STATE
Wink Savillee9b06d72009-05-18 21:47:50 -0700439 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 | PhoneStateListener.LISTEN_CALL_STATE
441 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
442 | PhoneStateListener.LISTEN_DATA_ACTIVITY);
443
444 // data_connection
445 mDataData = IconData.makeIcon("data_connection",
446 null, com.android.internal.R.drawable.stat_sys_data_connected_g, 0, 0);
447 mDataIcon = service.addIcon(mDataData, null);
448 service.setIconVisibility(mDataIcon, false);
449
450 // wifi
451 mWifiData = IconData.makeIcon("wifi", null, sWifiSignalImages[0], 0, 0);
452 mWifiIcon = service.addIcon(mWifiData, null);
453 service.setIconVisibility(mWifiIcon, false);
454 // wifi will get updated by the sticky intents
Wink Saville04e71b32009-04-02 11:00:54 -0700455
456 // TTY status
457 mTTYModeEnableIconData = IconData.makeIcon("tty",
458 null, com.android.internal.R.drawable.stat_sys_tty_mode, 0, 0);
459 mTTYModeIcon = service.addIcon(mTTYModeEnableIconData, null);
460 service.setIconVisibility(mTTYModeIcon, false);
461
Wink Savillee9b06d72009-05-18 21:47:50 -0700462 // Cdma Roaming Indicator, ERI
463 mCdmaRoamingIndicatorIconData = IconData.makeIcon("cdma_eri",
464 null, com.android.internal.R.drawable.stat_sys_roaming_cdma_0, 0, 0);
465 mCdmaRoamingIndicatorIcon = service.addIcon(mCdmaRoamingIndicatorIconData, null);
466 service.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 // bluetooth status
469 mBluetoothData = IconData.makeIcon("bluetooth",
470 null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
471 mBluetoothIcon = service.addIcon(mBluetoothData, null);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200472 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Nick Pellybd022f42009-08-14 18:33:38 -0700473 if (adapter != null) {
474 mBluetoothEnabled = adapter.isEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 } else {
476 mBluetoothEnabled = false;
477 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800478 mBluetoothA2dpConnected = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 mBluetoothHeadsetState = BluetoothHeadset.STATE_DISCONNECTED;
Jiafa Liu3f416732009-07-02 16:36:02 +0800480 mBluetoothPbapState = BluetoothPbap.STATE_DISCONNECTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
482
483 // Gps status
484 mGpsEnabledIconData = IconData.makeIcon("gps",
485 null, com.android.internal.R.drawable.stat_sys_gps_acquiring_anim, 0, 0);
486 mGpsFixIconData = IconData.makeIcon("gps",
487 null, com.android.internal.R.drawable.stat_sys_gps_on, 0, 0);
488 mGpsIcon = service.addIcon(mGpsEnabledIconData, null);
johnwang347c5a22009-08-24 22:11:11 -0700489 service.setIconVisibility(mGpsIcon, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490
491 // Alarm clock
492 mAlarmClockIconData = IconData.makeIcon(
493 "alarm_clock",
494 null, com.android.internal.R.drawable.stat_notify_alarm, 0, 0);
495 mAlarmClockIcon = service.addIcon(mAlarmClockIconData, null);
496 service.setIconVisibility(mAlarmClockIcon, false);
497
498 // Sync state
499 mSyncActiveIcon = service.addIcon(IconData.makeIcon("sync_active",
500 null, R.drawable.stat_notify_sync_anim0, 0, 0), null);
501 mSyncFailingIcon = service.addIcon(IconData.makeIcon("sync_failing",
502 null, R.drawable.stat_notify_sync_error, 0, 0), null);
503 service.setIconVisibility(mSyncActiveIcon, false);
504 service.setIconVisibility(mSyncFailingIcon, false);
505
506 // volume
507 mVolumeData = IconData.makeIcon("volume",
508 null, com.android.internal.R.drawable.stat_sys_ringer_silent, 0, 0);
509 mVolumeIcon = service.addIcon(mVolumeData, null);
510 service.setIconVisibility(mVolumeIcon, false);
511 updateVolume();
johnwang347c5a22009-08-24 22:11:11 -0700512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 IntentFilter filter = new IntentFilter();
514
515 // Register for Intent broadcasts for...
516 filter.addAction(Intent.ACTION_TIME_TICK);
517 filter.addAction(Intent.ACTION_TIME_CHANGED);
518 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
519 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Mihai Predaa82842f2009-04-29 15:05:56 +0200520 filter.addAction(Intent.ACTION_BATTERY_LOW);
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700521 filter.addAction(Intent.ACTION_BATTERY_OKAY);
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400522 filter.addAction(Intent.ACTION_POWER_CONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
524 filter.addAction(Intent.ACTION_ALARM_CHANGED);
525 filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
526 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
527 filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
Nick Pellyde893f52009-09-08 13:15:33 -0700528 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Nick Pelly005b2282009-09-10 10:21:56 -0700529 filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
530 filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
Jiafa Liu3f416732009-07-02 16:36:02 +0800531 filter.addAction(BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
533 filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
534 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
535 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
536 filter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION);
537 filter.addAction(GpsLocationProvider.GPS_FIX_CHANGE_ACTION);
538 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Wink Saville04e71b32009-04-02 11:00:54 -0700539 filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
John Wang33e21fc2009-10-08 10:35:27 -0700541
542 // load config to determine if to distinguish Hspa data icon
543 try {
544 mHspaDataDistinguishable = mContext.getResources().getBoolean(
545 com.android.internal.R.bool.config_hspa_data_distinguishable);
546 } catch (Exception e) {
547 mHspaDataDistinguishable = false;
548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 }
550
551 public static void installIcons(Context context, StatusBarService service) {
552 sInstance = new StatusBarPolicy(context, service);
553 }
554
Eric Fischer36e136c2010-01-14 17:42:48 -0800555 private final CharSequence getSmallTime() {
556 boolean b24 = DateFormat.is24HourFormat(mContext);
557 int res;
558
559 if (b24) {
560 res = R.string.twenty_four_hour_time_format;
561 } else {
562 res = R.string.twelve_hour_time_format;
563 }
564
Eric Fischer36e136c2010-01-14 17:42:48 -0800565 final char MAGIC1 = '\uEF00';
566 final char MAGIC2 = '\uEF01';
567
Joe Onorato63ce8e82010-01-17 19:06:51 -0500568 SimpleDateFormat sdf;
569 String format = mContext.getString(res);
570 if (!format.equals(mClockFormatString)) {
571 /*
572 * Search for an unquoted "a" in the format string, so we can
573 * add dummy characters around it to let us find it again after
574 * formatting and change its size.
575 */
576 int a = -1;
577 boolean quoted = false;
578 for (int i = 0; i < format.length(); i++) {
579 char c = format.charAt(i);
Eric Fischer36e136c2010-01-14 17:42:48 -0800580
Joe Onorato63ce8e82010-01-17 19:06:51 -0500581 if (c == '\'') {
582 quoted = !quoted;
583 }
584
585 if (!quoted && c == 'a') {
586 a = i;
587 break;
588 }
589 }
590
591 if (a >= 0) {
592 // Move a back so any whitespace before the AM/PM is also in the alternate size.
593 final int b = a;
594 while (a > 0 && Character.isWhitespace(format.charAt(a-1))) {
595 a--;
596 }
597 format = format.substring(0, a) + MAGIC1 + format.substring(a, b)
598 + "a" + MAGIC2 + format.substring(b + 1);
599 }
600
601 mClockFormat = sdf = new SimpleDateFormat(format);
602 mClockFormatString = format;
603 } else {
604 sdf = mClockFormat;
605 }
606 String result = sdf.format(mCalendar.getTime());
Eric Fischer36e136c2010-01-14 17:42:48 -0800607
608 int magic1 = result.indexOf(MAGIC1);
609 int magic2 = result.indexOf(MAGIC2);
610
611 if (magic1 >= 0 && magic2 > magic1) {
612 SpannableStringBuilder formatted = new SpannableStringBuilder(result);
613
614 formatted.setSpan(new RelativeSizeSpan(0.7f), magic1, magic2,
615 Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
616
617 formatted.delete(magic2, magic2 + 1);
618 formatted.delete(magic1, magic1 + 1);
619
620 return formatted;
621 } else {
622 return result;
623 }
624 }
625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 private final void updateClock() {
627 mCalendar.setTimeInMillis(System.currentTimeMillis());
Eric Fischer36e136c2010-01-14 17:42:48 -0800628 mClockData.text = getSmallTime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 mService.updateIcon(mClockIcon, mClockData, null);
630 }
631
632 private final void updateAlarm(Intent intent) {
633 boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
634 mService.setIconVisibility(mAlarmClockIcon, alarmSet);
635 }
636
637 private final void updateSyncState(Intent intent) {
638 boolean isActive = intent.getBooleanExtra("active", false);
639 boolean isFailing = intent.getBooleanExtra("failing", false);
640 mService.setIconVisibility(mSyncActiveIcon, isActive);
641 // Don't display sync failing icon: BUG 1297963 Set sync error timeout to "never"
642 //mService.setIconVisibility(mSyncFailingIcon, isFailing && !isActive);
643 }
644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 private final void updateBattery(Intent intent) {
646 mBatteryData.iconId = intent.getIntExtra("icon-small", 0);
647 mBatteryData.iconLevel = intent.getIntExtra("level", 0);
648 mService.updateIcon(mBatteryIcon, mBatteryData, null);
649
650 boolean plugged = intent.getIntExtra("plugged", 0) != 0;
651 int level = intent.getIntExtra("level", -1);
652 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800653 Slog.d(TAG, "updateBattery level=" + level
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 + " plugged=" + plugged
655 + " mBatteryPlugged=" + mBatteryPlugged
656 + " mBatteryLevel=" + mBatteryLevel
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657 + " mBatteryFirst=" + mBatteryFirst);
658 }
659
660 boolean oldPlugged = mBatteryPlugged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661
662 mBatteryPlugged = plugged;
663 mBatteryLevel = level;
664
665 if (mBatteryFirst) {
666 mBatteryFirst = false;
667 }
668 /*
669 * No longer showing the battery view because it draws attention away
670 * from the USB storage notification. We could still show it when
671 * connected to a brick, but that could lead to the user into thinking
672 * the device does not charge when plugged into USB (since he/she would
673 * not see the same battery screen on USB as he sees on brick).
674 */
675 /* else {
676 if (plugged && !oldPlugged) {
677 showBatteryView();
678 }
679 }
680 */
681 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800682 Slog.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685
Mihai Predaa82842f2009-04-29 15:05:56 +0200686 private void onBatteryLow(Intent intent) {
687 if (SHOW_LOW_BATTERY_WARNING) {
688 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800689 Slog.d(TAG, "mPhoneState=" + mPhoneState
Mihai Predaa82842f2009-04-29 15:05:56 +0200690 + " mLowBatteryDialog=" + mLowBatteryDialog
691 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200693
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500694 if (SHOW_BATTERY_WARNINGS_IN_CALL || mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
Mihai Predaa82842f2009-04-29 15:05:56 +0200695 showLowBatteryWarning();
696 } else {
697 mBatteryShowLowOnEndCall = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698 }
699 }
700 }
701
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700702 private void onBatteryOkay(Intent intent) {
703 if (mLowBatteryDialog != null
704 && SHOW_LOW_BATTERY_WARNING) {
705 mLowBatteryDialog.dismiss();
706 mBatteryShowLowOnEndCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 }
708 }
709
johnwang347c5a22009-08-24 22:11:11 -0700710 private void showBatteryView() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 closeLastBatteryView();
712 if (mLowBatteryDialog != null) {
713 mLowBatteryDialog.dismiss();
714 }
715
716 int level = mBatteryLevel;
717
718 View v = View.inflate(mContext, com.android.internal.R.layout.battery_status, null);
719 mBatteryView = v;
720 int pixelFormat = PixelFormat.TRANSLUCENT;
721 Drawable bg = v.getBackground();
722 if (bg != null) {
723 pixelFormat = bg.getOpacity();
724 }
725
Dianne Hackborn568cae52009-10-07 16:13:39 -0700726 int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
727 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
728 | WindowManager.LayoutParams.FLAG_DIM_BEHIND;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800729
Dianne Hackborn568cae52009-10-07 16:13:39 -0700730 if (!mContext.getResources().getBoolean(
731 com.android.internal.R.bool.config_sf_slowBlur)) {
732 flags |= WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
733 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
736 ViewGroup.LayoutParams.WRAP_CONTENT,
737 ViewGroup.LayoutParams.WRAP_CONTENT,
738 WindowManager.LayoutParams.TYPE_TOAST,
Dianne Hackborn568cae52009-10-07 16:13:39 -0700739 flags, pixelFormat);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740
741 // Get the dim amount from the theme
742 TypedArray a = mContext.obtainStyledAttributes(
743 com.android.internal.R.styleable.Theme);
744 lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
745 a.recycle();
Wink Saville04e71b32009-04-02 11:00:54 -0700746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 lp.setTitle("Battery");
748
749 TextView levelTextView = (TextView)v.findViewById(com.android.internal.R.id.level_percent);
750 levelTextView.setText(mContext.getString(
751 com.android.internal.R.string.battery_status_text_percent_format, level));
752
753 setBatteryLevel(v, com.android.internal.R.id.spacer, 100-level, 0, 0);
754 setBatteryLevel(v, com.android.internal.R.id.level, level,
755 com.android.internal.R.drawable.battery_charge_fill, level);
756
757 WindowManagerImpl.getDefault().addView(v, lp);
758
759 scheduleCloseBatteryView();
760 }
761
762 private void setBatteryLevel(View parent, int id, int height, int background, int level) {
763 ImageView v = (ImageView)parent.findViewById(id);
764 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)v.getLayoutParams();
765 lp.weight = height;
766 if (background != 0) {
767 v.setBackgroundResource(background);
768 Drawable bkg = v.getBackground();
769 bkg.setLevel(level);
770 }
771 }
772
773 private void showLowBatteryWarning() {
774 closeLastBatteryView();
775
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400776 // Show exact battery level.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 CharSequence levelText = mContext.getString(
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400778 com.android.internal.R.string.battery_low_percent_format, mBatteryLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779
780 if (mBatteryLevelTextView != null) {
781 mBatteryLevelTextView.setText(levelText);
782 } else {
783 View v = View.inflate(mContext, com.android.internal.R.layout.battery_low, null);
784 mBatteryLevelTextView=(TextView)v.findViewById(com.android.internal.R.id.level_percent);
785
786 mBatteryLevelTextView.setText(levelText);
787
788 AlertDialog.Builder b = new AlertDialog.Builder(mContext);
789 b.setCancelable(true);
790 b.setTitle(com.android.internal.R.string.battery_low_title);
791 b.setView(v);
792 b.setIcon(android.R.drawable.ic_dialog_alert);
793 b.setPositiveButton(android.R.string.ok, null);
johnwang347c5a22009-08-24 22:11:11 -0700794
Dianne Hackborn3d74bb42009-06-19 10:35:21 -0700795 final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
796 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
797 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
798 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
799 | Intent.FLAG_ACTIVITY_NO_HISTORY);
800 if (intent.resolveActivity(mContext.getPackageManager()) != null) {
801 b.setNegativeButton(com.android.internal.R.string.battery_low_why,
802 new DialogInterface.OnClickListener() {
803 public void onClick(DialogInterface dialog, int which) {
804 mContext.startActivity(intent);
805 if (mLowBatteryDialog != null) {
806 mLowBatteryDialog.dismiss();
807 }
808 }
809 });
810 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811
812 AlertDialog d = b.create();
813 d.setOnDismissListener(mLowBatteryListener);
814 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
815 d.show();
816 mLowBatteryDialog = d;
817 }
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500818
819 final ContentResolver cr = mContext.getContentResolver();
820 if (Settings.System.getInt(cr,
821 Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
822 {
823 final String soundPath = Settings.System.getString(cr,
824 Settings.System.LOW_BATTERY_SOUND);
825 if (soundPath != null) {
826 final Uri soundUri = Uri.parse("file://" + soundPath);
827 if (soundUri != null) {
828 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
Daniel Sandlerec2c88d2010-02-20 01:04:57 -0500829 if (sfx != null) {
830 sfx.setStreamType(AudioManager.STREAM_SYSTEM);
831 sfx.play();
832 }
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500833 }
834 }
835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 }
837
838 private final void updateCallState(int state) {
839 mPhoneState = state;
840 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800841 Slog.d(TAG, "mPhoneState=" + mPhoneState
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 + " mLowBatteryDialog=" + mLowBatteryDialog
843 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
844 }
845 if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
846 if (mBatteryShowLowOnEndCall) {
847 if (!mBatteryPlugged) {
848 showLowBatteryWarning();
849 }
850 mBatteryShowLowOnEndCall = false;
851 }
852 } else {
853 if (mLowBatteryDialog != null) {
854 mLowBatteryDialog.dismiss();
855 mBatteryShowLowOnEndCall = true;
856 }
857 }
858 }
859
860 private DialogInterface.OnDismissListener mLowBatteryListener
861 = new DialogInterface.OnDismissListener() {
862 public void onDismiss(DialogInterface dialog) {
863 mLowBatteryDialog = null;
864 mBatteryLevelTextView = null;
865 }
866 };
867
868 private void scheduleCloseBatteryView() {
869 Message m = mHandler.obtainMessage(EVENT_BATTERY_CLOSE);
870 m.arg1 = (++mBatteryViewSequence);
871 mHandler.sendMessageDelayed(m, 3000);
872 }
873
874 private void closeLastBatteryView() {
875 if (mBatteryView != null) {
876 //mBatteryView.debug();
877 WindowManagerImpl.getDefault().removeView(mBatteryView);
878 mBatteryView = null;
879 }
880 }
881
882 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
883 @Override
Wink Savillee9b06d72009-05-18 21:47:50 -0700884 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
885 mSignalStrength = signalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 updateSignalStrength();
887 }
888
889 @Override
890 public void onServiceStateChanged(ServiceState state) {
891 mServiceState = state;
892 updateSignalStrength();
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700893 updateCdmaRoamingIcon(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894 updateDataIcon();
895 }
896
897 @Override
898 public void onCallStateChanged(int state, String incomingNumber) {
899 updateCallState(state);
johnwang347c5a22009-08-24 22:11:11 -0700900 // In cdma, if a voice call is made, RSSI should switch to 1x.
901 if (isCdma()) {
902 updateSignalStrength();
903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 }
905
906 @Override
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700907 public void onDataConnectionStateChanged(int state, int networkType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 mDataState = state;
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700909 updateDataNetType(networkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 updateDataIcon();
911 }
912
913 @Override
914 public void onDataActivity(int direction) {
915 mDataActivity = direction;
916 updateDataIcon();
917 }
918 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919
920 private final void updateSimState(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -0700921 String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
922 if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
923 mSimState = IccCard.State.ABSENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 }
Wink Saville04e71b32009-04-02 11:00:54 -0700925 else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
926 mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 }
Wink Saville04e71b32009-04-02 11:00:54 -0700928 else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
929 final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
930 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
931 mSimState = IccCard.State.PIN_REQUIRED;
johnwang347c5a22009-08-24 22:11:11 -0700932 }
Wink Saville04e71b32009-04-02 11:00:54 -0700933 else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
934 mSimState = IccCard.State.PUK_REQUIRED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 }
936 else {
Wink Saville04e71b32009-04-02 11:00:54 -0700937 mSimState = IccCard.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 }
939 } else {
Wink Saville04e71b32009-04-02 11:00:54 -0700940 mSimState = IccCard.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 }
942 updateDataIcon();
943 }
944
Wink Savillee9b06d72009-05-18 21:47:50 -0700945 private boolean isCdma() {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700946 return (mSignalStrength != null) && !mSignalStrength.isGsm();
Wink Savillee9b06d72009-05-18 21:47:50 -0700947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948
johnwang347c5a22009-08-24 22:11:11 -0700949 private boolean isEvdo() {
950 return ( (mServiceState != null)
951 && ((mServiceState.getRadioTechnology()
952 == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
953 || (mServiceState.getRadioTechnology()
954 == ServiceState.RADIO_TECHNOLOGY_EVDO_A)));
955 }
956
Wink Savillee9b06d72009-05-18 21:47:50 -0700957 private boolean hasService() {
958 if (mServiceState != null) {
959 switch (mServiceState.getState()) {
960 case ServiceState.STATE_OUT_OF_SERVICE:
961 case ServiceState.STATE_POWER_OFF:
962 return false;
963 default:
964 return true;
965 }
966 } else {
967 return false;
968 }
969 }
970
971 private final void updateSignalStrength() {
972 int iconLevel = -1;
Wink Savillee9b06d72009-05-18 21:47:50 -0700973 int[] iconList;
Wink Savillee9b06d72009-05-18 21:47:50 -0700974
975 if (!hasService()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800976 //Slog.d(TAG, "updateSignalStrength: no service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 if (Settings.System.getInt(mContext.getContentResolver(),
978 Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
979 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_flightmode;
980 } else {
981 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_null;
982 }
983 mService.updateIcon(mPhoneIcon, mPhoneData, null);
984 return;
985 }
986
Wink Savillee9b06d72009-05-18 21:47:50 -0700987 if (!isCdma()) {
988 int asu = mSignalStrength.getGsmSignalStrength();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989
Wink Savillee9b06d72009-05-18 21:47:50 -0700990 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
991 // asu = 0 (-113dB or less) is very weak
992 // signal, its better to show 0 bars to the user in such cases.
993 // asu = 99 is a special case, where the signal strength is unknown.
jshee63e472010-03-18 11:14:42 -0700994 if (asu <= 2 || asu == 99) iconLevel = 0;
995 else if (asu >= 12) iconLevel = 4;
Wink Savillee9b06d72009-05-18 21:47:50 -0700996 else if (asu >= 8) iconLevel = 3;
jshee63e472010-03-18 11:14:42 -0700997 else if (asu >= 5) iconLevel = 2;
Wink Savillee9b06d72009-05-18 21:47:50 -0700998 else iconLevel = 1;
999
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001000 // Though mPhone is a Manager, this call is not an IPC
Wink Savillee9b06d72009-05-18 21:47:50 -07001001 if (mPhone.isNetworkRoaming()) {
1002 iconList = sSignalImages_r;
1003 } else {
1004 iconList = sSignalImages;
Wink Saville04e71b32009-04-02 11:00:54 -07001005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 } else {
johnwang347c5a22009-08-24 22:11:11 -07001007 iconList = this.sSignalImages;
Wink Savillee9b06d72009-05-18 21:47:50 -07001008
johnwang347c5a22009-08-24 22:11:11 -07001009 // If 3G(EV) and 1x network are available than 3G should be
1010 // displayed, displayed RSSI should be from the EV side.
1011 // If a voice call is made then RSSI should switch to 1x.
1012 if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
1013 iconLevel = getEvdoLevel();
1014 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001015 Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level=" + getCdmaLevel());
johnwang347c5a22009-08-24 22:11:11 -07001016 }
1017 } else {
1018 iconLevel = getCdmaLevel();
1019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001021 mPhoneData.iconId = iconList[iconLevel];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1023 }
1024
johnwang347c5a22009-08-24 22:11:11 -07001025 private int getCdmaLevel() {
1026 final int cdmaDbm = mSignalStrength.getCdmaDbm();
1027 final int cdmaEcio = mSignalStrength.getCdmaEcio();
1028 int levelDbm = 0;
1029 int levelEcio = 0;
1030
1031 if (cdmaDbm >= -75) levelDbm = 4;
1032 else if (cdmaDbm >= -85) levelDbm = 3;
1033 else if (cdmaDbm >= -95) levelDbm = 2;
1034 else if (cdmaDbm >= -100) levelDbm = 1;
1035 else levelDbm = 0;
1036
1037 // Ec/Io are in dB*10
1038 if (cdmaEcio >= -90) levelEcio = 4;
1039 else if (cdmaEcio >= -110) levelEcio = 3;
1040 else if (cdmaEcio >= -130) levelEcio = 2;
1041 else if (cdmaEcio >= -150) levelEcio = 1;
1042 else levelEcio = 0;
1043
1044 return (levelDbm < levelEcio) ? levelDbm : levelEcio;
1045 }
1046
1047 private int getEvdoLevel() {
1048 int evdoDbm = mSignalStrength.getEvdoDbm();
1049 int evdoSnr = mSignalStrength.getEvdoSnr();
1050 int levelEvdoDbm = 0;
1051 int levelEvdoSnr = 0;
1052
1053 if (evdoDbm >= -65) levelEvdoDbm = 4;
1054 else if (evdoDbm >= -75) levelEvdoDbm = 3;
1055 else if (evdoDbm >= -90) levelEvdoDbm = 2;
1056 else if (evdoDbm >= -105) levelEvdoDbm = 1;
1057 else levelEvdoDbm = 0;
1058
John Michelau1336a562009-09-28 10:41:02 -05001059 if (evdoSnr >= 7) levelEvdoSnr = 4;
1060 else if (evdoSnr >= 5) levelEvdoSnr = 3;
1061 else if (evdoSnr >= 3) levelEvdoSnr = 2;
1062 else if (evdoSnr >= 1) levelEvdoSnr = 1;
johnwang347c5a22009-08-24 22:11:11 -07001063 else levelEvdoSnr = 0;
1064
1065 return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
1066 }
1067
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001068 private final void updateDataNetType(int net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001069
1070 switch (net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001071 case TelephonyManager.NETWORK_TYPE_EDGE:
1072 mDataIconList = sDataNetType_e;
1073 break;
1074 case TelephonyManager.NETWORK_TYPE_UMTS:
1075 mDataIconList = sDataNetType_3g;
1076 break;
Li Zheebe66342009-08-14 19:22:16 +08001077 case TelephonyManager.NETWORK_TYPE_HSDPA:
1078 case TelephonyManager.NETWORK_TYPE_HSUPA:
1079 case TelephonyManager.NETWORK_TYPE_HSPA:
John Wang33e21fc2009-10-08 10:35:27 -07001080 if (mHspaDataDistinguishable) {
1081 mDataIconList = sDataNetType_h;
1082 } else {
1083 mDataIconList = sDataNetType_3g;
1084 }
Li Zheebe66342009-08-14 19:22:16 +08001085 break;
Wink Saville04e71b32009-04-02 11:00:54 -07001086 case TelephonyManager.NETWORK_TYPE_CDMA:
1087 // display 1xRTT for IS95A/B
johnwang9f87cb22009-08-25 15:25:37 -07001088 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001089 break;
1090 case TelephonyManager.NETWORK_TYPE_1xRTT:
johnwang9f87cb22009-08-25 15:25:37 -07001091 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001092 break;
1093 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
1094 case TelephonyManager.NETWORK_TYPE_EVDO_A:
johnwang9f87cb22009-08-25 15:25:37 -07001095 mDataIconList = sDataNetType_3g;
Wink Saville04e71b32009-04-02 11:00:54 -07001096 break;
1097 default:
1098 mDataIconList = sDataNetType_g;
1099 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 }
1101 }
1102
1103 private final void updateDataIcon() {
1104 int iconId;
1105 boolean visible = true;
1106
Wink Savillee9b06d72009-05-18 21:47:50 -07001107 if (!isCdma()) {
1108 // GSM case, we have to check also the sim state
1109 if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
1110 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
1111 switch (mDataActivity) {
1112 case TelephonyManager.DATA_ACTIVITY_IN:
1113 iconId = mDataIconList[1];
1114 break;
1115 case TelephonyManager.DATA_ACTIVITY_OUT:
1116 iconId = mDataIconList[2];
1117 break;
1118 case TelephonyManager.DATA_ACTIVITY_INOUT:
1119 iconId = mDataIconList[3];
1120 break;
1121 default:
1122 iconId = mDataIconList[0];
1123 break;
1124 }
1125 mDataData.iconId = iconId;
1126 mService.updateIcon(mDataIcon, mDataData, null);
1127 } else {
1128 visible = false;
1129 }
1130 } else {
1131 mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
1132 mService.updateIcon(mDataIcon, mDataData, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001134 } else {
1135 // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
1136 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 switch (mDataActivity) {
1138 case TelephonyManager.DATA_ACTIVITY_IN:
Wink Savillee9b06d72009-05-18 21:47:50 -07001139 iconId = mDataIconList[1];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 break;
1141 case TelephonyManager.DATA_ACTIVITY_OUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001142 iconId = mDataIconList[2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 break;
1144 case TelephonyManager.DATA_ACTIVITY_INOUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001145 iconId = mDataIconList[3];
1146 break;
1147 case TelephonyManager.DATA_ACTIVITY_DORMANT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 default:
Wink Savillee9b06d72009-05-18 21:47:50 -07001149 iconId = mDataIconList[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 break;
1151 }
1152 mDataData.iconId = iconId;
1153 mService.updateIcon(mDataIcon, mDataData, null);
1154 } else {
1155 visible = false;
1156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001158
Dianne Hackborn4840e142009-03-24 22:40:29 -07001159 long ident = Binder.clearCallingIdentity();
1160 try {
Wink Saville04e71b32009-04-02 11:00:54 -07001161 mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
Dianne Hackborn4840e142009-03-24 22:40:29 -07001162 } catch (RemoteException e) {
1163 } finally {
1164 Binder.restoreCallingIdentity(ident);
1165 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 if (mDataIconVisible != visible) {
1168 mService.setIconVisibility(mDataIcon, visible);
1169 mDataIconVisible = visible;
1170 }
1171 }
1172
1173 private final void updateVolume() {
1174 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1175 final int ringerMode = audioManager.getRingerMode();
1176 final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
Wink Savillee9b06d72009-05-18 21:47:50 -07001177 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
1179 ? com.android.internal.R.drawable.stat_sys_ringer_vibrate
1180 : com.android.internal.R.drawable.stat_sys_ringer_silent;
1181
1182 if (visible) {
1183 mVolumeData.iconId = iconId;
1184 mService.updateIcon(mVolumeIcon, mVolumeData, null);
1185 }
1186 if (visible != mVolumeVisible) {
1187 mService.setIconVisibility(mVolumeIcon, visible);
1188 mVolumeVisible = visible;
1189 }
1190 }
1191
1192 private final void updateBluetooth(Intent intent) {
1193 int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 String action = intent.getAction();
Nick Pellyde893f52009-09-08 13:15:33 -07001195 if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
Nick Pellyb24e11b2009-09-08 17:40:43 -07001196 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
Nick Pellyde893f52009-09-08 13:15:33 -07001197 mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
Nick Pelly005b2282009-09-10 10:21:56 -07001198 } else if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
1199 mBluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 BluetoothHeadset.STATE_ERROR);
Nick Pelly005b2282009-09-10 10:21:56 -07001201 } else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) {
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001202 BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
1203 if (a2dp.getConnectedSinks().size() != 0) {
1204 mBluetoothA2dpConnected = true;
1205 } else {
1206 mBluetoothA2dpConnected = false;
1207 }
Jiafa Liu3f416732009-07-02 16:36:02 +08001208 } else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
1209 mBluetoothPbapState = intent.getIntExtra(BluetoothPbap.PBAP_STATE,
1210 BluetoothPbap.STATE_DISCONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 } else {
1212 return;
1213 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001214
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001215 if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED || mBluetoothA2dpConnected ||
Jiafa Liu3f416732009-07-02 16:36:02 +08001216 mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
1218 }
1219
1220 mBluetoothData.iconId = iconId;
1221 mService.updateIcon(mBluetoothIcon, mBluetoothData, null);
1222 mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
1223 }
1224
1225 private final void updateWifi(Intent intent) {
1226 final String action = intent.getAction();
1227 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
1230 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
Wink Savillee9b06d72009-05-18 21:47:50 -07001231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 if (!enabled) {
1233 // If disabled, hide the icon. (We show icon when connected.)
1234 mService.setIconVisibility(mWifiIcon, false);
1235 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
1238 final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
1239 false);
1240 if (!enabled) {
1241 mService.setIconVisibility(mWifiIcon, false);
1242 }
1243 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
1244
Wink Savillee9b06d72009-05-18 21:47:50 -07001245 final NetworkInfo networkInfo = (NetworkInfo)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001246 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
Wink Savillee9b06d72009-05-18 21:47:50 -07001247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001248 int iconId;
1249 if (networkInfo != null && networkInfo.isConnected()) {
1250 mIsWifiConnected = true;
1251 if (mLastWifiSignalLevel == -1) {
1252 iconId = sWifiSignalImages[0];
1253 } else {
1254 iconId = sWifiSignalImages[mLastWifiSignalLevel];
1255 }
Wink Saville04e71b32009-04-02 11:00:54 -07001256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 // Show the icon since wi-fi is connected
1258 mService.setIconVisibility(mWifiIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 } else {
1261 mLastWifiSignalLevel = -1;
1262 mIsWifiConnected = false;
1263 iconId = sWifiSignalImages[0];
1264
1265 // Hide the icon since we're not connected
1266 mService.setIconVisibility(mWifiIcon, false);
1267 }
1268
1269 mWifiData.iconId = iconId;
1270 mService.updateIcon(mWifiIcon, mWifiData, null);
1271 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
1272 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
1273 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
1274 sWifiSignalImages.length);
1275 if (newSignalLevel != mLastWifiSignalLevel) {
1276 mLastWifiSignalLevel = newSignalLevel;
1277 if (mIsWifiConnected) {
1278 mWifiData.iconId = sWifiSignalImages[newSignalLevel];
1279 } else {
1280 mWifiData.iconId = sWifiTemporarilyNotConnectedImage;
1281 }
1282 mService.updateIcon(mWifiIcon, mWifiData, null);
1283 }
1284 }
1285 }
1286
1287 private final void updateGps(Intent intent) {
1288 final String action = intent.getAction();
1289 final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED, false);
1290
1291 if (action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION) && enabled) {
1292 // GPS is getting fixes
1293 mService.updateIcon(mGpsIcon, mGpsFixIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001294 mService.setIconVisibility(mGpsIcon, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001295 } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
1296 // GPS is off
Wink Savillee9b06d72009-05-18 21:47:50 -07001297 mService.setIconVisibility(mGpsIcon, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 } else {
1299 // GPS is on, but not receiving fixes
1300 mService.updateIcon(mGpsIcon, mGpsEnabledIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001301 mService.setIconVisibility(mGpsIcon, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 }
1303 }
1304
Wink Savillee9b06d72009-05-18 21:47:50 -07001305 private final void updateTTY(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -07001306 final String action = intent.getAction();
1307 final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
1308
Joe Onorato8a9b2202010-02-26 18:56:32 -08001309 if (false) Slog.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -07001310
1311 if (enabled) {
1312 // TTY is on
Joe Onorato8a9b2202010-02-26 18:56:32 -08001313 if (false) Slog.v(TAG, "updateTTY: set TTY on");
Wink Saville04e71b32009-04-02 11:00:54 -07001314 mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001315 mService.setIconVisibility(mTTYModeIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001316 } else {
1317 // TTY is off
Joe Onorato8a9b2202010-02-26 18:56:32 -08001318 if (false) Slog.v(TAG, "updateTTY: set TTY off");
Wink Savillee9b06d72009-05-18 21:47:50 -07001319 mService.setIconVisibility(mTTYModeIcon, false);
Wink Saville04e71b32009-04-02 11:00:54 -07001320 }
1321 }
1322
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001323 private final void updateCdmaRoamingIcon(ServiceState state) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001324 if (!hasService()) {
1325 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001326 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001327 }
1328
1329 if (!isCdma()) {
1330 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001331 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001332 }
1333
1334 int[] iconList = sRoamingIndicatorImages_cdma;
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001335 int iconIndex = state.getCdmaEriIconIndex();
1336 int iconMode = state.getCdmaEriIconMode();
Wink Savillee9b06d72009-05-18 21:47:50 -07001337
1338 if (iconIndex == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001339 Slog.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001340 return;
1341 }
1342
1343 if (iconMode == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001344 Slog.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001345 return;
1346 }
1347
1348 if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001349 if (false) Slog.v(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
Wink Savillee9b06d72009-05-18 21:47:50 -07001350 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
1351 return;
1352 }
1353
1354 switch (iconMode) {
1355 case EriInfo.ROAMING_ICON_MODE_NORMAL:
1356 mCdmaRoamingIndicatorIconData.iconId = iconList[iconIndex];
1357 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
1358 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
1359 break;
1360 case EriInfo.ROAMING_ICON_MODE_FLASH:
Wink Savillef3152382009-06-01 14:39:20 -07001361 mCdmaRoamingIndicatorIconData.iconId =
1362 com.android.internal.R.drawable.stat_sys_roaming_cdma_flash;
Wink Savillee9b06d72009-05-18 21:47:50 -07001363 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
Wink Savillef3152382009-06-01 14:39:20 -07001364 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
Wink Savillee9b06d72009-05-18 21:47:50 -07001365 break;
1366
1367 }
1368 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1369 }
1370
1371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 private class StatusBarHandler extends Handler {
1373 @Override
1374 public void handleMessage(Message msg) {
1375 switch (msg.what) {
1376 case EVENT_BATTERY_CLOSE:
1377 if (msg.arg1 == mBatteryViewSequence) {
1378 closeLastBatteryView();
1379 }
1380 break;
1381 }
1382 }
1383 }
1384}