blob: 38c46c4f61d630114597aca57aba1c84cee74bf1 [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
19import android.bluetooth.BluetoothAdapter;
20import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback;
21import android.content.BroadcastReceiver;
22import android.content.ContentResolver;
23import android.content.Context;
24import android.content.Intent;
25import android.content.IntentFilter;
Winson Chung43229d72012-09-12 18:04:18 -070026import android.content.pm.PackageManager;
Winson Chunge641b6a2012-09-10 17:30:27 -070027import android.content.res.Resources;
28import android.database.ContentObserver;
Winson Chungeaa5ab02012-09-13 16:36:41 -070029import android.graphics.drawable.Drawable;
Winson Chunge641b6a2012-09-10 17:30:27 -070030import android.hardware.display.WifiDisplayStatus;
Daniel Sandler50528052012-11-07 23:39:41 -050031import android.net.ConnectivityManager;
Winson Chunge641b6a2012-09-10 17:30:27 -070032import 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;
Michael Wright0087a142013-02-05 16:29:39 -080044import com.android.systemui.settings.CurrentUserTracker;
45import com.android.systemui.settings.BrightnessController.BrightnessStateChangeCallback;
Winson Chunge641b6a2012-09-10 17:30:27 -070046import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
47import 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
Daniel Sandlerb5538e62013-04-12 15:16:53 -040098 public static class BasicRefreshCallback implements RefreshCallback {
99 private final QuickSettingsBasicTile mView;
100 private boolean mShowWhenEnabled;
101
102 public BasicRefreshCallback(QuickSettingsBasicTile v) {
103 mView = v;
104 }
105 public void refreshView(QuickSettingsTileView ignored, State state) {
106 if (mShowWhenEnabled) {
107 mView.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
108 }
109 if (state.iconId != 0) {
110 mView.setImageDrawable(null); // needed to flush any cached IDs
111 mView.setImageResource(state.iconId);
112 }
113 if (state.label != null) {
114 mView.setText(state.label);
115 }
116 }
117 public BasicRefreshCallback setShowWhenEnabled(boolean swe) {
118 mShowWhenEnabled = swe;
119 return this;
120 }
121 }
122
Winson Chunge641b6a2012-09-10 17:30:27 -0700123 /** Broadcast receive to determine if there is an alarm set. */
124 private BroadcastReceiver mAlarmIntentReceiver = new BroadcastReceiver() {
125 @Override
126 public void onReceive(Context context, Intent intent) {
127 String action = intent.getAction();
128 if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
129 onAlarmChanged(intent);
130 onNextAlarmChanged();
131 }
132 }
133 };
134
135 /** ContentObserver to determine the next alarm */
136 private class NextAlarmObserver extends ContentObserver {
137 public NextAlarmObserver(Handler handler) {
138 super(handler);
139 }
140
141 @Override public void onChange(boolean selfChange) {
142 onNextAlarmChanged();
143 }
144
145 public void startObserving() {
146 final ContentResolver cr = mContext.getContentResolver();
147 cr.registerContentObserver(
Daniel Sandler0f92a802012-12-03 12:33:41 -0500148 Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this,
149 UserHandle.USER_ALL);
Winson Chunge641b6a2012-09-10 17:30:27 -0700150 }
151 }
152
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400153 /** ContentObserver to watch adb */
154 private class BugreportObserver extends ContentObserver {
155 public BugreportObserver(Handler handler) {
156 super(handler);
157 }
158
159 @Override public void onChange(boolean selfChange) {
160 onBugreportChanged();
161 }
162
163 public void startObserving() {
164 final ContentResolver cr = mContext.getContentResolver();
165 cr.registerContentObserver(
Christopher Tate58f41ec2013-01-11 15:40:36 -0800166 Settings.Global.getUriFor(Settings.Global.BUGREPORT_IN_POWER_MENU), false, this);
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400167 }
168 }
John Spurlock48f37ec2012-10-05 16:32:51 -0400169
170 /** ContentObserver to watch brightness **/
171 private class BrightnessObserver extends ContentObserver {
172 public BrightnessObserver(Handler handler) {
173 super(handler);
174 }
175
176 @Override
177 public void onChange(boolean selfChange) {
178 onBrightnessLevelChanged();
179 }
180
181 public void startObserving() {
182 final ContentResolver cr = mContext.getContentResolver();
183 cr.unregisterContentObserver(this);
184 cr.registerContentObserver(
185 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),
186 false, this, mUserTracker.getCurrentUserId());
187 cr.registerContentObserver(
188 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
189 false, this, mUserTracker.getCurrentUserId());
190 }
191 }
192
193 private final Context mContext;
194 private final Handler mHandler;
195 private final CurrentUserTracker mUserTracker;
196 private final NextAlarmObserver mNextAlarmObserver;
197 private final BugreportObserver mBugreportObserver;
198 private final BrightnessObserver mBrightnessObserver;
Winson Chunge641b6a2012-09-10 17:30:27 -0700199
Daniel Sandler50528052012-11-07 23:39:41 -0500200 private final boolean mHasMobileData;
201
Winson Chunge641b6a2012-09-10 17:30:27 -0700202 private QuickSettingsTileView mUserTile;
203 private RefreshCallback mUserCallback;
Winson Chungeaa5ab02012-09-13 16:36:41 -0700204 private UserState mUserState = new UserState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700205
206 private QuickSettingsTileView mTimeTile;
Winson Chungc86b23b2012-09-24 11:24:28 -0700207 private RefreshCallback mTimeCallback;
208 private State mTimeState = new State();
209
210 private QuickSettingsTileView mAlarmTile;
211 private RefreshCallback mAlarmCallback;
212 private State mAlarmState = new State();
Winson Chunge641b6a2012-09-10 17:30:27 -0700213
214 private QuickSettingsTileView mAirplaneModeTile;
215 private RefreshCallback mAirplaneModeCallback;
216 private State mAirplaneModeState = new State();
217
218 private QuickSettingsTileView mWifiTile;
219 private RefreshCallback mWifiCallback;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700220 private WifiState mWifiState = new WifiState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700221
222 private QuickSettingsTileView mWifiDisplayTile;
223 private RefreshCallback mWifiDisplayCallback;
224 private State mWifiDisplayState = new State();
225
226 private QuickSettingsTileView mRSSITile;
227 private RefreshCallback mRSSICallback;
Winson Chung4f49d942012-09-14 14:01:40 -0700228 private RSSIState mRSSIState = new RSSIState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700229
230 private QuickSettingsTileView mBluetoothTile;
231 private RefreshCallback mBluetoothCallback;
Chris Wrenb2a7d272012-10-03 10:16:51 -0400232 private BluetoothState mBluetoothState = new BluetoothState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700233
234 private QuickSettingsTileView mBatteryTile;
235 private RefreshCallback mBatteryCallback;
236 private BatteryState mBatteryState = new BatteryState();
237
238 private QuickSettingsTileView mLocationTile;
239 private RefreshCallback mLocationCallback;
240 private State mLocationState = new State();
241
Winson Chung43229d72012-09-12 18:04:18 -0700242 private QuickSettingsTileView mImeTile;
Daniel Sandleraca0c752012-10-01 12:59:36 -0400243 private RefreshCallback mImeCallback = null;
Winson Chung43229d72012-09-12 18:04:18 -0700244 private State mImeState = new State();
245
Winson Chungd4726d02012-09-14 12:27:29 -0700246 private QuickSettingsTileView mRotationLockTile;
247 private RefreshCallback mRotationLockCallback;
248 private State mRotationLockState = new State();
249
Winson Chung5f623012012-09-14 14:58:43 -0700250 private QuickSettingsTileView mBrightnessTile;
251 private RefreshCallback mBrightnessCallback;
252 private BrightnessState mBrightnessState = new BrightnessState();
253
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400254 private QuickSettingsTileView mBugreportTile;
255 private RefreshCallback mBugreportCallback;
256 private State mBugreportState = new State();
257
Winson Chungefba3232012-09-27 16:56:42 -0700258 private QuickSettingsTileView mSettingsTile;
259 private RefreshCallback mSettingsCallback;
260 private State mSettingsState = new State();
261
Winson Chunge641b6a2012-09-10 17:30:27 -0700262 public QuickSettingsModel(Context context) {
263 mContext = context;
264 mHandler = new Handler();
John Spurlock48f37ec2012-10-05 16:32:51 -0400265 mUserTracker = new CurrentUserTracker(mContext) {
Michael Wright0087a142013-02-05 16:29:39 -0800266 public void onUserSwitched(int newUserId) {
267 mBrightnessObserver.startObserving();
268 onRotationLockChanged();
269 onBrightnessLevelChanged();
270 onNextAlarmChanged();
271 onBugreportChanged();
John Spurlock48f37ec2012-10-05 16:32:51 -0400272 }
273 };
274
Winson Chunge641b6a2012-09-10 17:30:27 -0700275 mNextAlarmObserver = new NextAlarmObserver(mHandler);
276 mNextAlarmObserver.startObserving();
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400277 mBugreportObserver = new BugreportObserver(mHandler);
278 mBugreportObserver.startObserving();
John Spurlock48f37ec2012-10-05 16:32:51 -0400279 mBrightnessObserver = new BrightnessObserver(mHandler);
280 mBrightnessObserver.startObserving();
Winson Chunge641b6a2012-09-10 17:30:27 -0700281
Daniel Sandler50528052012-11-07 23:39:41 -0500282 ConnectivityManager cm = (ConnectivityManager)
283 context.getSystemService(Context.CONNECTIVITY_SERVICE);
284 mHasMobileData = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
285
Winson Chunge641b6a2012-09-10 17:30:27 -0700286 IntentFilter alarmIntentFilter = new IntentFilter();
287 alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED);
288 context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter);
289 }
290
Winson Chungefba3232012-09-27 16:56:42 -0700291 void updateResources() {
292 refreshSettingsTile();
293 refreshBatteryTile();
294 refreshBluetoothTile();
295 refreshBrightnessTile();
296 refreshRotationLockTile();
297 }
298
299 // Settings
300 void addSettingsTile(QuickSettingsTileView view, RefreshCallback cb) {
301 mSettingsTile = view;
302 mSettingsCallback = cb;
303 refreshSettingsTile();
304 }
305 void refreshSettingsTile() {
306 Resources r = mContext.getResources();
307 mSettingsState.label = r.getString(R.string.quick_settings_settings_label);
308 mSettingsCallback.refreshView(mSettingsTile, mSettingsState);
309 }
310
Winson Chunge641b6a2012-09-10 17:30:27 -0700311 // User
312 void addUserTile(QuickSettingsTileView view, RefreshCallback cb) {
313 mUserTile = view;
314 mUserCallback = cb;
315 mUserCallback.refreshView(mUserTile, mUserState);
316 }
Winson Chungeaa5ab02012-09-13 16:36:41 -0700317 void setUserTileInfo(String name, Drawable avatar) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700318 mUserState.label = name;
Winson Chungeaa5ab02012-09-13 16:36:41 -0700319 mUserState.avatar = avatar;
Winson Chunge641b6a2012-09-10 17:30:27 -0700320 mUserCallback.refreshView(mUserTile, mUserState);
321 }
322
323 // Time
324 void addTimeTile(QuickSettingsTileView view, RefreshCallback cb) {
325 mTimeTile = view;
Winson Chungc86b23b2012-09-24 11:24:28 -0700326 mTimeCallback = cb;
327 mTimeCallback.refreshView(view, mTimeState);
328 }
329
330 // Alarm
331 void addAlarmTile(QuickSettingsTileView view, RefreshCallback cb) {
332 mAlarmTile = view;
333 mAlarmCallback = cb;
334 mAlarmCallback.refreshView(view, mAlarmState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700335 }
336 void onAlarmChanged(Intent intent) {
Winson Chungc86b23b2012-09-24 11:24:28 -0700337 mAlarmState.enabled = intent.getBooleanExtra("alarmSet", false);
338 mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700339 }
340 void onNextAlarmChanged() {
Daniel Sandler0f92a802012-12-03 12:33:41 -0500341 final String alarmText = Settings.System.getStringForUser(mContext.getContentResolver(),
342 Settings.System.NEXT_ALARM_FORMATTED,
343 UserHandle.USER_CURRENT);
344 mAlarmState.label = alarmText;
345
346 // When switching users, this is the only clue we're going to get about whether the
347 // alarm is actually set, since we won't get the ACTION_ALARM_CHANGED broadcast
348 mAlarmState.enabled = ! TextUtils.isEmpty(alarmText);
349
Winson Chungc86b23b2012-09-24 11:24:28 -0700350 mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700351 }
352
353 // Airplane Mode
354 void addAirplaneModeTile(QuickSettingsTileView view, RefreshCallback cb) {
355 mAirplaneModeTile = view;
356 mAirplaneModeTile.setOnClickListener(new View.OnClickListener() {
357 @Override
358 public void onClick(View v) {
359 if (mAirplaneModeState.enabled) {
360 setAirplaneModeState(false);
361 } else {
362 setAirplaneModeState(true);
363 }
364 }
365 });
366 mAirplaneModeCallback = cb;
Winson Chungefba3232012-09-27 16:56:42 -0700367 int airplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
368 Settings.Global.AIRPLANE_MODE_ON, 0);
369 onAirplaneModeChanged(airplaneMode != 0);
Winson Chunge641b6a2012-09-10 17:30:27 -0700370 }
371 private void setAirplaneModeState(boolean enabled) {
372 // TODO: Sets the view to be "awaiting" if not already awaiting
373
374 // Change the system setting
Winson Chung08b1cc82012-09-11 10:00:53 -0700375 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
Winson Chunge641b6a2012-09-10 17:30:27 -0700376 enabled ? 1 : 0);
377
378 // Post the intent
379 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
380 intent.putExtra("state", enabled);
381 mContext.sendBroadcast(intent);
382 }
383 // NetworkSignalChanged callback
384 @Override
385 public void onAirplaneModeChanged(boolean enabled) {
386 // TODO: If view is in awaiting state, disable
387 Resources r = mContext.getResources();
388 mAirplaneModeState.enabled = enabled;
389 mAirplaneModeState.iconId = (enabled ?
Winson Chungeaa5ab02012-09-13 16:36:41 -0700390 R.drawable.ic_qs_airplane_on :
391 R.drawable.ic_qs_airplane_off);
Winson Chungefba3232012-09-27 16:56:42 -0700392 mAirplaneModeState.label = r.getString(R.string.quick_settings_airplane_mode_label);
Winson Chunge641b6a2012-09-10 17:30:27 -0700393 mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState);
394 }
395
396 // Wifi
397 void addWifiTile(QuickSettingsTileView view, RefreshCallback cb) {
398 mWifiTile = view;
399 mWifiCallback = cb;
400 mWifiCallback.refreshView(mWifiTile, mWifiState);
401 }
Winson Chung34563e22012-09-21 17:19:49 -0700402 // Remove the double quotes that the SSID may contain
403 public static String removeDoubleQuotes(String string) {
404 if (string == null) return null;
405 final int length = string.length();
406 if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
407 return string.substring(1, length - 1);
408 }
409 return string;
410 }
Winson Chungf4b5ab12012-09-24 16:47:46 -0700411 // Remove the period from the network name
412 public static String removeTrailingPeriod(String string) {
413 if (string == null) return null;
414 final int length = string.length();
415 if (string.endsWith(".")) {
416 string.substring(0, length - 1);
417 }
418 return string;
419 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700420 // NetworkSignalChanged callback
421 @Override
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700422 public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
423 String wifiSignalContentDescription, String enabledDesc) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700424 // TODO: If view is in awaiting state, disable
425 Resources r = mContext.getResources();
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700426
Winson Chungf4b5ab12012-09-24 16:47:46 -0700427 boolean wifiConnected = enabled && (wifiSignalIconId > 0) && (enabledDesc != null);
Winson Chungefba3232012-09-27 16:56:42 -0700428 boolean wifiNotConnected = (wifiSignalIconId > 0) && (enabledDesc == null);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700429 mWifiState.enabled = enabled;
430 mWifiState.connected = wifiConnected;
Winson Chungf4b5ab12012-09-24 16:47:46 -0700431 if (wifiConnected) {
432 mWifiState.iconId = wifiSignalIconId;
433 mWifiState.label = removeDoubleQuotes(enabledDesc);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700434 mWifiState.signalContentDescription = wifiSignalContentDescription;
Winson Chungf4b5ab12012-09-24 16:47:46 -0700435 } else if (wifiNotConnected) {
436 mWifiState.iconId = R.drawable.ic_qs_wifi_0;
Chris Wrendaab6af2012-10-03 15:13:10 -0400437 mWifiState.label = r.getString(R.string.quick_settings_wifi_label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700438 mWifiState.signalContentDescription = r.getString(R.string.accessibility_no_wifi);
Winson Chungf4b5ab12012-09-24 16:47:46 -0700439 } else {
440 mWifiState.iconId = R.drawable.ic_qs_wifi_no_network;
441 mWifiState.label = r.getString(R.string.quick_settings_wifi_off_label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700442 mWifiState.signalContentDescription = r.getString(R.string.accessibility_wifi_off);
Winson Chungf4b5ab12012-09-24 16:47:46 -0700443 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700444 mWifiCallback.refreshView(mWifiTile, mWifiState);
445 }
446
Daniel Sandler50528052012-11-07 23:39:41 -0500447 boolean deviceHasMobileData() {
448 return mHasMobileData;
449 }
450
Winson Chunge641b6a2012-09-10 17:30:27 -0700451 // RSSI
452 void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) {
453 mRSSITile = view;
454 mRSSICallback = cb;
455 mRSSICallback.refreshView(mRSSITile, mRSSIState);
456 }
457 // NetworkSignalChanged callback
458 @Override
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700459 public void onMobileDataSignalChanged(
460 boolean enabled, int mobileSignalIconId, String signalContentDescription,
461 int dataTypeIconId, String dataContentDescription, String enabledDesc) {
Daniel Sandler50528052012-11-07 23:39:41 -0500462 if (deviceHasMobileData()) {
Winson Chung43229d72012-09-12 18:04:18 -0700463 // TODO: If view is in awaiting state, disable
464 Resources r = mContext.getResources();
Winson Chung4f49d942012-09-14 14:01:40 -0700465 mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0)
Winson Chunged1395f2012-09-13 18:13:44 -0700466 ? mobileSignalIconId
467 : R.drawable.ic_qs_signal_no_signal;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700468 mRSSIState.signalContentDescription = enabled && (mobileSignalIconId > 0)
469 ? signalContentDescription
470 : r.getString(R.string.accessibility_no_signal);
Winson Chungc86b23b2012-09-24 11:24:28 -0700471 mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
Winson Chung4f49d942012-09-14 14:01:40 -0700472 ? dataTypeIconId
473 : 0;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700474 mRSSIState.dataContentDescription = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
475 ? dataContentDescription
476 : r.getString(R.string.accessibility_no_data);
Winson Chunged1395f2012-09-13 18:13:44 -0700477 mRSSIState.label = enabled
Winson Chungf4b5ab12012-09-24 16:47:46 -0700478 ? removeTrailingPeriod(enabledDesc)
Winson Chunged1395f2012-09-13 18:13:44 -0700479 : r.getString(R.string.quick_settings_rssi_emergency_only);
Winson Chung43229d72012-09-12 18:04:18 -0700480 mRSSICallback.refreshView(mRSSITile, mRSSIState);
481 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700482 }
483
484 // Bluetooth
485 void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) {
486 mBluetoothTile = view;
487 mBluetoothCallback = cb;
488
489 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Chris Wrenb2a7d272012-10-03 10:16:51 -0400490 mBluetoothState.enabled = adapter.isEnabled();
491 mBluetoothState.connected =
492 (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED);
493 onBluetoothStateChange(mBluetoothState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700494 }
Winson Chung6072b002012-09-11 17:10:10 -0700495 boolean deviceSupportsBluetooth() {
496 return (BluetoothAdapter.getDefaultAdapter() != null);
497 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700498 // BluetoothController callback
499 @Override
500 public void onBluetoothStateChange(boolean on) {
Chris Wrenb2a7d272012-10-03 10:16:51 -0400501 mBluetoothState.enabled = on;
502 onBluetoothStateChange(mBluetoothState);
503 }
504 public void onBluetoothStateChange(BluetoothState bluetoothStateIn) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700505 // TODO: If view is in awaiting state, disable
506 Resources r = mContext.getResources();
Chris Wrenb2a7d272012-10-03 10:16:51 -0400507 mBluetoothState.enabled = bluetoothStateIn.enabled;
508 mBluetoothState.connected = bluetoothStateIn.connected;
509 if (mBluetoothState.enabled) {
510 if (mBluetoothState.connected) {
511 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_on;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700512 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_connected);
Chris Wrenb2a7d272012-10-03 10:16:51 -0400513 } else {
514 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_not_connected;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700515 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_on);
Chris Wrenb2a7d272012-10-03 10:16:51 -0400516 }
Winson Chung34563e22012-09-21 17:19:49 -0700517 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_label);
Winson Chunge641b6a2012-09-10 17:30:27 -0700518 } else {
Winson Chungeaa5ab02012-09-13 16:36:41 -0700519 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off;
Winson Chung34563e22012-09-21 17:19:49 -0700520 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_off_label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700521 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_off);
Winson Chunge641b6a2012-09-10 17:30:27 -0700522 }
523 mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState);
524 }
Winson Chungefba3232012-09-27 16:56:42 -0700525 void refreshBluetoothTile() {
526 if (mBluetoothTile != null) {
527 onBluetoothStateChange(mBluetoothState.enabled);
528 }
529 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700530
531 // Battery
532 void addBatteryTile(QuickSettingsTileView view, RefreshCallback cb) {
533 mBatteryTile = view;
534 mBatteryCallback = cb;
535 mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
536 }
537 // BatteryController callback
538 @Override
539 public void onBatteryLevelChanged(int level, boolean pluggedIn) {
540 mBatteryState.batteryLevel = level;
541 mBatteryState.pluggedIn = pluggedIn;
542 mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
543 }
Winson Chungefba3232012-09-27 16:56:42 -0700544 void refreshBatteryTile() {
545 mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
546 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700547
548 // Location
549 void addLocationTile(QuickSettingsTileView view, RefreshCallback cb) {
550 mLocationTile = view;
551 mLocationCallback = cb;
552 mLocationCallback.refreshView(mLocationTile, mLocationState);
553 }
554 // LocationController callback
555 @Override
556 public void onLocationGpsStateChanged(boolean inUse, String description) {
557 mLocationState.enabled = inUse;
558 mLocationState.label = description;
559 mLocationCallback.refreshView(mLocationTile, mLocationState);
560 }
561
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400562 // Bug report
563 void addBugreportTile(QuickSettingsTileView view, RefreshCallback cb) {
564 mBugreportTile = view;
565 mBugreportCallback = cb;
566 onBugreportChanged();
567 }
568 // SettingsObserver callback
569 public void onBugreportChanged() {
570 final ContentResolver cr = mContext.getContentResolver();
571 boolean enabled = false;
572 try {
Christopher Tate58f41ec2013-01-11 15:40:36 -0800573 enabled = (Settings.Global.getInt(cr, Settings.Global.BUGREPORT_IN_POWER_MENU) != 0);
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400574 } catch (SettingNotFoundException e) {
575 }
576
577 mBugreportState.enabled = enabled;
578 mBugreportCallback.refreshView(mBugreportTile, mBugreportState);
579 }
580
Winson Chunge641b6a2012-09-10 17:30:27 -0700581 // Wifi Display
582 void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) {
583 mWifiDisplayTile = view;
584 mWifiDisplayCallback = cb;
585 }
586 public void onWifiDisplayStateChanged(WifiDisplayStatus status) {
Jeff Brown89d55462012-09-19 11:33:42 -0700587 mWifiDisplayState.enabled =
Winson Chung3ed6f942012-09-20 16:07:11 -0700588 (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON);
Winson Chunge641b6a2012-09-10 17:30:27 -0700589 if (status.getActiveDisplay() != null) {
Jeff Brown89d55462012-09-19 11:33:42 -0700590 mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName();
John Spurlock01e2f4f2012-10-05 17:33:31 -0400591 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display_connected;
Winson Chunge641b6a2012-09-10 17:30:27 -0700592 } else {
593 mWifiDisplayState.label = mContext.getString(
594 R.string.quick_settings_wifi_display_no_connection_label);
John Spurlock01e2f4f2012-10-05 17:33:31 -0400595 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display;
Winson Chunge641b6a2012-09-10 17:30:27 -0700596 }
597 mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState);
598
599 }
600
Winson Chung43229d72012-09-12 18:04:18 -0700601 // IME
602 void addImeTile(QuickSettingsTileView view, RefreshCallback cb) {
603 mImeTile = view;
604 mImeCallback = cb;
605 mImeCallback.refreshView(mImeTile, mImeState);
606 }
Winson Chung34563e22012-09-21 17:19:49 -0700607 /* This implementation is taken from
608 InputMethodManagerService.needsToShowImeSwitchOngoingNotification(). */
609 private boolean needsToShowImeSwitchOngoingNotification(InputMethodManager imm) {
610 List<InputMethodInfo> imis = imm.getEnabledInputMethodList();
611 final int N = imis.size();
612 if (N > 2) return true;
613 if (N < 1) return false;
614 int nonAuxCount = 0;
615 int auxCount = 0;
616 InputMethodSubtype nonAuxSubtype = null;
617 InputMethodSubtype auxSubtype = null;
618 for(int i = 0; i < N; ++i) {
619 final InputMethodInfo imi = imis.get(i);
620 final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(imi,
621 true);
622 final int subtypeCount = subtypes.size();
623 if (subtypeCount == 0) {
624 ++nonAuxCount;
625 } else {
626 for (int j = 0; j < subtypeCount; ++j) {
627 final InputMethodSubtype subtype = subtypes.get(j);
628 if (!subtype.isAuxiliary()) {
629 ++nonAuxCount;
630 nonAuxSubtype = subtype;
631 } else {
632 ++auxCount;
633 auxSubtype = subtype;
634 }
635 }
636 }
637 }
638 if (nonAuxCount > 1 || auxCount > 1) {
639 return true;
640 } else if (nonAuxCount == 1 && auxCount == 1) {
641 if (nonAuxSubtype != null && auxSubtype != null
642 && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
643 || auxSubtype.overridesImplicitlyEnabledSubtype()
644 || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
645 && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
646 return false;
647 }
648 return true;
649 }
650 return false;
651 }
Winson Chung43229d72012-09-12 18:04:18 -0700652 void onImeWindowStatusChanged(boolean visible) {
Winson Chung2a4057d2012-09-12 18:30:06 -0700653 InputMethodManager imm =
654 (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
655 List<InputMethodInfo> imis = imm.getInputMethodList();
656
Winson Chung34563e22012-09-21 17:19:49 -0700657 mImeState.enabled = (visible && needsToShowImeSwitchOngoingNotification(imm));
Winson Chung2a4057d2012-09-12 18:30:06 -0700658 mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(),
659 imm, imis, mContext.getPackageManager());
Daniel Sandleraca0c752012-10-01 12:59:36 -0400660 if (mImeCallback != null) {
661 mImeCallback.refreshView(mImeTile, mImeState);
662 }
Winson Chung43229d72012-09-12 18:04:18 -0700663 }
Winson Chung2a4057d2012-09-12 18:30:06 -0700664 private static String getCurrentInputMethodName(Context context, ContentResolver resolver,
665 InputMethodManager imm, List<InputMethodInfo> imis, PackageManager pm) {
666 if (resolver == null || imis == null) return null;
667 final String currentInputMethodId = Settings.Secure.getString(resolver,
668 Settings.Secure.DEFAULT_INPUT_METHOD);
669 if (TextUtils.isEmpty(currentInputMethodId)) return null;
670 for (InputMethodInfo imi : imis) {
671 if (currentInputMethodId.equals(imi.getId())) {
672 final InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype();
673 final CharSequence summary = subtype != null
674 ? subtype.getDisplayName(context, imi.getPackageName(),
675 imi.getServiceInfo().applicationInfo)
676 : context.getString(R.string.quick_settings_ime_label);
677 return summary.toString();
678 }
679 }
680 return null;
681 }
Winson Chung43229d72012-09-12 18:04:18 -0700682
Winson Chungd4726d02012-09-14 12:27:29 -0700683 // Rotation lock
684 void addRotationLockTile(QuickSettingsTileView view, RefreshCallback cb) {
685 mRotationLockTile = view;
686 mRotationLockCallback = cb;
687 onRotationLockChanged();
688 }
689 void onRotationLockChanged() {
690 boolean locked = RotationPolicy.isRotationLocked(mContext);
691 mRotationLockState.enabled = locked;
692 mRotationLockState.iconId = locked
693 ? R.drawable.ic_qs_rotation_locked
694 : R.drawable.ic_qs_auto_rotate;
695 mRotationLockState.label = locked
696 ? mContext.getString(R.string.quick_settings_rotation_locked_label)
697 : mContext.getString(R.string.quick_settings_rotation_unlocked_label);
Daniel Sandler8dd92062012-09-14 17:29:12 -0700698
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700699 // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings
Daniel Sandler8dd92062012-09-14 17:29:12 -0700700 if (mRotationLockTile != null && mRotationLockCallback != null) {
701 mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
702 }
Winson Chungd4726d02012-09-14 12:27:29 -0700703 }
Winson Chungefba3232012-09-27 16:56:42 -0700704 void refreshRotationLockTile() {
705 if (mRotationLockTile != null) {
706 onRotationLockChanged();
707 }
708 }
Winson Chungd4726d02012-09-14 12:27:29 -0700709
Winson Chung5f623012012-09-14 14:58:43 -0700710 // Brightness
711 void addBrightnessTile(QuickSettingsTileView view, RefreshCallback cb) {
712 mBrightnessTile = view;
713 mBrightnessCallback = cb;
714 onBrightnessLevelChanged();
715 }
716 @Override
717 public void onBrightnessLevelChanged() {
Winson Chungefba3232012-09-27 16:56:42 -0700718 Resources r = mContext.getResources();
John Spurlock48f37ec2012-10-05 16:32:51 -0400719 int mode = Settings.System.getIntForUser(mContext.getContentResolver(),
Winson Chung5f623012012-09-14 14:58:43 -0700720 Settings.System.SCREEN_BRIGHTNESS_MODE,
John Spurlock48f37ec2012-10-05 16:32:51 -0400721 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
722 mUserTracker.getCurrentUserId());
Winson Chung5f623012012-09-14 14:58:43 -0700723 mBrightnessState.autoBrightness =
724 (mode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
725 mBrightnessState.iconId = mBrightnessState.autoBrightness
726 ? R.drawable.ic_qs_brightness_auto_on
727 : R.drawable.ic_qs_brightness_auto_off;
Winson Chungefba3232012-09-27 16:56:42 -0700728 mBrightnessState.label = r.getString(R.string.quick_settings_brightness_label);
Winson Chung5f623012012-09-14 14:58:43 -0700729 mBrightnessCallback.refreshView(mBrightnessTile, mBrightnessState);
730 }
Winson Chungefba3232012-09-27 16:56:42 -0700731 void refreshBrightnessTile() {
732 onBrightnessLevelChanged();
733 }
Christopher Tate5e08af02012-09-21 17:17:22 -0700734}