QuickSettingsModel.java revision 3ed6f9456a60cb3a2cf4166a7fa19e30b9bbd972
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.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; 26import android.content.pm.PackageManager; 27import android.content.res.Resources; 28import android.database.ContentObserver; 29import android.graphics.drawable.Drawable; 30import android.hardware.display.WifiDisplayStatus; 31import android.os.Handler; 32import android.provider.Settings; 33import android.provider.Settings.SettingNotFoundException; 34import android.text.TextUtils; 35import android.view.View; 36import android.view.inputmethod.InputMethodInfo; 37import android.view.inputmethod.InputMethodManager; 38import android.view.inputmethod.InputMethodSubtype; 39 40import com.android.internal.view.RotationPolicy; 41import com.android.systemui.R; 42import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 43import com.android.systemui.statusbar.policy.BrightnessController.BrightnessStateChangeCallback; 44import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback; 45import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; 46 47import java.util.List; 48 49 50class QuickSettingsModel implements BluetoothStateChangeCallback, 51 NetworkSignalChangedCallback, 52 BatteryStateChangeCallback, 53 LocationGpsStateChangeCallback, 54 BrightnessStateChangeCallback { 55 56 /** Represents the state of a given attribute. */ 57 static class State { 58 int iconId; 59 String label; 60 boolean enabled = false; 61 } 62 static class BatteryState extends State { 63 int batteryLevel; 64 boolean pluggedIn; 65 } 66 static class RSSIState extends State { 67 int signalIconId; 68 int dataTypeIconId; 69 } 70 static class UserState extends State { 71 Drawable avatar; 72 } 73 static class BrightnessState extends State { 74 boolean autoBrightness; 75 } 76 77 /** The callback to update a given tile. */ 78 interface RefreshCallback { 79 public void refreshView(QuickSettingsTileView view, State state); 80 } 81 82 /** Broadcast receive to determine if there is an alarm set. */ 83 private BroadcastReceiver mAlarmIntentReceiver = new BroadcastReceiver() { 84 @Override 85 public void onReceive(Context context, Intent intent) { 86 String action = intent.getAction(); 87 if (action.equals(Intent.ACTION_ALARM_CHANGED)) { 88 onAlarmChanged(intent); 89 onNextAlarmChanged(); 90 } 91 } 92 }; 93 94 /** ContentObserver to determine the next alarm */ 95 private class NextAlarmObserver extends ContentObserver { 96 public NextAlarmObserver(Handler handler) { 97 super(handler); 98 } 99 100 @Override public void onChange(boolean selfChange) { 101 onNextAlarmChanged(); 102 } 103 104 public void startObserving() { 105 final ContentResolver cr = mContext.getContentResolver(); 106 cr.registerContentObserver( 107 Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this); 108 } 109 } 110 111 /** ContentObserver to watch adb */ 112 private class BugreportObserver extends ContentObserver { 113 public BugreportObserver(Handler handler) { 114 super(handler); 115 } 116 117 @Override public void onChange(boolean selfChange) { 118 onBugreportChanged(); 119 } 120 121 public void startObserving() { 122 final ContentResolver cr = mContext.getContentResolver(); 123 cr.registerContentObserver( 124 Settings.Secure.getUriFor(Settings.Secure.BUGREPORT_IN_POWER_MENU), false, this); 125 } 126 } 127 private Context mContext; 128 private Handler mHandler; 129 private NextAlarmObserver mNextAlarmObserver; 130 private BugreportObserver mBugreportObserver; 131 132 private QuickSettingsTileView mUserTile; 133 private RefreshCallback mUserCallback; 134 private UserState mUserState = new UserState(); 135 136 private QuickSettingsTileView mTimeTile; 137 private RefreshCallback mTimeAlarmCallback; 138 private State mTimeAlarmState = new State(); 139 140 private QuickSettingsTileView mAirplaneModeTile; 141 private RefreshCallback mAirplaneModeCallback; 142 private State mAirplaneModeState = new State(); 143 144 private QuickSettingsTileView mWifiTile; 145 private RefreshCallback mWifiCallback; 146 private State mWifiState = new State(); 147 148 private QuickSettingsTileView mWifiDisplayTile; 149 private RefreshCallback mWifiDisplayCallback; 150 private State mWifiDisplayState = new State(); 151 152 private QuickSettingsTileView mRSSITile; 153 private RefreshCallback mRSSICallback; 154 private RSSIState mRSSIState = new RSSIState(); 155 156 private QuickSettingsTileView mBluetoothTile; 157 private RefreshCallback mBluetoothCallback; 158 private State mBluetoothState = new State(); 159 160 private QuickSettingsTileView mBatteryTile; 161 private RefreshCallback mBatteryCallback; 162 private BatteryState mBatteryState = new BatteryState(); 163 164 private QuickSettingsTileView mLocationTile; 165 private RefreshCallback mLocationCallback; 166 private State mLocationState = new State(); 167 168 private QuickSettingsTileView mImeTile; 169 private RefreshCallback mImeCallback; 170 private State mImeState = new State(); 171 172 private QuickSettingsTileView mRotationLockTile; 173 private RefreshCallback mRotationLockCallback; 174 private State mRotationLockState = new State(); 175 176 private QuickSettingsTileView mBrightnessTile; 177 private RefreshCallback mBrightnessCallback; 178 private BrightnessState mBrightnessState = new BrightnessState(); 179 180 private QuickSettingsTileView mBugreportTile; 181 private RefreshCallback mBugreportCallback; 182 private State mBugreportState = new State(); 183 184 public QuickSettingsModel(Context context) { 185 mContext = context; 186 mHandler = new Handler(); 187 mNextAlarmObserver = new NextAlarmObserver(mHandler); 188 mNextAlarmObserver.startObserving(); 189 mBugreportObserver = new BugreportObserver(mHandler); 190 mBugreportObserver.startObserving(); 191 192 IntentFilter alarmIntentFilter = new IntentFilter(); 193 alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED); 194 context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter); 195 } 196 197 // User 198 void addUserTile(QuickSettingsTileView view, RefreshCallback cb) { 199 mUserTile = view; 200 mUserCallback = cb; 201 mUserCallback.refreshView(mUserTile, mUserState); 202 } 203 void setUserTileInfo(String name, Drawable avatar) { 204 mUserState.label = name; 205 mUserState.avatar = avatar; 206 mUserCallback.refreshView(mUserTile, mUserState); 207 } 208 209 // Time 210 void addTimeTile(QuickSettingsTileView view, RefreshCallback cb) { 211 mTimeTile = view; 212 mTimeAlarmCallback = cb; 213 mTimeAlarmCallback.refreshView(view, mTimeAlarmState); 214 } 215 void onAlarmChanged(Intent intent) { 216 mTimeAlarmState.enabled = intent.getBooleanExtra("alarmSet", false); 217 mTimeAlarmCallback.refreshView(mTimeTile, mTimeAlarmState); 218 } 219 void onNextAlarmChanged() { 220 mTimeAlarmState.label = Settings.System.getString(mContext.getContentResolver(), 221 Settings.System.NEXT_ALARM_FORMATTED); 222 mTimeAlarmCallback.refreshView(mTimeTile, mTimeAlarmState); 223 } 224 225 // Airplane Mode 226 void addAirplaneModeTile(QuickSettingsTileView view, RefreshCallback cb) { 227 mAirplaneModeTile = view; 228 mAirplaneModeTile.setOnClickListener(new View.OnClickListener() { 229 @Override 230 public void onClick(View v) { 231 if (mAirplaneModeState.enabled) { 232 setAirplaneModeState(false); 233 } else { 234 setAirplaneModeState(true); 235 } 236 } 237 }); 238 mAirplaneModeCallback = cb; 239 mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState); 240 } 241 private void setAirplaneModeState(boolean enabled) { 242 // TODO: Sets the view to be "awaiting" if not already awaiting 243 244 // Change the system setting 245 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 246 enabled ? 1 : 0); 247 248 // Post the intent 249 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 250 intent.putExtra("state", enabled); 251 mContext.sendBroadcast(intent); 252 } 253 // NetworkSignalChanged callback 254 @Override 255 public void onAirplaneModeChanged(boolean enabled) { 256 // TODO: If view is in awaiting state, disable 257 Resources r = mContext.getResources(); 258 mAirplaneModeState.enabled = enabled; 259 mAirplaneModeState.iconId = (enabled ? 260 R.drawable.ic_qs_airplane_on : 261 R.drawable.ic_qs_airplane_off); 262 mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState); 263 } 264 265 // Wifi 266 void addWifiTile(QuickSettingsTileView view, RefreshCallback cb) { 267 mWifiTile = view; 268 mWifiCallback = cb; 269 mWifiCallback.refreshView(mWifiTile, mWifiState); 270 } 271 // NetworkSignalChanged callback 272 @Override 273 public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, String enabledDesc) { 274 // TODO: If view is in awaiting state, disable 275 Resources r = mContext.getResources(); 276 mWifiState.iconId = enabled && (wifiSignalIconId > 0) 277 ? wifiSignalIconId 278 : R.drawable.ic_qs_wifi_no_network; 279 mWifiState.label = enabled 280 ? enabledDesc 281 : r.getString(R.string.quick_settings_wifi_no_network); 282 mWifiCallback.refreshView(mWifiTile, mWifiState); 283 } 284 285 // RSSI 286 void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) { 287 mRSSITile = view; 288 mRSSICallback = cb; 289 mRSSICallback.refreshView(mRSSITile, mRSSIState); 290 } 291 boolean deviceSupportsTelephony() { 292 PackageManager pm = mContext.getPackageManager(); 293 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); 294 } 295 // NetworkSignalChanged callback 296 @Override 297 public void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId, 298 int dataTypeIconId, String enabledDesc) { 299 if (deviceSupportsTelephony()) { 300 // TODO: If view is in awaiting state, disable 301 Resources r = mContext.getResources(); 302 mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0) 303 ? mobileSignalIconId 304 : R.drawable.ic_qs_signal_no_signal; 305 mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) 306 ? dataTypeIconId 307 : 0; 308 mRSSIState.label = enabled 309 ? enabledDesc 310 : r.getString(R.string.quick_settings_rssi_emergency_only); 311 mRSSICallback.refreshView(mRSSITile, mRSSIState); 312 } 313 } 314 315 // Bluetooth 316 void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) { 317 mBluetoothTile = view; 318 mBluetoothCallback = cb; 319 320 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 321 onBluetoothStateChange(adapter.isEnabled()); 322 } 323 boolean deviceSupportsBluetooth() { 324 return (BluetoothAdapter.getDefaultAdapter() != null); 325 } 326 // BluetoothController callback 327 @Override 328 public void onBluetoothStateChange(boolean on) { 329 // TODO: If view is in awaiting state, disable 330 Resources r = mContext.getResources(); 331 mBluetoothState.enabled = on; 332 if (on) { 333 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_on; 334 } else { 335 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off; 336 } 337 mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState); 338 } 339 340 // Battery 341 void addBatteryTile(QuickSettingsTileView view, RefreshCallback cb) { 342 mBatteryTile = view; 343 mBatteryCallback = cb; 344 mBatteryCallback.refreshView(mBatteryTile, mBatteryState); 345 } 346 // BatteryController callback 347 @Override 348 public void onBatteryLevelChanged(int level, boolean pluggedIn) { 349 mBatteryState.batteryLevel = level; 350 mBatteryState.pluggedIn = pluggedIn; 351 mBatteryCallback.refreshView(mBatteryTile, mBatteryState); 352 } 353 354 // Location 355 void addLocationTile(QuickSettingsTileView view, RefreshCallback cb) { 356 mLocationTile = view; 357 mLocationCallback = cb; 358 mLocationCallback.refreshView(mLocationTile, mLocationState); 359 } 360 // LocationController callback 361 @Override 362 public void onLocationGpsStateChanged(boolean inUse, String description) { 363 mLocationState.enabled = inUse; 364 mLocationState.label = description; 365 mLocationCallback.refreshView(mLocationTile, mLocationState); 366 } 367 368 // Bug report 369 void addBugreportTile(QuickSettingsTileView view, RefreshCallback cb) { 370 mBugreportTile = view; 371 mBugreportCallback = cb; 372 onBugreportChanged(); 373 } 374 // SettingsObserver callback 375 public void onBugreportChanged() { 376 final ContentResolver cr = mContext.getContentResolver(); 377 boolean enabled = false; 378 try { 379 enabled = (Settings.Secure.getInt(cr, Settings.Secure.BUGREPORT_IN_POWER_MENU) != 0); 380 } catch (SettingNotFoundException e) { 381 } 382 383 mBugreportState.enabled = enabled; 384 mBugreportCallback.refreshView(mBugreportTile, mBugreportState); 385 } 386 387 // Wifi Display 388 void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) { 389 mWifiDisplayTile = view; 390 mWifiDisplayCallback = cb; 391 } 392 public void onWifiDisplayStateChanged(WifiDisplayStatus status) { 393 mWifiDisplayState.enabled = 394 (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON); 395 if (status.getActiveDisplay() != null) { 396 mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName(); 397 } else { 398 mWifiDisplayState.label = mContext.getString( 399 R.string.quick_settings_wifi_display_no_connection_label); 400 } 401 mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState); 402 403 } 404 405 // IME 406 void addImeTile(QuickSettingsTileView view, RefreshCallback cb) { 407 mImeTile = view; 408 mImeCallback = cb; 409 mImeCallback.refreshView(mImeTile, mImeState); 410 } 411 void onImeWindowStatusChanged(boolean visible) { 412 InputMethodManager imm = 413 (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); 414 List<InputMethodInfo> imis = imm.getInputMethodList(); 415 416 mImeState.enabled = visible; 417 mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(), 418 imm, imis, mContext.getPackageManager()); 419 mImeCallback.refreshView(mImeTile, mImeState); 420 } 421 private static String getCurrentInputMethodName(Context context, ContentResolver resolver, 422 InputMethodManager imm, List<InputMethodInfo> imis, PackageManager pm) { 423 if (resolver == null || imis == null) return null; 424 final String currentInputMethodId = Settings.Secure.getString(resolver, 425 Settings.Secure.DEFAULT_INPUT_METHOD); 426 if (TextUtils.isEmpty(currentInputMethodId)) return null; 427 for (InputMethodInfo imi : imis) { 428 if (currentInputMethodId.equals(imi.getId())) { 429 final InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype(); 430 final CharSequence summary = subtype != null 431 ? subtype.getDisplayName(context, imi.getPackageName(), 432 imi.getServiceInfo().applicationInfo) 433 : context.getString(R.string.quick_settings_ime_label); 434 return summary.toString(); 435 } 436 } 437 return null; 438 } 439 440 // Rotation lock 441 void addRotationLockTile(QuickSettingsTileView view, RefreshCallback cb) { 442 mRotationLockTile = view; 443 mRotationLockCallback = cb; 444 onRotationLockChanged(); 445 } 446 void onRotationLockChanged() { 447 boolean locked = RotationPolicy.isRotationLocked(mContext); 448 mRotationLockState.enabled = locked; 449 mRotationLockState.iconId = locked 450 ? R.drawable.ic_qs_rotation_locked 451 : R.drawable.ic_qs_auto_rotate; 452 mRotationLockState.label = locked 453 ? mContext.getString(R.string.quick_settings_rotation_locked_label) 454 : mContext.getString(R.string.quick_settings_rotation_unlocked_label); 455 456 // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings 457 if (mRotationLockTile != null && mRotationLockCallback != null) { 458 mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState); 459 } 460 } 461 462 // Brightness 463 void addBrightnessTile(QuickSettingsTileView view, RefreshCallback cb) { 464 mBrightnessTile = view; 465 mBrightnessCallback = cb; 466 onBrightnessLevelChanged(); 467 } 468 @Override 469 public void onBrightnessLevelChanged() { 470 int mode = Settings.System.getInt(mContext.getContentResolver(), 471 Settings.System.SCREEN_BRIGHTNESS_MODE, 472 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); 473 mBrightnessState.autoBrightness = 474 (mode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); 475 mBrightnessState.iconId = mBrightnessState.autoBrightness 476 ? R.drawable.ic_qs_brightness_auto_on 477 : R.drawable.ic_qs_brightness_auto_off; 478 mBrightnessCallback.refreshView(mBrightnessTile, mBrightnessState); 479 } 480 481}