1/* 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.app.ActivityManager; 20import 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; 27import android.content.pm.PackageManager; 28import android.content.res.Resources; 29import android.database.ContentObserver; 30import android.graphics.drawable.Drawable; 31import android.hardware.display.WifiDisplayStatus; 32import android.os.Handler; 33import android.os.UserHandle; 34import android.provider.Settings; 35import android.provider.Settings.SettingNotFoundException; 36import android.text.TextUtils; 37import android.view.View; 38import android.view.inputmethod.InputMethodInfo; 39import android.view.inputmethod.InputMethodManager; 40import android.view.inputmethod.InputMethodSubtype; 41 42import com.android.internal.view.RotationPolicy; 43import com.android.systemui.R; 44import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 45import com.android.systemui.statusbar.policy.BrightnessController.BrightnessStateChangeCallback; 46import com.android.systemui.statusbar.policy.CurrentUserTracker; 47import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback; 48import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; 49 50import java.util.List; 51 52 53class QuickSettingsModel implements BluetoothStateChangeCallback, 54 NetworkSignalChangedCallback, 55 BatteryStateChangeCallback, 56 LocationGpsStateChangeCallback, 57 BrightnessStateChangeCallback { 58 59 // Sett InputMethoManagerService 60 private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher"; 61 62 /** 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 } 72 static class RSSIState extends State { 73 int signalIconId; 74 String signalContentDescription; 75 int dataTypeIconId; 76 String dataContentDescription; 77 } 78 static class WifiState extends State { 79 String signalContentDescription; 80 boolean connected; 81 } 82 static class UserState extends State { 83 Drawable avatar; 84 } 85 static class BrightnessState extends State { 86 boolean autoBrightness; 87 } 88 public static class BluetoothState extends State { 89 boolean connected = false; 90 String stateContentDescription; 91 } 92 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 127 /** 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 } 143 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; 173 174 private QuickSettingsTileView mUserTile; 175 private RefreshCallback mUserCallback; 176 private UserState mUserState = new UserState(); 177 178 private QuickSettingsTileView mTimeTile; 179 private RefreshCallback mTimeCallback; 180 private State mTimeState = new State(); 181 182 private QuickSettingsTileView mAlarmTile; 183 private RefreshCallback mAlarmCallback; 184 private State mAlarmState = new State(); 185 186 private QuickSettingsTileView mAirplaneModeTile; 187 private RefreshCallback mAirplaneModeCallback; 188 private State mAirplaneModeState = new State(); 189 190 private QuickSettingsTileView mWifiTile; 191 private RefreshCallback mWifiCallback; 192 private WifiState mWifiState = new WifiState(); 193 194 private QuickSettingsTileView mWifiDisplayTile; 195 private RefreshCallback mWifiDisplayCallback; 196 private State mWifiDisplayState = new State(); 197 198 private QuickSettingsTileView mRSSITile; 199 private RefreshCallback mRSSICallback; 200 private RSSIState mRSSIState = new RSSIState(); 201 202 private QuickSettingsTileView mBluetoothTile; 203 private RefreshCallback mBluetoothCallback; 204 private BluetoothState mBluetoothState = new BluetoothState(); 205 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 214 private QuickSettingsTileView mImeTile; 215 private RefreshCallback mImeCallback = null; 216 private State mImeState = new State(); 217 218 private QuickSettingsTileView mRotationLockTile; 219 private RefreshCallback mRotationLockCallback; 220 private State mRotationLockState = new State(); 221 222 private QuickSettingsTileView mBrightnessTile; 223 private RefreshCallback mBrightnessCallback; 224 private BrightnessState mBrightnessState = new BrightnessState(); 225 226 private QuickSettingsTileView mBugreportTile; 227 private RefreshCallback mBugreportCallback; 228 private State mBugreportState = new State(); 229 230 private QuickSettingsTileView mSettingsTile; 231 private RefreshCallback mSettingsCallback; 232 private State mSettingsState = new State(); 233 234 public QuickSettingsModel(Context context) { 235 mContext = context; 236 mHandler = new Handler(); 237 mUserTracker = new CurrentUserTracker(mContext) { 238 @Override 239 public void onReceive(Context context, Intent intent) { 240 super.onReceive(context, intent); 241 onUserSwitched(); 242 } 243 }; 244 245 mNextAlarmObserver = new NextAlarmObserver(mHandler); 246 mNextAlarmObserver.startObserving(); 247 mBugreportObserver = new BugreportObserver(mHandler); 248 mBugreportObserver.startObserving(); 249 mBrightnessObserver = new BrightnessObserver(mHandler); 250 mBrightnessObserver.startObserving(); 251 252 IntentFilter alarmIntentFilter = new IntentFilter(); 253 alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED); 254 context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter); 255 } 256 257 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 277 // User 278 void addUserTile(QuickSettingsTileView view, RefreshCallback cb) { 279 mUserTile = view; 280 mUserCallback = cb; 281 mUserCallback.refreshView(mUserTile, mUserState); 282 } 283 void setUserTileInfo(String name, Drawable avatar) { 284 mUserState.label = name; 285 mUserState.avatar = avatar; 286 mUserCallback.refreshView(mUserTile, mUserState); 287 } 288 289 // Time 290 void addTimeTile(QuickSettingsTileView view, RefreshCallback cb) { 291 mTimeTile = view; 292 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); 301 } 302 void onAlarmChanged(Intent intent) { 303 mAlarmState.enabled = intent.getBooleanExtra("alarmSet", false); 304 mAlarmCallback.refreshView(mAlarmTile, mAlarmState); 305 } 306 void onNextAlarmChanged() { 307 mAlarmState.label = Settings.System.getString(mContext.getContentResolver(), 308 Settings.System.NEXT_ALARM_FORMATTED); 309 mAlarmCallback.refreshView(mAlarmTile, mAlarmState); 310 } 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; 326 int airplaneMode = Settings.Global.getInt(mContext.getContentResolver(), 327 Settings.Global.AIRPLANE_MODE_ON, 0); 328 onAirplaneModeChanged(airplaneMode != 0); 329 } 330 private void setAirplaneModeState(boolean enabled) { 331 // TODO: Sets the view to be "awaiting" if not already awaiting 332 333 // Change the system setting 334 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 335 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 ? 349 R.drawable.ic_qs_airplane_on : 350 R.drawable.ic_qs_airplane_off); 351 mAirplaneModeState.label = r.getString(R.string.quick_settings_airplane_mode_label); 352 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 } 361 // 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 } 370 // 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 } 379 // NetworkSignalChanged callback 380 @Override 381 public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, 382 String wifiSignalContentDescription, String enabledDesc) { 383 // TODO: If view is in awaiting state, disable 384 Resources r = mContext.getResources(); 385 386 boolean wifiConnected = enabled && (wifiSignalIconId > 0) && (enabledDesc != null); 387 boolean wifiNotConnected = (wifiSignalIconId > 0) && (enabledDesc == null); 388 mWifiState.enabled = enabled; 389 mWifiState.connected = wifiConnected; 390 if (wifiConnected) { 391 mWifiState.iconId = wifiSignalIconId; 392 mWifiState.label = removeDoubleQuotes(enabledDesc); 393 mWifiState.signalContentDescription = wifiSignalContentDescription; 394 } else if (wifiNotConnected) { 395 mWifiState.iconId = R.drawable.ic_qs_wifi_0; 396 mWifiState.label = r.getString(R.string.quick_settings_wifi_label); 397 mWifiState.signalContentDescription = r.getString(R.string.accessibility_no_wifi); 398 } else { 399 mWifiState.iconId = R.drawable.ic_qs_wifi_no_network; 400 mWifiState.label = r.getString(R.string.quick_settings_wifi_off_label); 401 mWifiState.signalContentDescription = r.getString(R.string.accessibility_wifi_off); 402 } 403 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 } 412 boolean deviceSupportsTelephony() { 413 PackageManager pm = mContext.getPackageManager(); 414 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); 415 } 416 // NetworkSignalChanged callback 417 @Override 418 public void onMobileDataSignalChanged( 419 boolean enabled, int mobileSignalIconId, String signalContentDescription, 420 int dataTypeIconId, String dataContentDescription, String enabledDesc) { 421 if (deviceSupportsTelephony()) { 422 // TODO: If view is in awaiting state, disable 423 Resources r = mContext.getResources(); 424 mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0) 425 ? mobileSignalIconId 426 : R.drawable.ic_qs_signal_no_signal; 427 mRSSIState.signalContentDescription = enabled && (mobileSignalIconId > 0) 428 ? signalContentDescription 429 : r.getString(R.string.accessibility_no_signal); 430 mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) && !mWifiState.enabled 431 ? dataTypeIconId 432 : 0; 433 mRSSIState.dataContentDescription = enabled && (dataTypeIconId > 0) && !mWifiState.enabled 434 ? dataContentDescription 435 : r.getString(R.string.accessibility_no_data); 436 mRSSIState.label = enabled 437 ? removeTrailingPeriod(enabledDesc) 438 : r.getString(R.string.quick_settings_rssi_emergency_only); 439 mRSSICallback.refreshView(mRSSITile, mRSSIState); 440 } 441 } 442 443 // Bluetooth 444 void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) { 445 mBluetoothTile = view; 446 mBluetoothCallback = cb; 447 448 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 449 mBluetoothState.enabled = adapter.isEnabled(); 450 mBluetoothState.connected = 451 (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED); 452 onBluetoothStateChange(mBluetoothState); 453 } 454 boolean deviceSupportsBluetooth() { 455 return (BluetoothAdapter.getDefaultAdapter() != null); 456 } 457 // BluetoothController callback 458 @Override 459 public void onBluetoothStateChange(boolean on) { 460 mBluetoothState.enabled = on; 461 onBluetoothStateChange(mBluetoothState); 462 } 463 public void onBluetoothStateChange(BluetoothState bluetoothStateIn) { 464 // TODO: If view is in awaiting state, disable 465 Resources r = mContext.getResources(); 466 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; 471 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_connected); 472 } else { 473 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_not_connected; 474 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_on); 475 } 476 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_label); 477 } else { 478 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off; 479 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_off_label); 480 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_off); 481 } 482 mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState); 483 } 484 void refreshBluetoothTile() { 485 if (mBluetoothTile != null) { 486 onBluetoothStateChange(mBluetoothState.enabled); 487 } 488 } 489 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 } 503 void refreshBatteryTile() { 504 mBatteryCallback.refreshView(mBatteryTile, mBatteryState); 505 } 506 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 521 // 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 540 // Wifi Display 541 void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) { 542 mWifiDisplayTile = view; 543 mWifiDisplayCallback = cb; 544 } 545 public void onWifiDisplayStateChanged(WifiDisplayStatus status) { 546 mWifiDisplayState.enabled = 547 (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON); 548 if (status.getActiveDisplay() != null) { 549 mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName(); 550 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display_connected; 551 } else { 552 mWifiDisplayState.label = mContext.getString( 553 R.string.quick_settings_wifi_display_no_connection_label); 554 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display; 555 } 556 mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState); 557 558 } 559 560 // IME 561 void addImeTile(QuickSettingsTileView view, RefreshCallback cb) { 562 mImeTile = view; 563 mImeCallback = cb; 564 mImeCallback.refreshView(mImeTile, mImeState); 565 } 566 /* 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 } 611 void onImeWindowStatusChanged(boolean visible) { 612 InputMethodManager imm = 613 (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); 614 List<InputMethodInfo> imis = imm.getInputMethodList(); 615 616 mImeState.enabled = (visible && needsToShowImeSwitchOngoingNotification(imm)); 617 mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(), 618 imm, imis, mContext.getPackageManager()); 619 if (mImeCallback != null) { 620 mImeCallback.refreshView(mImeTile, mImeState); 621 } 622 } 623 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 } 641 642 // 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); 657 658 // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings 659 if (mRotationLockTile != null && mRotationLockCallback != null) { 660 mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState); 661 } 662 } 663 void refreshRotationLockTile() { 664 if (mRotationLockTile != null) { 665 onRotationLockChanged(); 666 } 667 } 668 669 // Brightness 670 void addBrightnessTile(QuickSettingsTileView view, RefreshCallback cb) { 671 mBrightnessTile = view; 672 mBrightnessCallback = cb; 673 onBrightnessLevelChanged(); 674 } 675 @Override 676 public void onBrightnessLevelChanged() { 677 Resources r = mContext.getResources(); 678 int mode = Settings.System.getIntForUser(mContext.getContentResolver(), 679 Settings.System.SCREEN_BRIGHTNESS_MODE, 680 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 681 mUserTracker.getCurrentUserId()); 682 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; 687 mBrightnessState.label = r.getString(R.string.quick_settings_brightness_label); 688 mBrightnessCallback.refreshView(mBrightnessTile, mBrightnessState); 689 } 690 void refreshBrightnessTile() { 691 onBrightnessLevelChanged(); 692 } 693 694 // User switch: need to update visuals of all tiles known to have per-user state 695 void onUserSwitched() { 696 mBrightnessObserver.startObserving(); 697 onRotationLockChanged(); 698 onBrightnessLevelChanged(); 699 onNextAlarmChanged(); 700 onBugreportChanged(); 701 } 702} 703