blob: 4513dcb8060f38fc4b8c9ae5ef37a29696b602c5 [file] [log] [blame]
Winson Chunge641b6a2012-09-10 17:30:27 -07001/*
2 * Copyright (C) 2012 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.systemui.statusbar.phone;
18
John Spurlock48f37ec2012-10-05 16:32:51 -040019import android.app.ActivityManager;
Winson Chunge641b6a2012-09-10 17:30:27 -070020import android.bluetooth.BluetoothAdapter;
21import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback;
22import android.content.BroadcastReceiver;
23import android.content.ContentResolver;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
Winson Chung43229d72012-09-12 18:04:18 -070027import android.content.pm.PackageManager;
Winson Chunge641b6a2012-09-10 17:30:27 -070028import android.content.res.Resources;
29import android.database.ContentObserver;
Winson Chungeaa5ab02012-09-13 16:36:41 -070030import android.graphics.drawable.Drawable;
Winson Chunge641b6a2012-09-10 17:30:27 -070031import android.hardware.display.WifiDisplayStatus;
32import android.os.Handler;
Christopher Tate5e08af02012-09-21 17:17:22 -070033import android.os.UserHandle;
Winson Chunge641b6a2012-09-10 17:30:27 -070034import android.provider.Settings;
Daniel Sandlerc19d4482012-09-19 16:26:39 -040035import android.provider.Settings.SettingNotFoundException;
Winson Chung2a4057d2012-09-12 18:30:06 -070036import android.text.TextUtils;
Winson Chunge641b6a2012-09-10 17:30:27 -070037import android.view.View;
Winson Chung2a4057d2012-09-12 18:30:06 -070038import android.view.inputmethod.InputMethodInfo;
39import android.view.inputmethod.InputMethodManager;
40import android.view.inputmethod.InputMethodSubtype;
Winson Chunge641b6a2012-09-10 17:30:27 -070041
Winson Chungd4726d02012-09-14 12:27:29 -070042import com.android.internal.view.RotationPolicy;
Winson Chunge641b6a2012-09-10 17:30:27 -070043import com.android.systemui.R;
44import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
Winson Chung5f623012012-09-14 14:58:43 -070045import com.android.systemui.statusbar.policy.BrightnessController.BrightnessStateChangeCallback;
John Spurlock48f37ec2012-10-05 16:32:51 -040046import com.android.systemui.statusbar.policy.CurrentUserTracker;
Winson Chunge641b6a2012-09-10 17:30:27 -070047import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback;
48import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
49
Winson Chung2a4057d2012-09-12 18:30:06 -070050import java.util.List;
51
Winson Chunge641b6a2012-09-10 17:30:27 -070052
53class QuickSettingsModel implements BluetoothStateChangeCallback,
54 NetworkSignalChangedCallback,
55 BatteryStateChangeCallback,
Winson Chung5f623012012-09-14 14:58:43 -070056 LocationGpsStateChangeCallback,
57 BrightnessStateChangeCallback {
Winson Chunge641b6a2012-09-10 17:30:27 -070058
Winson Chung34563e22012-09-21 17:19:49 -070059 // Sett InputMethoManagerService
60 private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
61
Winson Chunge641b6a2012-09-10 17:30:27 -070062 /** Represents the state of a given attribute. */
63 static class State {
64 int iconId;
65 String label;
66 boolean enabled = false;
67 }
68 static class BatteryState extends State {
69 int batteryLevel;
70 boolean pluggedIn;
71 }
Winson Chung4f49d942012-09-14 14:01:40 -070072 static class RSSIState extends State {
73 int signalIconId;
Casey Burkhardtbac221f2012-10-03 18:13:58 -070074 String signalContentDescription;
Winson Chung4f49d942012-09-14 14:01:40 -070075 int dataTypeIconId;
Casey Burkhardtbac221f2012-10-03 18:13:58 -070076 String dataContentDescription;
77 }
78 static class WifiState extends State {
79 String signalContentDescription;
80 boolean connected;
Winson Chung4f49d942012-09-14 14:01:40 -070081 }
Winson Chungeaa5ab02012-09-13 16:36:41 -070082 static class UserState extends State {
83 Drawable avatar;
84 }
Winson Chung5f623012012-09-14 14:58:43 -070085 static class BrightnessState extends State {
86 boolean autoBrightness;
87 }
Chris Wrenb2a7d272012-10-03 10:16:51 -040088 public static class BluetoothState extends State {
89 boolean connected = false;
Casey Burkhardtbac221f2012-10-03 18:13:58 -070090 String stateContentDescription;
Chris Wrenb2a7d272012-10-03 10:16:51 -040091 }
Winson Chunge641b6a2012-09-10 17:30:27 -070092
93 /** The callback to update a given tile. */
94 interface RefreshCallback {
95 public void refreshView(QuickSettingsTileView view, State state);
96 }
97
98 /** Broadcast receive to determine if there is an alarm set. */
99 private BroadcastReceiver mAlarmIntentReceiver = new BroadcastReceiver() {
100 @Override
101 public void onReceive(Context context, Intent intent) {
102 String action = intent.getAction();
103 if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
104 onAlarmChanged(intent);
105 onNextAlarmChanged();
106 }
107 }
108 };
109
110 /** ContentObserver to determine the next alarm */
111 private class NextAlarmObserver extends ContentObserver {
112 public NextAlarmObserver(Handler handler) {
113 super(handler);
114 }
115
116 @Override public void onChange(boolean selfChange) {
117 onNextAlarmChanged();
118 }
119
120 public void startObserving() {
121 final ContentResolver cr = mContext.getContentResolver();
122 cr.registerContentObserver(
123 Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this);
124 }
125 }
126
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400127 /** ContentObserver to watch adb */
128 private class BugreportObserver extends ContentObserver {
129 public BugreportObserver(Handler handler) {
130 super(handler);
131 }
132
133 @Override public void onChange(boolean selfChange) {
134 onBugreportChanged();
135 }
136
137 public void startObserving() {
138 final ContentResolver cr = mContext.getContentResolver();
139 cr.registerContentObserver(
140 Settings.Secure.getUriFor(Settings.Secure.BUGREPORT_IN_POWER_MENU), false, this);
141 }
142 }
John Spurlock48f37ec2012-10-05 16:32:51 -0400143
144 /** ContentObserver to watch brightness **/
145 private class BrightnessObserver extends ContentObserver {
146 public BrightnessObserver(Handler handler) {
147 super(handler);
148 }
149
150 @Override
151 public void onChange(boolean selfChange) {
152 onBrightnessLevelChanged();
153 }
154
155 public void startObserving() {
156 final ContentResolver cr = mContext.getContentResolver();
157 cr.unregisterContentObserver(this);
158 cr.registerContentObserver(
159 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),
160 false, this, mUserTracker.getCurrentUserId());
161 cr.registerContentObserver(
162 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
163 false, this, mUserTracker.getCurrentUserId());
164 }
165 }
166
167 private final Context mContext;
168 private final Handler mHandler;
169 private final CurrentUserTracker mUserTracker;
170 private final NextAlarmObserver mNextAlarmObserver;
171 private final BugreportObserver mBugreportObserver;
172 private final BrightnessObserver mBrightnessObserver;
Winson Chunge641b6a2012-09-10 17:30:27 -0700173
174 private QuickSettingsTileView mUserTile;
175 private RefreshCallback mUserCallback;
Winson Chungeaa5ab02012-09-13 16:36:41 -0700176 private UserState mUserState = new UserState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700177
178 private QuickSettingsTileView mTimeTile;
Winson Chungc86b23b2012-09-24 11:24:28 -0700179 private RefreshCallback mTimeCallback;
180 private State mTimeState = new State();
181
182 private QuickSettingsTileView mAlarmTile;
183 private RefreshCallback mAlarmCallback;
184 private State mAlarmState = new State();
Winson Chunge641b6a2012-09-10 17:30:27 -0700185
186 private QuickSettingsTileView mAirplaneModeTile;
187 private RefreshCallback mAirplaneModeCallback;
188 private State mAirplaneModeState = new State();
189
190 private QuickSettingsTileView mWifiTile;
191 private RefreshCallback mWifiCallback;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700192 private WifiState mWifiState = new WifiState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700193
194 private QuickSettingsTileView mWifiDisplayTile;
195 private RefreshCallback mWifiDisplayCallback;
196 private State mWifiDisplayState = new State();
197
198 private QuickSettingsTileView mRSSITile;
199 private RefreshCallback mRSSICallback;
Winson Chung4f49d942012-09-14 14:01:40 -0700200 private RSSIState mRSSIState = new RSSIState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700201
202 private QuickSettingsTileView mBluetoothTile;
203 private RefreshCallback mBluetoothCallback;
Chris Wrenb2a7d272012-10-03 10:16:51 -0400204 private BluetoothState mBluetoothState = new BluetoothState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700205
206 private QuickSettingsTileView mBatteryTile;
207 private RefreshCallback mBatteryCallback;
208 private BatteryState mBatteryState = new BatteryState();
209
210 private QuickSettingsTileView mLocationTile;
211 private RefreshCallback mLocationCallback;
212 private State mLocationState = new State();
213
Winson Chung43229d72012-09-12 18:04:18 -0700214 private QuickSettingsTileView mImeTile;
Daniel Sandleraca0c752012-10-01 12:59:36 -0400215 private RefreshCallback mImeCallback = null;
Winson Chung43229d72012-09-12 18:04:18 -0700216 private State mImeState = new State();
217
Winson Chungd4726d02012-09-14 12:27:29 -0700218 private QuickSettingsTileView mRotationLockTile;
219 private RefreshCallback mRotationLockCallback;
220 private State mRotationLockState = new State();
221
Winson Chung5f623012012-09-14 14:58:43 -0700222 private QuickSettingsTileView mBrightnessTile;
223 private RefreshCallback mBrightnessCallback;
224 private BrightnessState mBrightnessState = new BrightnessState();
225
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400226 private QuickSettingsTileView mBugreportTile;
227 private RefreshCallback mBugreportCallback;
228 private State mBugreportState = new State();
229
Winson Chungefba3232012-09-27 16:56:42 -0700230 private QuickSettingsTileView mSettingsTile;
231 private RefreshCallback mSettingsCallback;
232 private State mSettingsState = new State();
233
Winson Chunge641b6a2012-09-10 17:30:27 -0700234 public QuickSettingsModel(Context context) {
235 mContext = context;
236 mHandler = new Handler();
John Spurlock48f37ec2012-10-05 16:32:51 -0400237 mUserTracker = new CurrentUserTracker(mContext) {
238 @Override
239 public void onReceive(Context context, Intent intent) {
240 super.onReceive(context, intent);
241 onUserSwitched();
242 }
243 };
244
Winson Chunge641b6a2012-09-10 17:30:27 -0700245 mNextAlarmObserver = new NextAlarmObserver(mHandler);
246 mNextAlarmObserver.startObserving();
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400247 mBugreportObserver = new BugreportObserver(mHandler);
248 mBugreportObserver.startObserving();
John Spurlock48f37ec2012-10-05 16:32:51 -0400249 mBrightnessObserver = new BrightnessObserver(mHandler);
250 mBrightnessObserver.startObserving();
Winson Chunge641b6a2012-09-10 17:30:27 -0700251
252 IntentFilter alarmIntentFilter = new IntentFilter();
253 alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED);
254 context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter);
255 }
256
Winson Chungefba3232012-09-27 16:56:42 -0700257 void updateResources() {
258 refreshSettingsTile();
259 refreshBatteryTile();
260 refreshBluetoothTile();
261 refreshBrightnessTile();
262 refreshRotationLockTile();
263 }
264
265 // Settings
266 void addSettingsTile(QuickSettingsTileView view, RefreshCallback cb) {
267 mSettingsTile = view;
268 mSettingsCallback = cb;
269 refreshSettingsTile();
270 }
271 void refreshSettingsTile() {
272 Resources r = mContext.getResources();
273 mSettingsState.label = r.getString(R.string.quick_settings_settings_label);
274 mSettingsCallback.refreshView(mSettingsTile, mSettingsState);
275 }
276
Winson Chunge641b6a2012-09-10 17:30:27 -0700277 // User
278 void addUserTile(QuickSettingsTileView view, RefreshCallback cb) {
279 mUserTile = view;
280 mUserCallback = cb;
281 mUserCallback.refreshView(mUserTile, mUserState);
282 }
Winson Chungeaa5ab02012-09-13 16:36:41 -0700283 void setUserTileInfo(String name, Drawable avatar) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700284 mUserState.label = name;
Winson Chungeaa5ab02012-09-13 16:36:41 -0700285 mUserState.avatar = avatar;
Winson Chunge641b6a2012-09-10 17:30:27 -0700286 mUserCallback.refreshView(mUserTile, mUserState);
287 }
288
289 // Time
290 void addTimeTile(QuickSettingsTileView view, RefreshCallback cb) {
291 mTimeTile = view;
Winson Chungc86b23b2012-09-24 11:24:28 -0700292 mTimeCallback = cb;
293 mTimeCallback.refreshView(view, mTimeState);
294 }
295
296 // Alarm
297 void addAlarmTile(QuickSettingsTileView view, RefreshCallback cb) {
298 mAlarmTile = view;
299 mAlarmCallback = cb;
300 mAlarmCallback.refreshView(view, mAlarmState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700301 }
302 void onAlarmChanged(Intent intent) {
Winson Chungc86b23b2012-09-24 11:24:28 -0700303 mAlarmState.enabled = intent.getBooleanExtra("alarmSet", false);
304 mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700305 }
306 void onNextAlarmChanged() {
Winson Chungc86b23b2012-09-24 11:24:28 -0700307 mAlarmState.label = Settings.System.getString(mContext.getContentResolver(),
Winson Chunge641b6a2012-09-10 17:30:27 -0700308 Settings.System.NEXT_ALARM_FORMATTED);
Winson Chungc86b23b2012-09-24 11:24:28 -0700309 mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700310 }
311
312 // Airplane Mode
313 void addAirplaneModeTile(QuickSettingsTileView view, RefreshCallback cb) {
314 mAirplaneModeTile = view;
315 mAirplaneModeTile.setOnClickListener(new View.OnClickListener() {
316 @Override
317 public void onClick(View v) {
318 if (mAirplaneModeState.enabled) {
319 setAirplaneModeState(false);
320 } else {
321 setAirplaneModeState(true);
322 }
323 }
324 });
325 mAirplaneModeCallback = cb;
Winson Chungefba3232012-09-27 16:56:42 -0700326 int airplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
327 Settings.Global.AIRPLANE_MODE_ON, 0);
328 onAirplaneModeChanged(airplaneMode != 0);
Winson Chunge641b6a2012-09-10 17:30:27 -0700329 }
330 private void setAirplaneModeState(boolean enabled) {
331 // TODO: Sets the view to be "awaiting" if not already awaiting
332
333 // Change the system setting
Winson Chung08b1cc82012-09-11 10:00:53 -0700334 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
Winson Chunge641b6a2012-09-10 17:30:27 -0700335 enabled ? 1 : 0);
336
337 // Post the intent
338 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
339 intent.putExtra("state", enabled);
340 mContext.sendBroadcast(intent);
341 }
342 // NetworkSignalChanged callback
343 @Override
344 public void onAirplaneModeChanged(boolean enabled) {
345 // TODO: If view is in awaiting state, disable
346 Resources r = mContext.getResources();
347 mAirplaneModeState.enabled = enabled;
348 mAirplaneModeState.iconId = (enabled ?
Winson Chungeaa5ab02012-09-13 16:36:41 -0700349 R.drawable.ic_qs_airplane_on :
350 R.drawable.ic_qs_airplane_off);
Winson Chungefba3232012-09-27 16:56:42 -0700351 mAirplaneModeState.label = r.getString(R.string.quick_settings_airplane_mode_label);
Winson Chunge641b6a2012-09-10 17:30:27 -0700352 mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState);
353 }
354
355 // Wifi
356 void addWifiTile(QuickSettingsTileView view, RefreshCallback cb) {
357 mWifiTile = view;
358 mWifiCallback = cb;
359 mWifiCallback.refreshView(mWifiTile, mWifiState);
360 }
Winson Chung34563e22012-09-21 17:19:49 -0700361 // Remove the double quotes that the SSID may contain
362 public static String removeDoubleQuotes(String string) {
363 if (string == null) return null;
364 final int length = string.length();
365 if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
366 return string.substring(1, length - 1);
367 }
368 return string;
369 }
Winson Chungf4b5ab12012-09-24 16:47:46 -0700370 // Remove the period from the network name
371 public static String removeTrailingPeriod(String string) {
372 if (string == null) return null;
373 final int length = string.length();
374 if (string.endsWith(".")) {
375 string.substring(0, length - 1);
376 }
377 return string;
378 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700379 // NetworkSignalChanged callback
380 @Override
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700381 public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
382 String wifiSignalContentDescription, String enabledDesc) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700383 // TODO: If view is in awaiting state, disable
384 Resources r = mContext.getResources();
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700385
Winson Chungf4b5ab12012-09-24 16:47:46 -0700386 boolean wifiConnected = enabled && (wifiSignalIconId > 0) && (enabledDesc != null);
Winson Chungefba3232012-09-27 16:56:42 -0700387 boolean wifiNotConnected = (wifiSignalIconId > 0) && (enabledDesc == null);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700388 mWifiState.enabled = enabled;
389 mWifiState.connected = wifiConnected;
Winson Chungf4b5ab12012-09-24 16:47:46 -0700390 if (wifiConnected) {
391 mWifiState.iconId = wifiSignalIconId;
392 mWifiState.label = removeDoubleQuotes(enabledDesc);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700393 mWifiState.signalContentDescription = wifiSignalContentDescription;
Winson Chungf4b5ab12012-09-24 16:47:46 -0700394 } else if (wifiNotConnected) {
395 mWifiState.iconId = R.drawable.ic_qs_wifi_0;
Chris Wrendaab6af2012-10-03 15:13:10 -0400396 mWifiState.label = r.getString(R.string.quick_settings_wifi_label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700397 mWifiState.signalContentDescription = r.getString(R.string.accessibility_no_wifi);
Winson Chungf4b5ab12012-09-24 16:47:46 -0700398 } else {
399 mWifiState.iconId = R.drawable.ic_qs_wifi_no_network;
400 mWifiState.label = r.getString(R.string.quick_settings_wifi_off_label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700401 mWifiState.signalContentDescription = r.getString(R.string.accessibility_wifi_off);
Winson Chungf4b5ab12012-09-24 16:47:46 -0700402 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700403 mWifiCallback.refreshView(mWifiTile, mWifiState);
404 }
405
406 // RSSI
407 void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) {
408 mRSSITile = view;
409 mRSSICallback = cb;
410 mRSSICallback.refreshView(mRSSITile, mRSSIState);
411 }
Winson Chung43229d72012-09-12 18:04:18 -0700412 boolean deviceSupportsTelephony() {
413 PackageManager pm = mContext.getPackageManager();
414 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
415 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700416 // NetworkSignalChanged callback
417 @Override
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700418 public void onMobileDataSignalChanged(
419 boolean enabled, int mobileSignalIconId, String signalContentDescription,
420 int dataTypeIconId, String dataContentDescription, String enabledDesc) {
Winson Chung43229d72012-09-12 18:04:18 -0700421 if (deviceSupportsTelephony()) {
422 // TODO: If view is in awaiting state, disable
423 Resources r = mContext.getResources();
Winson Chung4f49d942012-09-14 14:01:40 -0700424 mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0)
Winson Chunged1395f2012-09-13 18:13:44 -0700425 ? mobileSignalIconId
426 : R.drawable.ic_qs_signal_no_signal;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700427 mRSSIState.signalContentDescription = enabled && (mobileSignalIconId > 0)
428 ? signalContentDescription
429 : r.getString(R.string.accessibility_no_signal);
Winson Chungc86b23b2012-09-24 11:24:28 -0700430 mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
Winson Chung4f49d942012-09-14 14:01:40 -0700431 ? dataTypeIconId
432 : 0;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700433 mRSSIState.dataContentDescription = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
434 ? dataContentDescription
435 : r.getString(R.string.accessibility_no_data);
Winson Chunged1395f2012-09-13 18:13:44 -0700436 mRSSIState.label = enabled
Winson Chungf4b5ab12012-09-24 16:47:46 -0700437 ? removeTrailingPeriod(enabledDesc)
Winson Chunged1395f2012-09-13 18:13:44 -0700438 : r.getString(R.string.quick_settings_rssi_emergency_only);
Winson Chung43229d72012-09-12 18:04:18 -0700439 mRSSICallback.refreshView(mRSSITile, mRSSIState);
440 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700441 }
442
443 // Bluetooth
444 void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) {
445 mBluetoothTile = view;
446 mBluetoothCallback = cb;
447
448 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Chris Wrenb2a7d272012-10-03 10:16:51 -0400449 mBluetoothState.enabled = adapter.isEnabled();
450 mBluetoothState.connected =
451 (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED);
452 onBluetoothStateChange(mBluetoothState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700453 }
Winson Chung6072b002012-09-11 17:10:10 -0700454 boolean deviceSupportsBluetooth() {
455 return (BluetoothAdapter.getDefaultAdapter() != null);
456 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700457 // BluetoothController callback
458 @Override
459 public void onBluetoothStateChange(boolean on) {
Chris Wrenb2a7d272012-10-03 10:16:51 -0400460 mBluetoothState.enabled = on;
461 onBluetoothStateChange(mBluetoothState);
462 }
463 public void onBluetoothStateChange(BluetoothState bluetoothStateIn) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700464 // TODO: If view is in awaiting state, disable
465 Resources r = mContext.getResources();
Chris Wrenb2a7d272012-10-03 10:16:51 -0400466 mBluetoothState.enabled = bluetoothStateIn.enabled;
467 mBluetoothState.connected = bluetoothStateIn.connected;
468 if (mBluetoothState.enabled) {
469 if (mBluetoothState.connected) {
470 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_on;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700471 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_connected);
Chris Wrenb2a7d272012-10-03 10:16:51 -0400472 } else {
473 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_not_connected;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700474 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_on);
Chris Wrenb2a7d272012-10-03 10:16:51 -0400475 }
Winson Chung34563e22012-09-21 17:19:49 -0700476 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_label);
Winson Chunge641b6a2012-09-10 17:30:27 -0700477 } else {
Winson Chungeaa5ab02012-09-13 16:36:41 -0700478 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off;
Winson Chung34563e22012-09-21 17:19:49 -0700479 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_off_label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700480 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_off);
Winson Chunge641b6a2012-09-10 17:30:27 -0700481 }
482 mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState);
483 }
Winson Chungefba3232012-09-27 16:56:42 -0700484 void refreshBluetoothTile() {
485 if (mBluetoothTile != null) {
486 onBluetoothStateChange(mBluetoothState.enabled);
487 }
488 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700489
490 // Battery
491 void addBatteryTile(QuickSettingsTileView view, RefreshCallback cb) {
492 mBatteryTile = view;
493 mBatteryCallback = cb;
494 mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
495 }
496 // BatteryController callback
497 @Override
498 public void onBatteryLevelChanged(int level, boolean pluggedIn) {
499 mBatteryState.batteryLevel = level;
500 mBatteryState.pluggedIn = pluggedIn;
501 mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
502 }
Winson Chungefba3232012-09-27 16:56:42 -0700503 void refreshBatteryTile() {
504 mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
505 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700506
507 // Location
508 void addLocationTile(QuickSettingsTileView view, RefreshCallback cb) {
509 mLocationTile = view;
510 mLocationCallback = cb;
511 mLocationCallback.refreshView(mLocationTile, mLocationState);
512 }
513 // LocationController callback
514 @Override
515 public void onLocationGpsStateChanged(boolean inUse, String description) {
516 mLocationState.enabled = inUse;
517 mLocationState.label = description;
518 mLocationCallback.refreshView(mLocationTile, mLocationState);
519 }
520
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400521 // Bug report
522 void addBugreportTile(QuickSettingsTileView view, RefreshCallback cb) {
523 mBugreportTile = view;
524 mBugreportCallback = cb;
525 onBugreportChanged();
526 }
527 // SettingsObserver callback
528 public void onBugreportChanged() {
529 final ContentResolver cr = mContext.getContentResolver();
530 boolean enabled = false;
531 try {
532 enabled = (Settings.Secure.getInt(cr, Settings.Secure.BUGREPORT_IN_POWER_MENU) != 0);
533 } catch (SettingNotFoundException e) {
534 }
535
536 mBugreportState.enabled = enabled;
537 mBugreportCallback.refreshView(mBugreportTile, mBugreportState);
538 }
539
Winson Chunge641b6a2012-09-10 17:30:27 -0700540 // Wifi Display
541 void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) {
542 mWifiDisplayTile = view;
543 mWifiDisplayCallback = cb;
544 }
545 public void onWifiDisplayStateChanged(WifiDisplayStatus status) {
Jeff Brown89d55462012-09-19 11:33:42 -0700546 mWifiDisplayState.enabled =
Winson Chung3ed6f942012-09-20 16:07:11 -0700547 (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON);
Winson Chunge641b6a2012-09-10 17:30:27 -0700548 if (status.getActiveDisplay() != null) {
Jeff Brown89d55462012-09-19 11:33:42 -0700549 mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName();
John Spurlock01e2f4f2012-10-05 17:33:31 -0400550 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display_connected;
Winson Chunge641b6a2012-09-10 17:30:27 -0700551 } else {
552 mWifiDisplayState.label = mContext.getString(
553 R.string.quick_settings_wifi_display_no_connection_label);
John Spurlock01e2f4f2012-10-05 17:33:31 -0400554 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display;
Winson Chunge641b6a2012-09-10 17:30:27 -0700555 }
556 mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState);
557
558 }
559
Winson Chung43229d72012-09-12 18:04:18 -0700560 // IME
561 void addImeTile(QuickSettingsTileView view, RefreshCallback cb) {
562 mImeTile = view;
563 mImeCallback = cb;
564 mImeCallback.refreshView(mImeTile, mImeState);
565 }
Winson Chung34563e22012-09-21 17:19:49 -0700566 /* This implementation is taken from
567 InputMethodManagerService.needsToShowImeSwitchOngoingNotification(). */
568 private boolean needsToShowImeSwitchOngoingNotification(InputMethodManager imm) {
569 List<InputMethodInfo> imis = imm.getEnabledInputMethodList();
570 final int N = imis.size();
571 if (N > 2) return true;
572 if (N < 1) return false;
573 int nonAuxCount = 0;
574 int auxCount = 0;
575 InputMethodSubtype nonAuxSubtype = null;
576 InputMethodSubtype auxSubtype = null;
577 for(int i = 0; i < N; ++i) {
578 final InputMethodInfo imi = imis.get(i);
579 final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(imi,
580 true);
581 final int subtypeCount = subtypes.size();
582 if (subtypeCount == 0) {
583 ++nonAuxCount;
584 } else {
585 for (int j = 0; j < subtypeCount; ++j) {
586 final InputMethodSubtype subtype = subtypes.get(j);
587 if (!subtype.isAuxiliary()) {
588 ++nonAuxCount;
589 nonAuxSubtype = subtype;
590 } else {
591 ++auxCount;
592 auxSubtype = subtype;
593 }
594 }
595 }
596 }
597 if (nonAuxCount > 1 || auxCount > 1) {
598 return true;
599 } else if (nonAuxCount == 1 && auxCount == 1) {
600 if (nonAuxSubtype != null && auxSubtype != null
601 && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
602 || auxSubtype.overridesImplicitlyEnabledSubtype()
603 || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
604 && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
605 return false;
606 }
607 return true;
608 }
609 return false;
610 }
Winson Chung43229d72012-09-12 18:04:18 -0700611 void onImeWindowStatusChanged(boolean visible) {
Winson Chung2a4057d2012-09-12 18:30:06 -0700612 InputMethodManager imm =
613 (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
614 List<InputMethodInfo> imis = imm.getInputMethodList();
615
Winson Chung34563e22012-09-21 17:19:49 -0700616 mImeState.enabled = (visible && needsToShowImeSwitchOngoingNotification(imm));
Winson Chung2a4057d2012-09-12 18:30:06 -0700617 mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(),
618 imm, imis, mContext.getPackageManager());
Daniel Sandleraca0c752012-10-01 12:59:36 -0400619 if (mImeCallback != null) {
620 mImeCallback.refreshView(mImeTile, mImeState);
621 }
Winson Chung43229d72012-09-12 18:04:18 -0700622 }
Winson Chung2a4057d2012-09-12 18:30:06 -0700623 private static String getCurrentInputMethodName(Context context, ContentResolver resolver,
624 InputMethodManager imm, List<InputMethodInfo> imis, PackageManager pm) {
625 if (resolver == null || imis == null) return null;
626 final String currentInputMethodId = Settings.Secure.getString(resolver,
627 Settings.Secure.DEFAULT_INPUT_METHOD);
628 if (TextUtils.isEmpty(currentInputMethodId)) return null;
629 for (InputMethodInfo imi : imis) {
630 if (currentInputMethodId.equals(imi.getId())) {
631 final InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype();
632 final CharSequence summary = subtype != null
633 ? subtype.getDisplayName(context, imi.getPackageName(),
634 imi.getServiceInfo().applicationInfo)
635 : context.getString(R.string.quick_settings_ime_label);
636 return summary.toString();
637 }
638 }
639 return null;
640 }
Winson Chung43229d72012-09-12 18:04:18 -0700641
Winson Chungd4726d02012-09-14 12:27:29 -0700642 // Rotation lock
643 void addRotationLockTile(QuickSettingsTileView view, RefreshCallback cb) {
644 mRotationLockTile = view;
645 mRotationLockCallback = cb;
646 onRotationLockChanged();
647 }
648 void onRotationLockChanged() {
649 boolean locked = RotationPolicy.isRotationLocked(mContext);
650 mRotationLockState.enabled = locked;
651 mRotationLockState.iconId = locked
652 ? R.drawable.ic_qs_rotation_locked
653 : R.drawable.ic_qs_auto_rotate;
654 mRotationLockState.label = locked
655 ? mContext.getString(R.string.quick_settings_rotation_locked_label)
656 : mContext.getString(R.string.quick_settings_rotation_unlocked_label);
Daniel Sandler8dd92062012-09-14 17:29:12 -0700657
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700658 // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings
Daniel Sandler8dd92062012-09-14 17:29:12 -0700659 if (mRotationLockTile != null && mRotationLockCallback != null) {
660 mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
661 }
Winson Chungd4726d02012-09-14 12:27:29 -0700662 }
Winson Chungefba3232012-09-27 16:56:42 -0700663 void refreshRotationLockTile() {
664 if (mRotationLockTile != null) {
665 onRotationLockChanged();
666 }
667 }
Winson Chungd4726d02012-09-14 12:27:29 -0700668
Winson Chung5f623012012-09-14 14:58:43 -0700669 // Brightness
670 void addBrightnessTile(QuickSettingsTileView view, RefreshCallback cb) {
671 mBrightnessTile = view;
672 mBrightnessCallback = cb;
673 onBrightnessLevelChanged();
674 }
675 @Override
676 public void onBrightnessLevelChanged() {
Winson Chungefba3232012-09-27 16:56:42 -0700677 Resources r = mContext.getResources();
John Spurlock48f37ec2012-10-05 16:32:51 -0400678 int mode = Settings.System.getIntForUser(mContext.getContentResolver(),
Winson Chung5f623012012-09-14 14:58:43 -0700679 Settings.System.SCREEN_BRIGHTNESS_MODE,
John Spurlock48f37ec2012-10-05 16:32:51 -0400680 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
681 mUserTracker.getCurrentUserId());
Winson Chung5f623012012-09-14 14:58:43 -0700682 mBrightnessState.autoBrightness =
683 (mode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
684 mBrightnessState.iconId = mBrightnessState.autoBrightness
685 ? R.drawable.ic_qs_brightness_auto_on
686 : R.drawable.ic_qs_brightness_auto_off;
Winson Chungefba3232012-09-27 16:56:42 -0700687 mBrightnessState.label = r.getString(R.string.quick_settings_brightness_label);
Winson Chung5f623012012-09-14 14:58:43 -0700688 mBrightnessCallback.refreshView(mBrightnessTile, mBrightnessState);
689 }
Winson Chungefba3232012-09-27 16:56:42 -0700690 void refreshBrightnessTile() {
691 onBrightnessLevelChanged();
692 }
Winson Chung5f623012012-09-14 14:58:43 -0700693
Christopher Tate5e08af02012-09-21 17:17:22 -0700694 // User switch: need to update visuals of all tiles known to have per-user state
John Spurlock48f37ec2012-10-05 16:32:51 -0400695 void onUserSwitched() {
696 mBrightnessObserver.startObserving();
Christopher Tate5e08af02012-09-21 17:17:22 -0700697 onRotationLockChanged();
698 onBrightnessLevelChanged();
699 onNextAlarmChanged();
700 onBugreportChanged();
701 }
Christopher Tate5e08af02012-09-21 17:17:22 -0700702}