blob: cab2662126a2fb196fb4321eee3de5f36e618d73 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.status;
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019import android.app.AlertDialog;
20import android.bluetooth.BluetoothA2dp;
Nick Pellybd022f42009-08-14 18:33:38 -070021import android.bluetooth.BluetoothAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.bluetooth.BluetoothHeadset;
Jiafa Liu3f416732009-07-02 16:36:02 +080023import android.bluetooth.BluetoothPbap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.BroadcastReceiver;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050025import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.content.Context;
27import android.content.DialogInterface;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.res.TypedArray;
31import android.graphics.PixelFormat;
Daniel Sandler2c195f72010-05-21 15:42:06 -040032import android.graphics.Typeface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.graphics.drawable.Drawable;
Mike Lockwood00b74272010-03-26 10:41:48 -040034import android.location.LocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.media.AudioManager;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050036import android.media.Ringtone;
37import android.media.RingtoneManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.net.NetworkInfo;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050039import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.net.wifi.WifiManager;
Dianne Hackborn4840e142009-03-24 22:40:29 -070041import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.Handler;
43import android.os.IBinder;
44import android.os.Message;
Dianne Hackborn4840e142009-03-24 22:40:29 -070045import android.os.RemoteException;
San Mehat4154c072010-02-09 18:37:54 -080046import android.os.storage.StorageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.provider.Settings;
48import android.telephony.PhoneStateListener;
49import android.telephony.ServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -070050import android.telephony.SignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.telephony.TelephonyManager;
52import android.text.format.DateFormat;
Daniel Sandler2c195f72010-05-21 15:42:06 -040053import android.text.style.CharacterStyle;
Eric Fischer36e136c2010-01-14 17:42:48 -080054import android.text.style.RelativeSizeSpan;
Daniel Sandler2c195f72010-05-21 15:42:06 -040055import android.text.style.ForegroundColorSpan;
56import android.text.style.StyleSpan;
Eric Fischer36e136c2010-01-14 17:42:48 -080057import android.text.Spannable;
58import android.text.SpannableStringBuilder;
Joe Onorato8a9b2202010-02-26 18:56:32 -080059import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.view.View;
61import android.view.ViewGroup;
62import android.view.WindowManager;
63import android.view.WindowManagerImpl;
64import android.widget.ImageView;
65import android.widget.LinearLayout;
66import android.widget.TextView;
67
Wink Saville04e71b32009-04-02 11:00:54 -070068import com.android.internal.R;
69import com.android.internal.app.IBatteryStats;
Wink Saville04e71b32009-04-02 11:00:54 -070070import com.android.internal.telephony.IccCard;
71import com.android.internal.telephony.TelephonyIntents;
Wink Savillee9b06d72009-05-18 21:47:50 -070072import com.android.internal.telephony.cdma.EriInfo;
Wink Saville04e71b32009-04-02 11:00:54 -070073import com.android.internal.telephony.cdma.TtyIntent;
74import com.android.server.am.BatteryStatsService;
75
Eric Fischer36e136c2010-01-14 17:42:48 -080076import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import java.util.Calendar;
78import java.util.TimeZone;
79
80/**
81 * This class contains all of the policy about which icons are installed in the status
82 * bar at boot time. In reality, it should go into the android.policy package, but
83 * putting it here is the first step from extracting it.
84 */
85public class StatusBarPolicy {
86 private static final String TAG = "StatusBarPolicy";
87
88 private static StatusBarPolicy sInstance;
89
90 // message codes for the handler
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 private static final int EVENT_BATTERY_CLOSE = 4;
92
Daniel Sandler2c195f72010-05-21 15:42:06 -040093 private static final int AM_PM_STYLE_NORMAL = 0;
94 private static final int AM_PM_STYLE_SMALL = 1;
95 private static final int AM_PM_STYLE_GONE = 2;
96
97 private static final int AM_PM_STYLE = AM_PM_STYLE_GONE;
98
Dianne Hackborn4840e142009-03-24 22:40:29 -070099 private final Context mContext;
100 private final StatusBarService mService;
101 private final Handler mHandler = new StatusBarHandler();
102 private final IBatteryStats mBatteryStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103
104 // clock
105 private Calendar mCalendar;
Joe Onorato63ce8e82010-01-17 19:06:51 -0500106 private String mClockFormatString;
107 private SimpleDateFormat mClockFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 private IBinder mClockIcon;
109 private IconData mClockData;
110
San Mehat4154c072010-02-09 18:37:54 -0800111 // storage
112 private StorageManager mStorageManager;
113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 // battery
115 private IBinder mBatteryIcon;
116 private IconData mBatteryData;
117 private boolean mBatteryFirst = true;
118 private boolean mBatteryPlugged;
119 private int mBatteryLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 private AlertDialog mLowBatteryDialog;
121 private TextView mBatteryLevelTextView;
122 private View mBatteryView;
123 private int mBatteryViewSequence;
124 private boolean mBatteryShowLowOnEndCall = false;
125 private static final boolean SHOW_LOW_BATTERY_WARNING = true;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500126 private static final boolean SHOW_BATTERY_WARNINGS_IN_CALL = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127
128 // phone
129 private TelephonyManager mPhone;
130 private IBinder mPhoneIcon;
Wink Saville04e71b32009-04-02 11:00:54 -0700131
132 //***** Signal strength icons
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 private IconData mPhoneData;
Wink Saville04e71b32009-04-02 11:00:54 -0700134 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 private static final int[] sSignalImages = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700136 com.android.internal.R.drawable.stat_sys_signal_0,
137 com.android.internal.R.drawable.stat_sys_signal_1,
138 com.android.internal.R.drawable.stat_sys_signal_2,
139 com.android.internal.R.drawable.stat_sys_signal_3,
140 com.android.internal.R.drawable.stat_sys_signal_4
141 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 private static final int[] sSignalImages_r = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700143 com.android.internal.R.drawable.stat_sys_r_signal_0,
144 com.android.internal.R.drawable.stat_sys_r_signal_1,
145 com.android.internal.R.drawable.stat_sys_r_signal_2,
146 com.android.internal.R.drawable.stat_sys_r_signal_3,
147 com.android.internal.R.drawable.stat_sys_r_signal_4
148 };
Wink Savillee9b06d72009-05-18 21:47:50 -0700149 private static final int[] sRoamingIndicatorImages_cdma = new int[] {
150 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
151 // 1 is Standard Roaming Indicator OFF
152 // TODO T: image never used, remove and put 0 instead?
153 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
154
155 // 2 is Standard Roaming Indicator FLASHING
156 // TODO T: image never used, remove and put 0 instead?
157 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
158
159 // 3-12 Standard ERI
160 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //3
161 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
162 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
163 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
164 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
165 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
166 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
167 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
168 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
169 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
170
171 // 13-63 Reserved for Standard ERI
172 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //13
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 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
214 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
215 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
216 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
217 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
218 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
219 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
220 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
221 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
222 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
223
224 // 64-127 Reserved for Non Standard (Operator Specific) ERI
225 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //64
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,
235 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
236 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
237 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
238 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
239 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
240 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
241 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
242 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
243 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
244 com.android.internal.R.drawable.stat_sys_roaming_cdma_0 //83
245
246 // 128-255 Reserved
Wink Saville04e71b32009-04-02 11:00:54 -0700247 };
Wink Saville04e71b32009-04-02 11:00:54 -0700248
249 //***** Data connection icons
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 private int[] mDataIconList = sDataNetType_g;
Wink Saville04e71b32009-04-02 11:00:54 -0700251 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 private static final int[] sDataNetType_g = new int[] {
253 com.android.internal.R.drawable.stat_sys_data_connected_g,
254 com.android.internal.R.drawable.stat_sys_data_in_g,
255 com.android.internal.R.drawable.stat_sys_data_out_g,
256 com.android.internal.R.drawable.stat_sys_data_inandout_g,
257 };
258 private static final int[] sDataNetType_3g = new int[] {
259 com.android.internal.R.drawable.stat_sys_data_connected_3g,
260 com.android.internal.R.drawable.stat_sys_data_in_3g,
261 com.android.internal.R.drawable.stat_sys_data_out_3g,
262 com.android.internal.R.drawable.stat_sys_data_inandout_3g,
263 };
264 private static final int[] sDataNetType_e = new int[] {
265 com.android.internal.R.drawable.stat_sys_data_connected_e,
266 com.android.internal.R.drawable.stat_sys_data_in_e,
267 com.android.internal.R.drawable.stat_sys_data_out_e,
268 com.android.internal.R.drawable.stat_sys_data_inandout_e,
269 };
Li Zheebe66342009-08-14 19:22:16 +0800270 //3.5G
271 private static final int[] sDataNetType_h = new int[] {
272 com.android.internal.R.drawable.stat_sys_data_connected_h,
273 com.android.internal.R.drawable.stat_sys_data_in_h,
274 com.android.internal.R.drawable.stat_sys_data_out_h,
275 com.android.internal.R.drawable.stat_sys_data_inandout_h,
276 };
277
Wink Saville04e71b32009-04-02 11:00:54 -0700278 //CDMA
johnwang9f87cb22009-08-25 15:25:37 -0700279 // Use 3G icons for EVDO data and 1x icons for 1XRTT data
280 private static final int[] sDataNetType_1x = new int[] {
281 com.android.internal.R.drawable.stat_sys_data_connected_1x,
282 com.android.internal.R.drawable.stat_sys_data_in_1x,
283 com.android.internal.R.drawable.stat_sys_data_out_1x,
284 com.android.internal.R.drawable.stat_sys_data_inandout_1x,
Wink Saville04e71b32009-04-02 11:00:54 -0700285 };
286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 // Assume it's all good unless we hear otherwise. We don't always seem
288 // to get broadcasts that it *is* there.
Wink Saville04e71b32009-04-02 11:00:54 -0700289 IccCard.State mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
291 int mDataState = TelephonyManager.DATA_DISCONNECTED;
292 int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
293 ServiceState mServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -0700294 SignalStrength mSignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295
296 // data connection
297 private IBinder mDataIcon;
298 private IconData mDataData;
299 private boolean mDataIconVisible;
John Wang33e21fc2009-10-08 10:35:27 -0700300 private boolean mHspaDataDistinguishable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301
302 // ringer volume
303 private IBinder mVolumeIcon;
304 private IconData mVolumeData;
305 private boolean mVolumeVisible;
Wink Saville04e71b32009-04-02 11:00:54 -0700306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 // bluetooth device status
308 private IBinder mBluetoothIcon;
309 private IconData mBluetoothData;
310 private int mBluetoothHeadsetState;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800311 private boolean mBluetoothA2dpConnected;
Jiafa Liu3f416732009-07-02 16:36:02 +0800312 private int mBluetoothPbapState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 private boolean mBluetoothEnabled;
314
315 // wifi
316 private static final int[] sWifiSignalImages = new int[] {
317 com.android.internal.R.drawable.stat_sys_wifi_signal_1,
318 com.android.internal.R.drawable.stat_sys_wifi_signal_2,
319 com.android.internal.R.drawable.stat_sys_wifi_signal_3,
320 com.android.internal.R.drawable.stat_sys_wifi_signal_4,
321 };
322 private static final int sWifiTemporarilyNotConnectedImage =
323 com.android.internal.R.drawable.stat_sys_wifi_signal_0;
324
325 private int mLastWifiSignalLevel = -1;
326 private boolean mIsWifiConnected = false;
327 private IBinder mWifiIcon;
328 private IconData mWifiData;
329
330 // gps
331 private IBinder mGpsIcon;
332 private IconData mGpsEnabledIconData;
333 private IconData mGpsFixIconData;
334
335 // alarm clock
336 // Icon lit when clock is set
337 private IBinder mAlarmClockIcon;
338 private IconData mAlarmClockIconData;
339
340 // sync state
341 // If sync is active the SyncActive icon is displayed. If sync is not active but
342 // sync is failing the SyncFailing icon is displayed. Otherwise neither are displayed.
343 private IBinder mSyncActiveIcon;
344 private IBinder mSyncFailingIcon;
345
Wink Saville04e71b32009-04-02 11:00:54 -0700346 // TTY mode
347 // Icon lit when TTY mode is enabled
348 private IBinder mTTYModeIcon;
349 private IconData mTTYModeEnableIconData;
350
Wink Savillee9b06d72009-05-18 21:47:50 -0700351 // Cdma Roaming Indicator, ERI
352 private IBinder mCdmaRoamingIndicatorIcon;
353 private IconData mCdmaRoamingIndicatorIconData;
354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
356 @Override
357 public void onReceive(Context context, Intent intent) {
358 String action = intent.getAction();
359 if (action.equals(Intent.ACTION_TIME_TICK)) {
360 updateClock();
361 }
362 else if (action.equals(Intent.ACTION_TIME_CHANGED)) {
363 updateClock();
364 }
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700365 else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
366 updateBattery(intent);
367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
369 updateClock();
370 }
371 else if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
372 String tz = intent.getStringExtra("time-zone");
373 mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz));
Amith Yamasanic4938fd2010-04-28 13:20:43 -0700374 if (mClockFormat != null) {
375 mClockFormat.setTimeZone(mCalendar.getTimeZone());
376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 updateClock();
378 }
379 else if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
380 updateAlarm(intent);
381 }
382 else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
383 updateSyncState(intent);
384 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200385 else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
386 onBatteryLow(intent);
387 }
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400388 else if (action.equals(Intent.ACTION_BATTERY_OKAY)
389 || action.equals(Intent.ACTION_POWER_CONNECTED)) {
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700390 onBatteryOkay(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 }
Nick Pellyde893f52009-09-08 13:15:33 -0700392 else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
Nick Pelly005b2282009-09-10 10:21:56 -0700393 action.equals(BluetoothHeadset.ACTION_STATE_CHANGED) ||
394 action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED) ||
Jiafa Liu3f416732009-07-02 16:36:02 +0800395 action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 updateBluetooth(intent);
397 }
398 else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
399 action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) ||
400 action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
401 updateWifi(intent);
402 }
Mike Lockwood00b74272010-03-26 10:41:48 -0400403 else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) ||
404 action.equals(LocationManager.GPS_FIX_CHANGE_ACTION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 updateGps(intent);
406 }
407 else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
408 action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
409 updateVolume();
410 }
411 else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
412 updateSimState(intent);
413 }
Wink Saville04e71b32009-04-02 11:00:54 -0700414 else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
415 updateTTY(intent);
416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 }
418 };
419
420 private StatusBarPolicy(Context context, StatusBarService service) {
421 mContext = context;
422 mService = service;
Wink Savillee9b06d72009-05-18 21:47:50 -0700423 mSignalStrength = new SignalStrength();
Dianne Hackborn4840e142009-03-24 22:40:29 -0700424 mBatteryStats = BatteryStatsService.getService();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425
426 // clock
427 mCalendar = Calendar.getInstance(TimeZone.getDefault());
428 mClockData = IconData.makeText("clock", "");
429 mClockIcon = service.addIcon(mClockData, null);
430 updateClock();
431
San Mehat4154c072010-02-09 18:37:54 -0800432 // storage
433 mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
434 mStorageManager.registerListener(
435 new com.android.server.status.StorageNotification(context));
436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 // battery
438 mBatteryData = IconData.makeIcon("battery",
439 null, com.android.internal.R.drawable.stat_sys_battery_unknown, 0, 0);
440 mBatteryIcon = service.addIcon(mBatteryData, null);
441
442 // phone_signal
443 mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Wink Savillee9b06d72009-05-18 21:47:50 -0700444 mPhoneData = IconData.makeIcon("phone_signal",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
446 mPhoneIcon = service.addIcon(mPhoneData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -0700447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 // register for phone state notifications.
449 ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
450 .listen(mPhoneStateListener,
451 PhoneStateListener.LISTEN_SERVICE_STATE
Wink Savillee9b06d72009-05-18 21:47:50 -0700452 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 | PhoneStateListener.LISTEN_CALL_STATE
454 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
455 | PhoneStateListener.LISTEN_DATA_ACTIVITY);
456
457 // data_connection
458 mDataData = IconData.makeIcon("data_connection",
459 null, com.android.internal.R.drawable.stat_sys_data_connected_g, 0, 0);
460 mDataIcon = service.addIcon(mDataData, null);
461 service.setIconVisibility(mDataIcon, false);
462
463 // wifi
464 mWifiData = IconData.makeIcon("wifi", null, sWifiSignalImages[0], 0, 0);
465 mWifiIcon = service.addIcon(mWifiData, null);
466 service.setIconVisibility(mWifiIcon, false);
467 // wifi will get updated by the sticky intents
Wink Saville04e71b32009-04-02 11:00:54 -0700468
469 // TTY status
470 mTTYModeEnableIconData = IconData.makeIcon("tty",
471 null, com.android.internal.R.drawable.stat_sys_tty_mode, 0, 0);
472 mTTYModeIcon = service.addIcon(mTTYModeEnableIconData, null);
473 service.setIconVisibility(mTTYModeIcon, false);
474
Wink Savillee9b06d72009-05-18 21:47:50 -0700475 // Cdma Roaming Indicator, ERI
476 mCdmaRoamingIndicatorIconData = IconData.makeIcon("cdma_eri",
477 null, com.android.internal.R.drawable.stat_sys_roaming_cdma_0, 0, 0);
478 mCdmaRoamingIndicatorIcon = service.addIcon(mCdmaRoamingIndicatorIconData, null);
479 service.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 // bluetooth status
482 mBluetoothData = IconData.makeIcon("bluetooth",
483 null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
484 mBluetoothIcon = service.addIcon(mBluetoothData, null);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200485 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Nick Pellybd022f42009-08-14 18:33:38 -0700486 if (adapter != null) {
487 mBluetoothEnabled = adapter.isEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488 } else {
489 mBluetoothEnabled = false;
490 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800491 mBluetoothA2dpConnected = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 mBluetoothHeadsetState = BluetoothHeadset.STATE_DISCONNECTED;
Jiafa Liu3f416732009-07-02 16:36:02 +0800493 mBluetoothPbapState = BluetoothPbap.STATE_DISCONNECTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
495
496 // Gps status
497 mGpsEnabledIconData = IconData.makeIcon("gps",
498 null, com.android.internal.R.drawable.stat_sys_gps_acquiring_anim, 0, 0);
499 mGpsFixIconData = IconData.makeIcon("gps",
500 null, com.android.internal.R.drawable.stat_sys_gps_on, 0, 0);
501 mGpsIcon = service.addIcon(mGpsEnabledIconData, null);
johnwang347c5a22009-08-24 22:11:11 -0700502 service.setIconVisibility(mGpsIcon, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503
504 // Alarm clock
505 mAlarmClockIconData = IconData.makeIcon(
506 "alarm_clock",
507 null, com.android.internal.R.drawable.stat_notify_alarm, 0, 0);
508 mAlarmClockIcon = service.addIcon(mAlarmClockIconData, null);
509 service.setIconVisibility(mAlarmClockIcon, false);
510
511 // Sync state
512 mSyncActiveIcon = service.addIcon(IconData.makeIcon("sync_active",
513 null, R.drawable.stat_notify_sync_anim0, 0, 0), null);
514 mSyncFailingIcon = service.addIcon(IconData.makeIcon("sync_failing",
515 null, R.drawable.stat_notify_sync_error, 0, 0), null);
516 service.setIconVisibility(mSyncActiveIcon, false);
517 service.setIconVisibility(mSyncFailingIcon, false);
518
519 // volume
520 mVolumeData = IconData.makeIcon("volume",
521 null, com.android.internal.R.drawable.stat_sys_ringer_silent, 0, 0);
522 mVolumeIcon = service.addIcon(mVolumeData, null);
523 service.setIconVisibility(mVolumeIcon, false);
524 updateVolume();
johnwang347c5a22009-08-24 22:11:11 -0700525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 IntentFilter filter = new IntentFilter();
527
528 // Register for Intent broadcasts for...
529 filter.addAction(Intent.ACTION_TIME_TICK);
530 filter.addAction(Intent.ACTION_TIME_CHANGED);
531 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
532 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Mihai Predaa82842f2009-04-29 15:05:56 +0200533 filter.addAction(Intent.ACTION_BATTERY_LOW);
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700534 filter.addAction(Intent.ACTION_BATTERY_OKAY);
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400535 filter.addAction(Intent.ACTION_POWER_CONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
537 filter.addAction(Intent.ACTION_ALARM_CHANGED);
538 filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
539 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
540 filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
Nick Pellyde893f52009-09-08 13:15:33 -0700541 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Nick Pelly005b2282009-09-10 10:21:56 -0700542 filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
543 filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
Jiafa Liu3f416732009-07-02 16:36:02 +0800544 filter.addAction(BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
546 filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
547 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
548 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
Mike Lockwood00b74272010-03-26 10:41:48 -0400549 filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION);
550 filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Wink Saville04e71b32009-04-02 11:00:54 -0700552 filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
John Wang33e21fc2009-10-08 10:35:27 -0700554
555 // load config to determine if to distinguish Hspa data icon
556 try {
557 mHspaDataDistinguishable = mContext.getResources().getBoolean(
558 com.android.internal.R.bool.config_hspa_data_distinguishable);
559 } catch (Exception e) {
560 mHspaDataDistinguishable = false;
561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 }
563
564 public static void installIcons(Context context, StatusBarService service) {
565 sInstance = new StatusBarPolicy(context, service);
566 }
567
Eric Fischer36e136c2010-01-14 17:42:48 -0800568 private final CharSequence getSmallTime() {
569 boolean b24 = DateFormat.is24HourFormat(mContext);
570 int res;
571
572 if (b24) {
573 res = R.string.twenty_four_hour_time_format;
574 } else {
575 res = R.string.twelve_hour_time_format;
576 }
577
Eric Fischer36e136c2010-01-14 17:42:48 -0800578 final char MAGIC1 = '\uEF00';
579 final char MAGIC2 = '\uEF01';
580
Joe Onorato63ce8e82010-01-17 19:06:51 -0500581 SimpleDateFormat sdf;
582 String format = mContext.getString(res);
583 if (!format.equals(mClockFormatString)) {
584 /*
585 * Search for an unquoted "a" in the format string, so we can
586 * add dummy characters around it to let us find it again after
587 * formatting and change its size.
588 */
Daniel Sandler2c195f72010-05-21 15:42:06 -0400589 if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) {
590 int a = -1;
591 boolean quoted = false;
592 for (int i = 0; i < format.length(); i++) {
593 char c = format.charAt(i);
Eric Fischer36e136c2010-01-14 17:42:48 -0800594
Daniel Sandler2c195f72010-05-21 15:42:06 -0400595 if (c == '\'') {
596 quoted = !quoted;
597 }
598
599 if (!quoted && c == 'a') {
600 a = i;
601 break;
602 }
Joe Onorato63ce8e82010-01-17 19:06:51 -0500603 }
604
Daniel Sandler2c195f72010-05-21 15:42:06 -0400605 if (a >= 0) {
606 // Move a back so any whitespace before the AM/PM is also in the alternate size.
607 final int b = a;
608 while (a > 0 && Character.isWhitespace(format.charAt(a-1))) {
609 a--;
610 }
611 format = format.substring(0, a) + MAGIC1 + format.substring(a, b)
612 + "a" + MAGIC2 + format.substring(b + 1);
Joe Onorato63ce8e82010-01-17 19:06:51 -0500613 }
614 }
615
Joe Onorato63ce8e82010-01-17 19:06:51 -0500616 mClockFormat = sdf = new SimpleDateFormat(format);
617 mClockFormatString = format;
618 } else {
619 sdf = mClockFormat;
620 }
621 String result = sdf.format(mCalendar.getTime());
Eric Fischer36e136c2010-01-14 17:42:48 -0800622
Daniel Sandler2c195f72010-05-21 15:42:06 -0400623 if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) {
624 int magic1 = result.indexOf(MAGIC1);
625 int magic2 = result.indexOf(MAGIC2);
Eric Fischer36e136c2010-01-14 17:42:48 -0800626
Daniel Sandler2c195f72010-05-21 15:42:06 -0400627 if (magic1 >= 0 && magic2 > magic1) {
628 SpannableStringBuilder formatted = new SpannableStringBuilder(result);
Eric Fischer36e136c2010-01-14 17:42:48 -0800629
Daniel Sandler2c195f72010-05-21 15:42:06 -0400630 if (AM_PM_STYLE == AM_PM_STYLE_GONE) {
631 formatted.delete(magic1, magic2+1);
632 } else {
633 if (AM_PM_STYLE == AM_PM_STYLE_SMALL) {
634 CharacterStyle style = new RelativeSizeSpan(0.7f);
635 formatted.setSpan(style, magic1, magic2,
636 Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
637 }
Eric Fischer36e136c2010-01-14 17:42:48 -0800638
Daniel Sandler2c195f72010-05-21 15:42:06 -0400639 formatted.delete(magic2, magic2 + 1);
640 formatted.delete(magic1, magic1 + 1);
641 }
Eric Fischer36e136c2010-01-14 17:42:48 -0800642
Daniel Sandler2c195f72010-05-21 15:42:06 -0400643 return formatted;
644 }
Eric Fischer36e136c2010-01-14 17:42:48 -0800645 }
Daniel Sandler2c195f72010-05-21 15:42:06 -0400646
647 return result;
Eric Fischer36e136c2010-01-14 17:42:48 -0800648 }
649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 private final void updateClock() {
651 mCalendar.setTimeInMillis(System.currentTimeMillis());
Eric Fischer36e136c2010-01-14 17:42:48 -0800652 mClockData.text = getSmallTime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 mService.updateIcon(mClockIcon, mClockData, null);
654 }
655
656 private final void updateAlarm(Intent intent) {
657 boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
658 mService.setIconVisibility(mAlarmClockIcon, alarmSet);
659 }
660
661 private final void updateSyncState(Intent intent) {
662 boolean isActive = intent.getBooleanExtra("active", false);
663 boolean isFailing = intent.getBooleanExtra("failing", false);
664 mService.setIconVisibility(mSyncActiveIcon, isActive);
665 // Don't display sync failing icon: BUG 1297963 Set sync error timeout to "never"
666 //mService.setIconVisibility(mSyncFailingIcon, isFailing && !isActive);
667 }
668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 private final void updateBattery(Intent intent) {
670 mBatteryData.iconId = intent.getIntExtra("icon-small", 0);
671 mBatteryData.iconLevel = intent.getIntExtra("level", 0);
672 mService.updateIcon(mBatteryIcon, mBatteryData, null);
673
674 boolean plugged = intent.getIntExtra("plugged", 0) != 0;
675 int level = intent.getIntExtra("level", -1);
676 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800677 Slog.d(TAG, "updateBattery level=" + level
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 + " plugged=" + plugged
679 + " mBatteryPlugged=" + mBatteryPlugged
680 + " mBatteryLevel=" + mBatteryLevel
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 + " mBatteryFirst=" + mBatteryFirst);
682 }
683
684 boolean oldPlugged = mBatteryPlugged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685
686 mBatteryPlugged = plugged;
687 mBatteryLevel = level;
688
689 if (mBatteryFirst) {
690 mBatteryFirst = false;
691 }
692 /*
693 * No longer showing the battery view because it draws attention away
694 * from the USB storage notification. We could still show it when
695 * connected to a brick, but that could lead to the user into thinking
696 * the device does not charge when plugged into USB (since he/she would
697 * not see the same battery screen on USB as he sees on brick).
698 */
699 /* else {
700 if (plugged && !oldPlugged) {
701 showBatteryView();
702 }
703 }
704 */
705 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800706 Slog.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709
Mihai Predaa82842f2009-04-29 15:05:56 +0200710 private void onBatteryLow(Intent intent) {
711 if (SHOW_LOW_BATTERY_WARNING) {
712 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800713 Slog.d(TAG, "mPhoneState=" + mPhoneState
Mihai Predaa82842f2009-04-29 15:05:56 +0200714 + " mLowBatteryDialog=" + mLowBatteryDialog
715 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200717
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500718 if (SHOW_BATTERY_WARNINGS_IN_CALL || mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
Mihai Predaa82842f2009-04-29 15:05:56 +0200719 showLowBatteryWarning();
720 } else {
721 mBatteryShowLowOnEndCall = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 }
723 }
724 }
725
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700726 private void onBatteryOkay(Intent intent) {
727 if (mLowBatteryDialog != null
728 && SHOW_LOW_BATTERY_WARNING) {
729 mLowBatteryDialog.dismiss();
730 mBatteryShowLowOnEndCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 }
732 }
733
johnwang347c5a22009-08-24 22:11:11 -0700734 private void showBatteryView() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 closeLastBatteryView();
736 if (mLowBatteryDialog != null) {
737 mLowBatteryDialog.dismiss();
738 }
739
740 int level = mBatteryLevel;
741
742 View v = View.inflate(mContext, com.android.internal.R.layout.battery_status, null);
743 mBatteryView = v;
744 int pixelFormat = PixelFormat.TRANSLUCENT;
745 Drawable bg = v.getBackground();
746 if (bg != null) {
747 pixelFormat = bg.getOpacity();
748 }
749
Dianne Hackborn568cae52009-10-07 16:13:39 -0700750 int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
751 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
752 | WindowManager.LayoutParams.FLAG_DIM_BEHIND;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800753
Dianne Hackborn568cae52009-10-07 16:13:39 -0700754 if (!mContext.getResources().getBoolean(
755 com.android.internal.R.bool.config_sf_slowBlur)) {
756 flags |= WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
757 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
760 ViewGroup.LayoutParams.WRAP_CONTENT,
761 ViewGroup.LayoutParams.WRAP_CONTENT,
762 WindowManager.LayoutParams.TYPE_TOAST,
Dianne Hackborn568cae52009-10-07 16:13:39 -0700763 flags, pixelFormat);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764
765 // Get the dim amount from the theme
766 TypedArray a = mContext.obtainStyledAttributes(
767 com.android.internal.R.styleable.Theme);
768 lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
769 a.recycle();
Wink Saville04e71b32009-04-02 11:00:54 -0700770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 lp.setTitle("Battery");
772
773 TextView levelTextView = (TextView)v.findViewById(com.android.internal.R.id.level_percent);
774 levelTextView.setText(mContext.getString(
775 com.android.internal.R.string.battery_status_text_percent_format, level));
776
777 setBatteryLevel(v, com.android.internal.R.id.spacer, 100-level, 0, 0);
778 setBatteryLevel(v, com.android.internal.R.id.level, level,
779 com.android.internal.R.drawable.battery_charge_fill, level);
780
781 WindowManagerImpl.getDefault().addView(v, lp);
782
783 scheduleCloseBatteryView();
784 }
785
786 private void setBatteryLevel(View parent, int id, int height, int background, int level) {
787 ImageView v = (ImageView)parent.findViewById(id);
788 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)v.getLayoutParams();
789 lp.weight = height;
790 if (background != 0) {
791 v.setBackgroundResource(background);
792 Drawable bkg = v.getBackground();
793 bkg.setLevel(level);
794 }
795 }
796
797 private void showLowBatteryWarning() {
798 closeLastBatteryView();
799
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400800 // Show exact battery level.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 CharSequence levelText = mContext.getString(
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400802 com.android.internal.R.string.battery_low_percent_format, mBatteryLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803
804 if (mBatteryLevelTextView != null) {
805 mBatteryLevelTextView.setText(levelText);
806 } else {
807 View v = View.inflate(mContext, com.android.internal.R.layout.battery_low, null);
808 mBatteryLevelTextView=(TextView)v.findViewById(com.android.internal.R.id.level_percent);
809
810 mBatteryLevelTextView.setText(levelText);
811
812 AlertDialog.Builder b = new AlertDialog.Builder(mContext);
813 b.setCancelable(true);
814 b.setTitle(com.android.internal.R.string.battery_low_title);
815 b.setView(v);
816 b.setIcon(android.R.drawable.ic_dialog_alert);
817 b.setPositiveButton(android.R.string.ok, null);
johnwang347c5a22009-08-24 22:11:11 -0700818
Dianne Hackborn3d74bb42009-06-19 10:35:21 -0700819 final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
820 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
821 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
822 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
823 | Intent.FLAG_ACTIVITY_NO_HISTORY);
824 if (intent.resolveActivity(mContext.getPackageManager()) != null) {
825 b.setNegativeButton(com.android.internal.R.string.battery_low_why,
826 new DialogInterface.OnClickListener() {
827 public void onClick(DialogInterface dialog, int which) {
828 mContext.startActivity(intent);
829 if (mLowBatteryDialog != null) {
830 mLowBatteryDialog.dismiss();
831 }
832 }
833 });
834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835
836 AlertDialog d = b.create();
837 d.setOnDismissListener(mLowBatteryListener);
838 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
839 d.show();
840 mLowBatteryDialog = d;
841 }
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500842
843 final ContentResolver cr = mContext.getContentResolver();
844 if (Settings.System.getInt(cr,
John Wang56c2d2f2010-04-07 08:57:17 -0700845 Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500846 {
847 final String soundPath = Settings.System.getString(cr,
848 Settings.System.LOW_BATTERY_SOUND);
849 if (soundPath != null) {
850 final Uri soundUri = Uri.parse("file://" + soundPath);
851 if (soundUri != null) {
852 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
Daniel Sandlerec2c88d2010-02-20 01:04:57 -0500853 if (sfx != null) {
854 sfx.setStreamType(AudioManager.STREAM_SYSTEM);
855 sfx.play();
856 }
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500857 }
858 }
859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 }
861
862 private final void updateCallState(int state) {
863 mPhoneState = state;
864 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800865 Slog.d(TAG, "mPhoneState=" + mPhoneState
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 + " mLowBatteryDialog=" + mLowBatteryDialog
867 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
868 }
869 if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
870 if (mBatteryShowLowOnEndCall) {
871 if (!mBatteryPlugged) {
872 showLowBatteryWarning();
873 }
874 mBatteryShowLowOnEndCall = false;
875 }
876 } else {
877 if (mLowBatteryDialog != null) {
878 mLowBatteryDialog.dismiss();
879 mBatteryShowLowOnEndCall = true;
880 }
881 }
882 }
883
884 private DialogInterface.OnDismissListener mLowBatteryListener
885 = new DialogInterface.OnDismissListener() {
886 public void onDismiss(DialogInterface dialog) {
887 mLowBatteryDialog = null;
888 mBatteryLevelTextView = null;
889 }
890 };
891
892 private void scheduleCloseBatteryView() {
893 Message m = mHandler.obtainMessage(EVENT_BATTERY_CLOSE);
894 m.arg1 = (++mBatteryViewSequence);
895 mHandler.sendMessageDelayed(m, 3000);
896 }
897
898 private void closeLastBatteryView() {
899 if (mBatteryView != null) {
900 //mBatteryView.debug();
901 WindowManagerImpl.getDefault().removeView(mBatteryView);
902 mBatteryView = null;
903 }
904 }
905
906 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
907 @Override
Wink Savillee9b06d72009-05-18 21:47:50 -0700908 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
909 mSignalStrength = signalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 updateSignalStrength();
911 }
912
913 @Override
914 public void onServiceStateChanged(ServiceState state) {
915 mServiceState = state;
916 updateSignalStrength();
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700917 updateCdmaRoamingIcon(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 updateDataIcon();
919 }
920
921 @Override
922 public void onCallStateChanged(int state, String incomingNumber) {
923 updateCallState(state);
johnwang347c5a22009-08-24 22:11:11 -0700924 // In cdma, if a voice call is made, RSSI should switch to 1x.
925 if (isCdma()) {
926 updateSignalStrength();
927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 }
929
930 @Override
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700931 public void onDataConnectionStateChanged(int state, int networkType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 mDataState = state;
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700933 updateDataNetType(networkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 updateDataIcon();
935 }
936
937 @Override
938 public void onDataActivity(int direction) {
939 mDataActivity = direction;
940 updateDataIcon();
941 }
942 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943
944 private final void updateSimState(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -0700945 String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
946 if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
947 mSimState = IccCard.State.ABSENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 }
Wink Saville04e71b32009-04-02 11:00:54 -0700949 else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
950 mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 }
Wink Saville04e71b32009-04-02 11:00:54 -0700952 else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
953 final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
954 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
955 mSimState = IccCard.State.PIN_REQUIRED;
johnwang347c5a22009-08-24 22:11:11 -0700956 }
Wink Saville04e71b32009-04-02 11:00:54 -0700957 else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
958 mSimState = IccCard.State.PUK_REQUIRED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 }
960 else {
Wink Saville04e71b32009-04-02 11:00:54 -0700961 mSimState = IccCard.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 }
963 } else {
Wink Saville04e71b32009-04-02 11:00:54 -0700964 mSimState = IccCard.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 }
966 updateDataIcon();
967 }
968
Wink Savillee9b06d72009-05-18 21:47:50 -0700969 private boolean isCdma() {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700970 return (mSignalStrength != null) && !mSignalStrength.isGsm();
Wink Savillee9b06d72009-05-18 21:47:50 -0700971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972
johnwang347c5a22009-08-24 22:11:11 -0700973 private boolean isEvdo() {
974 return ( (mServiceState != null)
975 && ((mServiceState.getRadioTechnology()
976 == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
977 || (mServiceState.getRadioTechnology()
Naveen Kalla0a5174a2010-04-21 14:48:03 -0700978 == ServiceState.RADIO_TECHNOLOGY_EVDO_A)
979 || (mServiceState.getRadioTechnology()
980 == ServiceState.RADIO_TECHNOLOGY_EVDO_B)));
johnwang347c5a22009-08-24 22:11:11 -0700981 }
982
Wink Savillee9b06d72009-05-18 21:47:50 -0700983 private boolean hasService() {
984 if (mServiceState != null) {
985 switch (mServiceState.getState()) {
986 case ServiceState.STATE_OUT_OF_SERVICE:
987 case ServiceState.STATE_POWER_OFF:
988 return false;
989 default:
990 return true;
991 }
992 } else {
993 return false;
994 }
995 }
996
997 private final void updateSignalStrength() {
998 int iconLevel = -1;
Wink Savillee9b06d72009-05-18 21:47:50 -0700999 int[] iconList;
Wink Savillee9b06d72009-05-18 21:47:50 -07001000
John Wang56c2d2f2010-04-07 08:57:17 -07001001 // Display signal strength while in "emergency calls only" mode
1002 if (!hasService() && !mServiceState.isEmergencyOnly()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001003 //Slog.d(TAG, "updateSignalStrength: no service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 if (Settings.System.getInt(mContext.getContentResolver(),
1005 Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
1006 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_flightmode;
1007 } else {
1008 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_null;
1009 }
1010 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1011 return;
1012 }
1013
Wink Savillee9b06d72009-05-18 21:47:50 -07001014 if (!isCdma()) {
1015 int asu = mSignalStrength.getGsmSignalStrength();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016
Wink Savillee9b06d72009-05-18 21:47:50 -07001017 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
1018 // asu = 0 (-113dB or less) is very weak
1019 // signal, its better to show 0 bars to the user in such cases.
1020 // asu = 99 is a special case, where the signal strength is unknown.
jshee63e472010-03-18 11:14:42 -07001021 if (asu <= 2 || asu == 99) iconLevel = 0;
1022 else if (asu >= 12) iconLevel = 4;
Wink Savillee9b06d72009-05-18 21:47:50 -07001023 else if (asu >= 8) iconLevel = 3;
jshee63e472010-03-18 11:14:42 -07001024 else if (asu >= 5) iconLevel = 2;
Wink Savillee9b06d72009-05-18 21:47:50 -07001025 else iconLevel = 1;
1026
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001027 // Though mPhone is a Manager, this call is not an IPC
Wink Savillee9b06d72009-05-18 21:47:50 -07001028 if (mPhone.isNetworkRoaming()) {
1029 iconList = sSignalImages_r;
1030 } else {
1031 iconList = sSignalImages;
Wink Saville04e71b32009-04-02 11:00:54 -07001032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 } else {
johnwang347c5a22009-08-24 22:11:11 -07001034 iconList = this.sSignalImages;
Wink Savillee9b06d72009-05-18 21:47:50 -07001035
johnwang347c5a22009-08-24 22:11:11 -07001036 // If 3G(EV) and 1x network are available than 3G should be
1037 // displayed, displayed RSSI should be from the EV side.
1038 // If a voice call is made then RSSI should switch to 1x.
1039 if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
1040 iconLevel = getEvdoLevel();
1041 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001042 Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level=" + getCdmaLevel());
johnwang347c5a22009-08-24 22:11:11 -07001043 }
1044 } else {
1045 iconLevel = getCdmaLevel();
1046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001048 mPhoneData.iconId = iconList[iconLevel];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1050 }
1051
johnwang347c5a22009-08-24 22:11:11 -07001052 private int getCdmaLevel() {
1053 final int cdmaDbm = mSignalStrength.getCdmaDbm();
1054 final int cdmaEcio = mSignalStrength.getCdmaEcio();
1055 int levelDbm = 0;
1056 int levelEcio = 0;
1057
1058 if (cdmaDbm >= -75) levelDbm = 4;
1059 else if (cdmaDbm >= -85) levelDbm = 3;
1060 else if (cdmaDbm >= -95) levelDbm = 2;
1061 else if (cdmaDbm >= -100) levelDbm = 1;
1062 else levelDbm = 0;
1063
1064 // Ec/Io are in dB*10
1065 if (cdmaEcio >= -90) levelEcio = 4;
1066 else if (cdmaEcio >= -110) levelEcio = 3;
1067 else if (cdmaEcio >= -130) levelEcio = 2;
1068 else if (cdmaEcio >= -150) levelEcio = 1;
1069 else levelEcio = 0;
1070
1071 return (levelDbm < levelEcio) ? levelDbm : levelEcio;
1072 }
1073
1074 private int getEvdoLevel() {
1075 int evdoDbm = mSignalStrength.getEvdoDbm();
1076 int evdoSnr = mSignalStrength.getEvdoSnr();
1077 int levelEvdoDbm = 0;
1078 int levelEvdoSnr = 0;
1079
1080 if (evdoDbm >= -65) levelEvdoDbm = 4;
1081 else if (evdoDbm >= -75) levelEvdoDbm = 3;
1082 else if (evdoDbm >= -90) levelEvdoDbm = 2;
1083 else if (evdoDbm >= -105) levelEvdoDbm = 1;
1084 else levelEvdoDbm = 0;
1085
John Michelau1336a562009-09-28 10:41:02 -05001086 if (evdoSnr >= 7) levelEvdoSnr = 4;
1087 else if (evdoSnr >= 5) levelEvdoSnr = 3;
1088 else if (evdoSnr >= 3) levelEvdoSnr = 2;
1089 else if (evdoSnr >= 1) levelEvdoSnr = 1;
johnwang347c5a22009-08-24 22:11:11 -07001090 else levelEvdoSnr = 0;
1091
1092 return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
1093 }
1094
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001095 private final void updateDataNetType(int net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001096 switch (net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001097 case TelephonyManager.NETWORK_TYPE_EDGE:
1098 mDataIconList = sDataNetType_e;
1099 break;
1100 case TelephonyManager.NETWORK_TYPE_UMTS:
1101 mDataIconList = sDataNetType_3g;
1102 break;
Li Zheebe66342009-08-14 19:22:16 +08001103 case TelephonyManager.NETWORK_TYPE_HSDPA:
1104 case TelephonyManager.NETWORK_TYPE_HSUPA:
1105 case TelephonyManager.NETWORK_TYPE_HSPA:
John Wang33e21fc2009-10-08 10:35:27 -07001106 if (mHspaDataDistinguishable) {
1107 mDataIconList = sDataNetType_h;
1108 } else {
1109 mDataIconList = sDataNetType_3g;
1110 }
Li Zheebe66342009-08-14 19:22:16 +08001111 break;
Wink Saville04e71b32009-04-02 11:00:54 -07001112 case TelephonyManager.NETWORK_TYPE_CDMA:
1113 // display 1xRTT for IS95A/B
johnwang9f87cb22009-08-25 15:25:37 -07001114 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001115 break;
1116 case TelephonyManager.NETWORK_TYPE_1xRTT:
johnwang9f87cb22009-08-25 15:25:37 -07001117 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001118 break;
1119 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
1120 case TelephonyManager.NETWORK_TYPE_EVDO_A:
Naveen Kalla0a5174a2010-04-21 14:48:03 -07001121 case TelephonyManager.NETWORK_TYPE_EVDO_B:
johnwang9f87cb22009-08-25 15:25:37 -07001122 mDataIconList = sDataNetType_3g;
Wink Saville04e71b32009-04-02 11:00:54 -07001123 break;
1124 default:
1125 mDataIconList = sDataNetType_g;
1126 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 }
1128 }
1129
1130 private final void updateDataIcon() {
1131 int iconId;
1132 boolean visible = true;
1133
Wink Savillee9b06d72009-05-18 21:47:50 -07001134 if (!isCdma()) {
1135 // GSM case, we have to check also the sim state
1136 if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
1137 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
1138 switch (mDataActivity) {
1139 case TelephonyManager.DATA_ACTIVITY_IN:
1140 iconId = mDataIconList[1];
1141 break;
1142 case TelephonyManager.DATA_ACTIVITY_OUT:
1143 iconId = mDataIconList[2];
1144 break;
1145 case TelephonyManager.DATA_ACTIVITY_INOUT:
1146 iconId = mDataIconList[3];
1147 break;
1148 default:
1149 iconId = mDataIconList[0];
1150 break;
1151 }
1152 mDataData.iconId = iconId;
1153 mService.updateIcon(mDataIcon, mDataData, null);
1154 } else {
1155 visible = false;
1156 }
1157 } else {
1158 mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
1159 mService.updateIcon(mDataIcon, mDataData, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001161 } else {
1162 // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
1163 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 switch (mDataActivity) {
1165 case TelephonyManager.DATA_ACTIVITY_IN:
Wink Savillee9b06d72009-05-18 21:47:50 -07001166 iconId = mDataIconList[1];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 break;
1168 case TelephonyManager.DATA_ACTIVITY_OUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001169 iconId = mDataIconList[2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 break;
1171 case TelephonyManager.DATA_ACTIVITY_INOUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001172 iconId = mDataIconList[3];
1173 break;
1174 case TelephonyManager.DATA_ACTIVITY_DORMANT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 default:
Wink Savillee9b06d72009-05-18 21:47:50 -07001176 iconId = mDataIconList[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 break;
1178 }
1179 mDataData.iconId = iconId;
1180 mService.updateIcon(mDataIcon, mDataData, null);
1181 } else {
1182 visible = false;
1183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001185
Dianne Hackborn4840e142009-03-24 22:40:29 -07001186 long ident = Binder.clearCallingIdentity();
1187 try {
Wink Saville04e71b32009-04-02 11:00:54 -07001188 mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
Dianne Hackborn4840e142009-03-24 22:40:29 -07001189 } catch (RemoteException e) {
1190 } finally {
1191 Binder.restoreCallingIdentity(ident);
1192 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 if (mDataIconVisible != visible) {
1195 mService.setIconVisibility(mDataIcon, visible);
1196 mDataIconVisible = visible;
1197 }
1198 }
1199
1200 private final void updateVolume() {
1201 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1202 final int ringerMode = audioManager.getRingerMode();
1203 final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
Wink Savillee9b06d72009-05-18 21:47:50 -07001204 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
1206 ? com.android.internal.R.drawable.stat_sys_ringer_vibrate
1207 : com.android.internal.R.drawable.stat_sys_ringer_silent;
1208
1209 if (visible) {
1210 mVolumeData.iconId = iconId;
1211 mService.updateIcon(mVolumeIcon, mVolumeData, null);
1212 }
1213 if (visible != mVolumeVisible) {
1214 mService.setIconVisibility(mVolumeIcon, visible);
1215 mVolumeVisible = visible;
1216 }
1217 }
1218
1219 private final void updateBluetooth(Intent intent) {
1220 int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 String action = intent.getAction();
Nick Pellyde893f52009-09-08 13:15:33 -07001222 if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
Nick Pellyb24e11b2009-09-08 17:40:43 -07001223 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
Nick Pellyde893f52009-09-08 13:15:33 -07001224 mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
Nick Pelly005b2282009-09-10 10:21:56 -07001225 } else if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
1226 mBluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 BluetoothHeadset.STATE_ERROR);
Nick Pelly005b2282009-09-10 10:21:56 -07001228 } else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) {
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001229 BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
1230 if (a2dp.getConnectedSinks().size() != 0) {
1231 mBluetoothA2dpConnected = true;
1232 } else {
1233 mBluetoothA2dpConnected = false;
1234 }
Jiafa Liu3f416732009-07-02 16:36:02 +08001235 } else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
1236 mBluetoothPbapState = intent.getIntExtra(BluetoothPbap.PBAP_STATE,
1237 BluetoothPbap.STATE_DISCONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 } else {
1239 return;
1240 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001241
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001242 if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED || mBluetoothA2dpConnected ||
Jiafa Liu3f416732009-07-02 16:36:02 +08001243 mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
1245 }
1246
1247 mBluetoothData.iconId = iconId;
1248 mService.updateIcon(mBluetoothIcon, mBluetoothData, null);
1249 mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
1250 }
1251
1252 private final void updateWifi(Intent intent) {
1253 final String action = intent.getAction();
1254 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
1257 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
Wink Savillee9b06d72009-05-18 21:47:50 -07001258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 if (!enabled) {
1260 // If disabled, hide the icon. (We show icon when connected.)
1261 mService.setIconVisibility(mWifiIcon, false);
1262 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
1265 final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
1266 false);
1267 if (!enabled) {
1268 mService.setIconVisibility(mWifiIcon, false);
1269 }
1270 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
1271
Wink Savillee9b06d72009-05-18 21:47:50 -07001272 final NetworkInfo networkInfo = (NetworkInfo)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
Wink Savillee9b06d72009-05-18 21:47:50 -07001274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 int iconId;
1276 if (networkInfo != null && networkInfo.isConnected()) {
1277 mIsWifiConnected = true;
1278 if (mLastWifiSignalLevel == -1) {
1279 iconId = sWifiSignalImages[0];
1280 } else {
1281 iconId = sWifiSignalImages[mLastWifiSignalLevel];
1282 }
Wink Saville04e71b32009-04-02 11:00:54 -07001283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 // Show the icon since wi-fi is connected
1285 mService.setIconVisibility(mWifiIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 } else {
1288 mLastWifiSignalLevel = -1;
1289 mIsWifiConnected = false;
1290 iconId = sWifiSignalImages[0];
1291
1292 // Hide the icon since we're not connected
1293 mService.setIconVisibility(mWifiIcon, false);
1294 }
1295
1296 mWifiData.iconId = iconId;
1297 mService.updateIcon(mWifiIcon, mWifiData, null);
1298 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
1299 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
1300 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
1301 sWifiSignalImages.length);
1302 if (newSignalLevel != mLastWifiSignalLevel) {
1303 mLastWifiSignalLevel = newSignalLevel;
1304 if (mIsWifiConnected) {
1305 mWifiData.iconId = sWifiSignalImages[newSignalLevel];
1306 } else {
1307 mWifiData.iconId = sWifiTemporarilyNotConnectedImage;
1308 }
1309 mService.updateIcon(mWifiIcon, mWifiData, null);
1310 }
1311 }
1312 }
1313
1314 private final void updateGps(Intent intent) {
1315 final String action = intent.getAction();
Mike Lockwood00b74272010-03-26 10:41:48 -04001316 final boolean enabled = intent.getBooleanExtra(LocationManager.EXTRA_GPS_ENABLED, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001317
Mike Lockwood00b74272010-03-26 10:41:48 -04001318 if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 // GPS is getting fixes
1320 mService.updateIcon(mGpsIcon, mGpsFixIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001321 mService.setIconVisibility(mGpsIcon, true);
Mike Lockwood00b74272010-03-26 10:41:48 -04001322 } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 // GPS is off
Wink Savillee9b06d72009-05-18 21:47:50 -07001324 mService.setIconVisibility(mGpsIcon, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 } else {
1326 // GPS is on, but not receiving fixes
1327 mService.updateIcon(mGpsIcon, mGpsEnabledIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001328 mService.setIconVisibility(mGpsIcon, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 }
1330 }
1331
Wink Savillee9b06d72009-05-18 21:47:50 -07001332 private final void updateTTY(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -07001333 final String action = intent.getAction();
1334 final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
1335
Joe Onorato8a9b2202010-02-26 18:56:32 -08001336 if (false) Slog.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -07001337
1338 if (enabled) {
1339 // TTY is on
Joe Onorato8a9b2202010-02-26 18:56:32 -08001340 if (false) Slog.v(TAG, "updateTTY: set TTY on");
Wink Saville04e71b32009-04-02 11:00:54 -07001341 mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001342 mService.setIconVisibility(mTTYModeIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001343 } else {
1344 // TTY is off
Joe Onorato8a9b2202010-02-26 18:56:32 -08001345 if (false) Slog.v(TAG, "updateTTY: set TTY off");
Wink Savillee9b06d72009-05-18 21:47:50 -07001346 mService.setIconVisibility(mTTYModeIcon, false);
Wink Saville04e71b32009-04-02 11:00:54 -07001347 }
1348 }
1349
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001350 private final void updateCdmaRoamingIcon(ServiceState state) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001351 if (!hasService()) {
1352 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001353 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001354 }
1355
1356 if (!isCdma()) {
1357 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001358 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001359 }
1360
1361 int[] iconList = sRoamingIndicatorImages_cdma;
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001362 int iconIndex = state.getCdmaEriIconIndex();
1363 int iconMode = state.getCdmaEriIconMode();
Wink Savillee9b06d72009-05-18 21:47:50 -07001364
1365 if (iconIndex == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001366 Slog.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001367 return;
1368 }
1369
1370 if (iconMode == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001371 Slog.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001372 return;
1373 }
1374
1375 if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001376 if (false) Slog.v(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
Wink Savillee9b06d72009-05-18 21:47:50 -07001377 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
1378 return;
1379 }
1380
1381 switch (iconMode) {
1382 case EriInfo.ROAMING_ICON_MODE_NORMAL:
1383 mCdmaRoamingIndicatorIconData.iconId = iconList[iconIndex];
1384 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
1385 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
1386 break;
1387 case EriInfo.ROAMING_ICON_MODE_FLASH:
Wink Savillef3152382009-06-01 14:39:20 -07001388 mCdmaRoamingIndicatorIconData.iconId =
1389 com.android.internal.R.drawable.stat_sys_roaming_cdma_flash;
Wink Savillee9b06d72009-05-18 21:47:50 -07001390 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
Wink Savillef3152382009-06-01 14:39:20 -07001391 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
Wink Savillee9b06d72009-05-18 21:47:50 -07001392 break;
1393
1394 }
1395 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1396 }
1397
1398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 private class StatusBarHandler extends Handler {
1400 @Override
1401 public void handleMessage(Message msg) {
1402 switch (msg.what) {
1403 case EVENT_BATTERY_CLOSE:
1404 if (msg.arg1 == mBatteryViewSequence) {
1405 closeLastBatteryView();
1406 }
1407 break;
1408 }
1409 }
1410 }
1411}