blob: c8db95b7ff9be2bc862a011082c8826ebba067fc [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;
21import android.bluetooth.BluetoothDevice;
The Android Open Source Project10592532009-03-18 17:39:46 -070022import android.bluetooth.BluetoothError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.bluetooth.BluetoothHeadset;
24import android.bluetooth.BluetoothIntent;
25import android.content.BroadcastReceiver;
26import 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;
34import android.net.NetworkInfo;
35import android.net.wifi.WifiManager;
Dianne Hackborn4840e142009-03-24 22:40:29 -070036import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.os.Handler;
38import android.os.IBinder;
39import android.os.Message;
Dianne Hackborn4840e142009-03-24 22:40:29 -070040import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.provider.Settings;
42import android.telephony.PhoneStateListener;
43import android.telephony.ServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -070044import android.telephony.SignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.telephony.TelephonyManager;
46import android.text.format.DateFormat;
47import android.util.Log;
48import android.view.View;
49import android.view.ViewGroup;
50import android.view.WindowManager;
51import android.view.WindowManagerImpl;
52import android.widget.ImageView;
53import android.widget.LinearLayout;
54import android.widget.TextView;
55
Wink Saville04e71b32009-04-02 11:00:54 -070056import com.android.internal.R;
57import com.android.internal.app.IBatteryStats;
58import com.android.internal.location.GpsLocationProvider;
59import com.android.internal.telephony.IccCard;
60import com.android.internal.telephony.TelephonyIntents;
Wink Savillee9b06d72009-05-18 21:47:50 -070061import com.android.internal.telephony.cdma.EriInfo;
Wink Saville04e71b32009-04-02 11:00:54 -070062import com.android.internal.telephony.cdma.TtyIntent;
63import com.android.server.am.BatteryStatsService;
64
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import java.util.Calendar;
66import java.util.TimeZone;
67
68/**
69 * This class contains all of the policy about which icons are installed in the status
70 * bar at boot time. In reality, it should go into the android.policy package, but
71 * putting it here is the first step from extracting it.
72 */
73public class StatusBarPolicy {
74 private static final String TAG = "StatusBarPolicy";
75
76 private static StatusBarPolicy sInstance;
77
78 // message codes for the handler
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 private static final int EVENT_BATTERY_CLOSE = 4;
80
Dianne Hackborn4840e142009-03-24 22:40:29 -070081 private final Context mContext;
82 private final StatusBarService mService;
83 private final Handler mHandler = new StatusBarHandler();
84 private final IBatteryStats mBatteryStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085
86 // clock
87 private Calendar mCalendar;
88 private IBinder mClockIcon;
89 private IconData mClockData;
90
91 // battery
92 private IBinder mBatteryIcon;
93 private IconData mBatteryData;
94 private boolean mBatteryFirst = true;
95 private boolean mBatteryPlugged;
96 private int mBatteryLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 private AlertDialog mLowBatteryDialog;
98 private TextView mBatteryLevelTextView;
99 private View mBatteryView;
100 private int mBatteryViewSequence;
101 private boolean mBatteryShowLowOnEndCall = false;
102 private static final boolean SHOW_LOW_BATTERY_WARNING = true;
103
104 // phone
105 private TelephonyManager mPhone;
106 private IBinder mPhoneIcon;
Wink Savillee9b06d72009-05-18 21:47:50 -0700107 private IBinder mPhoneEvdoIcon;
Wink Saville04e71b32009-04-02 11:00:54 -0700108
109 //***** Signal strength icons
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 private IconData mPhoneData;
Wink Savillee9b06d72009-05-18 21:47:50 -0700111 private IconData mPhoneEvdoData;
Wink Saville04e71b32009-04-02 11:00:54 -0700112 //GSM/UMTS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 private static final int[] sSignalImages = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700114 com.android.internal.R.drawable.stat_sys_signal_0,
115 com.android.internal.R.drawable.stat_sys_signal_1,
116 com.android.internal.R.drawable.stat_sys_signal_2,
117 com.android.internal.R.drawable.stat_sys_signal_3,
118 com.android.internal.R.drawable.stat_sys_signal_4
119 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 private static final int[] sSignalImages_r = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700121 com.android.internal.R.drawable.stat_sys_r_signal_0,
122 com.android.internal.R.drawable.stat_sys_r_signal_1,
123 com.android.internal.R.drawable.stat_sys_r_signal_2,
124 com.android.internal.R.drawable.stat_sys_r_signal_3,
125 com.android.internal.R.drawable.stat_sys_r_signal_4
126 };
Wink Saville04e71b32009-04-02 11:00:54 -0700127 //CDMA
128 private static final int[] sSignalImages_cdma = new int[] {
Wink Savillee9b06d72009-05-18 21:47:50 -0700129 com.android.internal.R.drawable.stat_sys_signal_cdma_0,
130 com.android.internal.R.drawable.stat_sys_signal_cdma_1,
131 com.android.internal.R.drawable.stat_sys_signal_cdma_2,
132 com.android.internal.R.drawable.stat_sys_signal_cdma_3,
133 com.android.internal.R.drawable.stat_sys_signal_cdma_4
Wink Saville04e71b32009-04-02 11:00:54 -0700134 };
Wink Savillee9b06d72009-05-18 21:47:50 -0700135 private static final int[] sRoamingIndicatorImages_cdma = new int[] {
136 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
137 // 1 is Standard Roaming Indicator OFF
138 // TODO T: image never used, remove and put 0 instead?
139 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
140
141 // 2 is Standard Roaming Indicator FLASHING
142 // TODO T: image never used, remove and put 0 instead?
143 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
144
145 // 3-12 Standard ERI
146 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //3
147 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
148 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
149 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
150 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
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
157 // 13-63 Reserved for Standard ERI
158 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //13
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 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
210 // 64-127 Reserved for Non Standard (Operator Specific) ERI
211 com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //64
212 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
213 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
214 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
215 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
216 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
217 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
218 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
219 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
220 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
221 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
222 com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
223 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 //83
231
232 // 128-255 Reserved
Wink Saville04e71b32009-04-02 11:00:54 -0700233 };
Wink Savillee9b06d72009-05-18 21:47:50 -0700234 // EVDO
235 private static final int[] sSignalImages_evdo = new int[] {
236 com.android.internal.R.drawable.stat_sys_signal_evdo_0,
237 com.android.internal.R.drawable.stat_sys_signal_evdo_1,
238 com.android.internal.R.drawable.stat_sys_signal_evdo_2,
239 com.android.internal.R.drawable.stat_sys_signal_evdo_3,
240 com.android.internal.R.drawable.stat_sys_signal_evdo_4
Wink Saville04e71b32009-04-02 11:00:54 -0700241 };
242
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 };
Wink Saville04e71b32009-04-02 11:00:54 -0700264 //CDMA
265 private static final int[] sDataNetType_evdo = new int[] {
266 com.android.internal.R.drawable.stat_sys_data_connected_evdo,
267 com.android.internal.R.drawable.stat_sys_data_in_evdo,
268 com.android.internal.R.drawable.stat_sys_data_out_evdo,
269 com.android.internal.R.drawable.stat_sys_data_inandout_evdo,
Wink Savillee9b06d72009-05-18 21:47:50 -0700270 com.android.internal.R.drawable.stat_sys_data_dormant_evdo,
Wink Saville04e71b32009-04-02 11:00:54 -0700271 };
272 private static final int[] sDataNetType_1xrtt = new int[] {
273 com.android.internal.R.drawable.stat_sys_data_connected_1xrtt,
274 com.android.internal.R.drawable.stat_sys_data_in_1xrtt,
275 com.android.internal.R.drawable.stat_sys_data_out_1xrtt,
276 com.android.internal.R.drawable.stat_sys_data_inandout_1xrtt,
Wink Savillee9b06d72009-05-18 21:47:50 -0700277 com.android.internal.R.drawable.stat_sys_data_dormant_1xrtt,
Wink Saville04e71b32009-04-02 11:00:54 -0700278 };
279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 // Assume it's all good unless we hear otherwise. We don't always seem
281 // to get broadcasts that it *is* there.
Wink Saville04e71b32009-04-02 11:00:54 -0700282 IccCard.State mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
284 int mDataState = TelephonyManager.DATA_DISCONNECTED;
285 int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
286 ServiceState mServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -0700287 SignalStrength mSignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 // data connection
290 private IBinder mDataIcon;
291 private IconData mDataData;
292 private boolean mDataIconVisible;
293
294 // ringer volume
295 private IBinder mVolumeIcon;
296 private IconData mVolumeData;
297 private boolean mVolumeVisible;
Wink Saville04e71b32009-04-02 11:00:54 -0700298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 // bluetooth device status
300 private IBinder mBluetoothIcon;
301 private IconData mBluetoothData;
302 private int mBluetoothHeadsetState;
303 private int mBluetoothA2dpState;
304 private boolean mBluetoothEnabled;
305
306 // wifi
307 private static final int[] sWifiSignalImages = new int[] {
308 com.android.internal.R.drawable.stat_sys_wifi_signal_1,
309 com.android.internal.R.drawable.stat_sys_wifi_signal_2,
310 com.android.internal.R.drawable.stat_sys_wifi_signal_3,
311 com.android.internal.R.drawable.stat_sys_wifi_signal_4,
312 };
313 private static final int sWifiTemporarilyNotConnectedImage =
314 com.android.internal.R.drawable.stat_sys_wifi_signal_0;
315
316 private int mLastWifiSignalLevel = -1;
317 private boolean mIsWifiConnected = false;
318 private IBinder mWifiIcon;
319 private IconData mWifiData;
320
321 // gps
322 private IBinder mGpsIcon;
323 private IconData mGpsEnabledIconData;
324 private IconData mGpsFixIconData;
325
326 // alarm clock
327 // Icon lit when clock is set
328 private IBinder mAlarmClockIcon;
329 private IconData mAlarmClockIconData;
330
331 // sync state
332 // If sync is active the SyncActive icon is displayed. If sync is not active but
333 // sync is failing the SyncFailing icon is displayed. Otherwise neither are displayed.
334 private IBinder mSyncActiveIcon;
335 private IBinder mSyncFailingIcon;
336
Wink Saville04e71b32009-04-02 11:00:54 -0700337 // TTY mode
338 // Icon lit when TTY mode is enabled
339 private IBinder mTTYModeIcon;
340 private IconData mTTYModeEnableIconData;
341
Wink Savillee9b06d72009-05-18 21:47:50 -0700342 // Cdma Roaming Indicator, ERI
343 private IBinder mCdmaRoamingIndicatorIcon;
344 private IconData mCdmaRoamingIndicatorIconData;
345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
347 @Override
348 public void onReceive(Context context, Intent intent) {
349 String action = intent.getAction();
350 if (action.equals(Intent.ACTION_TIME_TICK)) {
351 updateClock();
352 }
353 else if (action.equals(Intent.ACTION_TIME_CHANGED)) {
354 updateClock();
355 }
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700356 else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
357 updateBattery(intent);
358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
360 updateClock();
361 }
362 else if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
363 String tz = intent.getStringExtra("time-zone");
364 mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz));
365 updateClock();
366 }
367 else if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
368 updateAlarm(intent);
369 }
370 else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
371 updateSyncState(intent);
372 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200373 else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
374 onBatteryLow(intent);
375 }
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700376 else if (action.equals(Intent.ACTION_BATTERY_OKAY)) {
377 onBatteryOkay(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700379 else if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION) ||
381 action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
382 updateBluetooth(intent);
383 }
384 else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
385 action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) ||
386 action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
387 updateWifi(intent);
388 }
389 else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) ||
390 action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION)) {
391 updateGps(intent);
392 }
393 else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
394 action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
395 updateVolume();
396 }
397 else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
398 updateSimState(intent);
399 }
Wink Saville04e71b32009-04-02 11:00:54 -0700400 else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
401 updateTTY(intent);
402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 }
404 };
405
406 private StatusBarPolicy(Context context, StatusBarService service) {
407 mContext = context;
408 mService = service;
Wink Savillee9b06d72009-05-18 21:47:50 -0700409 mSignalStrength = new SignalStrength();
Dianne Hackborn4840e142009-03-24 22:40:29 -0700410 mBatteryStats = BatteryStatsService.getService();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411
412 // clock
413 mCalendar = Calendar.getInstance(TimeZone.getDefault());
414 mClockData = IconData.makeText("clock", "");
415 mClockIcon = service.addIcon(mClockData, null);
416 updateClock();
417
418 // battery
419 mBatteryData = IconData.makeIcon("battery",
420 null, com.android.internal.R.drawable.stat_sys_battery_unknown, 0, 0);
421 mBatteryIcon = service.addIcon(mBatteryData, null);
422
423 // phone_signal
424 mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Wink Savillee9b06d72009-05-18 21:47:50 -0700425 mPhoneData = IconData.makeIcon("phone_signal",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
427 mPhoneIcon = service.addIcon(mPhoneData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -0700428
429 // phone_evdo_signal
430 mPhoneEvdoData = IconData.makeIcon("phone_evdo_signal",
431 null, com.android.internal.R.drawable.stat_sys_signal_evdo_0, 0, 0);
432 mPhoneEvdoIcon = service.addIcon(mPhoneEvdoData, null);
433 service.setIconVisibility(mPhoneEvdoIcon, false);
434
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);
472 BluetoothDevice bluetooth =
473 (BluetoothDevice) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
474 if (bluetooth != null) {
475 mBluetoothEnabled = bluetooth.isEnabled();
476 } else {
477 mBluetoothEnabled = false;
478 }
479 mBluetoothA2dpState = BluetoothA2dp.STATE_DISCONNECTED;
480 mBluetoothHeadsetState = BluetoothHeadset.STATE_DISCONNECTED;
481 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);
489 service.setIconVisibility(mGpsIcon, false);
490
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();
512
513 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);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
523 filter.addAction(Intent.ACTION_ALARM_CHANGED);
524 filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
525 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
526 filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
The Android Open Source Project10592532009-03-18 17:39:46 -0700527 filter.addAction(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 filter.addAction(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION);
529 filter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
530 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
531 filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
532 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
533 filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
534 filter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION);
535 filter.addAction(GpsLocationProvider.GPS_FIX_CHANGE_ACTION);
536 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Wink Saville04e71b32009-04-02 11:00:54 -0700537 filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
539 }
540
541 public static void installIcons(Context context, StatusBarService service) {
542 sInstance = new StatusBarPolicy(context, service);
543 }
544
545 private final void updateClock() {
546 mCalendar.setTimeInMillis(System.currentTimeMillis());
547 mClockData.text = DateFormat.getTimeFormat(mContext)
548 .format(mCalendar.getTime());
549 mService.updateIcon(mClockIcon, mClockData, null);
550 }
551
552 private final void updateAlarm(Intent intent) {
553 boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
554 mService.setIconVisibility(mAlarmClockIcon, alarmSet);
555 }
556
557 private final void updateSyncState(Intent intent) {
558 boolean isActive = intent.getBooleanExtra("active", false);
559 boolean isFailing = intent.getBooleanExtra("failing", false);
560 mService.setIconVisibility(mSyncActiveIcon, isActive);
561 // Don't display sync failing icon: BUG 1297963 Set sync error timeout to "never"
562 //mService.setIconVisibility(mSyncFailingIcon, isFailing && !isActive);
563 }
564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 private final void updateBattery(Intent intent) {
566 mBatteryData.iconId = intent.getIntExtra("icon-small", 0);
567 mBatteryData.iconLevel = intent.getIntExtra("level", 0);
568 mService.updateIcon(mBatteryIcon, mBatteryData, null);
569
570 boolean plugged = intent.getIntExtra("plugged", 0) != 0;
571 int level = intent.getIntExtra("level", -1);
572 if (false) {
573 Log.d(TAG, "updateBattery level=" + level
574 + " plugged=" + plugged
575 + " mBatteryPlugged=" + mBatteryPlugged
576 + " mBatteryLevel=" + mBatteryLevel
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 + " mBatteryFirst=" + mBatteryFirst);
578 }
579
580 boolean oldPlugged = mBatteryPlugged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581
582 mBatteryPlugged = plugged;
583 mBatteryLevel = level;
584
585 if (mBatteryFirst) {
586 mBatteryFirst = false;
587 }
588 /*
589 * No longer showing the battery view because it draws attention away
590 * from the USB storage notification. We could still show it when
591 * connected to a brick, but that could lead to the user into thinking
592 * the device does not charge when plugged into USB (since he/she would
593 * not see the same battery screen on USB as he sees on brick).
594 */
595 /* else {
596 if (plugged && !oldPlugged) {
597 showBatteryView();
598 }
599 }
600 */
601 if (false) {
Mihai Predaa82842f2009-04-29 15:05:56 +0200602 Log.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605
Mihai Predaa82842f2009-04-29 15:05:56 +0200606 private void onBatteryLow(Intent intent) {
607 if (SHOW_LOW_BATTERY_WARNING) {
608 if (false) {
609 Log.d(TAG, "mPhoneState=" + mPhoneState
610 + " mLowBatteryDialog=" + mLowBatteryDialog
611 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 }
Mihai Predaa82842f2009-04-29 15:05:56 +0200613
614 if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
615 showLowBatteryWarning();
616 } else {
617 mBatteryShowLowOnEndCall = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 }
619 }
620 }
621
Dianne Hackborn8ec5b832009-07-01 21:19:35 -0700622 private void onBatteryOkay(Intent intent) {
623 if (mLowBatteryDialog != null
624 && SHOW_LOW_BATTERY_WARNING) {
625 mLowBatteryDialog.dismiss();
626 mBatteryShowLowOnEndCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 }
628 }
629
630 private void showBatteryView() {
631 closeLastBatteryView();
632 if (mLowBatteryDialog != null) {
633 mLowBatteryDialog.dismiss();
634 }
635
636 int level = mBatteryLevel;
637
638 View v = View.inflate(mContext, com.android.internal.R.layout.battery_status, null);
639 mBatteryView = v;
640 int pixelFormat = PixelFormat.TRANSLUCENT;
641 Drawable bg = v.getBackground();
642 if (bg != null) {
643 pixelFormat = bg.getOpacity();
644 }
645
646 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
647 ViewGroup.LayoutParams.WRAP_CONTENT,
648 ViewGroup.LayoutParams.WRAP_CONTENT,
649 WindowManager.LayoutParams.TYPE_TOAST,
650 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
651 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
652 | WindowManager.LayoutParams.FLAG_BLUR_BEHIND
653 | WindowManager.LayoutParams.FLAG_DIM_BEHIND,
654 pixelFormat);
655
656 // Get the dim amount from the theme
657 TypedArray a = mContext.obtainStyledAttributes(
658 com.android.internal.R.styleable.Theme);
659 lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
660 a.recycle();
Wink Saville04e71b32009-04-02 11:00:54 -0700661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 lp.setTitle("Battery");
663
664 TextView levelTextView = (TextView)v.findViewById(com.android.internal.R.id.level_percent);
665 levelTextView.setText(mContext.getString(
666 com.android.internal.R.string.battery_status_text_percent_format, level));
667
668 setBatteryLevel(v, com.android.internal.R.id.spacer, 100-level, 0, 0);
669 setBatteryLevel(v, com.android.internal.R.id.level, level,
670 com.android.internal.R.drawable.battery_charge_fill, level);
671
672 WindowManagerImpl.getDefault().addView(v, lp);
673
674 scheduleCloseBatteryView();
675 }
676
677 private void setBatteryLevel(View parent, int id, int height, int background, int level) {
678 ImageView v = (ImageView)parent.findViewById(id);
679 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)v.getLayoutParams();
680 lp.weight = height;
681 if (background != 0) {
682 v.setBackgroundResource(background);
683 Drawable bkg = v.getBackground();
684 bkg.setLevel(level);
685 }
686 }
687
688 private void showLowBatteryWarning() {
689 closeLastBatteryView();
690
Mihai Predaa82842f2009-04-29 15:05:56 +0200691 /* Show exact battery level.
692 * Add 1 because the text says "less than X%".
693 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 CharSequence levelText = mContext.getString(
Mihai Predaa82842f2009-04-29 15:05:56 +0200695 com.android.internal.R.string.battery_low_percent_format, mBatteryLevel + 1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696
697 if (mBatteryLevelTextView != null) {
698 mBatteryLevelTextView.setText(levelText);
699 } else {
700 View v = View.inflate(mContext, com.android.internal.R.layout.battery_low, null);
701 mBatteryLevelTextView=(TextView)v.findViewById(com.android.internal.R.id.level_percent);
702
703 mBatteryLevelTextView.setText(levelText);
704
705 AlertDialog.Builder b = new AlertDialog.Builder(mContext);
706 b.setCancelable(true);
707 b.setTitle(com.android.internal.R.string.battery_low_title);
708 b.setView(v);
709 b.setIcon(android.R.drawable.ic_dialog_alert);
710 b.setPositiveButton(android.R.string.ok, null);
Dianne Hackborn3d74bb42009-06-19 10:35:21 -0700711
712 final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
713 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
714 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
715 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
716 | Intent.FLAG_ACTIVITY_NO_HISTORY);
717 if (intent.resolveActivity(mContext.getPackageManager()) != null) {
718 b.setNegativeButton(com.android.internal.R.string.battery_low_why,
719 new DialogInterface.OnClickListener() {
720 public void onClick(DialogInterface dialog, int which) {
721 mContext.startActivity(intent);
722 if (mLowBatteryDialog != null) {
723 mLowBatteryDialog.dismiss();
724 }
725 }
726 });
727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728
729 AlertDialog d = b.create();
730 d.setOnDismissListener(mLowBatteryListener);
731 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
732 d.show();
733 mLowBatteryDialog = d;
734 }
735 }
736
737 private final void updateCallState(int state) {
738 mPhoneState = state;
739 if (false) {
740 Log.d(TAG, "mPhoneState=" + mPhoneState
741 + " mLowBatteryDialog=" + mLowBatteryDialog
742 + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
743 }
744 if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
745 if (mBatteryShowLowOnEndCall) {
746 if (!mBatteryPlugged) {
747 showLowBatteryWarning();
748 }
749 mBatteryShowLowOnEndCall = false;
750 }
751 } else {
752 if (mLowBatteryDialog != null) {
753 mLowBatteryDialog.dismiss();
754 mBatteryShowLowOnEndCall = true;
755 }
756 }
757 }
758
759 private DialogInterface.OnDismissListener mLowBatteryListener
760 = new DialogInterface.OnDismissListener() {
761 public void onDismiss(DialogInterface dialog) {
762 mLowBatteryDialog = null;
763 mBatteryLevelTextView = null;
764 }
765 };
766
767 private void scheduleCloseBatteryView() {
768 Message m = mHandler.obtainMessage(EVENT_BATTERY_CLOSE);
769 m.arg1 = (++mBatteryViewSequence);
770 mHandler.sendMessageDelayed(m, 3000);
771 }
772
773 private void closeLastBatteryView() {
774 if (mBatteryView != null) {
775 //mBatteryView.debug();
776 WindowManagerImpl.getDefault().removeView(mBatteryView);
777 mBatteryView = null;
778 }
779 }
780
781 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
782 @Override
Wink Savillee9b06d72009-05-18 21:47:50 -0700783 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
784 mSignalStrength = signalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 updateSignalStrength();
786 }
787
788 @Override
789 public void onServiceStateChanged(ServiceState state) {
790 mServiceState = state;
791 updateSignalStrength();
Wink Savillee9b06d72009-05-18 21:47:50 -0700792 updateCdmaRoamingIcon();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 updateDataIcon();
794 }
795
796 @Override
797 public void onCallStateChanged(int state, String incomingNumber) {
798 updateCallState(state);
799 }
800
801 @Override
802 public void onDataConnectionStateChanged(int state) {
803 mDataState = state;
804 updateDataNetType();
805 updateDataIcon();
806 }
807
808 @Override
809 public void onDataActivity(int direction) {
810 mDataActivity = direction;
811 updateDataIcon();
812 }
813 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814
815 private final void updateSimState(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -0700816 String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
817 if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
818 mSimState = IccCard.State.ABSENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 }
Wink Saville04e71b32009-04-02 11:00:54 -0700820 else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
821 mSimState = IccCard.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 }
Wink Saville04e71b32009-04-02 11:00:54 -0700823 else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
824 final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
825 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
826 mSimState = IccCard.State.PIN_REQUIRED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 }
Wink Saville04e71b32009-04-02 11:00:54 -0700828 else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
829 mSimState = IccCard.State.PUK_REQUIRED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 }
831 else {
Wink Saville04e71b32009-04-02 11:00:54 -0700832 mSimState = IccCard.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 }
834 } else {
Wink Saville04e71b32009-04-02 11:00:54 -0700835 mSimState = IccCard.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 }
837 updateDataIcon();
838 }
839
Wink Savillee9b06d72009-05-18 21:47:50 -0700840 private boolean isCdma() {
Wink Savillef3152382009-06-01 14:39:20 -0700841 return ((mPhone != null) && (mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA));
Wink Savillee9b06d72009-05-18 21:47:50 -0700842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843
Wink Savillee9b06d72009-05-18 21:47:50 -0700844 private boolean hasService() {
845 if (mServiceState != null) {
846 switch (mServiceState.getState()) {
847 case ServiceState.STATE_OUT_OF_SERVICE:
848 case ServiceState.STATE_POWER_OFF:
849 return false;
850 default:
851 return true;
852 }
853 } else {
854 return false;
855 }
856 }
857
858 private final void updateSignalStrength() {
859 int iconLevel = -1;
860 int evdoIconLevel = -1;
861 int[] iconList;
862 int[] evdoIconList;
863
864 if (!hasService()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 //Log.d(TAG, "updateSignalStrength: no service");
866 if (Settings.System.getInt(mContext.getContentResolver(),
867 Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
868 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_flightmode;
869 } else {
870 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_null;
871 }
872 mService.updateIcon(mPhoneIcon, mPhoneData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -0700873 mService.setIconVisibility(mPhoneEvdoIcon,false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 return;
875 }
876
Wink Savillee9b06d72009-05-18 21:47:50 -0700877 if (!isCdma()) {
878 int asu = mSignalStrength.getGsmSignalStrength();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879
Wink Savillee9b06d72009-05-18 21:47:50 -0700880 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
881 // asu = 0 (-113dB or less) is very weak
882 // signal, its better to show 0 bars to the user in such cases.
883 // asu = 99 is a special case, where the signal strength is unknown.
884 if (asu <= 0 || asu == 99) iconLevel = 0;
885 else if (asu >= 16) iconLevel = 4;
886 else if (asu >= 8) iconLevel = 3;
887 else if (asu >= 4) iconLevel = 2;
888 else iconLevel = 1;
889
890 if (mPhone.isNetworkRoaming()) {
891 iconList = sSignalImages_r;
892 } else {
893 iconList = sSignalImages;
Wink Saville04e71b32009-04-02 11:00:54 -0700894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 } else {
Wink Savillee9b06d72009-05-18 21:47:50 -0700896 iconList = this.sSignalImages_cdma;
897
898 int cdmaDbm = mSignalStrength.getCdmaDbm();
899 int cdmaEcio = mSignalStrength.getCdmaEcio();
900 int levelDbm = 0;
901 int levelEcio = 0;
902
903 if (cdmaDbm >= -75) levelDbm = 4;
904 else if (cdmaDbm >= -85) levelDbm = 3;
905 else if (cdmaDbm >= -95) levelDbm = 2;
906 else if (cdmaDbm >= -100) levelDbm = 1;
907 else levelDbm = 0;
908
909 // Ec/Io are in dB*10
910 if (cdmaEcio >= -90) levelEcio = 4;
911 else if (cdmaEcio >= -110) levelEcio = 3;
912 else if (cdmaEcio >= -130) levelEcio = 2;
913 else if (cdmaEcio >= -150) levelEcio = 1;
914 else levelEcio = 0;
915
916 iconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 }
Wink Saville04e71b32009-04-02 11:00:54 -0700918
Wink Savillee9b06d72009-05-18 21:47:50 -0700919 if ((mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
920 || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) {
921 // Use Evdo icon
922 evdoIconList = this.sSignalImages_evdo;
923
924 int evdoEcio = mSignalStrength.getEvdoEcio();
925 int evdoSnr = mSignalStrength.getEvdoSnr();
926 int levelEvdoEcio = 0;
927 int levelEvdoSnr = 0;
928
929 // Ec/Io are in dB*10
930 if (evdoEcio >= -650) levelEvdoEcio = 4;
931 else if (evdoEcio >= -750) levelEvdoEcio = 3;
932 else if (evdoEcio >= -900) levelEvdoEcio = 2;
933 else if (evdoEcio >= -1050) levelEvdoEcio = 1;
934 else levelEvdoEcio = 0;
935
936 if (evdoSnr > 7) levelEvdoSnr = 4;
937 else if (evdoSnr > 5) levelEvdoSnr = 3;
938 else if (evdoSnr > 3) levelEvdoSnr = 2;
939 else if (evdoSnr > 1) levelEvdoSnr = 1;
940 else levelEvdoSnr = 0;
941
942 evdoIconLevel = (levelEvdoEcio < levelEvdoSnr) ? levelEvdoEcio : levelEvdoSnr;
943
944 mPhoneEvdoData.iconId = evdoIconList[evdoIconLevel];
945 mService.updateIcon(mPhoneEvdoIcon, mPhoneEvdoData, null);
946 mService.setIconVisibility(mPhoneEvdoIcon,true);
947 } else {
948 mService.setIconVisibility(mPhoneEvdoIcon,false);
949 }
950
951 mPhoneData.iconId = iconList[iconLevel];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 mService.updateIcon(mPhoneIcon, mPhoneData, null);
953 }
954
955 private final void updateDataNetType() {
Wink Saville04e71b32009-04-02 11:00:54 -0700956 int net = mPhone.getNetworkType();
Wink Saville04e71b32009-04-02 11:00:54 -0700957
958 switch (net) {
Wink Saville04e71b32009-04-02 11:00:54 -0700959 case TelephonyManager.NETWORK_TYPE_EDGE:
960 mDataIconList = sDataNetType_e;
961 break;
962 case TelephonyManager.NETWORK_TYPE_UMTS:
963 mDataIconList = sDataNetType_3g;
964 break;
965 case TelephonyManager.NETWORK_TYPE_CDMA:
966 // display 1xRTT for IS95A/B
967 mDataIconList = this.sDataNetType_1xrtt;
968 break;
969 case TelephonyManager.NETWORK_TYPE_1xRTT:
970 mDataIconList = this.sDataNetType_1xrtt;
971 break;
972 case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
973 case TelephonyManager.NETWORK_TYPE_EVDO_A:
974 mDataIconList = sDataNetType_evdo;
975 break;
976 default:
977 mDataIconList = sDataNetType_g;
978 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 }
980 }
981
982 private final void updateDataIcon() {
983 int iconId;
984 boolean visible = true;
985
Wink Savillee9b06d72009-05-18 21:47:50 -0700986 if (!isCdma()) {
987 // GSM case, we have to check also the sim state
988 if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
989 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
990 switch (mDataActivity) {
991 case TelephonyManager.DATA_ACTIVITY_IN:
992 iconId = mDataIconList[1];
993 break;
994 case TelephonyManager.DATA_ACTIVITY_OUT:
995 iconId = mDataIconList[2];
996 break;
997 case TelephonyManager.DATA_ACTIVITY_INOUT:
998 iconId = mDataIconList[3];
999 break;
1000 default:
1001 iconId = mDataIconList[0];
1002 break;
1003 }
1004 mDataData.iconId = iconId;
1005 mService.updateIcon(mDataIcon, mDataData, null);
1006 } else {
1007 visible = false;
1008 }
1009 } else {
1010 mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
1011 mService.updateIcon(mDataIcon, mDataData, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001013 } else {
1014 // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
1015 if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 switch (mDataActivity) {
1017 case TelephonyManager.DATA_ACTIVITY_IN:
Wink Savillee9b06d72009-05-18 21:47:50 -07001018 iconId = mDataIconList[1];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 break;
1020 case TelephonyManager.DATA_ACTIVITY_OUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001021 iconId = mDataIconList[2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 break;
1023 case TelephonyManager.DATA_ACTIVITY_INOUT:
Wink Savillee9b06d72009-05-18 21:47:50 -07001024 iconId = mDataIconList[3];
1025 break;
1026 case TelephonyManager.DATA_ACTIVITY_DORMANT:
1027 iconId = mDataIconList[4];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001028 break;
1029 default:
Wink Savillee9b06d72009-05-18 21:47:50 -07001030 iconId = mDataIconList[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 break;
1032 }
1033 mDataData.iconId = iconId;
1034 mService.updateIcon(mDataIcon, mDataData, null);
1035 } else {
1036 visible = false;
1037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001039
Dianne Hackborn4840e142009-03-24 22:40:29 -07001040 long ident = Binder.clearCallingIdentity();
1041 try {
Wink Saville04e71b32009-04-02 11:00:54 -07001042 mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
Dianne Hackborn4840e142009-03-24 22:40:29 -07001043 } catch (RemoteException e) {
1044 } finally {
1045 Binder.restoreCallingIdentity(ident);
1046 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 if (mDataIconVisible != visible) {
1049 mService.setIconVisibility(mDataIcon, visible);
1050 mDataIconVisible = visible;
1051 }
1052 }
1053
1054 private final void updateVolume() {
1055 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1056 final int ringerMode = audioManager.getRingerMode();
1057 final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
Wink Savillee9b06d72009-05-18 21:47:50 -07001058 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
1060 ? com.android.internal.R.drawable.stat_sys_ringer_vibrate
1061 : com.android.internal.R.drawable.stat_sys_ringer_silent;
1062
1063 if (visible) {
1064 mVolumeData.iconId = iconId;
1065 mService.updateIcon(mVolumeIcon, mVolumeData, null);
1066 }
1067 if (visible != mVolumeVisible) {
1068 mService.setIconVisibility(mVolumeIcon, visible);
1069 mVolumeVisible = visible;
1070 }
1071 }
1072
1073 private final void updateBluetooth(Intent intent) {
1074 int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
1075
1076 String action = intent.getAction();
The Android Open Source Project10592532009-03-18 17:39:46 -07001077 if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) {
1078 int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE,
1079 BluetoothError.ERROR);
1080 mBluetoothEnabled = state == BluetoothDevice.BLUETOOTH_STATE_ON;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 } else if (action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION)) {
1082 mBluetoothHeadsetState = intent.getIntExtra(BluetoothIntent.HEADSET_STATE,
1083 BluetoothHeadset.STATE_ERROR);
1084 } else if (action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
1085 mBluetoothA2dpState = intent.getIntExtra(BluetoothA2dp.SINK_STATE,
1086 BluetoothA2dp.STATE_DISCONNECTED);
1087 } else {
1088 return;
1089 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED ||
1092 mBluetoothA2dpState == BluetoothA2dp.STATE_CONNECTED ||
1093 mBluetoothA2dpState == BluetoothA2dp.STATE_PLAYING) {
1094 iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
1095 }
1096
1097 mBluetoothData.iconId = iconId;
1098 mService.updateIcon(mBluetoothIcon, mBluetoothData, null);
1099 mService.setIconVisibility(mBluetoothIcon, mBluetoothEnabled);
1100 }
1101
1102 private final void updateWifi(Intent intent) {
1103 final String action = intent.getAction();
1104 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
Wink Savillee9b06d72009-05-18 21:47:50 -07001105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
1107 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
Wink Savillee9b06d72009-05-18 21:47:50 -07001108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 if (!enabled) {
1110 // If disabled, hide the icon. (We show icon when connected.)
1111 mService.setIconVisibility(mWifiIcon, false);
1112 }
Wink Savillee9b06d72009-05-18 21:47:50 -07001113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
1115 final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
1116 false);
1117 if (!enabled) {
1118 mService.setIconVisibility(mWifiIcon, false);
1119 }
1120 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
1121
Wink Savillee9b06d72009-05-18 21:47:50 -07001122 final NetworkInfo networkInfo = (NetworkInfo)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
Wink Savillee9b06d72009-05-18 21:47:50 -07001124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 int iconId;
1126 if (networkInfo != null && networkInfo.isConnected()) {
1127 mIsWifiConnected = true;
1128 if (mLastWifiSignalLevel == -1) {
1129 iconId = sWifiSignalImages[0];
1130 } else {
1131 iconId = sWifiSignalImages[mLastWifiSignalLevel];
1132 }
Wink Saville04e71b32009-04-02 11:00:54 -07001133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 // Show the icon since wi-fi is connected
1135 mService.setIconVisibility(mWifiIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 } else {
1138 mLastWifiSignalLevel = -1;
1139 mIsWifiConnected = false;
1140 iconId = sWifiSignalImages[0];
1141
1142 // Hide the icon since we're not connected
1143 mService.setIconVisibility(mWifiIcon, false);
1144 }
1145
1146 mWifiData.iconId = iconId;
1147 mService.updateIcon(mWifiIcon, mWifiData, null);
1148 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
1149 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
1150 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
1151 sWifiSignalImages.length);
1152 if (newSignalLevel != mLastWifiSignalLevel) {
1153 mLastWifiSignalLevel = newSignalLevel;
1154 if (mIsWifiConnected) {
1155 mWifiData.iconId = sWifiSignalImages[newSignalLevel];
1156 } else {
1157 mWifiData.iconId = sWifiTemporarilyNotConnectedImage;
1158 }
1159 mService.updateIcon(mWifiIcon, mWifiData, null);
1160 }
1161 }
1162 }
1163
1164 private final void updateGps(Intent intent) {
1165 final String action = intent.getAction();
1166 final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED, false);
1167
1168 if (action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION) && enabled) {
1169 // GPS is getting fixes
1170 mService.updateIcon(mGpsIcon, mGpsFixIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001171 mService.setIconVisibility(mGpsIcon, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
1173 // GPS is off
Wink Savillee9b06d72009-05-18 21:47:50 -07001174 mService.setIconVisibility(mGpsIcon, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 } else {
1176 // GPS is on, but not receiving fixes
1177 mService.updateIcon(mGpsIcon, mGpsEnabledIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001178 mService.setIconVisibility(mGpsIcon, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 }
1180 }
1181
Wink Savillee9b06d72009-05-18 21:47:50 -07001182 private final void updateTTY(Intent intent) {
Wink Saville04e71b32009-04-02 11:00:54 -07001183 final String action = intent.getAction();
1184 final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
1185
1186 Log.i(TAG, "updateTTY: enabled: " + enabled);
1187
1188 if (enabled) {
1189 // TTY is on
1190 Log.i(TAG, "updateTTY: set TTY on");
1191 mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
Wink Savillee9b06d72009-05-18 21:47:50 -07001192 mService.setIconVisibility(mTTYModeIcon, true);
Wink Saville04e71b32009-04-02 11:00:54 -07001193 } else {
1194 // TTY is off
1195 Log.i(TAG, "updateTTY: set TTY off");
Wink Savillee9b06d72009-05-18 21:47:50 -07001196 mService.setIconVisibility(mTTYModeIcon, false);
Wink Saville04e71b32009-04-02 11:00:54 -07001197 }
1198 }
1199
Wink Savillee9b06d72009-05-18 21:47:50 -07001200 private final void updateCdmaRoamingIcon() {
1201 if (!hasService()) {
1202 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001203 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001204 }
1205
1206 if (!isCdma()) {
1207 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
Wink Savillef3152382009-06-01 14:39:20 -07001208 return;
Wink Savillee9b06d72009-05-18 21:47:50 -07001209 }
1210
1211 int[] iconList = sRoamingIndicatorImages_cdma;
1212 int iconIndex = mPhone.getCdmaEriIconIndex();
1213 int iconMode = mPhone.getCdmaEriIconMode();
1214
1215 if (iconIndex == -1) {
1216 Log.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
1217 return;
1218 }
1219
1220 if (iconMode == -1) {
1221 Log.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
1222 return;
1223 }
1224
1225 if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
1226 Log.d(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
1227 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
1228 return;
1229 }
1230
1231 switch (iconMode) {
1232 case EriInfo.ROAMING_ICON_MODE_NORMAL:
1233 mCdmaRoamingIndicatorIconData.iconId = iconList[iconIndex];
1234 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
1235 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
1236 break;
1237 case EriInfo.ROAMING_ICON_MODE_FLASH:
Wink Savillef3152382009-06-01 14:39:20 -07001238 mCdmaRoamingIndicatorIconData.iconId =
1239 com.android.internal.R.drawable.stat_sys_roaming_cdma_flash;
Wink Savillee9b06d72009-05-18 21:47:50 -07001240 mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
Wink Savillef3152382009-06-01 14:39:20 -07001241 mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
Wink Savillee9b06d72009-05-18 21:47:50 -07001242 break;
1243
1244 }
1245 mService.updateIcon(mPhoneIcon, mPhoneData, null);
1246 }
1247
1248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 private class StatusBarHandler extends Handler {
1250 @Override
1251 public void handleMessage(Message msg) {
1252 switch (msg.what) {
1253 case EVENT_BATTERY_CLOSE:
1254 if (msg.arg1 == mBatteryViewSequence) {
1255 closeLastBatteryView();
1256 }
1257 break;
1258 }
1259 }
1260 }
1261}