blob: 465ff2e4508fb49954f495f227bcbeab8304335a [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,
John Wang56c2d2f2010-04-07 08:57:17 -0700821 Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500822 {
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
John Wang56c2d2f2010-04-07 08:57:17 -0700975 // Display signal strength while in "emergency calls only" mode
976 if (!hasService() && !mServiceState.isEmergencyOnly()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800977 //Slog.d(TAG, "updateSignalStrength: no service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 if (Settings.System.getInt(mContext.getContentResolver(),
979 Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
980 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_flightmode;
981 } else {
982 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_null;
983 }
984 mService.updateIcon(mPhoneIcon, mPhoneData, null);
985 return;
986 }
987
Wink Savillee9b06d72009-05-18 21:47:50 -0700988 if (!isCdma()) {
989 int asu = mSignalStrength.getGsmSignalStrength();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990
Wink Savillee9b06d72009-05-18 21:47:50 -0700991 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
992 // asu = 0 (-113dB or less) is very weak
993 // signal, its better to show 0 bars to the user in such cases.
994 // asu = 99 is a special case, where the signal strength is unknown.
jshee63e472010-03-18 11:14:42 -0700995 if (asu <= 2 || asu == 99) iconLevel = 0;
996 else if (asu >= 12) iconLevel = 4;
Wink Savillee9b06d72009-05-18 21:47:50 -0700997 else if (asu >= 8) iconLevel = 3;
jshee63e472010-03-18 11:14:42 -0700998 else if (asu >= 5) iconLevel = 2;
Wink Savillee9b06d72009-05-18 21:47:50 -0700999 else iconLevel = 1;
1000
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001001 // Though mPhone is a Manager, this call is not an IPC
Wink Savillee9b06d72009-05-18 21:47:50 -07001002 if (mPhone.isNetworkRoaming()) {
1003 iconList = sSignalImages_r;
1004 } else {
1005 iconList = sSignalImages;
Wink Saville04e71b32009-04-02 11:00:54 -07001006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 } else {
johnwang347c5a22009-08-24 22:11:11 -07001008 iconList = this.sSignalImages;
Wink Savillee9b06d72009-05-18 21:47:50 -07001009
johnwang347c5a22009-08-24 22:11:11 -07001010 // If 3G(EV) and 1x network are available than 3G should be
1011 // displayed, displayed RSSI should be from the EV side.
1012 // If a voice call is made then RSSI should switch to 1x.
1013 if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
1014 iconLevel = getEvdoLevel();
1015 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001016 Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level=" + getCdmaLevel());
johnwang347c5a22009-08-24 22:11:11 -07001017 }
1018 } else {
1019 iconLevel = getCdmaLevel();
1020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001022 mPhoneData.iconId = iconList[iconLevel];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1024 }
1025
johnwang347c5a22009-08-24 22:11:11 -07001026 private int getCdmaLevel() {
1027 final int cdmaDbm = mSignalStrength.getCdmaDbm();
1028 final int cdmaEcio = mSignalStrength.getCdmaEcio();
1029 int levelDbm = 0;
1030 int levelEcio = 0;
1031
1032 if (cdmaDbm >= -75) levelDbm = 4;
1033 else if (cdmaDbm >= -85) levelDbm = 3;
1034 else if (cdmaDbm >= -95) levelDbm = 2;
1035 else if (cdmaDbm >= -100) levelDbm = 1;
1036 else levelDbm = 0;
1037
1038 // Ec/Io are in dB*10
1039 if (cdmaEcio >= -90) levelEcio = 4;
1040 else if (cdmaEcio >= -110) levelEcio = 3;
1041 else if (cdmaEcio >= -130) levelEcio = 2;
1042 else if (cdmaEcio >= -150) levelEcio = 1;
1043 else levelEcio = 0;
1044
1045 return (levelDbm < levelEcio) ? levelDbm : levelEcio;
1046 }
1047
1048 private int getEvdoLevel() {
1049 int evdoDbm = mSignalStrength.getEvdoDbm();
1050 int evdoSnr = mSignalStrength.getEvdoSnr();
1051 int levelEvdoDbm = 0;
1052 int levelEvdoSnr = 0;
1053
1054 if (evdoDbm >= -65) levelEvdoDbm = 4;
1055 else if (evdoDbm >= -75) levelEvdoDbm = 3;
1056 else if (evdoDbm >= -90) levelEvdoDbm = 2;
1057 else if (evdoDbm >= -105) levelEvdoDbm = 1;
1058 else levelEvdoDbm = 0;
1059
John Michelau1336a562009-09-28 10:41:02 -05001060 if (evdoSnr >= 7) levelEvdoSnr = 4;
1061 else if (evdoSnr >= 5) levelEvdoSnr = 3;
1062 else if (evdoSnr >= 3) levelEvdoSnr = 2;
1063 else if (evdoSnr >= 1) levelEvdoSnr = 1;
johnwang347c5a22009-08-24 22:11:11 -07001064 else levelEvdoSnr = 0;
1065
1066 return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
1067 }
1068
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001069 private final void updateDataNetType(int net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001070
1071 switch (net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001072 case TelephonyManager.NETWORK_TYPE_EDGE:
1073 mDataIconList = sDataNetType_e;
1074 break;
1075 case TelephonyManager.NETWORK_TYPE_UMTS:
1076 mDataIconList = sDataNetType_3g;
1077 break;
Li Zheebe66342009-08-14 19:22:16 +08001078 case TelephonyManager.NETWORK_TYPE_HSDPA:
1079 case TelephonyManager.NETWORK_TYPE_HSUPA:
1080 case TelephonyManager.NETWORK_TYPE_HSPA:
John Wang33e21fc2009-10-08 10:35:27 -07001081 if (mHspaDataDistinguishable) {
1082 mDataIconList = sDataNetType_h;
1083 } else {
1084 mDataIconList = sDataNetType_3g;
1085 }
Li Zheebe66342009-08-14 19:22:16 +08001086 break;
Wink Saville04e71b32009-04-02 11:00:54 -07001087 case TelephonyManager.NETWORK_TYPE_CDMA:
1088 // display 1xRTT for IS95A/B
johnwang9f87cb22009-08-25 15:25:37 -07001089 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001090 break;
1091 case TelephonyManager.NETWORK_TYPE_1xRTT:
johnwang9f87cb22009-08-25 15:25:37 -07001092 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001093 break;
1094 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
1095 case TelephonyManager.NETWORK_TYPE_EVDO_A:
johnwang9f87cb22009-08-25 15:25:37 -07001096 mDataIconList = sDataNetType_3g;
Wink Saville04e71b32009-04-02 11:00:54 -07001097 break;
1098 default:
1099 mDataIconList = sDataNetType_g;
1100 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 }
1102 }
1103
1104 private final void updateDataIcon() {
1105 int iconId;
1106 boolean visible = true;
1107
Wink Savillee9b06d72009-05-18 21:47:50 -07001108 if (!isCdma()) {
1109 // GSM case, we have to check also the sim state
1110 if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
1111 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
1112 switch (mDataActivity) {
1113 case TelephonyManager.DATA_ACTIVITY_IN:
1114 iconId = mDataIconList[1];
1115 break;
1116 case TelephonyManager.DATA_ACTIVITY_OUT:
1117 iconId = mDataIconList[2];
1118 break;
1119 case TelephonyManager.DATA_ACTIVITY_INOUT:
1120 iconId = mDataIconList[3];
1121 break;
1122 default:
1123 iconId = mDataIconList[0];
1124 break;
1125 }
1126 mDataData.iconId = iconId;
1127 mService.updateIcon(mDataIcon, mDataData, null);
1128 } else {
1129 visible = false;
1130 }
1131 } else {
1132 mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
1133 mService.updateIcon(mDataIcon, mDataData, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001135 } else {
1136 // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
1137 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 switch (mDataActivity) {
1139 case TelephonyManager.DATA_ACTIVITY_IN:
Wink Savillee9b06d72009-05-18 21:47:50 -07001140 iconId = mDataIconList[1];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 break;
1142 case TelephonyManager.DATA_ACTIVITY_OUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001143 iconId = mDataIconList[2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 break;
1145 case TelephonyManager.DATA_ACTIVITY_INOUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001146 iconId = mDataIconList[3];
1147 break;
1148 case TelephonyManager.DATA_ACTIVITY_DORMANT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 default:
Wink Savillee9b06d72009-05-18 21:47:50 -07001150 iconId = mDataIconList[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 break;
1152 }
1153 mDataData.iconId = iconId;
1154 mService.updateIcon(mDataIcon, mDataData, null);
1155 } else {
1156 visible = false;
1157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001159
Dianne Hackborn4840e142009-03-24 22:40:29 -07001160 long ident = Binder.clearCallingIdentity();
1161 try {
Wink Saville04e71b32009-04-02 11:00:54 -07001162 mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
Dianne Hackborn4840e142009-03-24 22:40:29 -07001163 } catch (RemoteException e) {
1164 } finally {
1165 Binder.restoreCallingIdentity(ident);
1166 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 if (mDataIconVisible != visible) {
1169 mService.setIconVisibility(mDataIcon, visible);
1170 mDataIconVisible = visible;
1171 }
1172 }
1173
1174 private final void updateVolume() {
1175 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1176 final int ringerMode = audioManager.getRingerMode();
1177 final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
Wink Savillee9b06d72009-05-18 21:47:50 -07001178 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
1180 ? com.android.internal.R.drawable.stat_sys_ringer_vibrate
1181 : com.android.internal.R.drawable.stat_sys_ringer_silent;
1182
1183 if (visible) {
1184 mVolumeData.iconId = iconId;
1185 mService.updateIcon(mVolumeIcon, mVolumeData, null);
1186 }
1187 if (visible != mVolumeVisible) {
1188 mService.setIconVisibility(mVolumeIcon, visible);
1189 mVolumeVisible = visible;
1190 }
1191 }
1192
1193 private final void updateBluetooth(Intent intent) {
1194 int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 String action = intent.getAction();
Nick Pellyde893f52009-09-08 13:15:33 -07001196 if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
Nick Pellyb24e11b2009-09-08 17:40:43 -07001197 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
Nick Pellyde893f52009-09-08 13:15:33 -07001198 mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
Nick Pelly005b2282009-09-10 10:21:56 -07001199 } else if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
1200 mBluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 BluetoothHeadset.STATE_ERROR);
Nick Pelly005b2282009-09-10 10:21:56 -07001202 } else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) {
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001203 BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
1204 if (a2dp.getConnectedSinks().size() != 0) {
1205 mBluetoothA2dpConnected = true;
1206 } else {
1207 mBluetoothA2dpConnected = false;
1208 }
Jiafa Liu3f416732009-07-02 16:36:02 +08001209 } else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
1210 mBluetoothPbapState = intent.getIntExtra(BluetoothPbap.PBAP_STATE,
1211 BluetoothPbap.STATE_DISCONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 } else {
1213 return;
1214 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001215
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001216 if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED || mBluetoothA2dpConnected ||
Jiafa Liu3f416732009-07-02 16:36:02 +08001217 mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
1219 }
1220
1221 mBluetoothData.iconId = iconId;
1222 mService.updateIcon(mBluetoothIcon, mBluetoothData, null);
1223 mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
1224 }
1225
1226 private final void updateWifi(Intent intent) {
1227 final String action = intent.getAction();
1228 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
1231 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
Wink Savillee9b06d72009-05-18 21:47:50 -07001232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001233 if (!enabled) {
1234 // If disabled, hide the icon. (We show icon when connected.)
1235 mService.setIconVisibility(mWifiIcon, false);
1236 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
1239 final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
1240 false);
1241 if (!enabled) {
1242 mService.setIconVisibility(mWifiIcon, false);
1243 }
1244 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
1245
Wink Savillee9b06d72009-05-18 21:47:50 -07001246 final NetworkInfo networkInfo = (NetworkInfo)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
Wink Savillee9b06d72009-05-18 21:47:50 -07001248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 int iconId;
1250 if (networkInfo != null && networkInfo.isConnected()) {
1251 mIsWifiConnected = true;
1252 if (mLastWifiSignalLevel == -1) {
1253 iconId = sWifiSignalImages[0];
1254 } else {
1255 iconId = sWifiSignalImages[mLastWifiSignalLevel];
1256 }
Wink Saville04e71b32009-04-02 11:00:54 -07001257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 // Show the icon since wi-fi is connected
1259 mService.setIconVisibility(mWifiIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 } else {
1262 mLastWifiSignalLevel = -1;
1263 mIsWifiConnected = false;
1264 iconId = sWifiSignalImages[0];
1265
1266 // Hide the icon since we're not connected
1267 mService.setIconVisibility(mWifiIcon, false);
1268 }
1269
1270 mWifiData.iconId = iconId;
1271 mService.updateIcon(mWifiIcon, mWifiData, null);
1272 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
1273 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
1274 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
1275 sWifiSignalImages.length);
1276 if (newSignalLevel != mLastWifiSignalLevel) {
1277 mLastWifiSignalLevel = newSignalLevel;
1278 if (mIsWifiConnected) {
1279 mWifiData.iconId = sWifiSignalImages[newSignalLevel];
1280 } else {
1281 mWifiData.iconId = sWifiTemporarilyNotConnectedImage;
1282 }
1283 mService.updateIcon(mWifiIcon, mWifiData, null);
1284 }
1285 }
1286 }
1287
1288 private final void updateGps(Intent intent) {
1289 final String action = intent.getAction();
1290 final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED, false);
1291
1292 if (action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION) && enabled) {
1293 // GPS is getting fixes
1294 mService.updateIcon(mGpsIcon, mGpsFixIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001295 mService.setIconVisibility(mGpsIcon, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296 } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
1297 // GPS is off
Wink Savillee9b06d72009-05-18 21:47:50 -07001298 mService.setIconVisibility(mGpsIcon, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 } else {
1300 // GPS is on, but not receiving fixes
1301 mService.updateIcon(mGpsIcon, mGpsEnabledIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001302 mService.setIconVisibility(mGpsIcon, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 }
1304 }
1305
Wink Savillee9b06d72009-05-18 21:47:50 -07001306 private final void updateTTY(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -07001307 final String action = intent.getAction();
1308 final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
1309
Joe Onorato8a9b2202010-02-26 18:56:32 -08001310 if (false) Slog.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -07001311
1312 if (enabled) {
1313 // TTY is on
Joe Onorato8a9b2202010-02-26 18:56:32 -08001314 if (false) Slog.v(TAG, "updateTTY: set TTY on");
Wink Saville04e71b32009-04-02 11:00:54 -07001315 mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001316 mService.setIconVisibility(mTTYModeIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001317 } else {
1318 // TTY is off
Joe Onorato8a9b2202010-02-26 18:56:32 -08001319 if (false) Slog.v(TAG, "updateTTY: set TTY off");
Wink Savillee9b06d72009-05-18 21:47:50 -07001320 mService.setIconVisibility(mTTYModeIcon, false);
Wink Saville04e71b32009-04-02 11:00:54 -07001321 }
1322 }
1323
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001324 private final void updateCdmaRoamingIcon(ServiceState state) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001325 if (!hasService()) {
1326 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001327 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001328 }
1329
1330 if (!isCdma()) {
1331 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001332 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001333 }
1334
1335 int[] iconList = sRoamingIndicatorImages_cdma;
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001336 int iconIndex = state.getCdmaEriIconIndex();
1337 int iconMode = state.getCdmaEriIconMode();
Wink Savillee9b06d72009-05-18 21:47:50 -07001338
1339 if (iconIndex == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001340 Slog.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001341 return;
1342 }
1343
1344 if (iconMode == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001345 Slog.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001346 return;
1347 }
1348
1349 if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001350 if (false) Slog.v(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
Wink Savillee9b06d72009-05-18 21:47:50 -07001351 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
1352 return;
1353 }
1354
1355 switch (iconMode) {
1356 case EriInfo.ROAMING_ICON_MODE_NORMAL:
1357 mCdmaRoamingIndicatorIconData.iconId = iconList[iconIndex];
1358 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
1359 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
1360 break;
1361 case EriInfo.ROAMING_ICON_MODE_FLASH:
Wink Savillef3152382009-06-01 14:39:20 -07001362 mCdmaRoamingIndicatorIconData.iconId =
1363 com.android.internal.R.drawable.stat_sys_roaming_cdma_flash;
Wink Savillee9b06d72009-05-18 21:47:50 -07001364 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
Wink Savillef3152382009-06-01 14:39:20 -07001365 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
Wink Savillee9b06d72009-05-18 21:47:50 -07001366 break;
1367
1368 }
1369 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1370 }
1371
1372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 private class StatusBarHandler extends Handler {
1374 @Override
1375 public void handleMessage(Message msg) {
1376 switch (msg.what) {
1377 case EVENT_BATTERY_CLOSE:
1378 if (msg.arg1 == mBatteryViewSequence) {
1379 closeLastBatteryView();
1380 }
1381 break;
1382 }
1383 }
1384 }
1385}