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 17 package com.android.systemui.statusbar.phone; 18 19 import android.bluetooth.BluetoothAdapter; 20 import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback; 21 import android.content.BroadcastReceiver; 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.content.pm.PackageManager; 27 import android.content.res.Resources; 28 import android.database.ContentObserver; 29 import android.graphics.drawable.Drawable; 30 import android.hardware.display.WifiDisplayStatus; 31 import android.net.ConnectivityManager; 32 import android.os.Handler; 33 import android.os.UserHandle; 34 import android.provider.Settings; 35 import android.provider.Settings.SettingNotFoundException; 36 import android.text.TextUtils; 37 import android.view.View; 38 import android.view.inputmethod.InputMethodInfo; 39 import android.view.inputmethod.InputMethodManager; 40 import android.view.inputmethod.InputMethodSubtype; 41 42 import com.android.internal.view.RotationPolicy; 43 import com.android.systemui.R; 44 import com.android.systemui.settings.CurrentUserTracker; 45 import com.android.systemui.settings.BrightnessController.BrightnessStateChangeCallback; 46 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 47 import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback; 48 import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; 49 50 import java.util.List; 51 52 53 class 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 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 123 /** 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( 148 Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this, 149 UserHandle.USER_ALL); 150 } 151 } 152 153 /** 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( 166 Settings.Global.getUriFor(Settings.Global.BUGREPORT_IN_POWER_MENU), false, this); 167 } 168 } 169 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; 199 200 private final boolean mHasMobileData; 201 202 private QuickSettingsTileView mUserTile; 203 private RefreshCallback mUserCallback; 204 private UserState mUserState = new UserState(); 205 206 private QuickSettingsTileView mTimeTile; 207 private RefreshCallback mTimeCallback; 208 private State mTimeState = new State(); 209 210 private QuickSettingsTileView mAlarmTile; 211 private RefreshCallback mAlarmCallback; 212 private State mAlarmState = new State(); 213 214 private QuickSettingsTileView mAirplaneModeTile; 215 private RefreshCallback mAirplaneModeCallback; 216 private State mAirplaneModeState = new State(); 217 218 private QuickSettingsTileView mWifiTile; 219 private RefreshCallback mWifiCallback; 220 private WifiState mWifiState = new WifiState(); 221 222 private QuickSettingsTileView mWifiDisplayTile; 223 private RefreshCallback mWifiDisplayCallback; 224 private State mWifiDisplayState = new State(); 225 226 private QuickSettingsTileView mRSSITile; 227 private RefreshCallback mRSSICallback; 228 private RSSIState mRSSIState = new RSSIState(); 229 230 private QuickSettingsTileView mBluetoothTile; 231 private RefreshCallback mBluetoothCallback; 232 private BluetoothState mBluetoothState = new BluetoothState(); 233 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 242 private QuickSettingsTileView mImeTile; 243 private RefreshCallback mImeCallback = null; 244 private State mImeState = new State(); 245 246 private QuickSettingsTileView mRotationLockTile; 247 private RefreshCallback mRotationLockCallback; 248 private State mRotationLockState = new State(); 249 250 private QuickSettingsTileView mBrightnessTile; 251 private RefreshCallback mBrightnessCallback; 252 private BrightnessState mBrightnessState = new BrightnessState(); 253 254 private QuickSettingsTileView mBugreportTile; 255 private RefreshCallback mBugreportCallback; 256 private State mBugreportState = new State(); 257 258 private QuickSettingsTileView mSettingsTile; 259 private RefreshCallback mSettingsCallback; 260 private State mSettingsState = new State(); 261 262 public QuickSettingsModel(Context context) { 263 mContext = context; 264 mHandler = new Handler(); 265 mUserTracker = new CurrentUserTracker(mContext) { 266 public void onUserSwitched(int newUserId) { 267 mBrightnessObserver.startObserving(); 268 onRotationLockChanged(); 269 onBrightnessLevelChanged(); 270 onNextAlarmChanged(); 271 onBugreportChanged(); 272 } 273 }; 274 275 mNextAlarmObserver = new NextAlarmObserver(mHandler); 276 mNextAlarmObserver.startObserving(); 277 mBugreportObserver = new BugreportObserver(mHandler); 278 mBugreportObserver.startObserving(); 279 mBrightnessObserver = new BrightnessObserver(mHandler); 280 mBrightnessObserver.startObserving(); 281 282 ConnectivityManager cm = (ConnectivityManager) 283 context.getSystemService(Context.CONNECTIVITY_SERVICE); 284 mHasMobileData = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); 285 286 IntentFilter alarmIntentFilter = new IntentFilter(); 287 alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED); 288 context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter); 289 } 290 291 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 311 // User 312 void addUserTile(QuickSettingsTileView view, RefreshCallback cb) { 313 mUserTile = view; 314 mUserCallback = cb; 315 mUserCallback.refreshView(mUserTile, mUserState); 316 } 317 void setUserTileInfo(String name, Drawable avatar) { 318 mUserState.label = name; 319 mUserState.avatar = avatar; 320 mUserCallback.refreshView(mUserTile, mUserState); 321 } 322 323 // Time 324 void addTimeTile(QuickSettingsTileView view, RefreshCallback cb) { 325 mTimeTile = view; 326 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); 335 } 336 void onAlarmChanged(Intent intent) { 337 mAlarmState.enabled = intent.getBooleanExtra("alarmSet", false); 338 mAlarmCallback.refreshView(mAlarmTile, mAlarmState); 339 } 340 void onNextAlarmChanged() { 341 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 350 mAlarmCallback.refreshView(mAlarmTile, mAlarmState); 351 } 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; 367 int airplaneMode = Settings.Global.getInt(mContext.getContentResolver(), 368 Settings.Global.AIRPLANE_MODE_ON, 0); 369 onAirplaneModeChanged(airplaneMode != 0); 370 } 371 private void setAirplaneModeState(boolean enabled) { 372 // TODO: Sets the view to be "awaiting" if not already awaiting 373 374 // Change the system setting 375 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 376 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 ? 390 R.drawable.ic_qs_airplane_on : 391 R.drawable.ic_qs_airplane_off); 392 mAirplaneModeState.label = r.getString(R.string.quick_settings_airplane_mode_label); 393 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 } 402 // 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 } 411 // 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 } 420 // NetworkSignalChanged callback 421 @Override 422 public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, 423 String wifiSignalContentDescription, String enabledDesc) { 424 // TODO: If view is in awaiting state, disable 425 Resources r = mContext.getResources(); 426 427 boolean wifiConnected = enabled && (wifiSignalIconId > 0) && (enabledDesc != null); 428 boolean wifiNotConnected = (wifiSignalIconId > 0) && (enabledDesc == null); 429 mWifiState.enabled = enabled; 430 mWifiState.connected = wifiConnected; 431 if (wifiConnected) { 432 mWifiState.iconId = wifiSignalIconId; 433 mWifiState.label = removeDoubleQuotes(enabledDesc); 434 mWifiState.signalContentDescription = wifiSignalContentDescription; 435 } else if (wifiNotConnected) { 436 mWifiState.iconId = R.drawable.ic_qs_wifi_0; 437 mWifiState.label = r.getString(R.string.quick_settings_wifi_label); 438 mWifiState.signalContentDescription = r.getString(R.string.accessibility_no_wifi); 439 } else { 440 mWifiState.iconId = R.drawable.ic_qs_wifi_no_network; 441 mWifiState.label = r.getString(R.string.quick_settings_wifi_off_label); 442 mWifiState.signalContentDescription = r.getString(R.string.accessibility_wifi_off); 443 } 444 mWifiCallback.refreshView(mWifiTile, mWifiState); 445 } 446 447 boolean deviceHasMobileData() { 448 return mHasMobileData; 449 } 450 451 // 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 459 public void onMobileDataSignalChanged( 460 boolean enabled, int mobileSignalIconId, String signalContentDescription, 461 int dataTypeIconId, String dataContentDescription, String enabledDesc) { 462 if (deviceHasMobileData()) { 463 // TODO: If view is in awaiting state, disable 464 Resources r = mContext.getResources(); 465 mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0) 466 ? mobileSignalIconId 467 : R.drawable.ic_qs_signal_no_signal; 468 mRSSIState.signalContentDescription = enabled && (mobileSignalIconId > 0) 469 ? signalContentDescription 470 : r.getString(R.string.accessibility_no_signal); 471 mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) && !mWifiState.enabled 472 ? dataTypeIconId 473 : 0; 474 mRSSIState.dataContentDescription = enabled && (dataTypeIconId > 0) && !mWifiState.enabled 475 ? dataContentDescription 476 : r.getString(R.string.accessibility_no_data); 477 mRSSIState.label = enabled 478 ? removeTrailingPeriod(enabledDesc) 479 : r.getString(R.string.quick_settings_rssi_emergency_only); 480 mRSSICallback.refreshView(mRSSITile, mRSSIState); 481 } 482 } 483 484 // Bluetooth 485 void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) { 486 mBluetoothTile = view; 487 mBluetoothCallback = cb; 488 489 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 490 mBluetoothState.enabled = adapter.isEnabled(); 491 mBluetoothState.connected = 492 (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED); 493 onBluetoothStateChange(mBluetoothState); 494 } 495 boolean deviceSupportsBluetooth() { 496 return (BluetoothAdapter.getDefaultAdapter() != null); 497 } 498 // BluetoothController callback 499 @Override 500 public void onBluetoothStateChange(boolean on) { 501 mBluetoothState.enabled = on; 502 onBluetoothStateChange(mBluetoothState); 503 } 504 public void onBluetoothStateChange(BluetoothState bluetoothStateIn) { 505 // TODO: If view is in awaiting state, disable 506 Resources r = mContext.getResources(); 507 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; 512 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_connected); 513 } else { 514 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_not_connected; 515 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_on); 516 } 517 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_label); 518 } else { 519 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off; 520 mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_off_label); 521 mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_off); 522 } 523 mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState); 524 } 525 void refreshBluetoothTile() { 526 if (mBluetoothTile != null) { 527 onBluetoothStateChange(mBluetoothState.enabled); 528 } 529 } 530 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 } 544 void refreshBatteryTile() { 545 mBatteryCallback.refreshView(mBatteryTile, mBatteryState); 546 } 547 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 562 // 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 { 573 enabled = (Settings.Global.getInt(cr, Settings.Global.BUGREPORT_IN_POWER_MENU) != 0); 574 } catch (SettingNotFoundException e) { 575 } 576 577 mBugreportState.enabled = enabled; 578 mBugreportCallback.refreshView(mBugreportTile, mBugreportState); 579 } 580 581 // Wifi Display 582 void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) { 583 mWifiDisplayTile = view; 584 mWifiDisplayCallback = cb; 585 } 586 public void onWifiDisplayStateChanged(WifiDisplayStatus status) { 587 mWifiDisplayState.enabled = 588 (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON); 589 if (status.getActiveDisplay() != null) { 590 mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName(); 591 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display_connected; 592 } else { 593 mWifiDisplayState.label = mContext.getString( 594 R.string.quick_settings_wifi_display_no_connection_label); 595 mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display; 596 } 597 mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState); 598 599 } 600 601 // IME 602 void addImeTile(QuickSettingsTileView view, RefreshCallback cb) { 603 mImeTile = view; 604 mImeCallback = cb; 605 mImeCallback.refreshView(mImeTile, mImeState); 606 } 607 /* 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 } 652 void onImeWindowStatusChanged(boolean visible) { 653 InputMethodManager imm = 654 (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); 655 List<InputMethodInfo> imis = imm.getInputMethodList(); 656 657 mImeState.enabled = (visible && needsToShowImeSwitchOngoingNotification(imm)); 658 mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(), 659 imm, imis, mContext.getPackageManager()); 660 if (mImeCallback != null) { 661 mImeCallback.refreshView(mImeTile, mImeState); 662 } 663 } 664 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 } 682 683 // 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); 698 699 // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings 700 if (mRotationLockTile != null && mRotationLockCallback != null) { 701 mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState); 702 } 703 } 704 void refreshRotationLockTile() { 705 if (mRotationLockTile != null) { 706 onRotationLockChanged(); 707 } 708 } 709 710 // Brightness 711 void addBrightnessTile(QuickSettingsTileView view, RefreshCallback cb) { 712 mBrightnessTile = view; 713 mBrightnessCallback = cb; 714 onBrightnessLevelChanged(); 715 } 716 @Override 717 public void onBrightnessLevelChanged() { 718 Resources r = mContext.getResources(); 719 int mode = Settings.System.getIntForUser(mContext.getContentResolver(), 720 Settings.System.SCREEN_BRIGHTNESS_MODE, 721 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 722 mUserTracker.getCurrentUserId()); 723 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; 728 mBrightnessState.label = r.getString(R.string.quick_settings_brightness_label); 729 mBrightnessCallback.refreshView(mBrightnessTile, mBrightnessState); 730 } 731 void refreshBrightnessTile() { 732 onBrightnessLevelChanged(); 733 } 734 } 735