blob: 79495a7b3c0e4d71c44b083e679c8e0843bbdf8f [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
42import com.android.systemui.R;
Michael Wright0087a142013-02-05 16:29:39 -080043import com.android.systemui.settings.BrightnessController.BrightnessStateChangeCallback;
John Spurlockde84f0e2013-06-12 12:41:00 -040044import com.android.systemui.settings.CurrentUserTracker;
Winson Chunge641b6a2012-09-10 17:30:27 -070045import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
46import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback;
47import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
John Spurlockde84f0e2013-06-12 12:41:00 -040048import com.android.systemui.statusbar.policy.RotationLockController;
49import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
Winson Chunge641b6a2012-09-10 17:30:27 -070050
Winson Chung2a4057d2012-09-12 18:30:06 -070051import java.util.List;
52
Winson Chunge641b6a2012-09-10 17:30:27 -070053class QuickSettingsModel implements BluetoothStateChangeCallback,
54 NetworkSignalChangedCallback,
55 BatteryStateChangeCallback,
Winson Chung5f623012012-09-14 14:58:43 -070056 LocationGpsStateChangeCallback,
Svetoslav79578b22013-04-29 16:55:57 -070057 BrightnessStateChangeCallback,
58 RotationLockControllerCallback {
Winson Chunge641b6a2012-09-10 17:30:27 -070059
Winson Chung34563e22012-09-21 17:19:49 -070060 // Sett InputMethoManagerService
61 private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
62
Winson Chunge641b6a2012-09-10 17:30:27 -070063 /** Represents the state of a given attribute. */
64 static class State {
65 int iconId;
66 String label;
67 boolean enabled = false;
68 }
69 static class BatteryState extends State {
70 int batteryLevel;
71 boolean pluggedIn;
72 }
Winson Chung4f49d942012-09-14 14:01:40 -070073 static class RSSIState extends State {
74 int signalIconId;
Casey Burkhardtbac221f2012-10-03 18:13:58 -070075 String signalContentDescription;
Winson Chung4f49d942012-09-14 14:01:40 -070076 int dataTypeIconId;
Casey Burkhardtbac221f2012-10-03 18:13:58 -070077 String dataContentDescription;
78 }
79 static class WifiState extends State {
80 String signalContentDescription;
81 boolean connected;
Winson Chung4f49d942012-09-14 14:01:40 -070082 }
Winson Chungeaa5ab02012-09-13 16:36:41 -070083 static class UserState extends State {
84 Drawable avatar;
85 }
Winson Chung5f623012012-09-14 14:58:43 -070086 static class BrightnessState extends State {
87 boolean autoBrightness;
88 }
Chris Wrenb2a7d272012-10-03 10:16:51 -040089 public static class BluetoothState extends State {
90 boolean connected = false;
Casey Burkhardtbac221f2012-10-03 18:13:58 -070091 String stateContentDescription;
Chris Wrenb2a7d272012-10-03 10:16:51 -040092 }
Svetoslav79578b22013-04-29 16:55:57 -070093 public static class RotationLockState extends State {
94 boolean visible = false;
95 }
Winson Chunge641b6a2012-09-10 17:30:27 -070096
97 /** The callback to update a given tile. */
98 interface RefreshCallback {
99 public void refreshView(QuickSettingsTileView view, State state);
100 }
101
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400102 public static class BasicRefreshCallback implements RefreshCallback {
103 private final QuickSettingsBasicTile mView;
104 private boolean mShowWhenEnabled;
105
106 public BasicRefreshCallback(QuickSettingsBasicTile v) {
107 mView = v;
108 }
109 public void refreshView(QuickSettingsTileView ignored, State state) {
110 if (mShowWhenEnabled) {
111 mView.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
112 }
113 if (state.iconId != 0) {
114 mView.setImageDrawable(null); // needed to flush any cached IDs
115 mView.setImageResource(state.iconId);
116 }
117 if (state.label != null) {
118 mView.setText(state.label);
119 }
120 }
121 public BasicRefreshCallback setShowWhenEnabled(boolean swe) {
122 mShowWhenEnabled = swe;
123 return this;
124 }
125 }
126
Winson Chunge641b6a2012-09-10 17:30:27 -0700127 /** Broadcast receive to determine if there is an alarm set. */
128 private BroadcastReceiver mAlarmIntentReceiver = new BroadcastReceiver() {
129 @Override
130 public void onReceive(Context context, Intent intent) {
131 String action = intent.getAction();
132 if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
133 onAlarmChanged(intent);
134 onNextAlarmChanged();
135 }
136 }
137 };
138
139 /** ContentObserver to determine the next alarm */
140 private class NextAlarmObserver extends ContentObserver {
141 public NextAlarmObserver(Handler handler) {
142 super(handler);
143 }
144
145 @Override public void onChange(boolean selfChange) {
146 onNextAlarmChanged();
147 }
148
149 public void startObserving() {
150 final ContentResolver cr = mContext.getContentResolver();
151 cr.registerContentObserver(
Daniel Sandler0f92a802012-12-03 12:33:41 -0500152 Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this,
153 UserHandle.USER_ALL);
Winson Chunge641b6a2012-09-10 17:30:27 -0700154 }
155 }
156
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400157 /** ContentObserver to watch adb */
158 private class BugreportObserver extends ContentObserver {
159 public BugreportObserver(Handler handler) {
160 super(handler);
161 }
162
163 @Override public void onChange(boolean selfChange) {
164 onBugreportChanged();
165 }
166
167 public void startObserving() {
168 final ContentResolver cr = mContext.getContentResolver();
169 cr.registerContentObserver(
Christopher Tate58f41ec2013-01-11 15:40:36 -0800170 Settings.Global.getUriFor(Settings.Global.BUGREPORT_IN_POWER_MENU), false, this);
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400171 }
172 }
John Spurlock48f37ec2012-10-05 16:32:51 -0400173
174 /** ContentObserver to watch brightness **/
175 private class BrightnessObserver extends ContentObserver {
176 public BrightnessObserver(Handler handler) {
177 super(handler);
178 }
179
180 @Override
181 public void onChange(boolean selfChange) {
182 onBrightnessLevelChanged();
183 }
184
185 public void startObserving() {
186 final ContentResolver cr = mContext.getContentResolver();
187 cr.unregisterContentObserver(this);
188 cr.registerContentObserver(
189 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),
190 false, this, mUserTracker.getCurrentUserId());
191 cr.registerContentObserver(
192 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
193 false, this, mUserTracker.getCurrentUserId());
194 }
195 }
196
197 private final Context mContext;
198 private final Handler mHandler;
199 private final CurrentUserTracker mUserTracker;
200 private final NextAlarmObserver mNextAlarmObserver;
201 private final BugreportObserver mBugreportObserver;
202 private final BrightnessObserver mBrightnessObserver;
Winson Chunge641b6a2012-09-10 17:30:27 -0700203
Daniel Sandler50528052012-11-07 23:39:41 -0500204 private final boolean mHasMobileData;
205
Winson Chunge641b6a2012-09-10 17:30:27 -0700206 private QuickSettingsTileView mUserTile;
207 private RefreshCallback mUserCallback;
Winson Chungeaa5ab02012-09-13 16:36:41 -0700208 private UserState mUserState = new UserState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700209
210 private QuickSettingsTileView mTimeTile;
Winson Chungc86b23b2012-09-24 11:24:28 -0700211 private RefreshCallback mTimeCallback;
212 private State mTimeState = new State();
213
214 private QuickSettingsTileView mAlarmTile;
215 private RefreshCallback mAlarmCallback;
216 private State mAlarmState = new State();
Winson Chunge641b6a2012-09-10 17:30:27 -0700217
218 private QuickSettingsTileView mAirplaneModeTile;
219 private RefreshCallback mAirplaneModeCallback;
220 private State mAirplaneModeState = new State();
221
222 private QuickSettingsTileView mWifiTile;
223 private RefreshCallback mWifiCallback;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700224 private WifiState mWifiState = new WifiState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700225
226 private QuickSettingsTileView mWifiDisplayTile;
227 private RefreshCallback mWifiDisplayCallback;
228 private State mWifiDisplayState = new State();
229
230 private QuickSettingsTileView mRSSITile;
231 private RefreshCallback mRSSICallback;
Winson Chung4f49d942012-09-14 14:01:40 -0700232 private RSSIState mRSSIState = new RSSIState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700233
234 private QuickSettingsTileView mBluetoothTile;
235 private RefreshCallback mBluetoothCallback;
Chris Wrenb2a7d272012-10-03 10:16:51 -0400236 private BluetoothState mBluetoothState = new BluetoothState();
Winson Chunge641b6a2012-09-10 17:30:27 -0700237
238 private QuickSettingsTileView mBatteryTile;
239 private RefreshCallback mBatteryCallback;
240 private BatteryState mBatteryState = new BatteryState();
241
242 private QuickSettingsTileView mLocationTile;
243 private RefreshCallback mLocationCallback;
244 private State mLocationState = new State();
245
Winson Chung43229d72012-09-12 18:04:18 -0700246 private QuickSettingsTileView mImeTile;
Daniel Sandleraca0c752012-10-01 12:59:36 -0400247 private RefreshCallback mImeCallback = null;
Winson Chung43229d72012-09-12 18:04:18 -0700248 private State mImeState = new State();
249
Winson Chungd4726d02012-09-14 12:27:29 -0700250 private QuickSettingsTileView mRotationLockTile;
251 private RefreshCallback mRotationLockCallback;
Svetoslav79578b22013-04-29 16:55:57 -0700252 private RotationLockState mRotationLockState = new RotationLockState();
Winson Chungd4726d02012-09-14 12:27:29 -0700253
Winson Chung5f623012012-09-14 14:58:43 -0700254 private QuickSettingsTileView mBrightnessTile;
255 private RefreshCallback mBrightnessCallback;
256 private BrightnessState mBrightnessState = new BrightnessState();
257
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400258 private QuickSettingsTileView mBugreportTile;
259 private RefreshCallback mBugreportCallback;
260 private State mBugreportState = new State();
261
Winson Chungefba3232012-09-27 16:56:42 -0700262 private QuickSettingsTileView mSettingsTile;
263 private RefreshCallback mSettingsCallback;
264 private State mSettingsState = new State();
265
Svetoslav79578b22013-04-29 16:55:57 -0700266 private RotationLockController mRotationLockController;
267
Winson Chunge641b6a2012-09-10 17:30:27 -0700268 public QuickSettingsModel(Context context) {
269 mContext = context;
270 mHandler = new Handler();
John Spurlock48f37ec2012-10-05 16:32:51 -0400271 mUserTracker = new CurrentUserTracker(mContext) {
Michael Wright0087a142013-02-05 16:29:39 -0800272 public void onUserSwitched(int newUserId) {
273 mBrightnessObserver.startObserving();
274 onRotationLockChanged();
275 onBrightnessLevelChanged();
276 onNextAlarmChanged();
277 onBugreportChanged();
John Spurlock48f37ec2012-10-05 16:32:51 -0400278 }
279 };
280
Winson Chunge641b6a2012-09-10 17:30:27 -0700281 mNextAlarmObserver = new NextAlarmObserver(mHandler);
282 mNextAlarmObserver.startObserving();
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400283 mBugreportObserver = new BugreportObserver(mHandler);
284 mBugreportObserver.startObserving();
John Spurlock48f37ec2012-10-05 16:32:51 -0400285 mBrightnessObserver = new BrightnessObserver(mHandler);
286 mBrightnessObserver.startObserving();
Winson Chunge641b6a2012-09-10 17:30:27 -0700287
Daniel Sandler50528052012-11-07 23:39:41 -0500288 ConnectivityManager cm = (ConnectivityManager)
289 context.getSystemService(Context.CONNECTIVITY_SERVICE);
290 mHasMobileData = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
291
Winson Chunge641b6a2012-09-10 17:30:27 -0700292 IntentFilter alarmIntentFilter = new IntentFilter();
293 alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED);
294 context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter);
295 }
296
Winson Chungefba3232012-09-27 16:56:42 -0700297 void updateResources() {
298 refreshSettingsTile();
299 refreshBatteryTile();
300 refreshBluetoothTile();
301 refreshBrightnessTile();
302 refreshRotationLockTile();
303 }
304
305 // Settings
306 void addSettingsTile(QuickSettingsTileView view, RefreshCallback cb) {
307 mSettingsTile = view;
308 mSettingsCallback = cb;
309 refreshSettingsTile();
310 }
311 void refreshSettingsTile() {
312 Resources r = mContext.getResources();
313 mSettingsState.label = r.getString(R.string.quick_settings_settings_label);
314 mSettingsCallback.refreshView(mSettingsTile, mSettingsState);
315 }
316
Winson Chunge641b6a2012-09-10 17:30:27 -0700317 // User
318 void addUserTile(QuickSettingsTileView view, RefreshCallback cb) {
319 mUserTile = view;
320 mUserCallback = cb;
321 mUserCallback.refreshView(mUserTile, mUserState);
322 }
Winson Chungeaa5ab02012-09-13 16:36:41 -0700323 void setUserTileInfo(String name, Drawable avatar) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700324 mUserState.label = name;
Winson Chungeaa5ab02012-09-13 16:36:41 -0700325 mUserState.avatar = avatar;
Winson Chunge641b6a2012-09-10 17:30:27 -0700326 mUserCallback.refreshView(mUserTile, mUserState);
327 }
328
329 // Time
330 void addTimeTile(QuickSettingsTileView view, RefreshCallback cb) {
331 mTimeTile = view;
Winson Chungc86b23b2012-09-24 11:24:28 -0700332 mTimeCallback = cb;
333 mTimeCallback.refreshView(view, mTimeState);
334 }
335
336 // Alarm
337 void addAlarmTile(QuickSettingsTileView view, RefreshCallback cb) {
338 mAlarmTile = view;
339 mAlarmCallback = cb;
340 mAlarmCallback.refreshView(view, mAlarmState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700341 }
342 void onAlarmChanged(Intent intent) {
Winson Chungc86b23b2012-09-24 11:24:28 -0700343 mAlarmState.enabled = intent.getBooleanExtra("alarmSet", false);
344 mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700345 }
346 void onNextAlarmChanged() {
Daniel Sandler0f92a802012-12-03 12:33:41 -0500347 final String alarmText = Settings.System.getStringForUser(mContext.getContentResolver(),
348 Settings.System.NEXT_ALARM_FORMATTED,
349 UserHandle.USER_CURRENT);
350 mAlarmState.label = alarmText;
351
352 // When switching users, this is the only clue we're going to get about whether the
353 // alarm is actually set, since we won't get the ACTION_ALARM_CHANGED broadcast
354 mAlarmState.enabled = ! TextUtils.isEmpty(alarmText);
355
Winson Chungc86b23b2012-09-24 11:24:28 -0700356 mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700357 }
358
359 // Airplane Mode
360 void addAirplaneModeTile(QuickSettingsTileView view, RefreshCallback cb) {
361 mAirplaneModeTile = view;
362 mAirplaneModeTile.setOnClickListener(new View.OnClickListener() {
363 @Override
364 public void onClick(View v) {
365 if (mAirplaneModeState.enabled) {
366 setAirplaneModeState(false);
367 } else {
368 setAirplaneModeState(true);
369 }
370 }
371 });
372 mAirplaneModeCallback = cb;
Winson Chungefba3232012-09-27 16:56:42 -0700373 int airplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
374 Settings.Global.AIRPLANE_MODE_ON, 0);
375 onAirplaneModeChanged(airplaneMode != 0);
Winson Chunge641b6a2012-09-10 17:30:27 -0700376 }
377 private void setAirplaneModeState(boolean enabled) {
378 // TODO: Sets the view to be "awaiting" if not already awaiting
379
380 // Change the system setting
Winson Chung08b1cc82012-09-11 10:00:53 -0700381 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
Winson Chunge641b6a2012-09-10 17:30:27 -0700382 enabled ? 1 : 0);
383
384 // Post the intent
385 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
386 intent.putExtra("state", enabled);
387 mContext.sendBroadcast(intent);
388 }
389 // NetworkSignalChanged callback
390 @Override
391 public void onAirplaneModeChanged(boolean enabled) {
392 // TODO: If view is in awaiting state, disable
393 Resources r = mContext.getResources();
394 mAirplaneModeState.enabled = enabled;
395 mAirplaneModeState.iconId = (enabled ?
Winson Chungeaa5ab02012-09-13 16:36:41 -0700396 R.drawable.ic_qs_airplane_on :
397 R.drawable.ic_qs_airplane_off);
Winson Chungefba3232012-09-27 16:56:42 -0700398 mAirplaneModeState.label = r.getString(R.string.quick_settings_airplane_mode_label);
Winson Chunge641b6a2012-09-10 17:30:27 -0700399 mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState);
400 }
401
402 // Wifi
403 void addWifiTile(QuickSettingsTileView view, RefreshCallback cb) {
404 mWifiTile = view;
405 mWifiCallback = cb;
406 mWifiCallback.refreshView(mWifiTile, mWifiState);
407 }
Winson Chung34563e22012-09-21 17:19:49 -0700408 // Remove the double quotes that the SSID may contain
409 public static String removeDoubleQuotes(String string) {
410 if (string == null) return null;
411 final int length = string.length();
412 if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
413 return string.substring(1, length - 1);
414 }
415 return string;
416 }
Winson Chungf4b5ab12012-09-24 16:47:46 -0700417 // Remove the period from the network name
418 public static String removeTrailingPeriod(String string) {
419 if (string == null) return null;
420 final int length = string.length();
421 if (string.endsWith(".")) {
422 string.substring(0, length - 1);
423 }
424 return string;
425 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700426 // NetworkSignalChanged callback
427 @Override
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700428 public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
429 String wifiSignalContentDescription, String enabledDesc) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700430 // TODO: If view is in awaiting state, disable
431 Resources r = mContext.getResources();
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700432
Winson Chungf4b5ab12012-09-24 16:47:46 -0700433 boolean wifiConnected = enabled && (wifiSignalIconId > 0) && (enabledDesc != null);
Winson Chungefba3232012-09-27 16:56:42 -0700434 boolean wifiNotConnected = (wifiSignalIconId > 0) && (enabledDesc == null);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700435 mWifiState.enabled = enabled;
436 mWifiState.connected = wifiConnected;
Winson Chungf4b5ab12012-09-24 16:47:46 -0700437 if (wifiConnected) {
438 mWifiState.iconId = wifiSignalIconId;
439 mWifiState.label = removeDoubleQuotes(enabledDesc);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700440 mWifiState.signalContentDescription = wifiSignalContentDescription;
Winson Chungf4b5ab12012-09-24 16:47:46 -0700441 } else if (wifiNotConnected) {
442 mWifiState.iconId = R.drawable.ic_qs_wifi_0;
Chris Wrendaab6af2012-10-03 15:13:10 -0400443 mWifiState.label = r.getString(R.string.quick_settings_wifi_label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700444 mWifiState.signalContentDescription = r.getString(R.string.accessibility_no_wifi);
Winson Chungf4b5ab12012-09-24 16:47:46 -0700445 } else {
446 mWifiState.iconId = R.drawable.ic_qs_wifi_no_network;
447 mWifiState.label = r.getString(R.string.quick_settings_wifi_off_label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700448 mWifiState.signalContentDescription = r.getString(R.string.accessibility_wifi_off);
Winson Chungf4b5ab12012-09-24 16:47:46 -0700449 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700450 mWifiCallback.refreshView(mWifiTile, mWifiState);
451 }
452
Daniel Sandler50528052012-11-07 23:39:41 -0500453 boolean deviceHasMobileData() {
454 return mHasMobileData;
455 }
456
Winson Chunge641b6a2012-09-10 17:30:27 -0700457 // RSSI
458 void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) {
459 mRSSITile = view;
460 mRSSICallback = cb;
461 mRSSICallback.refreshView(mRSSITile, mRSSIState);
462 }
463 // NetworkSignalChanged callback
464 @Override
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700465 public void onMobileDataSignalChanged(
466 boolean enabled, int mobileSignalIconId, String signalContentDescription,
467 int dataTypeIconId, String dataContentDescription, String enabledDesc) {
Daniel Sandler50528052012-11-07 23:39:41 -0500468 if (deviceHasMobileData()) {
Winson Chung43229d72012-09-12 18:04:18 -0700469 // TODO: If view is in awaiting state, disable
470 Resources r = mContext.getResources();
Winson Chung4f49d942012-09-14 14:01:40 -0700471 mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0)
Winson Chunged1395f2012-09-13 18:13:44 -0700472 ? mobileSignalIconId
473 : R.drawable.ic_qs_signal_no_signal;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700474 mRSSIState.signalContentDescription = enabled && (mobileSignalIconId > 0)
475 ? signalContentDescription
476 : r.getString(R.string.accessibility_no_signal);
Winson Chungc86b23b2012-09-24 11:24:28 -0700477 mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
Winson Chung4f49d942012-09-14 14:01:40 -0700478 ? dataTypeIconId
479 : 0;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700480 mRSSIState.dataContentDescription = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
481 ? dataContentDescription
482 : r.getString(R.string.accessibility_no_data);
Winson Chunged1395f2012-09-13 18:13:44 -0700483 mRSSIState.label = enabled
Winson Chungf4b5ab12012-09-24 16:47:46 -0700484 ? removeTrailingPeriod(enabledDesc)
Winson Chunged1395f2012-09-13 18:13:44 -0700485 : r.getString(R.string.quick_settings_rssi_emergency_only);
Winson Chung43229d72012-09-12 18:04:18 -0700486 mRSSICallback.refreshView(mRSSITile, mRSSIState);
487 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700488 }
489
490 // Bluetooth
491 void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) {
492 mBluetoothTile = view;
493 mBluetoothCallback = cb;
494
495 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Chris Wrenb2a7d272012-10-03 10:16:51 -0400496 mBluetoothState.enabled = adapter.isEnabled();
497 mBluetoothState.connected =
498 (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED);
499 onBluetoothStateChange(mBluetoothState);
Winson Chunge641b6a2012-09-10 17:30:27 -0700500 }
Winson Chung6072b002012-09-11 17:10:10 -0700501 boolean deviceSupportsBluetooth() {
502 return (BluetoothAdapter.getDefaultAdapter() != null);
503 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700504 // BluetoothController callback
505 @Override
506 public void onBluetoothStateChange(boolean on) {
Chris Wrenb2a7d272012-10-03 10:16:51 -0400507 mBluetoothState.enabled = on;
508 onBluetoothStateChange(mBluetoothState);
509 }
510 public void onBluetoothStateChange(BluetoothState bluetoothStateIn) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700511 // TODO: If view is in awaiting state, disable
512 Resources r = mContext.getResources();
Chris Wrenb2a7d272012-10-03 10:16:51 -0400513 mBluetoothState.enabled = bluetoothStateIn.enabled;
514 mBluetoothState.connected = bluetoothStateIn.connected;
515 if (mBluetoothState.enabled) {
516 if (mBluetoothState.connected) {
517 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_on;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700518 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_connected);
Chris Wrenb2a7d272012-10-03 10:16:51 -0400519 } else {
520 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_not_connected;
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700521 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_on);
Chris Wrenb2a7d272012-10-03 10:16:51 -0400522 }
Winson Chung34563e22012-09-21 17:19:49 -0700523 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_label);
Winson Chunge641b6a2012-09-10 17:30:27 -0700524 } else {
Winson Chungeaa5ab02012-09-13 16:36:41 -0700525 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off;
Winson Chung34563e22012-09-21 17:19:49 -0700526 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_off_label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700527 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_off);
Winson Chunge641b6a2012-09-10 17:30:27 -0700528 }
529 mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState);
530 }
Winson Chungefba3232012-09-27 16:56:42 -0700531 void refreshBluetoothTile() {
532 if (mBluetoothTile != null) {
533 onBluetoothStateChange(mBluetoothState.enabled);
534 }
535 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700536
537 // Battery
538 void addBatteryTile(QuickSettingsTileView view, RefreshCallback cb) {
539 mBatteryTile = view;
540 mBatteryCallback = cb;
541 mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
542 }
543 // BatteryController callback
544 @Override
545 public void onBatteryLevelChanged(int level, boolean pluggedIn) {
546 mBatteryState.batteryLevel = level;
547 mBatteryState.pluggedIn = pluggedIn;
548 mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
549 }
Winson Chungefba3232012-09-27 16:56:42 -0700550 void refreshBatteryTile() {
551 mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
552 }
Winson Chunge641b6a2012-09-10 17:30:27 -0700553
554 // Location
555 void addLocationTile(QuickSettingsTileView view, RefreshCallback cb) {
556 mLocationTile = view;
557 mLocationCallback = cb;
558 mLocationCallback.refreshView(mLocationTile, mLocationState);
559 }
560 // LocationController callback
561 @Override
562 public void onLocationGpsStateChanged(boolean inUse, String description) {
563 mLocationState.enabled = inUse;
564 mLocationState.label = description;
565 mLocationCallback.refreshView(mLocationTile, mLocationState);
566 }
567
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400568 // Bug report
569 void addBugreportTile(QuickSettingsTileView view, RefreshCallback cb) {
570 mBugreportTile = view;
571 mBugreportCallback = cb;
572 onBugreportChanged();
573 }
574 // SettingsObserver callback
575 public void onBugreportChanged() {
576 final ContentResolver cr = mContext.getContentResolver();
577 boolean enabled = false;
578 try {
Christopher Tate58f41ec2013-01-11 15:40:36 -0800579 enabled = (Settings.Global.getInt(cr, Settings.Global.BUGREPORT_IN_POWER_MENU) != 0);
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400580 } catch (SettingNotFoundException e) {
581 }
582
Amith Yamasani3df21722013-06-10 13:43:10 -0700583 mBugreportState.enabled = enabled && mUserTracker.isCurrentUserOwner();
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400584 mBugreportCallback.refreshView(mBugreportTile, mBugreportState);
585 }
586
Winson Chunge641b6a2012-09-10 17:30:27 -0700587 // Wifi Display
588 void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) {
589 mWifiDisplayTile = view;
590 mWifiDisplayCallback = cb;
591 }
592 public void onWifiDisplayStateChanged(WifiDisplayStatus status) {
Jeff Brown89d55462012-09-19 11:33:42 -0700593 mWifiDisplayState.enabled =
Winson Chung3ed6f942012-09-20 16:07:11 -0700594 (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON);
Winson Chunge641b6a2012-09-10 17:30:27 -0700595 if (status.getActiveDisplay() != null) {
Jeff Brown89d55462012-09-19 11:33:42 -0700596 mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName();
John Spurlock01e2f4f2012-10-05 17:33:31 -0400597 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display_connected;
Winson Chunge641b6a2012-09-10 17:30:27 -0700598 } else {
599 mWifiDisplayState.label = mContext.getString(
600 R.string.quick_settings_wifi_display_no_connection_label);
John Spurlock01e2f4f2012-10-05 17:33:31 -0400601 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display;
Winson Chunge641b6a2012-09-10 17:30:27 -0700602 }
603 mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState);
604
605 }
606
Winson Chung43229d72012-09-12 18:04:18 -0700607 // IME
608 void addImeTile(QuickSettingsTileView view, RefreshCallback cb) {
609 mImeTile = view;
610 mImeCallback = cb;
611 mImeCallback.refreshView(mImeTile, mImeState);
612 }
Winson Chung34563e22012-09-21 17:19:49 -0700613 /* This implementation is taken from
614 InputMethodManagerService.needsToShowImeSwitchOngoingNotification(). */
615 private boolean needsToShowImeSwitchOngoingNotification(InputMethodManager imm) {
616 List<InputMethodInfo> imis = imm.getEnabledInputMethodList();
617 final int N = imis.size();
618 if (N > 2) return true;
619 if (N < 1) return false;
620 int nonAuxCount = 0;
621 int auxCount = 0;
622 InputMethodSubtype nonAuxSubtype = null;
623 InputMethodSubtype auxSubtype = null;
624 for(int i = 0; i < N; ++i) {
625 final InputMethodInfo imi = imis.get(i);
626 final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(imi,
627 true);
628 final int subtypeCount = subtypes.size();
629 if (subtypeCount == 0) {
630 ++nonAuxCount;
631 } else {
632 for (int j = 0; j < subtypeCount; ++j) {
633 final InputMethodSubtype subtype = subtypes.get(j);
634 if (!subtype.isAuxiliary()) {
635 ++nonAuxCount;
636 nonAuxSubtype = subtype;
637 } else {
638 ++auxCount;
639 auxSubtype = subtype;
640 }
641 }
642 }
643 }
644 if (nonAuxCount > 1 || auxCount > 1) {
645 return true;
646 } else if (nonAuxCount == 1 && auxCount == 1) {
647 if (nonAuxSubtype != null && auxSubtype != null
648 && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
649 || auxSubtype.overridesImplicitlyEnabledSubtype()
650 || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
651 && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
652 return false;
653 }
654 return true;
655 }
656 return false;
657 }
Winson Chung43229d72012-09-12 18:04:18 -0700658 void onImeWindowStatusChanged(boolean visible) {
Winson Chung2a4057d2012-09-12 18:30:06 -0700659 InputMethodManager imm =
660 (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
661 List<InputMethodInfo> imis = imm.getInputMethodList();
662
Winson Chung34563e22012-09-21 17:19:49 -0700663 mImeState.enabled = (visible && needsToShowImeSwitchOngoingNotification(imm));
Winson Chung2a4057d2012-09-12 18:30:06 -0700664 mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(),
665 imm, imis, mContext.getPackageManager());
Daniel Sandleraca0c752012-10-01 12:59:36 -0400666 if (mImeCallback != null) {
667 mImeCallback.refreshView(mImeTile, mImeState);
668 }
Winson Chung43229d72012-09-12 18:04:18 -0700669 }
Winson Chung2a4057d2012-09-12 18:30:06 -0700670 private static String getCurrentInputMethodName(Context context, ContentResolver resolver,
671 InputMethodManager imm, List<InputMethodInfo> imis, PackageManager pm) {
672 if (resolver == null || imis == null) return null;
673 final String currentInputMethodId = Settings.Secure.getString(resolver,
674 Settings.Secure.DEFAULT_INPUT_METHOD);
675 if (TextUtils.isEmpty(currentInputMethodId)) return null;
676 for (InputMethodInfo imi : imis) {
677 if (currentInputMethodId.equals(imi.getId())) {
678 final InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype();
679 final CharSequence summary = subtype != null
680 ? subtype.getDisplayName(context, imi.getPackageName(),
681 imi.getServiceInfo().applicationInfo)
682 : context.getString(R.string.quick_settings_ime_label);
683 return summary.toString();
684 }
685 }
686 return null;
687 }
Winson Chung43229d72012-09-12 18:04:18 -0700688
Winson Chungd4726d02012-09-14 12:27:29 -0700689 // Rotation lock
Svetoslav79578b22013-04-29 16:55:57 -0700690 void addRotationLockTile(QuickSettingsTileView view,
691 RotationLockController rotationLockController,
692 RefreshCallback cb) {
Winson Chungd4726d02012-09-14 12:27:29 -0700693 mRotationLockTile = view;
694 mRotationLockCallback = cb;
Svetoslav79578b22013-04-29 16:55:57 -0700695 mRotationLockController = rotationLockController;
Winson Chungd4726d02012-09-14 12:27:29 -0700696 onRotationLockChanged();
697 }
698 void onRotationLockChanged() {
Svetoslav79578b22013-04-29 16:55:57 -0700699 onRotationLockStateChanged(mRotationLockController.isRotationLocked(),
700 mRotationLockController.isRotationLockAffordanceVisible());
701 }
702 @Override
703 public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
704 mRotationLockState.visible = affordanceVisible;
705 mRotationLockState.enabled = rotationLocked;
706 mRotationLockState.iconId = rotationLocked
Winson Chungd4726d02012-09-14 12:27:29 -0700707 ? R.drawable.ic_qs_rotation_locked
708 : R.drawable.ic_qs_auto_rotate;
Svetoslav79578b22013-04-29 16:55:57 -0700709 mRotationLockState.label = rotationLocked
Winson Chungd4726d02012-09-14 12:27:29 -0700710 ? mContext.getString(R.string.quick_settings_rotation_locked_label)
711 : mContext.getString(R.string.quick_settings_rotation_unlocked_label);
Svetoslav79578b22013-04-29 16:55:57 -0700712 mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
Winson Chungd4726d02012-09-14 12:27:29 -0700713 }
Winson Chungefba3232012-09-27 16:56:42 -0700714 void refreshRotationLockTile() {
715 if (mRotationLockTile != null) {
716 onRotationLockChanged();
717 }
718 }
Winson Chungd4726d02012-09-14 12:27:29 -0700719
Winson Chung5f623012012-09-14 14:58:43 -0700720 // Brightness
721 void addBrightnessTile(QuickSettingsTileView view, RefreshCallback cb) {
722 mBrightnessTile = view;
723 mBrightnessCallback = cb;
724 onBrightnessLevelChanged();
725 }
726 @Override
727 public void onBrightnessLevelChanged() {
Winson Chungefba3232012-09-27 16:56:42 -0700728 Resources r = mContext.getResources();
John Spurlock48f37ec2012-10-05 16:32:51 -0400729 int mode = Settings.System.getIntForUser(mContext.getContentResolver(),
Winson Chung5f623012012-09-14 14:58:43 -0700730 Settings.System.SCREEN_BRIGHTNESS_MODE,
John Spurlock48f37ec2012-10-05 16:32:51 -0400731 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
732 mUserTracker.getCurrentUserId());
Winson Chung5f623012012-09-14 14:58:43 -0700733 mBrightnessState.autoBrightness =
734 (mode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
735 mBrightnessState.iconId = mBrightnessState.autoBrightness
736 ? R.drawable.ic_qs_brightness_auto_on
737 : R.drawable.ic_qs_brightness_auto_off;
Winson Chungefba3232012-09-27 16:56:42 -0700738 mBrightnessState.label = r.getString(R.string.quick_settings_brightness_label);
Winson Chung5f623012012-09-14 14:58:43 -0700739 mBrightnessCallback.refreshView(mBrightnessTile, mBrightnessState);
740 }
Winson Chungefba3232012-09-27 16:56:42 -0700741 void refreshBrightnessTile() {
742 onBrightnessLevelChanged();
743 }
Christopher Tate5e08af02012-09-21 17:17:22 -0700744}