blob: d13f9d38d36e9b2a67fc6745268ac593ee5c6ec2 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.status;
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019import android.app.AlertDialog;
20import android.bluetooth.BluetoothA2dp;
Nick Pellybd022f42009-08-14 18:33:38 -070021import android.bluetooth.BluetoothAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.bluetooth.BluetoothHeadset;
Jiafa Liu3f416732009-07-02 16:36:02 +080023import android.bluetooth.BluetoothPbap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.BroadcastReceiver;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050025import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.content.Context;
27import android.content.DialogInterface;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.res.TypedArray;
31import android.graphics.PixelFormat;
32import android.graphics.drawable.Drawable;
33import android.media.AudioManager;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050034import android.media.Ringtone;
35import android.media.RingtoneManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.net.NetworkInfo;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050037import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.net.wifi.WifiManager;
Dianne Hackborn4840e142009-03-24 22:40:29 -070039import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.Handler;
41import android.os.IBinder;
42import android.os.Message;
Dianne Hackborn4840e142009-03-24 22:40:29 -070043import android.os.RemoteException;
San Mehat4154c072010-02-09 18:37:54 -080044import android.os.storage.StorageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.provider.Settings;
46import android.telephony.PhoneStateListener;
47import android.telephony.ServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -070048import android.telephony.SignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.telephony.TelephonyManager;
50import android.text.format.DateFormat;
Eric Fischer36e136c2010-01-14 17:42:48 -080051import android.text.style.RelativeSizeSpan;
52import android.text.Spannable;
53import android.text.SpannableStringBuilder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.util.Log;
55import android.view.View;
56import android.view.ViewGroup;
57import android.view.WindowManager;
58import android.view.WindowManagerImpl;
59import android.widget.ImageView;
60import android.widget.LinearLayout;
61import android.widget.TextView;
62
Wink Saville04e71b32009-04-02 11:00:54 -070063import com.android.internal.R;
64import com.android.internal.app.IBatteryStats;
65import com.android.internal.location.GpsLocationProvider;
66import com.android.internal.telephony.IccCard;
67import com.android.internal.telephony.TelephonyIntents;
Wink Savillee9b06d72009-05-18 21:47:50 -070068import com.android.internal.telephony.cdma.EriInfo;
Wink Saville04e71b32009-04-02 11:00:54 -070069import com.android.internal.telephony.cdma.TtyIntent;
70import com.android.server.am.BatteryStatsService;
71
Eric Fischer36e136c2010-01-14 17:42:48 -080072import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import java.util.Calendar;
74import java.util.TimeZone;
75
76/**
77 * This class contains all of the policy about which icons are installed in the status
78 * bar at boot time. In reality, it should go into the android.policy package, but
79 * putting it here is the first step from extracting it.
80 */
81public class StatusBarPolicy {
82 private static final String TAG = "StatusBarPolicy";
83
84 private static StatusBarPolicy sInstance;
85
86 // message codes for the handler
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 private static final int EVENT_BATTERY_CLOSE = 4;
88
Dianne Hackborn4840e142009-03-24 22:40:29 -070089 private final Context mContext;
90 private final StatusBarService mService;
91 private final Handler mHandler = new StatusBarHandler();
92 private final IBatteryStats mBatteryStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093
94 // clock
95 private Calendar mCalendar;
Joe Onorato63ce8e82010-01-17 19:06:51 -050096 private String mClockFormatString;
97 private SimpleDateFormat mClockFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098 private IBinder mClockIcon;
99 private IconData mClockData;
100
San Mehat4154c072010-02-09 18:37:54 -0800101 // storage
102 private StorageManager mStorageManager;
103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 // battery
105 private IBinder mBatteryIcon;
106 private IconData mBatteryData;
107 private boolean mBatteryFirst = true;
108 private boolean mBatteryPlugged;
109 private int mBatteryLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 private AlertDialog mLowBatteryDialog;
111 private TextView mBatteryLevelTextView;
112 private View mBatteryView;
113 private int mBatteryViewSequence;
114 private boolean mBatteryShowLowOnEndCall = false;
115 private static final boolean SHOW_LOW_BATTERY_WARNING = true;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500116 private static final boolean SHOW_BATTERY_WARNINGS_IN_CALL = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117
118 // phone
119 private TelephonyManager mPhone;
120 private IBinder mPhoneIcon;
Wink Saville04e71b32009-04-02 11:00:54 -0700121
122 //***** Signal strength icons
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 private IconData mPhoneData;
Wink Saville04e71b32009-04-02 11:00:54 -0700124 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 private static final int[] sSignalImages = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700126 com.android.internal.R.drawable.stat_sys_signal_0,
127 com.android.internal.R.drawable.stat_sys_signal_1,
128 com.android.internal.R.drawable.stat_sys_signal_2,
129 com.android.internal.R.drawable.stat_sys_signal_3,
130 com.android.internal.R.drawable.stat_sys_signal_4
131 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 private static final int[] sSignalImages_r = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700133 com.android.internal.R.drawable.stat_sys_r_signal_0,
134 com.android.internal.R.drawable.stat_sys_r_signal_1,
135 com.android.internal.R.drawable.stat_sys_r_signal_2,
136 com.android.internal.R.drawable.stat_sys_r_signal_3,
137 com.android.internal.R.drawable.stat_sys_r_signal_4
138 };
Wink Savillee9b06d72009-05-18 21:47:50 -0700139 private static final int[] sRoamingIndicatorImages_cdma = new int[] {
140 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
141 // 1 is Standard Roaming Indicator OFF
142 // TODO T: image never used, remove and put 0 instead?
143 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
144
145 // 2 is Standard Roaming Indicator FLASHING
146 // TODO T: image never used, remove and put 0 instead?
147 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
148
149 // 3-12 Standard ERI
150 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //3
151 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
152 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
153 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
154 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
155 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
156 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
157 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
158 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
159 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
160
161 // 13-63 Reserved for Standard ERI
162 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //13
163 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
164 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
165 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
166 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
167 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
168 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
169 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
170 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
171 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
172 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
173 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
174 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
175 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
176 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
177 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
178 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
179 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
180 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
181 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
182 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
183 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
184 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
185 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
186 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
187 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
188 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
189 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
190 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
191 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
192 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
193 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
194 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
195 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
196 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
197 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
198 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
199 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
200 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
201 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
202 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
203 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
204 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
205 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
206 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
207 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
208 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
209 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
210 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
211 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
212 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
213
214 // 64-127 Reserved for Non Standard (Operator Specific) ERI
215 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //64
216 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
217 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
218 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
219 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
220 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
221 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
222 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
223 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
224 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
225 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
226 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
227 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
228 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
229 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
230 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
231 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
232 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
233 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
234 com.android.internal.R.drawable.stat_sys_roaming_cdma_0 //83
235
236 // 128-255 Reserved
Wink Saville04e71b32009-04-02 11:00:54 -0700237 };
Wink Saville04e71b32009-04-02 11:00:54 -0700238
239 //***** Data connection icons
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 private int[] mDataIconList = sDataNetType_g;
Wink Saville04e71b32009-04-02 11:00:54 -0700241 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 private static final int[] sDataNetType_g = new int[] {
243 com.android.internal.R.drawable.stat_sys_data_connected_g,
244 com.android.internal.R.drawable.stat_sys_data_in_g,
245 com.android.internal.R.drawable.stat_sys_data_out_g,
246 com.android.internal.R.drawable.stat_sys_data_inandout_g,
247 };
248 private static final int[] sDataNetType_3g = new int[] {
249 com.android.internal.R.drawable.stat_sys_data_connected_3g,
250 com.android.internal.R.drawable.stat_sys_data_in_3g,
251 com.android.internal.R.drawable.stat_sys_data_out_3g,
252 com.android.internal.R.drawable.stat_sys_data_inandout_3g,
253 };
254 private static final int[] sDataNetType_e = new int[] {
255 com.android.internal.R.drawable.stat_sys_data_connected_e,
256 com.android.internal.R.drawable.stat_sys_data_in_e,
257 com.android.internal.R.drawable.stat_sys_data_out_e,
258 com.android.internal.R.drawable.stat_sys_data_inandout_e,
259 };
Li Zheebe66342009-08-14 19:22:16 +0800260 //3.5G
261 private static final int[] sDataNetType_h = new int[] {
262 com.android.internal.R.drawable.stat_sys_data_connected_h,
263 com.android.internal.R.drawable.stat_sys_data_in_h,
264 com.android.internal.R.drawable.stat_sys_data_out_h,
265 com.android.internal.R.drawable.stat_sys_data_inandout_h,
266 };
267
Wink Saville04e71b32009-04-02 11:00:54 -0700268 //CDMA
johnwang9f87cb22009-08-25 15:25:37 -0700269 // Use 3G icons for EVDO data and 1x icons for 1XRTT data
270 private static final int[] sDataNetType_1x = new int[] {
271 com.android.internal.R.drawable.stat_sys_data_connected_1x,
272 com.android.internal.R.drawable.stat_sys_data_in_1x,
273 com.android.internal.R.drawable.stat_sys_data_out_1x,
274 com.android.internal.R.drawable.stat_sys_data_inandout_1x,
Wink Saville04e71b32009-04-02 11:00:54 -0700275 };
276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 // Assume it's all good unless we hear otherwise. We don't always seem
278 // to get broadcasts that it *is* there.
Wink Saville04e71b32009-04-02 11:00:54 -0700279 IccCard.State mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
281 int mDataState = TelephonyManager.DATA_DISCONNECTED;
282 int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
283 ServiceState mServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -0700284 SignalStrength mSignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
286 // data connection
287 private IBinder mDataIcon;
288 private IconData mDataData;
289 private boolean mDataIconVisible;
John Wang33e21fc2009-10-08 10:35:27 -0700290 private boolean mHspaDataDistinguishable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
292 // ringer volume
293 private IBinder mVolumeIcon;
294 private IconData mVolumeData;
295 private boolean mVolumeVisible;
Wink Saville04e71b32009-04-02 11:00:54 -0700296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 // bluetooth device status
298 private IBinder mBluetoothIcon;
299 private IconData mBluetoothData;
300 private int mBluetoothHeadsetState;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800301 private boolean mBluetoothA2dpConnected;
Jiafa Liu3f416732009-07-02 16:36:02 +0800302 private int mBluetoothPbapState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 private boolean mBluetoothEnabled;
304
305 // wifi
306 private static final int[] sWifiSignalImages = new int[] {
307 com.android.internal.R.drawable.stat_sys_wifi_signal_1,
308 com.android.internal.R.drawable.stat_sys_wifi_signal_2,
309 com.android.internal.R.drawable.stat_sys_wifi_signal_3,
310 com.android.internal.R.drawable.stat_sys_wifi_signal_4,
311 };
312 private static final int sWifiTemporarilyNotConnectedImage =
313 com.android.internal.R.drawable.stat_sys_wifi_signal_0;
314
315 private int mLastWifiSignalLevel = -1;
316 private boolean mIsWifiConnected = false;
317 private IBinder mWifiIcon;
318 private IconData mWifiData;
319
320 // gps
321 private IBinder mGpsIcon;
322 private IconData mGpsEnabledIconData;
323 private IconData mGpsFixIconData;
324
325 // alarm clock
326 // Icon lit when clock is set
327 private IBinder mAlarmClockIcon;
328 private IconData mAlarmClockIconData;
329
330 // sync state
331 // If sync is active the SyncActive icon is displayed. If sync is not active but
332 // sync is failing the SyncFailing icon is displayed. Otherwise neither are displayed.
333 private IBinder mSyncActiveIcon;
334 private IBinder mSyncFailingIcon;
335
Wink Saville04e71b32009-04-02 11:00:54 -0700336 // TTY mode
337 // Icon lit when TTY mode is enabled
338 private IBinder mTTYModeIcon;
339 private IconData mTTYModeEnableIconData;
340
Wink Savillee9b06d72009-05-18 21:47:50 -0700341 // Cdma Roaming Indicator, ERI
342 private IBinder mCdmaRoamingIndicatorIcon;
343 private IconData mCdmaRoamingIndicatorIconData;
344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
346 @Override
347 public void onReceive(Context context, Intent intent) {
348 String action = intent.getAction();
349 if (action.equals(Intent.ACTION_TIME_TICK)) {
350 updateClock();
351 }
352 else if (action.equals(Intent.ACTION_TIME_CHANGED)) {
353 updateClock();
354 }
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700355 else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
356 updateBattery(intent);
357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
359 updateClock();
360 }
361 else if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
362 String tz = intent.getStringExtra("time-zone");
363 mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz));
364 updateClock();
365 }
366 else if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
367 updateAlarm(intent);
368 }
369 else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
370 updateSyncState(intent);
371 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200372 else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
373 onBatteryLow(intent);
374 }
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400375 else if (action.equals(Intent.ACTION_BATTERY_OKAY)
376 || action.equals(Intent.ACTION_POWER_CONNECTED)) {
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700377 onBatteryOkay(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 }
Nick Pellyde893f52009-09-08 13:15:33 -0700379 else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
Nick Pelly005b2282009-09-10 10:21:56 -0700380 action.equals(BluetoothHeadset.ACTION_STATE_CHANGED) ||
381 action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED) ||
Jiafa Liu3f416732009-07-02 16:36:02 +0800382 action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 updateBluetooth(intent);
384 }
385 else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
386 action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) ||
387 action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
388 updateWifi(intent);
389 }
390 else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) ||
391 action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION)) {
392 updateGps(intent);
393 }
394 else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
395 action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
396 updateVolume();
397 }
398 else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
399 updateSimState(intent);
400 }
Wink Saville04e71b32009-04-02 11:00:54 -0700401 else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
402 updateTTY(intent);
403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 }
405 };
406
407 private StatusBarPolicy(Context context, StatusBarService service) {
408 mContext = context;
409 mService = service;
Wink Savillee9b06d72009-05-18 21:47:50 -0700410 mSignalStrength = new SignalStrength();
Dianne Hackborn4840e142009-03-24 22:40:29 -0700411 mBatteryStats = BatteryStatsService.getService();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412
413 // clock
414 mCalendar = Calendar.getInstance(TimeZone.getDefault());
415 mClockData = IconData.makeText("clock", "");
416 mClockIcon = service.addIcon(mClockData, null);
417 updateClock();
418
San Mehat4154c072010-02-09 18:37:54 -0800419 // storage
420 mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
421 mStorageManager.registerListener(
422 new com.android.server.status.StorageNotification(context));
423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 // battery
425 mBatteryData = IconData.makeIcon("battery",
426 null, com.android.internal.R.drawable.stat_sys_battery_unknown, 0, 0);
427 mBatteryIcon = service.addIcon(mBatteryData, null);
428
429 // phone_signal
430 mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Wink Savillee9b06d72009-05-18 21:47:50 -0700431 mPhoneData = IconData.makeIcon("phone_signal",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
433 mPhoneIcon = service.addIcon(mPhoneData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -0700434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 // register for phone state notifications.
436 ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
437 .listen(mPhoneStateListener,
438 PhoneStateListener.LISTEN_SERVICE_STATE
Wink Savillee9b06d72009-05-18 21:47:50 -0700439 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 | PhoneStateListener.LISTEN_CALL_STATE
441 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
442 | PhoneStateListener.LISTEN_DATA_ACTIVITY);
443
444 // data_connection
445 mDataData = IconData.makeIcon("data_connection",
446 null, com.android.internal.R.drawable.stat_sys_data_connected_g, 0, 0);
447 mDataIcon = service.addIcon(mDataData, null);
448 service.setIconVisibility(mDataIcon, false);
449
450 // wifi
451 mWifiData = IconData.makeIcon("wifi", null, sWifiSignalImages[0], 0, 0);
452 mWifiIcon = service.addIcon(mWifiData, null);
453 service.setIconVisibility(mWifiIcon, false);
454 // wifi will get updated by the sticky intents
Wink Saville04e71b32009-04-02 11:00:54 -0700455
456 // TTY status
457 mTTYModeEnableIconData = IconData.makeIcon("tty",
458 null, com.android.internal.R.drawable.stat_sys_tty_mode, 0, 0);
459 mTTYModeIcon = service.addIcon(mTTYModeEnableIconData, null);
460 service.setIconVisibility(mTTYModeIcon, false);
461
Wink Savillee9b06d72009-05-18 21:47:50 -0700462 // Cdma Roaming Indicator, ERI
463 mCdmaRoamingIndicatorIconData = IconData.makeIcon("cdma_eri",
464 null, com.android.internal.R.drawable.stat_sys_roaming_cdma_0, 0, 0);
465 mCdmaRoamingIndicatorIcon = service.addIcon(mCdmaRoamingIndicatorIconData, null);
466 service.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 // bluetooth status
469 mBluetoothData = IconData.makeIcon("bluetooth",
470 null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
471 mBluetoothIcon = service.addIcon(mBluetoothData, null);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200472 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Nick Pellybd022f42009-08-14 18:33:38 -0700473 if (adapter != null) {
474 mBluetoothEnabled = adapter.isEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 } else {
476 mBluetoothEnabled = false;
477 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800478 mBluetoothA2dpConnected = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 mBluetoothHeadsetState = BluetoothHeadset.STATE_DISCONNECTED;
Jiafa Liu3f416732009-07-02 16:36:02 +0800480 mBluetoothPbapState = BluetoothPbap.STATE_DISCONNECTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
482
483 // Gps status
484 mGpsEnabledIconData = IconData.makeIcon("gps",
485 null, com.android.internal.R.drawable.stat_sys_gps_acquiring_anim, 0, 0);
486 mGpsFixIconData = IconData.makeIcon("gps",
487 null, com.android.internal.R.drawable.stat_sys_gps_on, 0, 0);
488 mGpsIcon = service.addIcon(mGpsEnabledIconData, null);
johnwang347c5a22009-08-24 22:11:11 -0700489 service.setIconVisibility(mGpsIcon, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490
491 // Alarm clock
492 mAlarmClockIconData = IconData.makeIcon(
493 "alarm_clock",
494 null, com.android.internal.R.drawable.stat_notify_alarm, 0, 0);
495 mAlarmClockIcon = service.addIcon(mAlarmClockIconData, null);
496 service.setIconVisibility(mAlarmClockIcon, false);
497
498 // Sync state
499 mSyncActiveIcon = service.addIcon(IconData.makeIcon("sync_active",
500 null, R.drawable.stat_notify_sync_anim0, 0, 0), null);
501 mSyncFailingIcon = service.addIcon(IconData.makeIcon("sync_failing",
502 null, R.drawable.stat_notify_sync_error, 0, 0), null);
503 service.setIconVisibility(mSyncActiveIcon, false);
504 service.setIconVisibility(mSyncFailingIcon, false);
505
506 // volume
507 mVolumeData = IconData.makeIcon("volume",
508 null, com.android.internal.R.drawable.stat_sys_ringer_silent, 0, 0);
509 mVolumeIcon = service.addIcon(mVolumeData, null);
510 service.setIconVisibility(mVolumeIcon, false);
511 updateVolume();
johnwang347c5a22009-08-24 22:11:11 -0700512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 IntentFilter filter = new IntentFilter();
514
515 // Register for Intent broadcasts for...
516 filter.addAction(Intent.ACTION_TIME_TICK);
517 filter.addAction(Intent.ACTION_TIME_CHANGED);
518 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
519 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Mihai Predaa82842f2009-04-29 15:05:56 +0200520 filter.addAction(Intent.ACTION_BATTERY_LOW);
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700521 filter.addAction(Intent.ACTION_BATTERY_OKAY);
Mike Lockwood69eb0bf2009-08-01 23:02:28 -0400522 filter.addAction(Intent.ACTION_POWER_CONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
524 filter.addAction(Intent.ACTION_ALARM_CHANGED);
525 filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
526 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
527 filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
Nick Pellyde893f52009-09-08 13:15:33 -0700528 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Nick Pelly005b2282009-09-10 10:21:56 -0700529 filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
530 filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
Jiafa Liu3f416732009-07-02 16:36:02 +0800531 filter.addAction(BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
533 filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
534 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
535 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
536 filter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION);
537 filter.addAction(GpsLocationProvider.GPS_FIX_CHANGE_ACTION);
538 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Wink Saville04e71b32009-04-02 11:00:54 -0700539 filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
John Wang33e21fc2009-10-08 10:35:27 -0700541
542 // load config to determine if to distinguish Hspa data icon
543 try {
544 mHspaDataDistinguishable = mContext.getResources().getBoolean(
545 com.android.internal.R.bool.config_hspa_data_distinguishable);
546 } catch (Exception e) {
547 mHspaDataDistinguishable = false;
548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 }
550
551 public static void installIcons(Context context, StatusBarService service) {
552 sInstance = new StatusBarPolicy(context, service);
553 }
554
Eric Fischer36e136c2010-01-14 17:42:48 -0800555 private final CharSequence getSmallTime() {
556 boolean b24 = DateFormat.is24HourFormat(mContext);
557 int res;
558
559 if (b24) {
560 res = R.string.twenty_four_hour_time_format;
561 } else {
562 res = R.string.twelve_hour_time_format;
563 }
564
Eric Fischer36e136c2010-01-14 17:42:48 -0800565 final char MAGIC1 = '\uEF00';
566 final char MAGIC2 = '\uEF01';
567
Joe Onorato63ce8e82010-01-17 19:06:51 -0500568 SimpleDateFormat sdf;
569 String format = mContext.getString(res);
570 if (!format.equals(mClockFormatString)) {
571 /*
572 * Search for an unquoted "a" in the format string, so we can
573 * add dummy characters around it to let us find it again after
574 * formatting and change its size.
575 */
576 int a = -1;
577 boolean quoted = false;
578 for (int i = 0; i < format.length(); i++) {
579 char c = format.charAt(i);
Eric Fischer36e136c2010-01-14 17:42:48 -0800580
Joe Onorato63ce8e82010-01-17 19:06:51 -0500581 if (c == '\'') {
582 quoted = !quoted;
583 }
584
585 if (!quoted && c == 'a') {
586 a = i;
587 break;
588 }
589 }
590
591 if (a >= 0) {
592 // Move a back so any whitespace before the AM/PM is also in the alternate size.
593 final int b = a;
594 while (a > 0 && Character.isWhitespace(format.charAt(a-1))) {
595 a--;
596 }
597 format = format.substring(0, a) + MAGIC1 + format.substring(a, b)
598 + "a" + MAGIC2 + format.substring(b + 1);
599 }
600
601 mClockFormat = sdf = new SimpleDateFormat(format);
602 mClockFormatString = format;
603 } else {
604 sdf = mClockFormat;
605 }
606 String result = sdf.format(mCalendar.getTime());
Eric Fischer36e136c2010-01-14 17:42:48 -0800607
608 int magic1 = result.indexOf(MAGIC1);
609 int magic2 = result.indexOf(MAGIC2);
610
611 if (magic1 >= 0 && magic2 > magic1) {
612 SpannableStringBuilder formatted = new SpannableStringBuilder(result);
613
614 formatted.setSpan(new RelativeSizeSpan(0.7f), magic1, magic2,
615 Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
616
617 formatted.delete(magic2, magic2 + 1);
618 formatted.delete(magic1, magic1 + 1);
619
620 return formatted;
621 } else {
622 return result;
623 }
624 }
625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 private final void updateClock() {
627 mCalendar.setTimeInMillis(System.currentTimeMillis());
Eric Fischer36e136c2010-01-14 17:42:48 -0800628 mClockData.text = getSmallTime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 mService.updateIcon(mClockIcon, mClockData, null);
630 }
631
632 private final void updateAlarm(Intent intent) {
633 boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
634 mService.setIconVisibility(mAlarmClockIcon, alarmSet);
635 }
636
637 private final void updateSyncState(Intent intent) {
638 boolean isActive = intent.getBooleanExtra("active", false);
639 boolean isFailing = intent.getBooleanExtra("failing", false);
640 mService.setIconVisibility(mSyncActiveIcon, isActive);
641 // Don't display sync failing icon: BUG 1297963 Set sync error timeout to "never"
642 //mService.setIconVisibility(mSyncFailingIcon, isFailing && !isActive);
643 }
644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 private final void updateBattery(Intent intent) {
646 mBatteryData.iconId = intent.getIntExtra("icon-small", 0);
647 mBatteryData.iconLevel = intent.getIntExtra("level", 0);
648 mService.updateIcon(mBatteryIcon, mBatteryData, null);
649
650 boolean plugged = intent.getIntExtra("plugged", 0) != 0;
651 int level = intent.getIntExtra("level", -1);
652 if (false) {
653 Log.d(TAG, "updateBattery level=" + level
654 + " plugged=" + plugged
655 + " mBatteryPlugged=" + mBatteryPlugged
656 + " mBatteryLevel=" + mBatteryLevel
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657 + " mBatteryFirst=" + mBatteryFirst);
658 }
659
660 boolean oldPlugged = mBatteryPlugged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661
662 mBatteryPlugged = plugged;
663 mBatteryLevel = level;
664
665 if (mBatteryFirst) {
666 mBatteryFirst = false;
667 }
668 /*
669 * No longer showing the battery view because it draws attention away
670 * from the USB storage notification. We could still show it when
671 * connected to a brick, but that could lead to the user into thinking
672 * the device does not charge when plugged into USB (since he/she would
673 * not see the same battery screen on USB as he sees on brick).
674 */
675 /* else {
676 if (plugged && !oldPlugged) {
677 showBatteryView();
678 }
679 }
680 */
681 if (false) {
Mihai Predaa82842f2009-04-29 15:05:56 +0200682 Log.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685
Mihai Predaa82842f2009-04-29 15:05:56 +0200686 private void onBatteryLow(Intent intent) {
687 if (SHOW_LOW_BATTERY_WARNING) {
688 if (false) {
689 Log.d(TAG, "mPhoneState=" + mPhoneState
690 + " mLowBatteryDialog=" + mLowBatteryDialog
691 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200693
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500694 if (SHOW_BATTERY_WARNINGS_IN_CALL || mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
Mihai Predaa82842f2009-04-29 15:05:56 +0200695 showLowBatteryWarning();
696 } else {
697 mBatteryShowLowOnEndCall = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698 }
699 }
700 }
701
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700702 private void onBatteryOkay(Intent intent) {
703 if (mLowBatteryDialog != null
704 && SHOW_LOW_BATTERY_WARNING) {
705 mLowBatteryDialog.dismiss();
706 mBatteryShowLowOnEndCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 }
708 }
709
johnwang347c5a22009-08-24 22:11:11 -0700710 private void showBatteryView() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 closeLastBatteryView();
712 if (mLowBatteryDialog != null) {
713 mLowBatteryDialog.dismiss();
714 }
715
716 int level = mBatteryLevel;
717
718 View v = View.inflate(mContext, com.android.internal.R.layout.battery_status, null);
719 mBatteryView = v;
720 int pixelFormat = PixelFormat.TRANSLUCENT;
721 Drawable bg = v.getBackground();
722 if (bg != null) {
723 pixelFormat = bg.getOpacity();
724 }
725
Dianne Hackborn568cae52009-10-07 16:13:39 -0700726 int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
727 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
728 | WindowManager.LayoutParams.FLAG_DIM_BEHIND;
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800729
Dianne Hackborn568cae52009-10-07 16:13:39 -0700730 if (!mContext.getResources().getBoolean(
731 com.android.internal.R.bool.config_sf_slowBlur)) {
732 flags |= WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
733 }
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
736 ViewGroup.LayoutParams.WRAP_CONTENT,
737 ViewGroup.LayoutParams.WRAP_CONTENT,
738 WindowManager.LayoutParams.TYPE_TOAST,
Dianne Hackborn568cae52009-10-07 16:13:39 -0700739 flags, pixelFormat);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740
741 // Get the dim amount from the theme
742 TypedArray a = mContext.obtainStyledAttributes(
743 com.android.internal.R.styleable.Theme);
744 lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
745 a.recycle();
Wink Saville04e71b32009-04-02 11:00:54 -0700746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 lp.setTitle("Battery");
748
749 TextView levelTextView = (TextView)v.findViewById(com.android.internal.R.id.level_percent);
750 levelTextView.setText(mContext.getString(
751 com.android.internal.R.string.battery_status_text_percent_format, level));
752
753 setBatteryLevel(v, com.android.internal.R.id.spacer, 100-level, 0, 0);
754 setBatteryLevel(v, com.android.internal.R.id.level, level,
755 com.android.internal.R.drawable.battery_charge_fill, level);
756
757 WindowManagerImpl.getDefault().addView(v, lp);
758
759 scheduleCloseBatteryView();
760 }
761
762 private void setBatteryLevel(View parent, int id, int height, int background, int level) {
763 ImageView v = (ImageView)parent.findViewById(id);
764 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)v.getLayoutParams();
765 lp.weight = height;
766 if (background != 0) {
767 v.setBackgroundResource(background);
768 Drawable bkg = v.getBackground();
769 bkg.setLevel(level);
770 }
771 }
772
773 private void showLowBatteryWarning() {
774 closeLastBatteryView();
775
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400776 // Show exact battery level.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 CharSequence levelText = mContext.getString(
Mike Lockwoodd81b1f42009-09-25 09:32:19 -0400778 com.android.internal.R.string.battery_low_percent_format, mBatteryLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779
780 if (mBatteryLevelTextView != null) {
781 mBatteryLevelTextView.setText(levelText);
782 } else {
783 View v = View.inflate(mContext, com.android.internal.R.layout.battery_low, null);
784 mBatteryLevelTextView=(TextView)v.findViewById(com.android.internal.R.id.level_percent);
785
786 mBatteryLevelTextView.setText(levelText);
787
788 AlertDialog.Builder b = new AlertDialog.Builder(mContext);
789 b.setCancelable(true);
790 b.setTitle(com.android.internal.R.string.battery_low_title);
791 b.setView(v);
792 b.setIcon(android.R.drawable.ic_dialog_alert);
793 b.setPositiveButton(android.R.string.ok, null);
johnwang347c5a22009-08-24 22:11:11 -0700794
Dianne Hackborn3d74bb42009-06-19 10:35:21 -0700795 final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
796 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
797 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
798 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
799 | Intent.FLAG_ACTIVITY_NO_HISTORY);
800 if (intent.resolveActivity(mContext.getPackageManager()) != null) {
801 b.setNegativeButton(com.android.internal.R.string.battery_low_why,
802 new DialogInterface.OnClickListener() {
803 public void onClick(DialogInterface dialog, int which) {
804 mContext.startActivity(intent);
805 if (mLowBatteryDialog != null) {
806 mLowBatteryDialog.dismiss();
807 }
808 }
809 });
810 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811
812 AlertDialog d = b.create();
813 d.setOnDismissListener(mLowBatteryListener);
814 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
815 d.show();
816 mLowBatteryDialog = d;
817 }
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500818
819 final ContentResolver cr = mContext.getContentResolver();
820 if (Settings.System.getInt(cr,
821 Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
822 {
823 final String soundPath = Settings.System.getString(cr,
824 Settings.System.LOW_BATTERY_SOUND);
825 if (soundPath != null) {
826 final Uri soundUri = Uri.parse("file://" + soundPath);
827 if (soundUri != null) {
828 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
829 if (sfx != null) sfx.play();
830 }
831 }
832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 }
834
835 private final void updateCallState(int state) {
836 mPhoneState = state;
837 if (false) {
838 Log.d(TAG, "mPhoneState=" + mPhoneState
839 + " mLowBatteryDialog=" + mLowBatteryDialog
840 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
841 }
842 if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
843 if (mBatteryShowLowOnEndCall) {
844 if (!mBatteryPlugged) {
845 showLowBatteryWarning();
846 }
847 mBatteryShowLowOnEndCall = false;
848 }
849 } else {
850 if (mLowBatteryDialog != null) {
851 mLowBatteryDialog.dismiss();
852 mBatteryShowLowOnEndCall = true;
853 }
854 }
855 }
856
857 private DialogInterface.OnDismissListener mLowBatteryListener
858 = new DialogInterface.OnDismissListener() {
859 public void onDismiss(DialogInterface dialog) {
860 mLowBatteryDialog = null;
861 mBatteryLevelTextView = null;
862 }
863 };
864
865 private void scheduleCloseBatteryView() {
866 Message m = mHandler.obtainMessage(EVENT_BATTERY_CLOSE);
867 m.arg1 = (++mBatteryViewSequence);
868 mHandler.sendMessageDelayed(m, 3000);
869 }
870
871 private void closeLastBatteryView() {
872 if (mBatteryView != null) {
873 //mBatteryView.debug();
874 WindowManagerImpl.getDefault().removeView(mBatteryView);
875 mBatteryView = null;
876 }
877 }
878
879 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
880 @Override
Wink Savillee9b06d72009-05-18 21:47:50 -0700881 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
882 mSignalStrength = signalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 updateSignalStrength();
884 }
885
886 @Override
887 public void onServiceStateChanged(ServiceState state) {
888 mServiceState = state;
889 updateSignalStrength();
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700890 updateCdmaRoamingIcon(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 updateDataIcon();
892 }
893
894 @Override
895 public void onCallStateChanged(int state, String incomingNumber) {
896 updateCallState(state);
johnwang347c5a22009-08-24 22:11:11 -0700897 // In cdma, if a voice call is made, RSSI should switch to 1x.
898 if (isCdma()) {
899 updateSignalStrength();
900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 }
902
903 @Override
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700904 public void onDataConnectionStateChanged(int state, int networkType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 mDataState = state;
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700906 updateDataNetType(networkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 updateDataIcon();
908 }
909
910 @Override
911 public void onDataActivity(int direction) {
912 mDataActivity = direction;
913 updateDataIcon();
914 }
915 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916
917 private final void updateSimState(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -0700918 String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
919 if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
920 mSimState = IccCard.State.ABSENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 }
Wink Saville04e71b32009-04-02 11:00:54 -0700922 else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
923 mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 }
Wink Saville04e71b32009-04-02 11:00:54 -0700925 else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
926 final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
927 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
928 mSimState = IccCard.State.PIN_REQUIRED;
johnwang347c5a22009-08-24 22:11:11 -0700929 }
Wink Saville04e71b32009-04-02 11:00:54 -0700930 else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
931 mSimState = IccCard.State.PUK_REQUIRED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 }
933 else {
Wink Saville04e71b32009-04-02 11:00:54 -0700934 mSimState = IccCard.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 }
936 } else {
Wink Saville04e71b32009-04-02 11:00:54 -0700937 mSimState = IccCard.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 }
939 updateDataIcon();
940 }
941
Wink Savillee9b06d72009-05-18 21:47:50 -0700942 private boolean isCdma() {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700943 return (mSignalStrength != null) && !mSignalStrength.isGsm();
Wink Savillee9b06d72009-05-18 21:47:50 -0700944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945
johnwang347c5a22009-08-24 22:11:11 -0700946 private boolean isEvdo() {
947 return ( (mServiceState != null)
948 && ((mServiceState.getRadioTechnology()
949 == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
950 || (mServiceState.getRadioTechnology()
951 == ServiceState.RADIO_TECHNOLOGY_EVDO_A)));
952 }
953
Wink Savillee9b06d72009-05-18 21:47:50 -0700954 private boolean hasService() {
955 if (mServiceState != null) {
956 switch (mServiceState.getState()) {
957 case ServiceState.STATE_OUT_OF_SERVICE:
958 case ServiceState.STATE_POWER_OFF:
959 return false;
960 default:
961 return true;
962 }
963 } else {
964 return false;
965 }
966 }
967
968 private final void updateSignalStrength() {
969 int iconLevel = -1;
Wink Savillee9b06d72009-05-18 21:47:50 -0700970 int[] iconList;
Wink Savillee9b06d72009-05-18 21:47:50 -0700971
972 if (!hasService()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 //Log.d(TAG, "updateSignalStrength: no service");
974 if (Settings.System.getInt(mContext.getContentResolver(),
975 Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
976 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_flightmode;
977 } else {
978 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_null;
979 }
980 mService.updateIcon(mPhoneIcon, mPhoneData, null);
981 return;
982 }
983
Wink Savillee9b06d72009-05-18 21:47:50 -0700984 if (!isCdma()) {
985 int asu = mSignalStrength.getGsmSignalStrength();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986
Wink Savillee9b06d72009-05-18 21:47:50 -0700987 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
988 // asu = 0 (-113dB or less) is very weak
989 // signal, its better to show 0 bars to the user in such cases.
990 // asu = 99 is a special case, where the signal strength is unknown.
991 if (asu <= 0 || asu == 99) iconLevel = 0;
992 else if (asu >= 16) iconLevel = 4;
993 else if (asu >= 8) iconLevel = 3;
994 else if (asu >= 4) iconLevel = 2;
995 else iconLevel = 1;
996
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700997 // Though mPhone is a Manager, this call is not an IPC
Wink Savillee9b06d72009-05-18 21:47:50 -0700998 if (mPhone.isNetworkRoaming()) {
999 iconList = sSignalImages_r;
1000 } else {
1001 iconList = sSignalImages;
Wink Saville04e71b32009-04-02 11:00:54 -07001002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 } else {
johnwang347c5a22009-08-24 22:11:11 -07001004 iconList = this.sSignalImages;
Wink Savillee9b06d72009-05-18 21:47:50 -07001005
johnwang347c5a22009-08-24 22:11:11 -07001006 // If 3G(EV) and 1x network are available than 3G should be
1007 // displayed, displayed RSSI should be from the EV side.
1008 // If a voice call is made then RSSI should switch to 1x.
1009 if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
1010 iconLevel = getEvdoLevel();
1011 if (false) {
1012 Log.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level=" + getCdmaLevel());
1013 }
1014 } else {
1015 iconLevel = getCdmaLevel();
1016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001018 mPhoneData.iconId = iconList[iconLevel];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1020 }
1021
johnwang347c5a22009-08-24 22:11:11 -07001022 private int getCdmaLevel() {
1023 final int cdmaDbm = mSignalStrength.getCdmaDbm();
1024 final int cdmaEcio = mSignalStrength.getCdmaEcio();
1025 int levelDbm = 0;
1026 int levelEcio = 0;
1027
1028 if (cdmaDbm >= -75) levelDbm = 4;
1029 else if (cdmaDbm >= -85) levelDbm = 3;
1030 else if (cdmaDbm >= -95) levelDbm = 2;
1031 else if (cdmaDbm >= -100) levelDbm = 1;
1032 else levelDbm = 0;
1033
1034 // Ec/Io are in dB*10
1035 if (cdmaEcio >= -90) levelEcio = 4;
1036 else if (cdmaEcio >= -110) levelEcio = 3;
1037 else if (cdmaEcio >= -130) levelEcio = 2;
1038 else if (cdmaEcio >= -150) levelEcio = 1;
1039 else levelEcio = 0;
1040
1041 return (levelDbm < levelEcio) ? levelDbm : levelEcio;
1042 }
1043
1044 private int getEvdoLevel() {
1045 int evdoDbm = mSignalStrength.getEvdoDbm();
1046 int evdoSnr = mSignalStrength.getEvdoSnr();
1047 int levelEvdoDbm = 0;
1048 int levelEvdoSnr = 0;
1049
1050 if (evdoDbm >= -65) levelEvdoDbm = 4;
1051 else if (evdoDbm >= -75) levelEvdoDbm = 3;
1052 else if (evdoDbm >= -90) levelEvdoDbm = 2;
1053 else if (evdoDbm >= -105) levelEvdoDbm = 1;
1054 else levelEvdoDbm = 0;
1055
John Michelau1336a562009-09-28 10:41:02 -05001056 if (evdoSnr >= 7) levelEvdoSnr = 4;
1057 else if (evdoSnr >= 5) levelEvdoSnr = 3;
1058 else if (evdoSnr >= 3) levelEvdoSnr = 2;
1059 else if (evdoSnr >= 1) levelEvdoSnr = 1;
johnwang347c5a22009-08-24 22:11:11 -07001060 else levelEvdoSnr = 0;
1061
1062 return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
1063 }
1064
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001065 private final void updateDataNetType(int net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001066
1067 switch (net) {
Wink Saville04e71b32009-04-02 11:00:54 -07001068 case TelephonyManager.NETWORK_TYPE_EDGE:
1069 mDataIconList = sDataNetType_e;
1070 break;
1071 case TelephonyManager.NETWORK_TYPE_UMTS:
1072 mDataIconList = sDataNetType_3g;
1073 break;
Li Zheebe66342009-08-14 19:22:16 +08001074 case TelephonyManager.NETWORK_TYPE_HSDPA:
1075 case TelephonyManager.NETWORK_TYPE_HSUPA:
1076 case TelephonyManager.NETWORK_TYPE_HSPA:
John Wang33e21fc2009-10-08 10:35:27 -07001077 if (mHspaDataDistinguishable) {
1078 mDataIconList = sDataNetType_h;
1079 } else {
1080 mDataIconList = sDataNetType_3g;
1081 }
Li Zheebe66342009-08-14 19:22:16 +08001082 break;
Wink Saville04e71b32009-04-02 11:00:54 -07001083 case TelephonyManager.NETWORK_TYPE_CDMA:
1084 // display 1xRTT for IS95A/B
johnwang9f87cb22009-08-25 15:25:37 -07001085 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001086 break;
1087 case TelephonyManager.NETWORK_TYPE_1xRTT:
johnwang9f87cb22009-08-25 15:25:37 -07001088 mDataIconList = this.sDataNetType_1x;
Wink Saville04e71b32009-04-02 11:00:54 -07001089 break;
1090 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
1091 case TelephonyManager.NETWORK_TYPE_EVDO_A:
johnwang9f87cb22009-08-25 15:25:37 -07001092 mDataIconList = sDataNetType_3g;
Wink Saville04e71b32009-04-02 11:00:54 -07001093 break;
1094 default:
1095 mDataIconList = sDataNetType_g;
1096 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 }
1098 }
1099
1100 private final void updateDataIcon() {
1101 int iconId;
1102 boolean visible = true;
1103
Wink Savillee9b06d72009-05-18 21:47:50 -07001104 if (!isCdma()) {
1105 // GSM case, we have to check also the sim state
1106 if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
1107 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
1108 switch (mDataActivity) {
1109 case TelephonyManager.DATA_ACTIVITY_IN:
1110 iconId = mDataIconList[1];
1111 break;
1112 case TelephonyManager.DATA_ACTIVITY_OUT:
1113 iconId = mDataIconList[2];
1114 break;
1115 case TelephonyManager.DATA_ACTIVITY_INOUT:
1116 iconId = mDataIconList[3];
1117 break;
1118 default:
1119 iconId = mDataIconList[0];
1120 break;
1121 }
1122 mDataData.iconId = iconId;
1123 mService.updateIcon(mDataIcon, mDataData, null);
1124 } else {
1125 visible = false;
1126 }
1127 } else {
1128 mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
1129 mService.updateIcon(mDataIcon, mDataData, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001131 } else {
1132 // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
1133 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 switch (mDataActivity) {
1135 case TelephonyManager.DATA_ACTIVITY_IN:
Wink Savillee9b06d72009-05-18 21:47:50 -07001136 iconId = mDataIconList[1];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 break;
1138 case TelephonyManager.DATA_ACTIVITY_OUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001139 iconId = mDataIconList[2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 break;
1141 case TelephonyManager.DATA_ACTIVITY_INOUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001142 iconId = mDataIconList[3];
1143 break;
1144 case TelephonyManager.DATA_ACTIVITY_DORMANT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 default:
Wink Savillee9b06d72009-05-18 21:47:50 -07001146 iconId = mDataIconList[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 break;
1148 }
1149 mDataData.iconId = iconId;
1150 mService.updateIcon(mDataIcon, mDataData, null);
1151 } else {
1152 visible = false;
1153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001155
Dianne Hackborn4840e142009-03-24 22:40:29 -07001156 long ident = Binder.clearCallingIdentity();
1157 try {
Wink Saville04e71b32009-04-02 11:00:54 -07001158 mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
Dianne Hackborn4840e142009-03-24 22:40:29 -07001159 } catch (RemoteException e) {
1160 } finally {
1161 Binder.restoreCallingIdentity(ident);
1162 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 if (mDataIconVisible != visible) {
1165 mService.setIconVisibility(mDataIcon, visible);
1166 mDataIconVisible = visible;
1167 }
1168 }
1169
1170 private final void updateVolume() {
1171 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1172 final int ringerMode = audioManager.getRingerMode();
1173 final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
Wink Savillee9b06d72009-05-18 21:47:50 -07001174 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
1176 ? com.android.internal.R.drawable.stat_sys_ringer_vibrate
1177 : com.android.internal.R.drawable.stat_sys_ringer_silent;
1178
1179 if (visible) {
1180 mVolumeData.iconId = iconId;
1181 mService.updateIcon(mVolumeIcon, mVolumeData, null);
1182 }
1183 if (visible != mVolumeVisible) {
1184 mService.setIconVisibility(mVolumeIcon, visible);
1185 mVolumeVisible = visible;
1186 }
1187 }
1188
1189 private final void updateBluetooth(Intent intent) {
1190 int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 String action = intent.getAction();
Nick Pellyde893f52009-09-08 13:15:33 -07001192 if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
Nick Pellyb24e11b2009-09-08 17:40:43 -07001193 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
Nick Pellyde893f52009-09-08 13:15:33 -07001194 mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
Nick Pelly005b2282009-09-10 10:21:56 -07001195 } else if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
1196 mBluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 BluetoothHeadset.STATE_ERROR);
Nick Pelly005b2282009-09-10 10:21:56 -07001198 } else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) {
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001199 BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
1200 if (a2dp.getConnectedSinks().size() != 0) {
1201 mBluetoothA2dpConnected = true;
1202 } else {
1203 mBluetoothA2dpConnected = false;
1204 }
Jiafa Liu3f416732009-07-02 16:36:02 +08001205 } else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
1206 mBluetoothPbapState = intent.getIntExtra(BluetoothPbap.PBAP_STATE,
1207 BluetoothPbap.STATE_DISCONNECTED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 } else {
1209 return;
1210 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001211
Jaikumar Ganesh084c6652009-12-07 10:58:18 -08001212 if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED || mBluetoothA2dpConnected ||
Jiafa Liu3f416732009-07-02 16:36:02 +08001213 mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
1215 }
1216
1217 mBluetoothData.iconId = iconId;
1218 mService.updateIcon(mBluetoothIcon, mBluetoothData, null);
1219 mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
1220 }
1221
1222 private final void updateWifi(Intent intent) {
1223 final String action = intent.getAction();
1224 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
1227 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
Wink Savillee9b06d72009-05-18 21:47:50 -07001228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 if (!enabled) {
1230 // If disabled, hide the icon. (We show icon when connected.)
1231 mService.setIconVisibility(mWifiIcon, false);
1232 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
1235 final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
1236 false);
1237 if (!enabled) {
1238 mService.setIconVisibility(mWifiIcon, false);
1239 }
1240 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
1241
Wink Savillee9b06d72009-05-18 21:47:50 -07001242 final NetworkInfo networkInfo = (NetworkInfo)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
Wink Savillee9b06d72009-05-18 21:47:50 -07001244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245 int iconId;
1246 if (networkInfo != null && networkInfo.isConnected()) {
1247 mIsWifiConnected = true;
1248 if (mLastWifiSignalLevel == -1) {
1249 iconId = sWifiSignalImages[0];
1250 } else {
1251 iconId = sWifiSignalImages[mLastWifiSignalLevel];
1252 }
Wink Saville04e71b32009-04-02 11:00:54 -07001253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 // Show the icon since wi-fi is connected
1255 mService.setIconVisibility(mWifiIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 } else {
1258 mLastWifiSignalLevel = -1;
1259 mIsWifiConnected = false;
1260 iconId = sWifiSignalImages[0];
1261
1262 // Hide the icon since we're not connected
1263 mService.setIconVisibility(mWifiIcon, false);
1264 }
1265
1266 mWifiData.iconId = iconId;
1267 mService.updateIcon(mWifiIcon, mWifiData, null);
1268 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
1269 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
1270 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
1271 sWifiSignalImages.length);
1272 if (newSignalLevel != mLastWifiSignalLevel) {
1273 mLastWifiSignalLevel = newSignalLevel;
1274 if (mIsWifiConnected) {
1275 mWifiData.iconId = sWifiSignalImages[newSignalLevel];
1276 } else {
1277 mWifiData.iconId = sWifiTemporarilyNotConnectedImage;
1278 }
1279 mService.updateIcon(mWifiIcon, mWifiData, null);
1280 }
1281 }
1282 }
1283
1284 private final void updateGps(Intent intent) {
1285 final String action = intent.getAction();
1286 final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED, false);
1287
1288 if (action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION) && enabled) {
1289 // GPS is getting fixes
1290 mService.updateIcon(mGpsIcon, mGpsFixIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001291 mService.setIconVisibility(mGpsIcon, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
1293 // GPS is off
Wink Savillee9b06d72009-05-18 21:47:50 -07001294 mService.setIconVisibility(mGpsIcon, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001295 } else {
1296 // GPS is on, but not receiving fixes
1297 mService.updateIcon(mGpsIcon, mGpsEnabledIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001298 mService.setIconVisibility(mGpsIcon, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 }
1300 }
1301
Wink Savillee9b06d72009-05-18 21:47:50 -07001302 private final void updateTTY(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -07001303 final String action = intent.getAction();
1304 final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
1305
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001306 if (false) Log.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -07001307
1308 if (enabled) {
1309 // TTY is on
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001310 if (false) Log.v(TAG, "updateTTY: set TTY on");
Wink Saville04e71b32009-04-02 11:00:54 -07001311 mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001312 mService.setIconVisibility(mTTYModeIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001313 } else {
1314 // TTY is off
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001315 if (false) Log.v(TAG, "updateTTY: set TTY off");
Wink Savillee9b06d72009-05-18 21:47:50 -07001316 mService.setIconVisibility(mTTYModeIcon, false);
Wink Saville04e71b32009-04-02 11:00:54 -07001317 }
1318 }
1319
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001320 private final void updateCdmaRoamingIcon(ServiceState state) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001321 if (!hasService()) {
1322 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001323 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001324 }
1325
1326 if (!isCdma()) {
1327 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001328 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001329 }
1330
1331 int[] iconList = sRoamingIndicatorImages_cdma;
Robert Greenwalt98e0b142009-10-08 21:15:52 -07001332 int iconIndex = state.getCdmaEriIconIndex();
1333 int iconMode = state.getCdmaEriIconMode();
Wink Savillee9b06d72009-05-18 21:47:50 -07001334
1335 if (iconIndex == -1) {
1336 Log.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
1337 return;
1338 }
1339
1340 if (iconMode == -1) {
1341 Log.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
1342 return;
1343 }
1344
1345 if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001346 if (false) Log.v(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
Wink Savillee9b06d72009-05-18 21:47:50 -07001347 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
1348 return;
1349 }
1350
1351 switch (iconMode) {
1352 case EriInfo.ROAMING_ICON_MODE_NORMAL:
1353 mCdmaRoamingIndicatorIconData.iconId = iconList[iconIndex];
1354 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
1355 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
1356 break;
1357 case EriInfo.ROAMING_ICON_MODE_FLASH:
Wink Savillef3152382009-06-01 14:39:20 -07001358 mCdmaRoamingIndicatorIconData.iconId =
1359 com.android.internal.R.drawable.stat_sys_roaming_cdma_flash;
Wink Savillee9b06d72009-05-18 21:47:50 -07001360 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
Wink Savillef3152382009-06-01 14:39:20 -07001361 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
Wink Savillee9b06d72009-05-18 21:47:50 -07001362 break;
1363
1364 }
1365 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1366 }
1367
1368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 private class StatusBarHandler extends Handler {
1370 @Override
1371 public void handleMessage(Message msg) {
1372 switch (msg.what) {
1373 case EVENT_BATTERY_CLOSE:
1374 if (msg.arg1 == mBatteryViewSequence) {
1375 closeLastBatteryView();
1376 }
1377 break;
1378 }
1379 }
1380 }
1381}