QuickSettings.java revision 21c7153d30071dcbeb92daa1fd48ed181e42aef3
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.systemui.statusbar.phone; 18 19import android.app.Dialog; 20import android.bluetooth.BluetoothAdapter; 21import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback; 22import android.content.BroadcastReceiver; 23import android.content.Context; 24import android.content.CursorLoader; 25import android.content.Intent; 26import android.content.IntentFilter; 27import android.content.Loader; 28import android.content.res.Resources; 29import android.database.Cursor; 30import android.graphics.drawable.ClipDrawable; 31import android.hardware.display.DisplayManager; 32import android.hardware.display.WifiDisplay; 33import android.hardware.display.WifiDisplayStatus; 34import android.net.Uri; 35import android.provider.ContactsContract; 36import android.provider.Settings; 37import android.view.LayoutInflater; 38import android.view.View; 39import android.view.ViewGroup; 40import android.view.WindowManager; 41import android.widget.AdapterView; 42import android.widget.ArrayAdapter; 43import android.widget.Button; 44import android.widget.ListView; 45import android.widget.TextView; 46 47import java.util.ArrayList; 48import java.util.Comparator; 49 50import com.android.systemui.R; 51import com.android.systemui.statusbar.phone.QuickSettingsModel.State; 52import com.android.systemui.statusbar.policy.BatteryController; 53import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 54import com.android.systemui.statusbar.policy.BluetoothController; 55import com.android.systemui.statusbar.policy.LocationController; 56import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback; 57import com.android.systemui.statusbar.policy.NetworkController; 58import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; 59 60class QuickSettingsModel implements BluetoothStateChangeCallback, 61 NetworkSignalChangedCallback, 62 BatteryStateChangeCallback, 63 LocationGpsStateChangeCallback { 64 65 /** Represents the state of a given attribute. */ 66 static class State { 67 int iconId; 68 String label; 69 boolean enabled; 70 } 71 static class BatteryState extends State { 72 int batteryLevel; 73 boolean pluggedIn; 74 } 75 76 /** The callback to update a given tile. */ 77 interface RefreshCallback { 78 public void refreshView(QuickSettingsTileView view, State state); 79 } 80 81 private Context mContext; 82 83 private QuickSettingsTileView mUserTile; 84 private RefreshCallback mUserCallback; 85 private State mUserState = new State(); 86 87 private QuickSettingsTileView mAirplaneModeTile; 88 private RefreshCallback mAirplaneModeCallback; 89 private State mAirplaneModeState = new State(); 90 91 private QuickSettingsTileView mWifiTile; 92 private RefreshCallback mWifiCallback; 93 private State mWifiState = new State(); 94 95 private QuickSettingsTileView mWifiDisplayTile; 96 private RefreshCallback mWifiDisplayCallback; 97 private State mWifiDisplayState = new State(); 98 99 private QuickSettingsTileView mRSSITile; 100 private RefreshCallback mRSSICallback; 101 private State mRSSIState = new State(); 102 103 private QuickSettingsTileView mBluetoothTile; 104 private RefreshCallback mBluetoothCallback; 105 private State mBluetoothState = new State(); 106 107 private QuickSettingsTileView mBatteryTile; 108 private RefreshCallback mBatteryCallback; 109 private BatteryState mBatteryState = new BatteryState(); 110 111 private QuickSettingsTileView mLocationTile; 112 private RefreshCallback mLocationCallback; 113 private State mLocationState = new State(); 114 115 public QuickSettingsModel(Context context) { 116 mContext = context; 117 } 118 119 // User 120 void addUserTile(QuickSettingsTileView view, RefreshCallback cb) { 121 mUserTile = view; 122 mUserCallback = cb; 123 mUserCallback.refreshView(mUserTile, mUserState); 124 } 125 void setUserTileInfo(String name) { 126 mUserState.label = name; 127 mUserCallback.refreshView(mUserTile, mUserState); 128 } 129 130 // Airplane Mode 131 void addAirplaneModeTile(QuickSettingsTileView view, RefreshCallback cb) { 132 mAirplaneModeTile = view; 133 mAirplaneModeTile.setOnClickListener(new View.OnClickListener() { 134 @Override 135 public void onClick(View v) { 136 if (mAirplaneModeState.enabled) { 137 setAirplaneModeState(false); 138 } else { 139 setAirplaneModeState(true); 140 } 141 } 142 }); 143 mAirplaneModeCallback = cb; 144 mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState); 145 } 146 private void setAirplaneModeState(boolean enabled) { 147 // TODO: Sets the view to be "awaiting" if not already awaiting 148 149 // Change the system setting 150 Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 151 enabled ? 1 : 0); 152 153 // TODO: Update the UI to reflect system setting 154 // mCheckBoxPref.setChecked(enabled); 155 156 // Post the intent 157 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 158 intent.putExtra("state", enabled); 159 mContext.sendBroadcast(intent); 160 } 161 // NetworkSignalChanged callback 162 @Override 163 public void onAirplaneModeChanged(boolean enabled) { 164 // TODO: If view is in awaiting state, disable 165 Resources r = mContext.getResources(); 166 mAirplaneModeState.enabled = enabled; 167 mAirplaneModeState.iconId = (enabled ? 168 R.drawable.ic_qs_airplane_enabled : 169 R.drawable.ic_qs_airplane_normal); 170 mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState); 171 } 172 173 // Wifi 174 void addWifiTile(QuickSettingsTileView view, RefreshCallback cb) { 175 mWifiTile = view; 176 mWifiCallback = cb; 177 mWifiCallback.refreshView(mWifiTile, mWifiState); 178 } 179 // NetworkSignalChanged callback 180 @Override 181 public void onWifiSignalChanged(boolean enabled, String description) { 182 // TODO: If view is in awaiting state, disable 183 Resources r = mContext.getResources(); 184 // TODO: Check if wifi is enabled 185 mWifiState.enabled = enabled; 186 mWifiState.iconId = (enabled ? 187 R.drawable.ic_qs_wifi_enabled : 188 R.drawable.ic_qs_wifi_normal); 189 mWifiState.label = (enabled ? 190 description : 191 r.getString(R.string.quick_settings_wifi_no_network)); 192 mWifiCallback.refreshView(mWifiTile, mWifiState); 193 } 194 195 // RSSI 196 void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) { 197 mRSSITile = view; 198 mRSSICallback = cb; 199 mRSSICallback.refreshView(mRSSITile, mRSSIState); 200 } 201 private void setRSSIState(boolean enabled) { 202 // TODO: Set RSSI enabled 203 // TODO: Sets the view to be "awaiting" if not already awaiting 204 } 205 // NetworkSignalChanged callback 206 @Override 207 public void onMobileDataSignalChanged(boolean enabled, String description) { 208 // TODO: If view is in awaiting state, disable 209 Resources r = mContext.getResources(); 210 // TODO: Check if RSSI is enabled 211 mRSSIState.enabled = enabled; 212 mRSSIState.iconId = (enabled ? 213 R.drawable.ic_qs_rssi_enabled : 214 R.drawable.ic_qs_rssi_normal); 215 mRSSIState.label = (enabled ? 216 description : 217 r.getString(R.string.quick_settings_rssi_emergency_only)); 218 mRSSICallback.refreshView(mRSSITile, mRSSIState); 219 } 220 221 // Bluetooth 222 void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) { 223 mBluetoothTile = view; 224 mBluetoothTile.setOnClickListener(new View.OnClickListener() { 225 @Override 226 public void onClick(View v) { 227 if (mBluetoothState.enabled) { 228 setBluetoothState(false); 229 } else { 230 setBluetoothState(true); 231 } 232 } 233 }); 234 mBluetoothCallback = cb; 235 236 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 237 onBluetoothStateChange(adapter.isEnabled()); 238 } 239 private void setBluetoothState(boolean enabled) { 240 // TODO: Sets the view to be "awaiting" if not already awaiting 241 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 242 if (adapter != null) { 243 if (enabled) { 244 adapter.enable(); 245 } else { 246 adapter.disable(); 247 } 248 } 249 } 250 // BluetoothController callback 251 @Override 252 public void onBluetoothStateChange(boolean on) { 253 // TODO: If view is in awaiting state, disable 254 Resources r = mContext.getResources(); 255 mBluetoothState.enabled = on; 256 if (on) { 257 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_enabled; 258 } else { 259 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_normal; 260 } 261 mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState); 262 } 263 264 // Battery 265 void addBatteryTile(QuickSettingsTileView view, RefreshCallback cb) { 266 mBatteryTile = view; 267 mBatteryCallback = cb; 268 mBatteryCallback.refreshView(mBatteryTile, mBatteryState); 269 } 270 // BatteryController callback 271 @Override 272 public void onBatteryLevelChanged(int level, boolean pluggedIn) { 273 mBatteryState.batteryLevel = level; 274 mBatteryState.pluggedIn = pluggedIn; 275 mBatteryCallback.refreshView(mBatteryTile, mBatteryState); 276 } 277 278 // Location 279 void addLocationTile(QuickSettingsTileView view, RefreshCallback cb) { 280 mLocationTile = view; 281 mLocationCallback = cb; 282 mLocationCallback.refreshView(mLocationTile, mLocationState); 283 disableLocationTile(); 284 } 285 private void enableLocationTile() { 286 mLocationTile.setVisibility(View.VISIBLE); 287 } 288 private void disableLocationTile() { 289 mLocationTile.setVisibility(View.GONE); 290 } 291 // LocationController callback 292 @Override 293 public void onLocationGpsStateChanged(boolean inUse, String description) { 294 if (inUse) { 295 mLocationState.enabled = inUse; 296 mLocationState.label = description; 297 mLocationCallback.refreshView(mLocationTile, mLocationState); 298 enableLocationTile(); 299 } else { 300 disableLocationTile(); 301 } 302 } 303 304 // Wifi Display 305 void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) { 306 mWifiDisplayTile = view; 307 mWifiDisplayCallback = cb; 308 } 309 private void enableWifiDisplayTile() { 310 mWifiDisplayTile.setVisibility(View.VISIBLE); 311 } 312 private void disableWifiDisplayTile() { 313 mWifiDisplayTile.setVisibility(View.GONE); 314 } 315 public void onWifiDisplayStateChanged(WifiDisplayStatus status) { 316 if (status.isEnabled()) { 317 if (status.getActiveDisplay() != null) { 318 mWifiDisplayState.label = status.getActiveDisplay().getDeviceName(); 319 } else { 320 mWifiDisplayState.label = mContext.getString( 321 R.string.quick_settings_wifi_display_no_connection_label); 322 } 323 mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState); 324 enableWifiDisplayTile(); 325 } else { 326 disableWifiDisplayTile(); 327 } 328 } 329 330} 331 332/** 333 * 334 */ 335class QuickSettings { 336 337 private Context mContext; 338 private PanelBar mBar; 339 private QuickSettingsModel mModel; 340 private QuickSettingsContainerView mContainerView; 341 342 private DisplayManager mDisplayManager; 343 private WifiDisplayStatus mWifiDisplayStatus; 344 private WifiDisplayListAdapter mWifiDisplayListAdapter; 345 346 private CursorLoader mUserInfoLoader; 347 348 // The set of QuickSettingsTiles that have dynamic spans (and need to be updated on 349 // configuration change) 350 private final ArrayList<QuickSettingsTileView> mDynamicSpannedTiles = 351 new ArrayList<QuickSettingsTileView>(); 352 353 public QuickSettings(Context context, QuickSettingsContainerView container) { 354 mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); 355 mContext = context; 356 mContainerView = container; 357 mModel = new QuickSettingsModel(context); 358 mWifiDisplayStatus = new WifiDisplayStatus(); 359 mWifiDisplayListAdapter = new WifiDisplayListAdapter(context); 360 361 IntentFilter filter = new IntentFilter(); 362 filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 363 mContext.registerReceiver(mReceiver, filter); 364 365 setupQuickSettings(); 366 updateWifiDisplayStatus(); 367 updateResources(); 368 } 369 370 void setBar(PanelBar bar) { 371 mBar = bar; 372 } 373 374 void setup(NetworkController networkController, BluetoothController bluetoothController, 375 BatteryController batteryController, LocationController locationController) { 376 networkController.addNetworkSignalChangedCallback(mModel); 377 bluetoothController.addStateChangedCallback(mModel); 378 batteryController.addStateChangedCallback(mModel); 379 locationController.addStateChangedCallback(mModel); 380 } 381 382 private void queryForUserInformation() { 383 Uri userContactUri = Uri.withAppendedPath( 384 ContactsContract.Profile.CONTENT_URI, 385 ContactsContract.Contacts.Data.CONTENT_DIRECTORY); 386 387 String[] selectArgs = { 388 ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, 389 ContactsContract.CommonDataKinds.Photo.PHOTO 390 }; 391 String where = String.format("(%s = ? OR %s = ?) AND %s IS NULL", 392 ContactsContract.Contacts.Data.MIMETYPE, 393 ContactsContract.Contacts.Data.MIMETYPE, 394 ContactsContract.RawContacts.ACCOUNT_TYPE); 395 String[] whereArgs = { 396 ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, 397 ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE 398 }; 399 400 mUserInfoLoader = new CursorLoader(mContext, userContactUri, selectArgs, where, whereArgs, 401 null); 402 mUserInfoLoader.registerListener(0, 403 new Loader.OnLoadCompleteListener<Cursor>() { 404 @Override 405 public void onLoadComplete(Loader<Cursor> loader, 406 Cursor cursor) { 407 if (cursor.moveToFirst()) { 408 String name = cursor.getString(0); // DISPLAY_NAME 409 mModel.setUserTileInfo(name); 410 /* 411 byte[] photoData = cursor.getBlob(0); 412 Bitmap b = 413 BitmapFactory.decodeByteArray(photoData, 0, photoData.length); 414 */ 415 } 416 mUserInfoLoader.stopLoading(); 417 } 418 }); 419 mUserInfoLoader.startLoading(); 420 } 421 422 private void setupQuickSettings() { 423 // Setup the tiles that we are going to be showing (including the temporary ones) 424 LayoutInflater inflater = LayoutInflater.from(mContext); 425 426 addUserTiles(mContainerView, inflater); 427 addSystemTiles(mContainerView, inflater); 428 addTemporaryTiles(mContainerView, inflater); 429 430 queryForUserInformation(); 431 } 432 433 private void addUserTiles(ViewGroup parent, LayoutInflater inflater) { 434 QuickSettingsTileView userTile = (QuickSettingsTileView) 435 inflater.inflate(R.layout.quick_settings_tile, parent, false); 436 userTile.setContent(R.layout.quick_settings_tile_user, inflater); 437 mModel.addUserTile(userTile, new QuickSettingsModel.RefreshCallback() { 438 @Override 439 public void refreshView(QuickSettingsTileView view, State state) { 440 TextView tv = (TextView) view.findViewById(R.id.user_textview); 441 tv.setText(state.label); 442 } 443 }); 444 parent.addView(userTile); 445 mDynamicSpannedTiles.add(userTile); 446 447 // Time tile 448 QuickSettingsTileView timeTile = (QuickSettingsTileView) 449 inflater.inflate(R.layout.quick_settings_tile, parent, false); 450 timeTile.setContent(R.layout.quick_settings_tile_time, inflater); 451 parent.addView(timeTile); 452 mDynamicSpannedTiles.add(timeTile); 453 454 // Settings tile 455 QuickSettingsTileView settingsTile = (QuickSettingsTileView) 456 inflater.inflate(R.layout.quick_settings_tile, parent, false); 457 settingsTile.setContent(R.layout.quick_settings_tile_settings, inflater); 458 settingsTile.setOnClickListener(new View.OnClickListener() { 459 @Override 460 public void onClick(View v) { 461 Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS); 462 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 463 mContext.startActivity(intent); 464 mBar.collapseAllPanels(true); 465 } 466 }); 467 parent.addView(settingsTile); 468 mDynamicSpannedTiles.add(settingsTile); 469 } 470 471 private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) { 472 // Wi-fi 473 QuickSettingsTileView wifiTile = (QuickSettingsTileView) 474 inflater.inflate(R.layout.quick_settings_tile, parent, false); 475 wifiTile.setContent(R.layout.quick_settings_tile_wifi, inflater); 476 wifiTile.setOnClickListener(new View.OnClickListener() { 477 @Override 478 public void onClick(View v) { 479 Intent intent = new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS); 480 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 481 mContext.startActivity(intent); 482 mBar.collapseAllPanels(true); 483 } 484 }); 485 mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() { 486 @Override 487 public void refreshView(QuickSettingsTileView view, State state) { 488 TextView tv = (TextView) view.findViewById(R.id.wifi_textview); 489 tv.setCompoundDrawablesRelativeWithIntrinsicBounds(0, state.iconId, 0, 0); 490 tv.setText(state.label); 491 } 492 }); 493 parent.addView(wifiTile); 494 495 // RSSI 496 QuickSettingsTileView rssiTile = (QuickSettingsTileView) 497 inflater.inflate(R.layout.quick_settings_tile, parent, false); 498 rssiTile.setContent(R.layout.quick_settings_tile_rssi, inflater); 499 rssiTile.setOnClickListener(new View.OnClickListener() { 500 @Override 501 public void onClick(View v) { 502 Intent intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS); 503 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 504 mContext.startActivity(intent); 505 mBar.collapseAllPanels(true); 506 } 507 }); 508 mModel.addRSSITile(rssiTile, new QuickSettingsModel.RefreshCallback() { 509 @Override 510 public void refreshView(QuickSettingsTileView view, State state) { 511 TextView tv = (TextView) view.findViewById(R.id.rssi_textview); 512 tv.setCompoundDrawablesRelativeWithIntrinsicBounds(0, state.iconId, 0, 0); 513 tv.setText(state.label); 514 } 515 }); 516 parent.addView(rssiTile); 517 518 // Battery 519 QuickSettingsTileView batteryTile = (QuickSettingsTileView) 520 inflater.inflate(R.layout.quick_settings_tile, parent, false); 521 batteryTile.setContent(R.layout.quick_settings_tile_battery, inflater); 522 batteryTile.setOnClickListener(new View.OnClickListener() { 523 @Override 524 public void onClick(View v) { 525 Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY); 526 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 527 mContext.startActivity(intent); 528 mBar.collapseAllPanels(true); 529 } 530 }); 531 mModel.addBatteryTile(batteryTile, new QuickSettingsModel.RefreshCallback() { 532 @Override 533 public void refreshView(QuickSettingsTileView view, State state) { 534 QuickSettingsModel.BatteryState batteryState = 535 (QuickSettingsModel.BatteryState) state; 536 TextView tv = (TextView) view.findViewById(R.id.battery_textview); 537 ClipDrawable drawable = (ClipDrawable) tv.getCompoundDrawables()[1]; 538 drawable.setLevel((int) (10000 * (batteryState.batteryLevel / 100.0f))); 539 // TODO: use format string 540 tv.setText(batteryState.batteryLevel + "%"); 541 } 542 }); 543 parent.addView(batteryTile); 544 545 // Airplane Mode 546 QuickSettingsTileView airplaneTile = (QuickSettingsTileView) 547 inflater.inflate(R.layout.quick_settings_tile, parent, false); 548 airplaneTile.setContent(R.layout.quick_settings_tile_airplane, inflater); 549 mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() { 550 @Override 551 public void refreshView(QuickSettingsTileView view, State state) { 552 TextView tv = (TextView) view.findViewById(R.id.airplane_mode_textview); 553 tv.setCompoundDrawablesRelativeWithIntrinsicBounds(0, state.iconId, 0, 0); 554 } 555 }); 556 parent.addView(airplaneTile); 557 558 // Bluetooth 559 QuickSettingsTileView bluetoothTile = (QuickSettingsTileView) 560 inflater.inflate(R.layout.quick_settings_tile, parent, false); 561 bluetoothTile.setContent(R.layout.quick_settings_tile_bluetooth, inflater); 562 mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() { 563 @Override 564 public void refreshView(QuickSettingsTileView view, State state) { 565 TextView tv = (TextView) view.findViewById(R.id.bluetooth_textview); 566 tv.setCompoundDrawablesRelativeWithIntrinsicBounds(0, state.iconId, 0, 0); 567 } 568 }); 569 parent.addView(bluetoothTile); 570 571 // Brightness 572 QuickSettingsTileView brightnessTile = (QuickSettingsTileView) 573 inflater.inflate(R.layout.quick_settings_tile, parent, false); 574 brightnessTile.setContent(R.layout.quick_settings_tile_brightness, inflater); 575 brightnessTile.setOnClickListener(new View.OnClickListener() { 576 @Override 577 public void onClick(View v) { 578 Intent intent = new Intent(android.provider.Settings.ACTION_DISPLAY_SETTINGS); 579 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 580 mContext.startActivity(intent); 581 mBar.collapseAllPanels(true); 582 } 583 }); 584 parent.addView(brightnessTile); 585 } 586 587 private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) { 588 // Location 589 QuickSettingsTileView locationTile = (QuickSettingsTileView) 590 inflater.inflate(R.layout.quick_settings_tile, parent, false); 591 locationTile.setContent(R.layout.quick_settings_tile_location, inflater); 592 locationTile.setOnClickListener(new View.OnClickListener() { 593 @Override 594 public void onClick(View v) { 595 Intent intent = 596 new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); 597 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 598 mContext.startActivity(intent); 599 mBar.collapseAllPanels(true); 600 } 601 }); 602 mModel.addLocationTile(locationTile, new QuickSettingsModel.RefreshCallback() { 603 @Override 604 public void refreshView(QuickSettingsTileView view, State state) { 605 TextView tv = (TextView) view.findViewById(R.id.location_textview); 606 tv.setText(state.label); 607 } 608 }); 609 parent.addView(locationTile); 610 611 // Wifi Display 612 QuickSettingsTileView wifiDisplayTile = (QuickSettingsTileView) 613 inflater.inflate(R.layout.quick_settings_tile, parent, false); 614 wifiDisplayTile.setContent(R.layout.quick_settings_tile_wifi_display, inflater); 615 wifiDisplayTile.setOnClickListener(new View.OnClickListener() { 616 @Override 617 public void onClick(View v) { 618 showWifiDisplayDialog(); 619 mBar.collapseAllPanels(true); 620 } 621 }); 622 mModel.addWifiDisplayTile(wifiDisplayTile, new QuickSettingsModel.RefreshCallback() { 623 @Override 624 public void refreshView(QuickSettingsTileView view, State state) { 625 TextView tv = (TextView) view.findViewById(R.id.wifi_display_textview); 626 tv.setText(state.label); 627 } 628 }); 629 parent.addView(wifiDisplayTile); 630 631 /* 632 QuickSettingsTileView mediaTile = (QuickSettingsTileView) 633 inflater.inflate(R.layout.quick_settings_tile, parent, false); 634 mediaTile.setContent(R.layout.quick_settings_tile_media, inflater); 635 parent.addView(mediaTile); 636 QuickSettingsTileView imeTile = (QuickSettingsTileView) 637 inflater.inflate(R.layout.quick_settings_tile, parent, false); 638 imeTile.setContent(R.layout.quick_settings_tile_ime, inflater); 639 imeTile.setOnClickListener(new View.OnClickListener() { 640 @Override 641 public void onClick(View v) { 642 parent.removeViewAt(0); 643 } 644 }); 645 parent.addView(imeTile); 646 */ 647 } 648 649 void updateResources() { 650 Resources r = mContext.getResources(); 651 652 // Update the User, Time, and Settings tiles spans, and reset everything else 653 int span = r.getInteger(R.integer.quick_settings_user_time_settings_tile_span); 654 for (QuickSettingsTileView v : mDynamicSpannedTiles) { 655 v.setColumnSpan(span); 656 } 657 mContainerView.requestLayout(); 658 } 659 660 private void showWifiDisplayDialog() { 661 mDisplayManager.scanWifiDisplays(); 662 updateWifiDisplayStatus(); 663 664 Dialog dialog = new Dialog(mContext); 665 dialog.setContentView(R.layout.wifi_display_dialog); 666 dialog.setCanceledOnTouchOutside(true); 667 dialog.setTitle(R.string.wifi_display_dialog_title); 668 669 Button scanButton = (Button)dialog.findViewById(R.id.scan); 670 scanButton.setOnClickListener(new View.OnClickListener() { 671 @Override 672 public void onClick(View v) { 673 mDisplayManager.scanWifiDisplays(); 674 } 675 }); 676 677 Button disconnectButton = (Button)dialog.findViewById(R.id.disconnect); 678 disconnectButton.setOnClickListener(new View.OnClickListener() { 679 @Override 680 public void onClick(View v) { 681 mDisplayManager.disconnectWifiDisplay(); 682 } 683 }); 684 685 ListView list = (ListView)dialog.findViewById(R.id.list); 686 list.setAdapter(mWifiDisplayListAdapter); 687 list.setOnItemClickListener(new AdapterView.OnItemClickListener() { 688 @Override 689 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 690 WifiDisplay display = mWifiDisplayListAdapter.getItem(position); 691 mDisplayManager.connectWifiDisplay(display.getDeviceAddress()); 692 } 693 }); 694 695 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 696 dialog.show(); 697 } 698 699 private void updateWifiDisplayStatus() { 700 applyWifiDisplayStatus(mDisplayManager.getWifiDisplayStatus()); 701 } 702 703 private void applyWifiDisplayStatus(WifiDisplayStatus status) { 704 mWifiDisplayStatus = status; 705 706 mWifiDisplayListAdapter.clear(); 707 mWifiDisplayListAdapter.addAll(status.getKnownDisplays()); 708 if (status.getActiveDisplay() != null 709 && !contains(status.getKnownDisplays(), status.getActiveDisplay())) { 710 mWifiDisplayListAdapter.add(status.getActiveDisplay()); 711 } 712 mWifiDisplayListAdapter.sort(mWifiDisplayComparator); 713 714 mModel.onWifiDisplayStateChanged(status); 715 } 716 717 private static boolean contains(WifiDisplay[] displays, WifiDisplay display) { 718 for (WifiDisplay d : displays) { 719 if (d.equals(display)) { 720 return true; 721 } 722 } 723 return false; 724 } 725 726 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 727 @Override 728 public void onReceive(Context context, Intent intent) { 729 if (intent.getAction().equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) { 730 WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra( 731 DisplayManager.EXTRA_WIFI_DISPLAY_STATUS); 732 applyWifiDisplayStatus(status); 733 } 734 } 735 }; 736 737 private final class WifiDisplayListAdapter extends ArrayAdapter<WifiDisplay> { 738 private final LayoutInflater mInflater; 739 740 public WifiDisplayListAdapter(Context context) { 741 super(context, android.R.layout.simple_list_item_2); 742 mInflater = LayoutInflater.from(context); 743 } 744 745 @Override 746 public View getView(int position, View convertView, ViewGroup parent) { 747 WifiDisplay item = getItem(position); 748 View view = convertView; 749 if (view == null) { 750 view = mInflater.inflate(android.R.layout.simple_list_item_2, 751 parent, false); 752 } 753 TextView headline = (TextView) view.findViewById(android.R.id.text1); 754 TextView subText = (TextView) view.findViewById(android.R.id.text2); 755 headline.setText(item.getDeviceName()); 756 757 int state = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 758 if (item.equals(mWifiDisplayStatus.getActiveDisplay())) { 759 state = mWifiDisplayStatus.getActiveDisplayState(); 760 } 761 switch (state) { 762 case WifiDisplayStatus.DISPLAY_STATE_CONNECTING: 763 subText.setText(R.string.wifi_display_state_connecting); 764 break; 765 case WifiDisplayStatus.DISPLAY_STATE_CONNECTED: 766 subText.setText(R.string.wifi_display_state_connected); 767 break; 768 case WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED: 769 default: 770 subText.setText(R.string.wifi_display_state_available); 771 break; 772 } 773 return view; 774 } 775 } 776 777 private final Comparator<WifiDisplay> mWifiDisplayComparator = new Comparator<WifiDisplay>() { 778 @Override 779 public int compare(WifiDisplay lhs, WifiDisplay rhs) { 780 int c = lhs.getDeviceName().compareToIgnoreCase(rhs.getDeviceName()); 781 if (c == 0) { 782 c = lhs.getDeviceAddress().compareToIgnoreCase(rhs.getDeviceAddress()); 783 } 784 return c; 785 } 786 }; 787}