QuickSettings.java revision f7614fc7442e9cf2df89d4230af3f56f03a74c6e
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 com.android.internal.view.RotationPolicy; 20import com.android.internal.widget.LockPatternUtils; 21import com.android.systemui.R; 22 23import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState; 24import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState; 25import com.android.systemui.statusbar.phone.QuickSettingsModel.State; 26import com.android.systemui.statusbar.phone.QuickSettingsModel.UserState; 27import com.android.systemui.statusbar.phone.QuickSettingsModel.WifiState; 28import com.android.systemui.statusbar.policy.BatteryController; 29import com.android.systemui.statusbar.policy.BluetoothController; 30import com.android.systemui.statusbar.policy.BrightnessController; 31import com.android.systemui.statusbar.policy.LocationController; 32import com.android.systemui.statusbar.policy.NetworkController; 33import com.android.systemui.statusbar.policy.ToggleSlider; 34 35import android.app.ActivityManagerNative; 36import android.app.AlertDialog; 37import android.app.Dialog; 38import android.app.PendingIntent; 39import android.bluetooth.BluetoothAdapter; 40import android.content.BroadcastReceiver; 41import android.content.ComponentName; 42import android.content.Context; 43import android.content.CursorLoader; 44import android.content.DialogInterface; 45import android.content.DialogInterface.OnClickListener; 46import android.content.Intent; 47import android.content.IntentFilter; 48import android.content.pm.PackageManager.NameNotFoundException; 49import android.content.pm.UserInfo; 50import android.content.res.Resources; 51import android.database.Cursor; 52import android.graphics.Bitmap; 53import android.graphics.drawable.BitmapDrawable; 54import android.graphics.drawable.Drawable; 55import android.graphics.drawable.LevelListDrawable; 56import android.hardware.display.DisplayManager; 57import android.hardware.display.WifiDisplayStatus; 58import android.net.wifi.WifiManager; 59import android.os.AsyncTask; 60import android.os.Handler; 61import android.os.RemoteException; 62import android.os.UserHandle; 63import android.os.UserManager; 64import android.provider.ContactsContract; 65import android.provider.ContactsContract.CommonDataKinds.Phone; 66import android.provider.ContactsContract.Profile; 67import android.provider.Settings; 68import android.util.Log; 69import android.util.Pair; 70import android.view.LayoutInflater; 71import android.view.View; 72import android.view.ViewGroup; 73import android.view.Window; 74import android.view.WindowManager; 75import android.view.WindowManagerGlobal; 76import android.widget.ImageView; 77import android.widget.TextView; 78 79import java.util.ArrayList; 80 81 82/** 83 * 84 */ 85class QuickSettings { 86 private static final String TAG = "QuickSettings"; 87 public static final boolean SHOW_IME_TILE = false; 88 89 public static final boolean LONG_PRESS_TOGGLES = true; 90 91 private Context mContext; 92 private PanelBar mBar; 93 private QuickSettingsModel mModel; 94 private ViewGroup mContainerView; 95 96 private DisplayManager mDisplayManager; 97 private WifiDisplayStatus mWifiDisplayStatus; 98 private PhoneStatusBar mStatusBarService; 99 private BluetoothState mBluetoothState; 100 private BluetoothAdapter mBluetoothAdapter; 101 private WifiManager mWifiManager; 102 103 private BrightnessController mBrightnessController; 104 private BluetoothController mBluetoothController; 105 106 private Dialog mBrightnessDialog; 107 private int mBrightnessDialogShortTimeout; 108 private int mBrightnessDialogLongTimeout; 109 110 private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask; 111 112 private LevelListDrawable mBatteryLevels; 113 private LevelListDrawable mChargingBatteryLevels; 114 115 boolean mTilesSetUp = false; 116 117 private Handler mHandler; 118 119 // The set of QuickSettingsTiles that have dynamic spans (and need to be updated on 120 // configuration change) 121 private final ArrayList<QuickSettingsTileView> mDynamicSpannedTiles = 122 new ArrayList<QuickSettingsTileView>(); 123 124 private final RotationPolicy.RotationPolicyListener mRotationPolicyListener = 125 new RotationPolicy.RotationPolicyListener() { 126 @Override 127 public void onChange() { 128 mModel.onRotationLockChanged(); 129 } 130 }; 131 132 public QuickSettings(Context context, QuickSettingsContainerView container) { 133 mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); 134 mContext = context; 135 mContainerView = container; 136 mModel = new QuickSettingsModel(context); 137 mWifiDisplayStatus = new WifiDisplayStatus(); 138 mBluetoothState = new QuickSettingsModel.BluetoothState(); 139 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 140 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 141 142 mHandler = new Handler(); 143 144 Resources r = mContext.getResources(); 145 mBatteryLevels = (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery); 146 mChargingBatteryLevels = 147 (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery_charging); 148 mBrightnessDialogLongTimeout = 149 r.getInteger(R.integer.quick_settings_brightness_dialog_long_timeout); 150 mBrightnessDialogShortTimeout = 151 r.getInteger(R.integer.quick_settings_brightness_dialog_short_timeout); 152 153 IntentFilter filter = new IntentFilter(); 154 filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 155 filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 156 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 157 filter.addAction(Intent.ACTION_USER_SWITCHED); 158 mContext.registerReceiver(mReceiver, filter); 159 160 IntentFilter profileFilter = new IntentFilter(); 161 profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED); 162 profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED); 163 mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter, 164 null, null); 165 } 166 167 void setBar(PanelBar bar) { 168 mBar = bar; 169 } 170 171 public void setService(PhoneStatusBar phoneStatusBar) { 172 mStatusBarService = phoneStatusBar; 173 } 174 175 public PhoneStatusBar getService() { 176 return mStatusBarService; 177 } 178 179 public void setImeWindowStatus(boolean visible) { 180 mModel.onImeWindowStatusChanged(visible); 181 } 182 183 void setup(NetworkController networkController, BluetoothController bluetoothController, 184 BatteryController batteryController, LocationController locationController) { 185 mBluetoothController = bluetoothController; 186 187 setupQuickSettings(); 188 updateWifiDisplayStatus(); 189 updateResources(); 190 191 networkController.addNetworkSignalChangedCallback(mModel); 192 bluetoothController.addStateChangedCallback(mModel); 193 batteryController.addStateChangedCallback(mModel); 194 locationController.addStateChangedCallback(mModel); 195 RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener, 196 UserHandle.USER_ALL); 197 } 198 199 private void queryForUserInformation() { 200 Context currentUserContext = null; 201 UserInfo userInfo = null; 202 try { 203 userInfo = ActivityManagerNative.getDefault().getCurrentUser(); 204 currentUserContext = mContext.createPackageContextAsUser("android", 0, 205 new UserHandle(userInfo.id)); 206 } catch (NameNotFoundException e) { 207 Log.e(TAG, "Couldn't create user context", e); 208 throw new RuntimeException(e); 209 } catch (RemoteException e) { 210 Log.e(TAG, "Couldn't get user info", e); 211 } 212 final int userId = userInfo.id; 213 final String userName = userInfo.name; 214 215 final Context context = currentUserContext; 216 mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() { 217 @Override 218 protected Pair<String, Drawable> doInBackground(Void... params) { 219 final UserManager um = 220 (UserManager) mContext.getSystemService(Context.USER_SERVICE); 221 222 // Fall back to the UserManager nickname if we can't read the name from the local 223 // profile below. 224 String name = userName; 225 Drawable avatar = null; 226 Bitmap rawAvatar = um.getUserIcon(userId); 227 if (rawAvatar != null) { 228 avatar = new BitmapDrawable(mContext.getResources(), rawAvatar); 229 } else { 230 avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user); 231 } 232 233 // If it's a single-user device, get the profile name, since the nickname is not 234 // usually valid 235 if (um.getUsers().size() <= 1) { 236 // Try and read the display name from the local profile 237 final Cursor cursor = context.getContentResolver().query( 238 Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME}, 239 null, null, null); 240 if (cursor != null) { 241 try { 242 if (cursor.moveToFirst()) { 243 name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME)); 244 } 245 } finally { 246 cursor.close(); 247 } 248 } 249 } 250 return new Pair<String, Drawable>(name, avatar); 251 } 252 253 @Override 254 protected void onPostExecute(Pair<String, Drawable> result) { 255 super.onPostExecute(result); 256 mModel.setUserTileInfo(result.first, result.second); 257 mUserInfoTask = null; 258 } 259 }; 260 mUserInfoTask.execute(); 261 } 262 263 private void setupQuickSettings() { 264 // Setup the tiles that we are going to be showing (including the temporary ones) 265 LayoutInflater inflater = LayoutInflater.from(mContext); 266 267 addUserTiles(mContainerView, inflater); 268 addSystemTiles(mContainerView, inflater); 269 addTemporaryTiles(mContainerView, inflater); 270 271 queryForUserInformation(); 272 mTilesSetUp = true; 273 } 274 275 private void startSettingsActivity(String action) { 276 Intent intent = new Intent(action); 277 startSettingsActivity(intent); 278 } 279 280 private void startSettingsActivity(Intent intent) { 281 startSettingsActivity(intent, true); 282 } 283 284 private void startSettingsActivity(Intent intent, boolean onlyProvisioned) { 285 if (onlyProvisioned && !getService().isDeviceProvisioned()) return; 286 try { 287 // Dismiss the lock screen when Settings starts. 288 ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); 289 } catch (RemoteException e) { 290 } 291 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 292 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 293 getService().animateCollapsePanels(); 294 } 295 296 private void addUserTiles(ViewGroup parent, LayoutInflater inflater) { 297 QuickSettingsTileView userTile = (QuickSettingsTileView) 298 inflater.inflate(R.layout.quick_settings_tile, parent, false); 299 userTile.setContent(R.layout.quick_settings_tile_user, inflater); 300 userTile.setOnClickListener(new View.OnClickListener() { 301 @Override 302 public void onClick(View v) { 303 mBar.collapseAllPanels(true); 304 final UserManager um = 305 (UserManager) mContext.getSystemService(Context.USER_SERVICE); 306 if (um.getUsers(true).size() > 1) { 307 try { 308 WindowManagerGlobal.getWindowManagerService().lockNow(null); 309 } catch (RemoteException e) { 310 Log.e(TAG, "Couldn't show user switcher", e); 311 } 312 } else { 313 Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent( 314 mContext, v, ContactsContract.Profile.CONTENT_URI, 315 ContactsContract.QuickContact.MODE_LARGE, null); 316 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 317 } 318 } 319 }); 320 mModel.addUserTile(userTile, new QuickSettingsModel.RefreshCallback() { 321 @Override 322 public void refreshView(QuickSettingsTileView view, State state) { 323 UserState us = (UserState) state; 324 ImageView iv = (ImageView) view.findViewById(R.id.user_imageview); 325 TextView tv = (TextView) view.findViewById(R.id.user_textview); 326 tv.setText(state.label); 327 iv.setImageDrawable(us.avatar); 328 view.setContentDescription(mContext.getString( 329 R.string.accessibility_quick_settings_user, state.label)); 330 } 331 }); 332 parent.addView(userTile); 333 mDynamicSpannedTiles.add(userTile); 334 335 // Brightness 336 QuickSettingsTileView brightnessTile = (QuickSettingsTileView) 337 inflater.inflate(R.layout.quick_settings_tile, parent, false); 338 brightnessTile.setContent(R.layout.quick_settings_tile_brightness, inflater); 339 brightnessTile.setOnClickListener(new View.OnClickListener() { 340 @Override 341 public void onClick(View v) { 342 mBar.collapseAllPanels(true); 343 showBrightnessDialog(); 344 } 345 }); 346 mModel.addBrightnessTile(brightnessTile, new QuickSettingsModel.RefreshCallback() { 347 @Override 348 public void refreshView(QuickSettingsTileView view, State state) { 349 TextView tv = (TextView) view.findViewById(R.id.brightness_textview); 350 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0); 351 tv.setText(state.label); 352 dismissBrightnessDialog(mBrightnessDialogShortTimeout); 353 } 354 }); 355 parent.addView(brightnessTile); 356 mDynamicSpannedTiles.add(brightnessTile); 357 358 // Time tile 359 /* 360 QuickSettingsTileView timeTile = (QuickSettingsTileView) 361 inflater.inflate(R.layout.quick_settings_tile, parent, false); 362 timeTile.setContent(R.layout.quick_settings_tile_time, inflater); 363 timeTile.setOnClickListener(new View.OnClickListener() { 364 @Override 365 public void onClick(View v) { 366 // Quick. Clock. Quick. Clock. Quick. Clock. 367 startSettingsActivity(Intent.ACTION_QUICK_CLOCK); 368 } 369 }); 370 mModel.addTimeTile(timeTile, new QuickSettingsModel.RefreshCallback() { 371 @Override 372 public void refreshView(QuickSettingsTileView view, State alarmState) {} 373 }); 374 parent.addView(timeTile); 375 mDynamicSpannedTiles.add(timeTile); 376 */ 377 378 // Settings tile 379 QuickSettingsTileView settingsTile = (QuickSettingsTileView) 380 inflater.inflate(R.layout.quick_settings_tile, parent, false); 381 settingsTile.setContent(R.layout.quick_settings_tile_settings, inflater); 382 settingsTile.setOnClickListener(new View.OnClickListener() { 383 @Override 384 public void onClick(View v) { 385 startSettingsActivity(android.provider.Settings.ACTION_SETTINGS); 386 } 387 }); 388 mModel.addSettingsTile(settingsTile, new QuickSettingsModel.RefreshCallback() { 389 @Override 390 public void refreshView(QuickSettingsTileView view, State state) { 391 TextView tv = (TextView) view.findViewById(R.id.settings_tileview); 392 tv.setText(state.label); 393 } 394 }); 395 parent.addView(settingsTile); 396 mDynamicSpannedTiles.add(settingsTile); 397 } 398 399 private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) { 400 // Wi-fi 401 final QuickSettingsTileView wifiTile = (QuickSettingsTileView) 402 inflater.inflate(R.layout.quick_settings_tile, parent, false); 403 wifiTile.setContent(R.layout.quick_settings_tile_wifi, inflater); 404 wifiTile.setOnClickListener(new View.OnClickListener() { 405 @Override 406 public void onClick(View v) { 407 startSettingsActivity(android.provider.Settings.ACTION_WIFI_SETTINGS); 408 } 409 }); 410 if (LONG_PRESS_TOGGLES) { 411 wifiTile.setOnLongClickListener(new View.OnLongClickListener() { 412 @Override 413 public boolean onLongClick(View v) { 414 final boolean enable = 415 (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED); 416 new AsyncTask<Void, Void, Void>() { 417 @Override 418 protected Void doInBackground(Void... args) { 419 // Disable tethering if enabling Wifi 420 final int wifiApState = mWifiManager.getWifiApState(); 421 if (enable && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) || 422 (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) { 423 mWifiManager.setWifiApEnabled(null, false); 424 } 425 426 mWifiManager.setWifiEnabled(enable); 427 return null; 428 } 429 }.execute(); 430 wifiTile.setPressed(false); 431 return true; 432 }} ); 433 } 434 mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() { 435 @Override 436 public void refreshView(QuickSettingsTileView view, State state) { 437 WifiState wifiState = (WifiState) state; 438 TextView tv = (TextView) view.findViewById(R.id.wifi_textview); 439 tv.setCompoundDrawablesWithIntrinsicBounds(0, wifiState.iconId, 0, 0); 440 tv.setText(wifiState.label); 441 view.setContentDescription(mContext.getString( 442 R.string.accessibility_quick_settings_wifi, 443 wifiState.signalContentDescription, 444 (wifiState.connected) ? wifiState.label : "")); 445 } 446 }); 447 parent.addView(wifiTile); 448 449 if (mModel.deviceHasMobileData()) { 450 // RSSI 451 QuickSettingsTileView rssiTile = (QuickSettingsTileView) 452 inflater.inflate(R.layout.quick_settings_tile, parent, false); 453 rssiTile.setContent(R.layout.quick_settings_tile_rssi, inflater); 454 rssiTile.setOnClickListener(new View.OnClickListener() { 455 @Override 456 public void onClick(View v) { 457 Intent intent = new Intent(); 458 intent.setComponent(new ComponentName( 459 "com.android.settings", 460 "com.android.settings.Settings$DataUsageSummaryActivity")); 461 startSettingsActivity(intent); 462 } 463 }); 464 mModel.addRSSITile(rssiTile, new QuickSettingsModel.RefreshCallback() { 465 @Override 466 public void refreshView(QuickSettingsTileView view, State state) { 467 RSSIState rssiState = (RSSIState) state; 468 ImageView iv = (ImageView) view.findViewById(R.id.rssi_image); 469 ImageView iov = (ImageView) view.findViewById(R.id.rssi_overlay_image); 470 TextView tv = (TextView) view.findViewById(R.id.rssi_textview); 471 iv.setImageResource(rssiState.signalIconId); 472 473 if (rssiState.dataTypeIconId > 0) { 474 iov.setImageResource(rssiState.dataTypeIconId); 475 } else { 476 iov.setImageDrawable(null); 477 } 478 tv.setText(state.label); 479 view.setContentDescription(mContext.getResources().getString( 480 R.string.accessibility_quick_settings_mobile, 481 rssiState.signalContentDescription, rssiState.dataContentDescription, 482 state.label)); 483 } 484 }); 485 parent.addView(rssiTile); 486 } 487 488 // Rotation Lock 489 if (mContext.getResources().getBoolean(R.bool.quick_settings_show_rotation_lock)) { 490 QuickSettingsTileView rotationLockTile = (QuickSettingsTileView) 491 inflater.inflate(R.layout.quick_settings_tile, parent, false); 492 rotationLockTile.setContent(R.layout.quick_settings_tile_rotation_lock, inflater); 493 rotationLockTile.setOnClickListener(new View.OnClickListener() { 494 @Override 495 public void onClick(View v) { 496 boolean locked = RotationPolicy.isRotationLocked(mContext); 497 RotationPolicy.setRotationLock(mContext, !locked); 498 } 499 }); 500 mModel.addRotationLockTile(rotationLockTile, new QuickSettingsModel.RefreshCallback() { 501 @Override 502 public void refreshView(QuickSettingsTileView view, State state) { 503 TextView tv = (TextView) view.findViewById(R.id.rotation_lock_textview); 504 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0); 505 tv.setText(state.label); 506 } 507 }); 508 parent.addView(rotationLockTile); 509 } 510 511 // Battery 512 QuickSettingsTileView batteryTile = (QuickSettingsTileView) 513 inflater.inflate(R.layout.quick_settings_tile, parent, false); 514 batteryTile.setContent(R.layout.quick_settings_tile_battery, inflater); 515 batteryTile.setOnClickListener(new View.OnClickListener() { 516 @Override 517 public void onClick(View v) { 518 startSettingsActivity(Intent.ACTION_POWER_USAGE_SUMMARY); 519 } 520 }); 521 mModel.addBatteryTile(batteryTile, new QuickSettingsModel.RefreshCallback() { 522 @Override 523 public void refreshView(QuickSettingsTileView view, State state) { 524 QuickSettingsModel.BatteryState batteryState = 525 (QuickSettingsModel.BatteryState) state; 526 TextView tv = (TextView) view.findViewById(R.id.battery_textview); 527 ImageView iv = (ImageView) view.findViewById(R.id.battery_image); 528 Drawable d = batteryState.pluggedIn 529 ? mChargingBatteryLevels 530 : mBatteryLevels; 531 String t; 532 if (batteryState.batteryLevel == 100) { 533 t = mContext.getString(R.string.quick_settings_battery_charged_label); 534 } else { 535 t = batteryState.pluggedIn 536 ? mContext.getString(R.string.quick_settings_battery_charging_label, 537 batteryState.batteryLevel) 538 : mContext.getString(R.string.status_bar_settings_battery_meter_format, 539 batteryState.batteryLevel); 540 } 541 iv.setImageDrawable(d); 542 iv.setImageLevel(batteryState.batteryLevel); 543 tv.setText(t); 544 view.setContentDescription( 545 mContext.getString(R.string.accessibility_quick_settings_battery, t)); 546 } 547 }); 548 parent.addView(batteryTile); 549 550 // Airplane Mode 551 QuickSettingsTileView airplaneTile = (QuickSettingsTileView) 552 inflater.inflate(R.layout.quick_settings_tile, parent, false); 553 airplaneTile.setContent(R.layout.quick_settings_tile_airplane, inflater); 554 mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() { 555 @Override 556 public void refreshView(QuickSettingsTileView view, State state) { 557 TextView tv = (TextView) view.findViewById(R.id.airplane_mode_textview); 558 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0); 559 560 String airplaneState = mContext.getString( 561 (state.enabled) ? R.string.accessibility_desc_on 562 : R.string.accessibility_desc_off); 563 view.setContentDescription( 564 mContext.getString(R.string.accessibility_quick_settings_airplane, airplaneState)); 565 tv.setText(state.label); 566 } 567 }); 568 parent.addView(airplaneTile); 569 570 // Bluetooth 571 if (mModel.deviceSupportsBluetooth()) { 572 final QuickSettingsTileView bluetoothTile = (QuickSettingsTileView) 573 inflater.inflate(R.layout.quick_settings_tile, parent, false); 574 bluetoothTile.setContent(R.layout.quick_settings_tile_bluetooth, inflater); 575 bluetoothTile.setOnClickListener(new View.OnClickListener() { 576 @Override 577 public void onClick(View v) { 578 startSettingsActivity(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS); 579 } 580 }); 581 if (LONG_PRESS_TOGGLES) { 582 bluetoothTile.setOnLongClickListener(new View.OnLongClickListener() { 583 @Override 584 public boolean onLongClick(View v) { 585 if (mBluetoothAdapter.isEnabled()) { 586 mBluetoothAdapter.disable(); 587 } else { 588 mBluetoothAdapter.enable(); 589 } 590 bluetoothTile.setPressed(false); 591 return true; 592 }}); 593 } 594 mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() { 595 @Override 596 public void refreshView(QuickSettingsTileView view, State state) { 597 BluetoothState bluetoothState = (BluetoothState) state; 598 TextView tv = (TextView) view.findViewById(R.id.bluetooth_textview); 599 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0); 600 601 Resources r = mContext.getResources(); 602 String label = state.label; 603 /* 604 //TODO: Show connected bluetooth device label 605 Set<BluetoothDevice> btDevices = 606 mBluetoothController.getBondedBluetoothDevices(); 607 if (btDevices.size() == 1) { 608 // Show the name of the bluetooth device you are connected to 609 label = btDevices.iterator().next().getName(); 610 } else if (btDevices.size() > 1) { 611 // Show a generic label about the number of bluetooth devices 612 label = r.getString(R.string.quick_settings_bluetooth_multiple_devices_label, 613 btDevices.size()); 614 } 615 */ 616 view.setContentDescription(mContext.getString( 617 R.string.accessibility_quick_settings_bluetooth, 618 bluetoothState.stateContentDescription)); 619 tv.setText(label); 620 } 621 }); 622 parent.addView(bluetoothTile); 623 } 624 625 } 626 627 private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) { 628 // Alarm tile 629 QuickSettingsTileView alarmTile = (QuickSettingsTileView) 630 inflater.inflate(R.layout.quick_settings_tile, parent, false); 631 alarmTile.setContent(R.layout.quick_settings_tile_alarm, inflater); 632 alarmTile.setOnClickListener(new View.OnClickListener() { 633 @Override 634 public void onClick(View v) { 635 // TODO: Jump into the alarm application 636 Intent intent = new Intent(); 637 intent.setComponent(new ComponentName( 638 "com.google.android.deskclock", 639 "com.android.deskclock.AlarmClock")); 640 startSettingsActivity(intent); 641 } 642 }); 643 mModel.addAlarmTile(alarmTile, new QuickSettingsModel.RefreshCallback() { 644 @Override 645 public void refreshView(QuickSettingsTileView view, State alarmState) { 646 TextView tv = (TextView) view.findViewById(R.id.alarm_textview); 647 tv.setText(alarmState.label); 648 view.setVisibility(alarmState.enabled ? View.VISIBLE : View.GONE); 649 view.setContentDescription(mContext.getString( 650 R.string.accessibility_quick_settings_alarm, alarmState.label)); 651 } 652 }); 653 parent.addView(alarmTile); 654 655 // Location 656 QuickSettingsTileView locationTile = (QuickSettingsTileView) 657 inflater.inflate(R.layout.quick_settings_tile, parent, false); 658 locationTile.setContent(R.layout.quick_settings_tile_location, inflater); 659 locationTile.setOnClickListener(new View.OnClickListener() { 660 @Override 661 public void onClick(View v) { 662 startSettingsActivity(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); 663 } 664 }); 665 mModel.addLocationTile(locationTile, new QuickSettingsModel.RefreshCallback() { 666 @Override 667 public void refreshView(QuickSettingsTileView view, State state) { 668 TextView tv = (TextView) view.findViewById(R.id.location_textview); 669 tv.setText(state.label); 670 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE); 671 } 672 }); 673 parent.addView(locationTile); 674 675 // Wifi Display 676 QuickSettingsTileView wifiDisplayTile = (QuickSettingsTileView) 677 inflater.inflate(R.layout.quick_settings_tile, parent, false); 678 wifiDisplayTile.setContent(R.layout.quick_settings_tile_wifi_display, inflater); 679 wifiDisplayTile.setOnClickListener(new View.OnClickListener() { 680 @Override 681 public void onClick(View v) { 682 startSettingsActivity(android.provider.Settings.ACTION_WIFI_DISPLAY_SETTINGS); 683 } 684 }); 685 mModel.addWifiDisplayTile(wifiDisplayTile, new QuickSettingsModel.RefreshCallback() { 686 @Override 687 public void refreshView(QuickSettingsTileView view, State state) { 688 TextView tv = (TextView) view.findViewById(R.id.wifi_display_textview); 689 tv.setText(state.label); 690 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0); 691 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE); 692 } 693 }); 694 parent.addView(wifiDisplayTile); 695 696 if (SHOW_IME_TILE) { 697 // IME 698 QuickSettingsTileView imeTile = (QuickSettingsTileView) 699 inflater.inflate(R.layout.quick_settings_tile, parent, false); 700 imeTile.setContent(R.layout.quick_settings_tile_ime, inflater); 701 imeTile.setOnClickListener(new View.OnClickListener() { 702 @Override 703 public void onClick(View v) { 704 try { 705 mBar.collapseAllPanels(true); 706 Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER); 707 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); 708 pendingIntent.send(); 709 } catch (Exception e) {} 710 } 711 }); 712 mModel.addImeTile(imeTile, new QuickSettingsModel.RefreshCallback() { 713 @Override 714 public void refreshView(QuickSettingsTileView view, State state) { 715 TextView tv = (TextView) view.findViewById(R.id.ime_textview); 716 if (state.label != null) { 717 tv.setText(state.label); 718 } 719 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE); 720 } 721 }); 722 parent.addView(imeTile); 723 } 724 725 // Bug reports 726 QuickSettingsTileView bugreportTile = (QuickSettingsTileView) 727 inflater.inflate(R.layout.quick_settings_tile, parent, false); 728 bugreportTile.setContent(R.layout.quick_settings_tile_bugreport, inflater); 729 bugreportTile.setOnClickListener(new View.OnClickListener() { 730 @Override 731 public void onClick(View v) { 732 mBar.collapseAllPanels(true); 733 showBugreportDialog(); 734 } 735 }); 736 mModel.addBugreportTile(bugreportTile, new QuickSettingsModel.RefreshCallback() { 737 @Override 738 public void refreshView(QuickSettingsTileView view, State state) { 739 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE); 740 } 741 }); 742 parent.addView(bugreportTile); 743 /* 744 QuickSettingsTileView mediaTile = (QuickSettingsTileView) 745 inflater.inflate(R.layout.quick_settings_tile, parent, false); 746 mediaTile.setContent(R.layout.quick_settings_tile_media, inflater); 747 parent.addView(mediaTile); 748 QuickSettingsTileView imeTile = (QuickSettingsTileView) 749 inflater.inflate(R.layout.quick_settings_tile, parent, false); 750 imeTile.setContent(R.layout.quick_settings_tile_ime, inflater); 751 imeTile.setOnClickListener(new View.OnClickListener() { 752 @Override 753 public void onClick(View v) { 754 parent.removeViewAt(0); 755 } 756 }); 757 parent.addView(imeTile); 758 */ 759 } 760 761 void updateResources() { 762 Resources r = mContext.getResources(); 763 764 // Update the model 765 mModel.updateResources(); 766 767 // Update the User, Time, and Settings tiles spans, and reset everything else 768 int span = r.getInteger(R.integer.quick_settings_user_time_settings_tile_span); 769 for (QuickSettingsTileView v : mDynamicSpannedTiles) { 770 v.setColumnSpan(span); 771 } 772 ((QuickSettingsContainerView)mContainerView).updateResources(); 773 mContainerView.requestLayout(); 774 775 // Reset the dialog 776 boolean isBrightnessDialogVisible = false; 777 if (mBrightnessDialog != null) { 778 removeAllBrightnessDialogCallbacks(); 779 780 isBrightnessDialogVisible = mBrightnessDialog.isShowing(); 781 mBrightnessDialog.dismiss(); 782 } 783 mBrightnessDialog = null; 784 if (isBrightnessDialogVisible) { 785 showBrightnessDialog(); 786 } 787 } 788 789 private void removeAllBrightnessDialogCallbacks() { 790 mHandler.removeCallbacks(mDismissBrightnessDialogRunnable); 791 } 792 793 private Runnable mDismissBrightnessDialogRunnable = new Runnable() { 794 public void run() { 795 if (mBrightnessDialog != null && mBrightnessDialog.isShowing()) { 796 mBrightnessDialog.dismiss(); 797 } 798 removeAllBrightnessDialogCallbacks(); 799 }; 800 }; 801 802 private void showBrightnessDialog() { 803 if (mBrightnessDialog == null) { 804 mBrightnessDialog = new Dialog(mContext); 805 mBrightnessDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 806 mBrightnessDialog.setContentView(R.layout.quick_settings_brightness_dialog); 807 mBrightnessDialog.setCanceledOnTouchOutside(true); 808 809 mBrightnessController = new BrightnessController(mContext, 810 (ImageView) mBrightnessDialog.findViewById(R.id.brightness_icon), 811 (ToggleSlider) mBrightnessDialog.findViewById(R.id.brightness_slider)); 812 mBrightnessController.addStateChangedCallback(mModel); 813 mBrightnessDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { 814 @Override 815 public void onDismiss(DialogInterface dialog) { 816 mBrightnessController = null; 817 } 818 }); 819 820 mBrightnessDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 821 mBrightnessDialog.getWindow().getAttributes().privateFlags |= 822 WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 823 mBrightnessDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 824 } 825 if (!mBrightnessDialog.isShowing()) { 826 try { 827 WindowManagerGlobal.getWindowManagerService().dismissKeyguard(); 828 } catch (RemoteException e) { 829 } 830 mBrightnessDialog.show(); 831 dismissBrightnessDialog(mBrightnessDialogLongTimeout); 832 } 833 } 834 835 private void dismissBrightnessDialog(int timeout) { 836 removeAllBrightnessDialogCallbacks(); 837 if (mBrightnessDialog != null) { 838 mHandler.postDelayed(mDismissBrightnessDialogRunnable, timeout); 839 } 840 } 841 842 private void showBugreportDialog() { 843 final AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 844 builder.setPositiveButton(com.android.internal.R.string.report, new OnClickListener() { 845 @Override 846 public void onClick(DialogInterface dialog, int which) { 847 if (which == DialogInterface.BUTTON_POSITIVE) { 848 // Add a little delay before executing, to give the 849 // dialog a chance to go away before it takes a 850 // screenshot. 851 mHandler.postDelayed(new Runnable() { 852 @Override public void run() { 853 try { 854 ActivityManagerNative.getDefault() 855 .requestBugReport(); 856 } catch (RemoteException e) { 857 } 858 } 859 }, 500); 860 } 861 } 862 }); 863 builder.setMessage(com.android.internal.R.string.bugreport_message); 864 builder.setTitle(com.android.internal.R.string.bugreport_title); 865 builder.setCancelable(true); 866 final Dialog dialog = builder.create(); 867 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 868 try { 869 WindowManagerGlobal.getWindowManagerService().dismissKeyguard(); 870 } catch (RemoteException e) { 871 } 872 dialog.show(); 873 } 874 875 private void updateWifiDisplayStatus() { 876 mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus(); 877 applyWifiDisplayStatus(); 878 } 879 880 private void applyWifiDisplayStatus() { 881 mModel.onWifiDisplayStateChanged(mWifiDisplayStatus); 882 } 883 884 private void applyBluetoothStatus() { 885 mModel.onBluetoothStateChange(mBluetoothState); 886 } 887 888 void reloadUserInfo() { 889 if (mUserInfoTask != null) { 890 mUserInfoTask.cancel(false); 891 mUserInfoTask = null; 892 } 893 if (mTilesSetUp) { 894 queryForUserInformation(); 895 } 896 } 897 898 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 899 @Override 900 public void onReceive(Context context, Intent intent) { 901 final String action = intent.getAction(); 902 if (DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED.equals(action)) { 903 WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra( 904 DisplayManager.EXTRA_WIFI_DISPLAY_STATUS); 905 mWifiDisplayStatus = status; 906 applyWifiDisplayStatus(); 907 } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { 908 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 909 BluetoothAdapter.ERROR); 910 mBluetoothState.enabled = (state == BluetoothAdapter.STATE_ON); 911 applyBluetoothStatus(); 912 } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { 913 int status = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 914 BluetoothAdapter.STATE_DISCONNECTED); 915 mBluetoothState.connected = (status == BluetoothAdapter.STATE_CONNECTED); 916 applyBluetoothStatus(); 917 } else if (Intent.ACTION_USER_SWITCHED.equals(action)) { 918 reloadUserInfo(); 919 } 920 } 921 }; 922 923 private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() { 924 @Override 925 public void onReceive(Context context, Intent intent) { 926 final String action = intent.getAction(); 927 if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) || 928 Intent.ACTION_USER_INFO_CHANGED.equals(action)) { 929 try { 930 final int userId = ActivityManagerNative.getDefault().getCurrentUser().id; 931 if (getSendingUserId() == userId) { 932 reloadUserInfo(); 933 } 934 } catch (RemoteException e) { 935 Log.e(TAG, "Couldn't get current user id for profile change", e); 936 } 937 } 938 939 } 940 }; 941} 942