blob: 1838eed4af67390ac7e14723bc18f032774558ab [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.status;
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019import android.app.AlertDialog;
20import android.bluetooth.BluetoothA2dp;
Nick Pellybd022f42009-08-14 18:33:38 -070021import android.bluetooth.BluetoothAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.bluetooth.BluetoothHeadset;
Jiafa Liu3f416732009-07-02 16:36:02 +080023import android.bluetooth.BluetoothPbap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.BroadcastReceiver;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050025import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.content.Context;
27import android.content.DialogInterface;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.res.TypedArray;
31import android.graphics.PixelFormat;
Daniel Sandler2c195f72010-05-21 15:42:06 -040032import android.graphics.Typeface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.graphics.drawable.Drawable;
Mike Lockwood00b74272010-03-26 10:41:48 -040034import android.location.LocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.media.AudioManager;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050036import android.media.Ringtone;
37import android.media.RingtoneManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.net.NetworkInfo;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050039import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.net.wifi.WifiManager;
Dianne Hackborn4840e142009-03-24 22:40:29 -070041import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.os.Message;
Dianne Hackborn4840e142009-03-24 22:40:29 -070044import android.os.RemoteException;
San Mehat4154c072010-02-09 18:37:54 -080045import android.os.storage.StorageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.provider.Settings;
47import android.telephony.PhoneStateListener;
48import android.telephony.ServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -070049import android.telephony.SignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.telephony.TelephonyManager;
51import android.text.format.DateFormat;
Daniel Sandler2c195f72010-05-21 15:42:06 -040052import android.text.style.CharacterStyle;
Eric Fischer36e136c2010-01-14 17:42:48 -080053import android.text.style.RelativeSizeSpan;
Daniel Sandler2c195f72010-05-21 15:42:06 -040054import android.text.style.ForegroundColorSpan;
55import android.text.style.StyleSpan;
Eric Fischer36e136c2010-01-14 17:42:48 -080056import android.text.Spannable;
57import android.text.SpannableStringBuilder;
Joe Onorato8a9b2202010-02-26 18:56:32 -080058import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.view.View;
60import android.view.ViewGroup;
61import android.view.WindowManager;
62import android.view.WindowManagerImpl;
63import android.widget.ImageView;
64import android.widget.LinearLayout;
65import android.widget.TextView;
66
Wink Saville04e71b32009-04-02 11:00:54 -070067import com.android.internal.R;
68import com.android.internal.app.IBatteryStats;
Wink Saville04e71b32009-04-02 11:00:54 -070069import com.android.internal.telephony.IccCard;
70import com.android.internal.telephony.TelephonyIntents;
Wink Savillee9b06d72009-05-18 21:47:50 -070071import com.android.internal.telephony.cdma.EriInfo;
Wink Saville04e71b32009-04-02 11:00:54 -070072import com.android.internal.telephony.cdma.TtyIntent;
73import com.android.server.am.BatteryStatsService;
74
Eric Fischer36e136c2010-01-14 17:42:48 -080075import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import java.util.Calendar;
77import java.util.TimeZone;
78
79/**
80 * This class contains all of the policy about which icons are installed in the status
81 * bar at boot time. In reality, it should go into the android.policy package, but
82 * putting it here is the first step from extracting it.
83 */
84public class StatusBarPolicy {
85 private static final String TAG = "StatusBarPolicy";
86
87 private static StatusBarPolicy sInstance;
88
89 // message codes for the handler
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 private static final int EVENT_BATTERY_CLOSE = 4;
91
Daniel Sandler2c195f72010-05-21 15:42:06 -040092 private static final int AM_PM_STYLE_NORMAL = 0;
93 private static final int AM_PM_STYLE_SMALL = 1;
94 private static final int AM_PM_STYLE_GONE = 2;
95
96 private static final int AM_PM_STYLE = AM_PM_STYLE_GONE;
97
Dianne Hackborn4840e142009-03-24 22:40:29 -070098 private final Context mContext;
Joe Onorato089de882010-04-12 08:18:45 -070099 private final StatusBarManagerService mService;
Dianne Hackborn4840e142009-03-24 22:40:29 -0700100 private final Handler mHandler = new StatusBarHandler();
101 private final IBatteryStats mBatteryStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102
103 // clock
104 private Calendar mCalendar;
Joe Onorato63ce8e82010-01-17 19:06:51 -0500105 private String mClockFormatString;
106 private SimpleDateFormat mClockFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107
San Mehat4154c072010-02-09 18:37:54 -0800108 // storage
109 private StorageManager mStorageManager;
110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 // battery
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 private boolean mBatteryFirst = true;
113 private boolean mBatteryPlugged;
114 private int mBatteryLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 private AlertDialog mLowBatteryDialog;
116 private TextView mBatteryLevelTextView;
117 private View mBatteryView;
118 private int mBatteryViewSequence;
119 private boolean mBatteryShowLowOnEndCall = false;
120 private static final boolean SHOW_LOW_BATTERY_WARNING = true;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500121 private static final boolean SHOW_BATTERY_WARNINGS_IN_CALL = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122
123 // phone
124 private TelephonyManager mPhone;
Joe Onorato0cbda992010-05-02 16:28:15 -0700125 private int mPhoneSignalIconId;
Wink Saville04e71b32009-04-02 11:00:54 -0700126
127 //***** Signal strength icons
Wink Saville04e71b32009-04-02 11:00:54 -0700128 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 private static final int[] sSignalImages = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700130 com.android.internal.R.drawable.stat_sys_signal_0,
131 com.android.internal.R.drawable.stat_sys_signal_1,
132 com.android.internal.R.drawable.stat_sys_signal_2,
133 com.android.internal.R.drawable.stat_sys_signal_3,
134 com.android.internal.R.drawable.stat_sys_signal_4
135 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 private static final int[] sSignalImages_r = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700137 com.android.internal.R.drawable.stat_sys_r_signal_0,
138 com.android.internal.R.drawable.stat_sys_r_signal_1,
139 com.android.internal.R.drawable.stat_sys_r_signal_2,
140 com.android.internal.R.drawable.stat_sys_r_signal_3,
141 com.android.internal.R.drawable.stat_sys_r_signal_4
142 };
Wink Savillee9b06d72009-05-18 21:47:50 -0700143 private static final int[] sRoamingIndicatorImages_cdma = new int[] {
144 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
145 // 1 is Standard Roaming Indicator OFF
146 // TODO T: image never used, remove and put 0 instead?
147 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
148
149 // 2 is Standard Roaming Indicator FLASHING
150 // TODO T: image never used, remove and put 0 instead?
151 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
152
153 // 3-12 Standard ERI
154 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //3
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 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
161 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
162 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
163 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
164
165 // 13-63 Reserved for Standard ERI
166 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //13
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 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
218 // 64-127 Reserved for Non Standard (Operator Specific) ERI
219 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //64
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,
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 //83
239
240 // 128-255 Reserved
Wink Saville04e71b32009-04-02 11:00:54 -0700241 };
Wink Saville04e71b32009-04-02 11:00:54 -0700242
243 //***** Data connection icons
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 private int[] mDataIconList = sDataNetType_g;
Wink Saville04e71b32009-04-02 11:00:54 -0700245 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 private static final int[] sDataNetType_g = new int[] {
247 com.android.internal.R.drawable.stat_sys_data_connected_g,
248 com.android.internal.R.drawable.stat_sys_data_in_g,
249 com.android.internal.R.drawable.stat_sys_data_out_g,
250 com.android.internal.R.drawable.stat_sys_data_inandout_g,
251 };
252 private static final int[] sDataNetType_3g = new int[] {
253 com.android.internal.R.drawable.stat_sys_data_connected_3g,
254 com.android.internal.R.drawable.stat_sys_data_in_3g,
255 com.android.internal.R.drawable.stat_sys_data_out_3g,
256 com.android.internal.R.drawable.stat_sys_data_inandout_3g,
257 };
258 private static final int[] sDataNetType_e = new int[] {
259 com.android.internal.R.drawable.stat_sys_data_connected_e,
260 com.android.internal.R.drawable.stat_sys_data_in_e,
261 com.android.internal.R.drawable.stat_sys_data_out_e,
262 com.android.internal.R.drawable.stat_sys_data_inandout_e,
263 };
Li Zheebe66342009-08-14 19:22:16 +0800264 //3.5G
265 private static final int[] sDataNetType_h = new int[] {
266 com.android.internal.R.drawable.stat_sys_data_connected_h,
267 com.android.internal.R.drawable.stat_sys_data_in_h,
268 com.android.internal.R.drawable.stat_sys_data_out_h,
269 com.android.internal.R.drawable.stat_sys_data_inandout_h,
270 };
271
Wink Saville04e71b32009-04-02 11:00:54 -0700272 //CDMA
johnwang9f87cb22009-08-25 15:25:37 -0700273 // Use 3G icons for EVDO data and 1x icons for 1XRTT data
274 private static final int[] sDataNetType_1x = new int[] {
275 com.android.internal.R.drawable.stat_sys_data_connected_1x,
276 com.android.internal.R.drawable.stat_sys_data_in_1x,
277 com.android.internal.R.drawable.stat_sys_data_out_1x,
278 com.android.internal.R.drawable.stat_sys_data_inandout_1x,
Wink Saville04e71b32009-04-02 11:00:54 -0700279 };
280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 // Assume it's all good unless we hear otherwise. We don't always seem
282 // to get broadcasts that it *is* there.
Wink Saville04e71b32009-04-02 11:00:54 -0700283 IccCard.State mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
285 int mDataState = TelephonyManager.DATA_DISCONNECTED;
286 int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
287 ServiceState mServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -0700288 SignalStrength mSignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289
290 // data connection
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 private boolean mDataIconVisible;
John Wang33e21fc2009-10-08 10:35:27 -0700292 private boolean mHspaDataDistinguishable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293
294 // ringer volume
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 private int mBluetoothHeadsetState;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800299 private boolean mBluetoothA2dpConnected;
Jiafa Liu3f416732009-07-02 16:36:02 +0800300 private int mBluetoothPbapState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 private boolean mBluetoothEnabled;
302
303 // wifi
304 private static final int[] sWifiSignalImages = new int[] {
305 com.android.internal.R.drawable.stat_sys_wifi_signal_1,
306 com.android.internal.R.drawable.stat_sys_wifi_signal_2,
307 com.android.internal.R.drawable.stat_sys_wifi_signal_3,
308 com.android.internal.R.drawable.stat_sys_wifi_signal_4,
309 };
310 private static final int sWifiTemporarilyNotConnectedImage =
311 com.android.internal.R.drawable.stat_sys_wifi_signal_0;
312
313 private int mLastWifiSignalLevel = -1;
314 private boolean mIsWifiConnected = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315
316 // sync state
317 // If sync is active the SyncActive icon is displayed. If sync is not active but
318 // sync is failing the SyncFailing icon is displayed. Otherwise neither are displayed.
Wink Savillee9b06d72009-05-18 21:47:50 -0700319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
321 @Override
322 public void onReceive(Context context, Intent intent) {
323 String action = intent.getAction();
324 if (action.equals(Intent.ACTION_TIME_TICK)) {
325 updateClock();
326 }
327 else if (action.equals(Intent.ACTION_TIME_CHANGED)) {
328 updateClock();
329 }
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700330 else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
331 updateBattery(intent);
332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
334 updateClock();
335 }
336 else if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
337 String tz = intent.getStringExtra("time-zone");
338 mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz));
Amith Yamasanic4938fd2010-04-28 13:20:43 -0700339 if (mClockFormat != null) {
340 mClockFormat.setTimeZone(mCalendar.getTimeZone());
341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 updateClock();
343 }
344 else if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
345 updateAlarm(intent);
346 }
347 else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
348 updateSyncState(intent);
349 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200350 else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
351 onBatteryLow(intent);
352 }
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400353 else if (action.equals(Intent.ACTION_BATTERY_OKAY)
354 || action.equals(Intent.ACTION_POWER_CONNECTED)) {
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700355 onBatteryOkay(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 }
Nick Pellyde893f52009-09-08 13:15:33 -0700357 else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
Nick Pelly005b2282009-09-10 10:21:56 -0700358 action.equals(BluetoothHeadset.ACTION_STATE_CHANGED) ||
359 action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED) ||
Jiafa Liu3f416732009-07-02 16:36:02 +0800360 action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 updateBluetooth(intent);
362 }
363 else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
364 action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) ||
365 action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
366 updateWifi(intent);
367 }
Mike Lockwood00b74272010-03-26 10:41:48 -0400368 else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) ||
369 action.equals(LocationManager.GPS_FIX_CHANGE_ACTION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 updateGps(intent);
371 }
372 else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
373 action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
374 updateVolume();
375 }
376 else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
377 updateSimState(intent);
378 }
Wink Saville04e71b32009-04-02 11:00:54 -0700379 else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
380 updateTTY(intent);
381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 }
383 };
384
Joe Onorato089de882010-04-12 08:18:45 -0700385 private StatusBarPolicy(Context context, StatusBarManagerService service) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 mContext = context;
387 mService = service;
Wink Savillee9b06d72009-05-18 21:47:50 -0700388 mSignalStrength = new SignalStrength();
Dianne Hackborn4840e142009-03-24 22:40:29 -0700389 mBatteryStats = BatteryStatsService.getService();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390
391 // clock
392 mCalendar = Calendar.getInstance(TimeZone.getDefault());
Joe Onorato0cbda992010-05-02 16:28:15 -0700393 service.setIcon("clock", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 updateClock();
395
San Mehat4154c072010-02-09 18:37:54 -0800396 // storage
397 mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
398 mStorageManager.registerListener(
399 new com.android.server.status.StorageNotification(context));
400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 // battery
Joe Onorato0cbda992010-05-02 16:28:15 -0700402 service.setIcon("battery",
403 null, com.android.internal.R.drawable.stat_sys_battery_unknown, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404
405 // phone_signal
406 mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Joe Onorato0cbda992010-05-02 16:28:15 -0700407 mPhoneSignalIconId = com.android.internal.R.drawable.stat_sys_signal_null;
408 service.setIcon("phone_signal", null, mPhoneSignalIconId, 0);
Wink Savillee9b06d72009-05-18 21:47:50 -0700409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 // register for phone state notifications.
411 ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
412 .listen(mPhoneStateListener,
413 PhoneStateListener.LISTEN_SERVICE_STATE
Wink Savillee9b06d72009-05-18 21:47:50 -0700414 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 | PhoneStateListener.LISTEN_CALL_STATE
416 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
417 | PhoneStateListener.LISTEN_DATA_ACTIVITY);
418
419 // data_connection
Joe Onorato0cbda992010-05-02 16:28:15 -0700420 service.setIcon("data_connection",
421 null, com.android.internal.R.drawable.stat_sys_data_connected_g, 0);
422 service.setIconVisibility("data_connection", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423
424 // wifi
Joe Onorato0cbda992010-05-02 16:28:15 -0700425 service.setIcon("wifi", null, sWifiSignalImages[0], 0);
426 service.setIconVisibility("wifi", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 // wifi will get updated by the sticky intents
Wink Saville04e71b32009-04-02 11:00:54 -0700428
429 // TTY status
Joe Onorato0cbda992010-05-02 16:28:15 -0700430 service.setIcon("tty", null, com.android.internal.R.drawable.stat_sys_tty_mode, 0);
431 service.setIconVisibility("tty", false);
Wink Saville04e71b32009-04-02 11:00:54 -0700432
Wink Savillee9b06d72009-05-18 21:47:50 -0700433 // Cdma Roaming Indicator, ERI
Joe Onorato0cbda992010-05-02 16:28:15 -0700434 service.setIcon("cdma_eri",
435 null, com.android.internal.R.drawable.stat_sys_roaming_cdma_0, 0);
436 service.setIconVisibility("cdma_eri", false);
Wink Savillee9b06d72009-05-18 21:47:50 -0700437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 // bluetooth status
Joe Onorato0cbda992010-05-02 16:28:15 -0700439 service.setIcon("bluetooth",
440 null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200441 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Nick Pellybd022f42009-08-14 18:33:38 -0700442 if (adapter != null) {
443 mBluetoothEnabled = adapter.isEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 } else {
445 mBluetoothEnabled = false;
446 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800447 mBluetoothA2dpConnected = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 mBluetoothHeadsetState = BluetoothHeadset.STATE_DISCONNECTED;
Jiafa Liu3f416732009-07-02 16:36:02 +0800449 mBluetoothPbapState = BluetoothPbap.STATE_DISCONNECTED;
Joe Onorato0cbda992010-05-02 16:28:15 -0700450 mService.setIconVisibility("bluetooth", mBluetoothEnabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451
452 // Gps status
Joe Onorato0cbda992010-05-02 16:28:15 -0700453 service.setIcon("gps",
454 null, com.android.internal.R.drawable.stat_sys_gps_acquiring_anim, 0);
455 service.setIconVisibility("gps", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456
457 // Alarm clock
Joe Onorato0cbda992010-05-02 16:28:15 -0700458 service.setIcon("alarm_clock", null, com.android.internal.R.drawable.stat_notify_alarm, 0);
459 service.setIconVisibility("alarm_clock", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460
461 // Sync state
Joe Onorato0cbda992010-05-02 16:28:15 -0700462 service.setIcon("sync_active", null, R.drawable.stat_notify_sync_anim0, 0);
463 service.setIcon("sync_failing", null, R.drawable.stat_notify_sync_error, 0);
464 service.setIconVisibility("sync_active", false);
465 service.setIconVisibility("sync_failing", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466
467 // volume
Joe Onorato0cbda992010-05-02 16:28:15 -0700468 service.setIcon("volume", null, com.android.internal.R.drawable.stat_sys_ringer_silent, 0);
469 service.setIconVisibility("volume", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 updateVolume();
johnwang347c5a22009-08-24 22:11:11 -0700471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 IntentFilter filter = new IntentFilter();
473
474 // Register for Intent broadcasts for...
475 filter.addAction(Intent.ACTION_TIME_TICK);
476 filter.addAction(Intent.ACTION_TIME_CHANGED);
477 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
478 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Mihai Predaa82842f2009-04-29 15:05:56 +0200479 filter.addAction(Intent.ACTION_BATTERY_LOW);
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700480 filter.addAction(Intent.ACTION_BATTERY_OKAY);
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400481 filter.addAction(Intent.ACTION_POWER_CONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
483 filter.addAction(Intent.ACTION_ALARM_CHANGED);
484 filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
485 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
486 filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
Nick Pellyde893f52009-09-08 13:15:33 -0700487 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Nick Pelly005b2282009-09-10 10:21:56 -0700488 filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
489 filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
Jiafa Liu3f416732009-07-02 16:36:02 +0800490 filter.addAction(BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
492 filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
493 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
494 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
Mike Lockwood00b74272010-03-26 10:41:48 -0400495 filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION);
496 filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Wink Saville04e71b32009-04-02 11:00:54 -0700498 filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
John Wang33e21fc2009-10-08 10:35:27 -0700500
501 // load config to determine if to distinguish Hspa data icon
502 try {
503 mHspaDataDistinguishable = mContext.getResources().getBoolean(
504 com.android.internal.R.bool.config_hspa_data_distinguishable);
505 } catch (Exception e) {
506 mHspaDataDistinguishable = false;
507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 }
509
Joe Onorato089de882010-04-12 08:18:45 -0700510 public static void installIcons(Context context, StatusBarManagerService service) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 sInstance = new StatusBarPolicy(context, service);
512 }
513
Eric Fischer36e136c2010-01-14 17:42:48 -0800514 private final CharSequence getSmallTime() {
515 boolean b24 = DateFormat.is24HourFormat(mContext);
516 int res;
517
518 if (b24) {
519 res = R.string.twenty_four_hour_time_format;
520 } else {
521 res = R.string.twelve_hour_time_format;
522 }
523
Eric Fischer36e136c2010-01-14 17:42:48 -0800524 final char MAGIC1 = '\uEF00';
525 final char MAGIC2 = '\uEF01';
526
Joe Onorato63ce8e82010-01-17 19:06:51 -0500527 SimpleDateFormat sdf;
528 String format = mContext.getString(res);
529 if (!format.equals(mClockFormatString)) {
530 /*
531 * Search for an unquoted "a" in the format string, so we can
532 * add dummy characters around it to let us find it again after
533 * formatting and change its size.
534 */
Daniel Sandler2c195f72010-05-21 15:42:06 -0400535 if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) {
536 int a = -1;
537 boolean quoted = false;
538 for (int i = 0; i < format.length(); i++) {
539 char c = format.charAt(i);
Eric Fischer36e136c2010-01-14 17:42:48 -0800540
Daniel Sandler2c195f72010-05-21 15:42:06 -0400541 if (c == '\'') {
542 quoted = !quoted;
543 }
544
545 if (!quoted && c == 'a') {
546 a = i;
547 break;
548 }
Joe Onorato63ce8e82010-01-17 19:06:51 -0500549 }
550
Daniel Sandler2c195f72010-05-21 15:42:06 -0400551 if (a >= 0) {
552 // Move a back so any whitespace before the AM/PM is also in the alternate size.
553 final int b = a;
554 while (a > 0 && Character.isWhitespace(format.charAt(a-1))) {
555 a--;
556 }
557 format = format.substring(0, a) + MAGIC1 + format.substring(a, b)
558 + "a" + MAGIC2 + format.substring(b + 1);
Joe Onorato63ce8e82010-01-17 19:06:51 -0500559 }
560 }
561
Joe Onorato63ce8e82010-01-17 19:06:51 -0500562 mClockFormat = sdf = new SimpleDateFormat(format);
563 mClockFormatString = format;
564 } else {
565 sdf = mClockFormat;
566 }
567 String result = sdf.format(mCalendar.getTime());
Eric Fischer36e136c2010-01-14 17:42:48 -0800568
Daniel Sandler2c195f72010-05-21 15:42:06 -0400569 if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) {
570 int magic1 = result.indexOf(MAGIC1);
571 int magic2 = result.indexOf(MAGIC2);
Eric Fischer36e136c2010-01-14 17:42:48 -0800572
Daniel Sandler2c195f72010-05-21 15:42:06 -0400573 if (magic1 >= 0 && magic2 > magic1) {
574 SpannableStringBuilder formatted = new SpannableStringBuilder(result);
Eric Fischer36e136c2010-01-14 17:42:48 -0800575
Daniel Sandler2c195f72010-05-21 15:42:06 -0400576 if (AM_PM_STYLE == AM_PM_STYLE_GONE) {
577 formatted.delete(magic1, magic2+1);
578 } else {
579 if (AM_PM_STYLE == AM_PM_STYLE_SMALL) {
580 CharacterStyle style = new RelativeSizeSpan(0.7f);
581 formatted.setSpan(style, magic1, magic2,
582 Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
583 }
Eric Fischer36e136c2010-01-14 17:42:48 -0800584
Daniel Sandler2c195f72010-05-21 15:42:06 -0400585 formatted.delete(magic2, magic2 + 1);
586 formatted.delete(magic1, magic1 + 1);
587 }
Eric Fischer36e136c2010-01-14 17:42:48 -0800588
Daniel Sandler2c195f72010-05-21 15:42:06 -0400589 return formatted;
590 }
Eric Fischer36e136c2010-01-14 17:42:48 -0800591 }
Daniel Sandler2c195f72010-05-21 15:42:06 -0400592
593 return result;
Eric Fischer36e136c2010-01-14 17:42:48 -0800594 }
595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 private final void updateClock() {
597 mCalendar.setTimeInMillis(System.currentTimeMillis());
Joe Onorato0cbda992010-05-02 16:28:15 -0700598 mService.setIcon("clock", getSmallTime());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 }
600
601 private final void updateAlarm(Intent intent) {
602 boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
Joe Onorato0cbda992010-05-02 16:28:15 -0700603 mService.setIconVisibility("alarm_clock", alarmSet);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 }
605
606 private final void updateSyncState(Intent intent) {
607 boolean isActive = intent.getBooleanExtra("active", false);
608 boolean isFailing = intent.getBooleanExtra("failing", false);
Joe Onorato0cbda992010-05-02 16:28:15 -0700609 mService.setIconVisibility("sync_active", isActive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 // Don't display sync failing icon: BUG 1297963 Set sync error timeout to "never"
Joe Onorato0cbda992010-05-02 16:28:15 -0700611 //mService.setIconVisibility("sync_failing", isFailing && !isActive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 }
613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 private final void updateBattery(Intent intent) {
Joe Onorato0cbda992010-05-02 16:28:15 -0700615 final int id = intent.getIntExtra("icon-small", 0);
616 int level = intent.getIntExtra("level", 0);
617 mService.setIcon("battery", null, id, level);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618
619 boolean plugged = intent.getIntExtra("plugged", 0) != 0;
Joe Onorato0cbda992010-05-02 16:28:15 -0700620 level = intent.getIntExtra("level", -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800622 Slog.d(TAG, "updateBattery level=" + level
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 + " plugged=" + plugged
624 + " mBatteryPlugged=" + mBatteryPlugged
625 + " mBatteryLevel=" + mBatteryLevel
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 + " mBatteryFirst=" + mBatteryFirst);
627 }
628
629 boolean oldPlugged = mBatteryPlugged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630
631 mBatteryPlugged = plugged;
632 mBatteryLevel = level;
633
634 if (mBatteryFirst) {
635 mBatteryFirst = false;
636 }
637 /*
638 * No longer showing the battery view because it draws attention away
639 * from the USB storage notification. We could still show it when
640 * connected to a brick, but that could lead to the user into thinking
641 * the device does not charge when plugged into USB (since he/she would
642 * not see the same battery screen on USB as he sees on brick).
643 */
644 /* else {
645 if (plugged && !oldPlugged) {
646 showBatteryView();
647 }
648 }
649 */
650 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800651 Slog.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654
Mihai Predaa82842f2009-04-29 15:05:56 +0200655 private void onBatteryLow(Intent intent) {
656 if (SHOW_LOW_BATTERY_WARNING) {
657 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800658 Slog.d(TAG, "mPhoneState=" + mPhoneState
Mihai Predaa82842f2009-04-29 15:05:56 +0200659 + " mLowBatteryDialog=" + mLowBatteryDialog
660 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200662
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500663 if (SHOW_BATTERY_WARNINGS_IN_CALL || mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
Mihai Predaa82842f2009-04-29 15:05:56 +0200664 showLowBatteryWarning();
665 } else {
666 mBatteryShowLowOnEndCall = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 }
668 }
669 }
670
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700671 private void onBatteryOkay(Intent intent) {
672 if (mLowBatteryDialog != null
673 && SHOW_LOW_BATTERY_WARNING) {
674 mLowBatteryDialog.dismiss();
675 mBatteryShowLowOnEndCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 }
677 }
678
johnwang347c5a22009-08-24 22:11:11 -0700679 private void showBatteryView() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 closeLastBatteryView();
681 if (mLowBatteryDialog != null) {
682 mLowBatteryDialog.dismiss();
683 }
684
685 int level = mBatteryLevel;
686
687 View v = View.inflate(mContext, com.android.internal.R.layout.battery_status, null);
688 mBatteryView = v;
689 int pixelFormat = PixelFormat.TRANSLUCENT;
690 Drawable bg = v.getBackground();
691 if (bg != null) {
692 pixelFormat = bg.getOpacity();
693 }
694
Dianne Hackborn568cae52009-10-07 16:13:39 -0700695 int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
696 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
697 | WindowManager.LayoutParams.FLAG_DIM_BEHIND;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800698
Dianne Hackborn568cae52009-10-07 16:13:39 -0700699 if (!mContext.getResources().getBoolean(
700 com.android.internal.R.bool.config_sf_slowBlur)) {
701 flags |= WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
702 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
705 ViewGroup.LayoutParams.WRAP_CONTENT,
706 ViewGroup.LayoutParams.WRAP_CONTENT,
707 WindowManager.LayoutParams.TYPE_TOAST,
Dianne Hackborn568cae52009-10-07 16:13:39 -0700708 flags, pixelFormat);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709
710 // Get the dim amount from the theme
711 TypedArray a = mContext.obtainStyledAttributes(
712 com.android.internal.R.styleable.Theme);
713 lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
714 a.recycle();
Wink Saville04e71b32009-04-02 11:00:54 -0700715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 lp.setTitle("Battery");
717
718 TextView levelTextView = (TextView)v.findViewById(com.android.internal.R.id.level_percent);
719 levelTextView.setText(mContext.getString(
720 com.android.internal.R.string.battery_status_text_percent_format, level));
721
722 setBatteryLevel(v, com.android.internal.R.id.spacer, 100-level, 0, 0);
723 setBatteryLevel(v, com.android.internal.R.id.level, level,
724 com.android.internal.R.drawable.battery_charge_fill, level);
725
726 WindowManagerImpl.getDefault().addView(v, lp);
727
728 scheduleCloseBatteryView();
729 }
730
731 private void setBatteryLevel(View parent, int id, int height, int background, int level) {
732 ImageView v = (ImageView)parent.findViewById(id);
733 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)v.getLayoutParams();
734 lp.weight = height;
735 if (background != 0) {
736 v.setBackgroundResource(background);
737 Drawable bkg = v.getBackground();
738 bkg.setLevel(level);
739 }
740 }
741
742 private void showLowBatteryWarning() {
743 closeLastBatteryView();
744
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400745 // Show exact battery level.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 CharSequence levelText = mContext.getString(
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400747 com.android.internal.R.string.battery_low_percent_format, mBatteryLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748
749 if (mBatteryLevelTextView != null) {
750 mBatteryLevelTextView.setText(levelText);
751 } else {
752 View v = View.inflate(mContext, com.android.internal.R.layout.battery_low, null);
753 mBatteryLevelTextView=(TextView)v.findViewById(com.android.internal.R.id.level_percent);
754
755 mBatteryLevelTextView.setText(levelText);
756
757 AlertDialog.Builder b = new AlertDialog.Builder(mContext);
758 b.setCancelable(true);
759 b.setTitle(com.android.internal.R.string.battery_low_title);
760 b.setView(v);
761 b.setIcon(android.R.drawable.ic_dialog_alert);
762 b.setPositiveButton(android.R.string.ok, null);
johnwang347c5a22009-08-24 22:11:11 -0700763
Dianne Hackborn3d74bb42009-06-19 10:35:21 -0700764 final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
765 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
766 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
767 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
768 | Intent.FLAG_ACTIVITY_NO_HISTORY);
769 if (intent.resolveActivity(mContext.getPackageManager()) != null) {
770 b.setNegativeButton(com.android.internal.R.string.battery_low_why,
771 new DialogInterface.OnClickListener() {
772 public void onClick(DialogInterface dialog, int which) {
773 mContext.startActivity(intent);
774 if (mLowBatteryDialog != null) {
775 mLowBatteryDialog.dismiss();
776 }
777 }
778 });
779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780
781 AlertDialog d = b.create();
782 d.setOnDismissListener(mLowBatteryListener);
783 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
784 d.show();
785 mLowBatteryDialog = d;
786 }
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500787
788 final ContentResolver cr = mContext.getContentResolver();
789 if (Settings.System.getInt(cr,
John Wang56c2d2f2010-04-07 08:57:17 -0700790 Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500791 {
792 final String soundPath = Settings.System.getString(cr,
793 Settings.System.LOW_BATTERY_SOUND);
794 if (soundPath != null) {
795 final Uri soundUri = Uri.parse("file://" + soundPath);
796 if (soundUri != null) {
797 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
Daniel Sandlerec2c88d2010-02-20 01:04:57 -0500798 if (sfx != null) {
799 sfx.setStreamType(AudioManager.STREAM_SYSTEM);
800 sfx.play();
801 }
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500802 }
803 }
804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 }
806
807 private final void updateCallState(int state) {
808 mPhoneState = state;
809 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800810 Slog.d(TAG, "mPhoneState=" + mPhoneState
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 + " mLowBatteryDialog=" + mLowBatteryDialog
812 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
813 }
814 if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
815 if (mBatteryShowLowOnEndCall) {
816 if (!mBatteryPlugged) {
817 showLowBatteryWarning();
818 }
819 mBatteryShowLowOnEndCall = false;
820 }
821 } else {
822 if (mLowBatteryDialog != null) {
823 mLowBatteryDialog.dismiss();
824 mBatteryShowLowOnEndCall = true;
825 }
826 }
827 }
828
829 private DialogInterface.OnDismissListener mLowBatteryListener
830 = new DialogInterface.OnDismissListener() {
831 public void onDismiss(DialogInterface dialog) {
832 mLowBatteryDialog = null;
833 mBatteryLevelTextView = null;
834 }
835 };
836
837 private void scheduleCloseBatteryView() {
838 Message m = mHandler.obtainMessage(EVENT_BATTERY_CLOSE);
839 m.arg1 = (++mBatteryViewSequence);
840 mHandler.sendMessageDelayed(m, 3000);
841 }
842
843 private void closeLastBatteryView() {
844 if (mBatteryView != null) {
845 //mBatteryView.debug();
846 WindowManagerImpl.getDefault().removeView(mBatteryView);
847 mBatteryView = null;
848 }
849 }
850
851 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
852 @Override
Wink Savillee9b06d72009-05-18 21:47:50 -0700853 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
854 mSignalStrength = signalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 updateSignalStrength();
856 }
857
858 @Override
859 public void onServiceStateChanged(ServiceState state) {
860 mServiceState = state;
861 updateSignalStrength();
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700862 updateCdmaRoamingIcon(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 updateDataIcon();
864 }
865
866 @Override
867 public void onCallStateChanged(int state, String incomingNumber) {
868 updateCallState(state);
johnwang347c5a22009-08-24 22:11:11 -0700869 // In cdma, if a voice call is made, RSSI should switch to 1x.
870 if (isCdma()) {
871 updateSignalStrength();
872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 }
874
875 @Override
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700876 public void onDataConnectionStateChanged(int state, int networkType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 mDataState = state;
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700878 updateDataNetType(networkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 updateDataIcon();
880 }
881
882 @Override
883 public void onDataActivity(int direction) {
884 mDataActivity = direction;
885 updateDataIcon();
886 }
887 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888
889 private final void updateSimState(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -0700890 String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
891 if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
892 mSimState = IccCard.State.ABSENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 }
Wink Saville04e71b32009-04-02 11:00:54 -0700894 else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
895 mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896 }
Wink Saville04e71b32009-04-02 11:00:54 -0700897 else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
898 final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
899 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
900 mSimState = IccCard.State.PIN_REQUIRED;
johnwang347c5a22009-08-24 22:11:11 -0700901 }
Wink Saville04e71b32009-04-02 11:00:54 -0700902 else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
903 mSimState = IccCard.State.PUK_REQUIRED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 }
905 else {
Wink Saville04e71b32009-04-02 11:00:54 -0700906 mSimState = IccCard.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 }
908 } else {
Wink Saville04e71b32009-04-02 11:00:54 -0700909 mSimState = IccCard.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 }
911 updateDataIcon();
912 }
913
Wink Savillee9b06d72009-05-18 21:47:50 -0700914 private boolean isCdma() {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700915 return (mSignalStrength != null) && !mSignalStrength.isGsm();
Wink Savillee9b06d72009-05-18 21:47:50 -0700916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917
johnwang347c5a22009-08-24 22:11:11 -0700918 private boolean isEvdo() {
919 return ( (mServiceState != null)
920 && ((mServiceState.getRadioTechnology()
921 == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
922 || (mServiceState.getRadioTechnology()
Naveen Kalla0a5174a2010-04-21 14:48:03 -0700923 == ServiceState.RADIO_TECHNOLOGY_EVDO_A)
924 || (mServiceState.getRadioTechnology()
925 == ServiceState.RADIO_TECHNOLOGY_EVDO_B)));
johnwang347c5a22009-08-24 22:11:11 -0700926 }
927
Wink Savillee9b06d72009-05-18 21:47:50 -0700928 private boolean hasService() {
929 if (mServiceState != null) {
930 switch (mServiceState.getState()) {
931 case ServiceState.STATE_OUT_OF_SERVICE:
932 case ServiceState.STATE_POWER_OFF:
933 return false;
934 default:
935 return true;
936 }
937 } else {
938 return false;
939 }
940 }
941
942 private final void updateSignalStrength() {
943 int iconLevel = -1;
Wink Savillee9b06d72009-05-18 21:47:50 -0700944 int[] iconList;
Wink Savillee9b06d72009-05-18 21:47:50 -0700945
John Wang56c2d2f2010-04-07 08:57:17 -0700946 // Display signal strength while in "emergency calls only" mode
947 if (!hasService() && !mServiceState.isEmergencyOnly()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800948 //Slog.d(TAG, "updateSignalStrength: no service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 if (Settings.System.getInt(mContext.getContentResolver(),
950 Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
Joe Onorato0cbda992010-05-02 16:28:15 -0700951 mPhoneSignalIconId = com.android.internal.R.drawable.stat_sys_signal_flightmode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 } else {
Joe Onorato0cbda992010-05-02 16:28:15 -0700953 mPhoneSignalIconId = com.android.internal.R.drawable.stat_sys_signal_null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 }
Joe Onorato0cbda992010-05-02 16:28:15 -0700955 mService.setIcon("phone_signal", null, mPhoneSignalIconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 return;
957 }
958
Wink Savillee9b06d72009-05-18 21:47:50 -0700959 if (!isCdma()) {
960 int asu = mSignalStrength.getGsmSignalStrength();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961
Wink Savillee9b06d72009-05-18 21:47:50 -0700962 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
963 // asu = 0 (-113dB or less) is very weak
964 // signal, its better to show 0 bars to the user in such cases.
965 // asu = 99 is a special case, where the signal strength is unknown.
jshee63e472010-03-18 11:14:42 -0700966 if (asu <= 2 || asu == 99) iconLevel = 0;
967 else if (asu >= 12) iconLevel = 4;
Wink Savillee9b06d72009-05-18 21:47:50 -0700968 else if (asu >= 8) iconLevel = 3;
jshee63e472010-03-18 11:14:42 -0700969 else if (asu >= 5) iconLevel = 2;
Wink Savillee9b06d72009-05-18 21:47:50 -0700970 else iconLevel = 1;
971
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700972 // Though mPhone is a Manager, this call is not an IPC
Wink Savillee9b06d72009-05-18 21:47:50 -0700973 if (mPhone.isNetworkRoaming()) {
974 iconList = sSignalImages_r;
975 } else {
976 iconList = sSignalImages;
Wink Saville04e71b32009-04-02 11:00:54 -0700977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 } else {
johnwang347c5a22009-08-24 22:11:11 -0700979 iconList = this.sSignalImages;
Wink Savillee9b06d72009-05-18 21:47:50 -0700980
johnwang347c5a22009-08-24 22:11:11 -0700981 // If 3G(EV) and 1x network are available than 3G should be
982 // displayed, displayed RSSI should be from the EV side.
983 // If a voice call is made then RSSI should switch to 1x.
984 if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
985 iconLevel = getEvdoLevel();
986 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800987 Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level=" + getCdmaLevel());
johnwang347c5a22009-08-24 22:11:11 -0700988 }
989 } else {
990 iconLevel = getCdmaLevel();
991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 }
Joe Onorato0cbda992010-05-02 16:28:15 -0700993 mPhoneSignalIconId = iconList[iconLevel];
994 mService.setIcon("phone_signal", null, mPhoneSignalIconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 }
996
johnwang347c5a22009-08-24 22:11:11 -0700997 private int getCdmaLevel() {
998 final int cdmaDbm = mSignalStrength.getCdmaDbm();
999 final int cdmaEcio = mSignalStrength.getCdmaEcio();
1000 int levelDbm = 0;
1001 int levelEcio = 0;
1002
1003 if (cdmaDbm >= -75) levelDbm = 4;
1004 else if (cdmaDbm >= -85) levelDbm = 3;
1005 else if (cdmaDbm >= -95) levelDbm = 2;
1006 else if (cdmaDbm >= -100) levelDbm = 1;
1007 else levelDbm = 0;
1008
1009 // Ec/Io are in dB*10
1010 if (cdmaEcio >= -90) levelEcio = 4;
1011 else if (cdmaEcio >= -110) levelEcio = 3;
1012 else if (cdmaEcio >= -130) levelEcio = 2;
1013 else if (cdmaEcio >= -150) levelEcio = 1;
1014 else levelEcio = 0;
1015
1016 return (levelDbm < levelEcio) ? levelDbm : levelEcio;
1017 }
1018
1019 private int getEvdoLevel() {
1020 int evdoDbm = mSignalStrength.getEvdoDbm();
1021 int evdoSnr = mSignalStrength.getEvdoSnr();
1022 int levelEvdoDbm = 0;
1023 int levelEvdoSnr = 0;
1024
1025 if (evdoDbm >= -65) levelEvdoDbm = 4;
1026 else if (evdoDbm >= -75) levelEvdoDbm = 3;
1027 else if (evdoDbm >= -90) levelEvdoDbm = 2;
1028 else if (evdoDbm >= -105) levelEvdoDbm = 1;
1029 else levelEvdoDbm = 0;
1030
John Michelau1336a562009-09-28 10:41:02 -05001031 if (evdoSnr >= 7) levelEvdoSnr = 4;
1032 else if (evdoSnr >= 5) levelEvdoSnr = 3;
1033 else if (evdoSnr >= 3) levelEvdoSnr = 2;
1034 else if (evdoSnr >= 1) levelEvdoSnr = 1;
johnwang347c5a22009-08-24 22:11:11 -07001035 else levelEvdoSnr = 0;
1036
1037 return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
1038 }
1039
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001040 private final void updateDataNetType(int net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001041 switch (net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001042 case TelephonyManager.NETWORK_TYPE_EDGE:
1043 mDataIconList = sDataNetType_e;
1044 break;
1045 case TelephonyManager.NETWORK_TYPE_UMTS:
1046 mDataIconList = sDataNetType_3g;
1047 break;
Li Zheebe66342009-08-14 19:22:16 +08001048 case TelephonyManager.NETWORK_TYPE_HSDPA:
1049 case TelephonyManager.NETWORK_TYPE_HSUPA:
1050 case TelephonyManager.NETWORK_TYPE_HSPA:
John Wang33e21fc2009-10-08 10:35:27 -07001051 if (mHspaDataDistinguishable) {
1052 mDataIconList = sDataNetType_h;
1053 } else {
1054 mDataIconList = sDataNetType_3g;
1055 }
Li Zheebe66342009-08-14 19:22:16 +08001056 break;
Wink Saville04e71b32009-04-02 11:00:54 -07001057 case TelephonyManager.NETWORK_TYPE_CDMA:
1058 // display 1xRTT for IS95A/B
johnwang9f87cb22009-08-25 15:25:37 -07001059 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001060 break;
1061 case TelephonyManager.NETWORK_TYPE_1xRTT:
johnwang9f87cb22009-08-25 15:25:37 -07001062 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001063 break;
1064 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
1065 case TelephonyManager.NETWORK_TYPE_EVDO_A:
Naveen Kalla0a5174a2010-04-21 14:48:03 -07001066 case TelephonyManager.NETWORK_TYPE_EVDO_B:
johnwang9f87cb22009-08-25 15:25:37 -07001067 mDataIconList = sDataNetType_3g;
Wink Saville04e71b32009-04-02 11:00:54 -07001068 break;
1069 default:
1070 mDataIconList = sDataNetType_g;
1071 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 }
1073 }
1074
1075 private final void updateDataIcon() {
1076 int iconId;
1077 boolean visible = true;
1078
Wink Savillee9b06d72009-05-18 21:47:50 -07001079 if (!isCdma()) {
1080 // GSM case, we have to check also the sim state
1081 if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
1082 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
1083 switch (mDataActivity) {
1084 case TelephonyManager.DATA_ACTIVITY_IN:
1085 iconId = mDataIconList[1];
1086 break;
1087 case TelephonyManager.DATA_ACTIVITY_OUT:
1088 iconId = mDataIconList[2];
1089 break;
1090 case TelephonyManager.DATA_ACTIVITY_INOUT:
1091 iconId = mDataIconList[3];
1092 break;
1093 default:
1094 iconId = mDataIconList[0];
1095 break;
1096 }
Joe Onorato0cbda992010-05-02 16:28:15 -07001097 mService.setIcon("data_connection", null, iconId, 0);
Wink Savillee9b06d72009-05-18 21:47:50 -07001098 } else {
1099 visible = false;
1100 }
1101 } else {
Joe Onorato0cbda992010-05-02 16:28:15 -07001102 iconId = com.android.internal.R.drawable.stat_sys_no_sim;
1103 mService.setIcon("data_connection", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001105 } else {
1106 // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
1107 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 switch (mDataActivity) {
1109 case TelephonyManager.DATA_ACTIVITY_IN:
Wink Savillee9b06d72009-05-18 21:47:50 -07001110 iconId = mDataIconList[1];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 break;
1112 case TelephonyManager.DATA_ACTIVITY_OUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001113 iconId = mDataIconList[2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 break;
1115 case TelephonyManager.DATA_ACTIVITY_INOUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001116 iconId = mDataIconList[3];
1117 break;
1118 case TelephonyManager.DATA_ACTIVITY_DORMANT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 default:
Wink Savillee9b06d72009-05-18 21:47:50 -07001120 iconId = mDataIconList[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 break;
1122 }
Joe Onorato0cbda992010-05-02 16:28:15 -07001123 mService.setIcon("data_connection", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 } else {
1125 visible = false;
1126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001128
Dianne Hackborn4840e142009-03-24 22:40:29 -07001129 long ident = Binder.clearCallingIdentity();
1130 try {
Wink Saville04e71b32009-04-02 11:00:54 -07001131 mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
Dianne Hackborn4840e142009-03-24 22:40:29 -07001132 } catch (RemoteException e) {
1133 } finally {
1134 Binder.restoreCallingIdentity(ident);
1135 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 if (mDataIconVisible != visible) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001138 mService.setIconVisibility("data_connection", visible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 mDataIconVisible = visible;
1140 }
1141 }
1142
1143 private final void updateVolume() {
1144 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1145 final int ringerMode = audioManager.getRingerMode();
1146 final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
Wink Savillee9b06d72009-05-18 21:47:50 -07001147 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
1149 ? com.android.internal.R.drawable.stat_sys_ringer_vibrate
1150 : com.android.internal.R.drawable.stat_sys_ringer_silent;
1151
1152 if (visible) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001153 mService.setIcon("volume", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 }
1155 if (visible != mVolumeVisible) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001156 mService.setIconVisibility("volume", visible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 mVolumeVisible = visible;
1158 }
1159 }
1160
1161 private final void updateBluetooth(Intent intent) {
1162 int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 String action = intent.getAction();
Nick Pellyde893f52009-09-08 13:15:33 -07001164 if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
Nick Pellyb24e11b2009-09-08 17:40:43 -07001165 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
Nick Pellyde893f52009-09-08 13:15:33 -07001166 mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
Nick Pelly005b2282009-09-10 10:21:56 -07001167 } else if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
1168 mBluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 BluetoothHeadset.STATE_ERROR);
Nick Pelly005b2282009-09-10 10:21:56 -07001170 } else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) {
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001171 BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
1172 if (a2dp.getConnectedSinks().size() != 0) {
1173 mBluetoothA2dpConnected = true;
1174 } else {
1175 mBluetoothA2dpConnected = false;
1176 }
Jiafa Liu3f416732009-07-02 16:36:02 +08001177 } else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
1178 mBluetoothPbapState = intent.getIntExtra(BluetoothPbap.PBAP_STATE,
1179 BluetoothPbap.STATE_DISCONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 } else {
1181 return;
1182 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001183
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001184 if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED || mBluetoothA2dpConnected ||
Jiafa Liu3f416732009-07-02 16:36:02 +08001185 mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
1187 }
1188
Joe Onorato0cbda992010-05-02 16:28:15 -07001189 mService.setIcon("bluetooth", null, iconId, 0);
1190 mService.setIconVisibility("bluetooth", mBluetoothEnabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 }
1192
1193 private final void updateWifi(Intent intent) {
1194 final String action = intent.getAction();
1195 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
1198 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
Wink Savillee9b06d72009-05-18 21:47:50 -07001199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 if (!enabled) {
1201 // If disabled, hide the icon. (We show icon when connected.)
Joe Onorato0cbda992010-05-02 16:28:15 -07001202 mService.setIconVisibility("wifi", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
1206 final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
1207 false);
1208 if (!enabled) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001209 mService.setIconVisibility("wifi", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 }
1211 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
1212
Wink Savillee9b06d72009-05-18 21:47:50 -07001213 final NetworkInfo networkInfo = (NetworkInfo)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
Wink Savillee9b06d72009-05-18 21:47:50 -07001215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 int iconId;
1217 if (networkInfo != null && networkInfo.isConnected()) {
1218 mIsWifiConnected = true;
1219 if (mLastWifiSignalLevel == -1) {
1220 iconId = sWifiSignalImages[0];
1221 } else {
1222 iconId = sWifiSignalImages[mLastWifiSignalLevel];
1223 }
Wink Saville04e71b32009-04-02 11:00:54 -07001224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 // Show the icon since wi-fi is connected
Joe Onorato0cbda992010-05-02 16:28:15 -07001226 mService.setIconVisibility("wifi", true);
Wink Saville04e71b32009-04-02 11:00:54 -07001227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 } else {
1229 mLastWifiSignalLevel = -1;
1230 mIsWifiConnected = false;
1231 iconId = sWifiSignalImages[0];
1232
1233 // Hide the icon since we're not connected
Joe Onorato0cbda992010-05-02 16:28:15 -07001234 mService.setIconVisibility("wifi", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001235 }
1236
Joe Onorato0cbda992010-05-02 16:28:15 -07001237 mService.setIcon("wifi", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001239 int iconId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
1241 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
1242 sWifiSignalImages.length);
1243 if (newSignalLevel != mLastWifiSignalLevel) {
1244 mLastWifiSignalLevel = newSignalLevel;
1245 if (mIsWifiConnected) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001246 iconId = sWifiSignalImages[newSignalLevel];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 } else {
Joe Onorato0cbda992010-05-02 16:28:15 -07001248 iconId = sWifiTemporarilyNotConnectedImage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 }
Joe Onorato0cbda992010-05-02 16:28:15 -07001250 mService.setIcon("wifi", null, iconId, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 }
1252 }
1253 }
1254
1255 private final void updateGps(Intent intent) {
1256 final String action = intent.getAction();
Mike Lockwood00b74272010-03-26 10:41:48 -04001257 final boolean enabled = intent.getBooleanExtra(LocationManager.EXTRA_GPS_ENABLED, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258
Mike Lockwood00b74272010-03-26 10:41:48 -04001259 if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 // GPS is getting fixes
Joe Onorato0cbda992010-05-02 16:28:15 -07001261 mService.setIcon("gps", null, com.android.internal.R.drawable.stat_sys_gps_on, 0);
1262 mService.setIconVisibility("gps", true);
Mike Lockwood00b74272010-03-26 10:41:48 -04001263 } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 // GPS is off
Joe Onorato0cbda992010-05-02 16:28:15 -07001265 mService.setIconVisibility("gps", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 } else {
1267 // GPS is on, but not receiving fixes
Joe Onorato0cbda992010-05-02 16:28:15 -07001268 mService.setIcon("gps",
1269 null, com.android.internal.R.drawable.stat_sys_gps_acquiring_anim, 0);
1270 mService.setIconVisibility("gps", true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 }
1272 }
1273
Wink Savillee9b06d72009-05-18 21:47:50 -07001274 private final void updateTTY(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -07001275 final String action = intent.getAction();
1276 final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
1277
Joe Onorato8a9b2202010-02-26 18:56:32 -08001278 if (false) Slog.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -07001279
1280 if (enabled) {
1281 // TTY is on
Joe Onorato8a9b2202010-02-26 18:56:32 -08001282 if (false) Slog.v(TAG, "updateTTY: set TTY on");
Joe Onorato0cbda992010-05-02 16:28:15 -07001283 mService.setIcon("tty", null, com.android.internal.R.drawable.stat_sys_tty_mode, 0);
1284 mService.setIconVisibility("tty", true);
Wink Saville04e71b32009-04-02 11:00:54 -07001285 } else {
1286 // TTY is off
Joe Onorato8a9b2202010-02-26 18:56:32 -08001287 if (false) Slog.v(TAG, "updateTTY: set TTY off");
Joe Onorato0cbda992010-05-02 16:28:15 -07001288 mService.setIconVisibility("tty", false);
Wink Saville04e71b32009-04-02 11:00:54 -07001289 }
1290 }
1291
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001292 private final void updateCdmaRoamingIcon(ServiceState state) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001293 if (!hasService()) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001294 mService.setIconVisibility("cdma_eri", false);
Wink Savillef3152382009-06-01 14:39:20 -07001295 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001296 }
1297
1298 if (!isCdma()) {
Joe Onorato0cbda992010-05-02 16:28:15 -07001299 mService.setIconVisibility("cdma_eri", false);
Wink Savillef3152382009-06-01 14:39:20 -07001300 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001301 }
1302
1303 int[] iconList = sRoamingIndicatorImages_cdma;
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001304 int iconIndex = state.getCdmaEriIconIndex();
1305 int iconMode = state.getCdmaEriIconMode();
Wink Savillee9b06d72009-05-18 21:47:50 -07001306
1307 if (iconIndex == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001308 Slog.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001309 return;
1310 }
1311
1312 if (iconMode == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001313 Slog.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
Wink Savillee9b06d72009-05-18 21:47:50 -07001314 return;
1315 }
1316
1317 if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001318 if (false) Slog.v(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
Joe Onorato0cbda992010-05-02 16:28:15 -07001319 mService.setIconVisibility("cdma_eri", false);
Wink Savillee9b06d72009-05-18 21:47:50 -07001320 return;
1321 }
1322
1323 switch (iconMode) {
1324 case EriInfo.ROAMING_ICON_MODE_NORMAL:
Joe Onorato0cbda992010-05-02 16:28:15 -07001325 mService.setIcon("cdma_eri", null, iconList[iconIndex], 0);
1326 mService.setIconVisibility("cdma_eri", true);
Wink Savillee9b06d72009-05-18 21:47:50 -07001327 break;
1328 case EriInfo.ROAMING_ICON_MODE_FLASH:
Joe Onorato0cbda992010-05-02 16:28:15 -07001329 mService.setIcon("cdma_eri",
1330 null, com.android.internal.R.drawable.stat_sys_roaming_cdma_flash, 0);
1331 mService.setIconVisibility("cdma_eri", true);
Wink Savillee9b06d72009-05-18 21:47:50 -07001332 break;
1333
1334 }
Joe Onorato0cbda992010-05-02 16:28:15 -07001335 mService.setIcon("phone_signal", null, mPhoneSignalIconId, 0);
Wink Savillee9b06d72009-05-18 21:47:50 -07001336 }
1337
1338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 private class StatusBarHandler extends Handler {
1340 @Override
1341 public void handleMessage(Message msg) {
1342 switch (msg.what) {
1343 case EVENT_BATTERY_CLOSE:
1344 if (msg.arg1 == mBatteryViewSequence) {
1345 closeLastBatteryView();
1346 }
1347 break;
1348 }
1349 }
1350 }
1351}