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