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.settings.wfd; 18 19 import android.app.ActionBar; 20 import android.app.Activity; 21 import android.app.AlertDialog; 22 import android.app.Service; 23 import android.content.BroadcastReceiver; 24 import android.content.Context; 25 import android.content.DialogInterface; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.database.ContentObserver; 29 import android.hardware.display.DisplayManager; 30 import android.hardware.display.WifiDisplay; 31 import android.hardware.display.WifiDisplayStatus; 32 import android.media.MediaRouter; 33 import android.media.MediaRouter.RouteInfo; 34 import android.net.Uri; 35 import android.net.wifi.p2p.WifiP2pManager; 36 import android.net.wifi.p2p.WifiP2pManager.ActionListener; 37 import android.net.wifi.p2p.WifiP2pManager.Channel; 38 import android.net.wifi.WpsInfo; 39 import android.os.Bundle; 40 import android.os.Handler; 41 import android.os.Looper; 42 import android.preference.CheckBoxPreference; 43 import android.preference.ListPreference; 44 import android.preference.Preference; 45 import android.preference.PreferenceActivity; 46 import android.preference.PreferenceCategory; 47 import android.preference.PreferenceGroup; 48 import android.preference.PreferenceScreen; 49 import android.provider.Settings; 50 import android.text.Html; 51 import android.util.Slog; 52 import android.util.TypedValue; 53 import android.view.Gravity; 54 import android.view.LayoutInflater; 55 import android.view.Menu; 56 import android.view.MenuInflater; 57 import android.view.MenuItem; 58 import android.view.View; 59 import android.view.View.OnClickListener; 60 import android.view.ViewGroup; 61 import android.widget.Button; 62 import android.widget.CompoundButton; 63 import android.widget.EditText; 64 import android.widget.ImageView; 65 import android.widget.Switch; 66 import android.widget.TextView; 67 68 import com.android.internal.app.MediaRouteDialogPresenter; 69 import com.android.settings.ProgressCategory; 70 import com.android.settings.R; 71 import com.android.settings.SettingsPreferenceFragment; 72 73 /** 74 * The Settings screen for WifiDisplay configuration and connection management. 75 * 76 * The wifi display routes are integrated together with other remote display routes 77 * from the media router. It may happen that wifi display isn't actually available 78 * on the system. In that case, the enable option will not be shown but other 79 * remote display routes will continue to be made available. 80 */ 81 public final class WifiDisplaySettings extends SettingsPreferenceFragment { 82 private static final String TAG = "WifiDisplaySettings"; 83 private static final boolean DEBUG = false; 84 85 private static final int MENU_ID_ENABLE_WIFI_DISPLAY = Menu.FIRST; 86 87 private static final int CHANGE_SETTINGS = 1 << 0; 88 private static final int CHANGE_ROUTES = 1 << 1; 89 private static final int CHANGE_WIFI_DISPLAY_STATUS = 1 << 2; 90 private static final int CHANGE_ALL = -1; 91 92 private static final int ORDER_CERTIFICATION = 1; 93 private static final int ORDER_CONNECTED = 2; 94 private static final int ORDER_AVAILABLE = 3; 95 private static final int ORDER_UNAVAILABLE = 4; 96 97 private final Handler mHandler; 98 99 private MediaRouter mRouter; 100 private DisplayManager mDisplayManager; 101 102 private boolean mStarted; 103 private int mPendingChanges; 104 105 private boolean mWifiDisplayOnSetting; 106 private WifiDisplayStatus mWifiDisplayStatus; 107 108 private TextView mEmptyView; 109 110 /* certification */ 111 private boolean mWifiDisplayCertificationOn; 112 private WifiP2pManager mWifiP2pManager; 113 private Channel mWifiP2pChannel; 114 private PreferenceGroup mCertCategory; 115 private boolean mListen; 116 private boolean mAutoGO; 117 private int mWpsConfig = WpsInfo.INVALID; 118 private int mListenChannel; 119 private int mOperatingChannel; 120 121 public WifiDisplaySettings() { 122 mHandler = new Handler(); 123 } 124 125 @Override 126 public void onCreate(Bundle icicle) { 127 super.onCreate(icicle); 128 129 final Context context = getActivity(); 130 mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE); 131 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 132 mWifiP2pManager = (WifiP2pManager)context.getSystemService(Context.WIFI_P2P_SERVICE); 133 mWifiP2pChannel = mWifiP2pManager.initialize(context, Looper.getMainLooper(), null); 134 135 addPreferencesFromResource(R.xml.wifi_display_settings); 136 setHasOptionsMenu(true); 137 } 138 139 @Override 140 protected int getHelpResource() { 141 return R.string.help_url_remote_display; 142 } 143 144 @Override 145 public void onActivityCreated(Bundle savedInstanceState) { 146 super.onActivityCreated(savedInstanceState); 147 148 mEmptyView = (TextView) getView().findViewById(android.R.id.empty); 149 mEmptyView.setText(R.string.wifi_display_no_devices_found); 150 getListView().setEmptyView(mEmptyView); 151 } 152 153 @Override 154 public void onStart() { 155 super.onStart(); 156 mStarted = true; 157 158 final Context context = getActivity(); 159 IntentFilter filter = new IntentFilter(); 160 filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 161 context.registerReceiver(mReceiver, filter); 162 163 getContentResolver().registerContentObserver(Settings.Global.getUriFor( 164 Settings.Global.WIFI_DISPLAY_ON), false, mSettingsObserver); 165 getContentResolver().registerContentObserver(Settings.Global.getUriFor( 166 Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON), false, mSettingsObserver); 167 getContentResolver().registerContentObserver(Settings.Global.getUriFor( 168 Settings.Global.WIFI_DISPLAY_WPS_CONFIG), false, mSettingsObserver); 169 170 mRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mRouterCallback, 171 MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); 172 173 update(CHANGE_ALL); 174 } 175 176 @Override 177 public void onStop() { 178 super.onStop(); 179 mStarted = false; 180 181 final Context context = getActivity(); 182 context.unregisterReceiver(mReceiver); 183 184 getContentResolver().unregisterContentObserver(mSettingsObserver); 185 186 mRouter.removeCallback(mRouterCallback); 187 188 unscheduleUpdate(); 189 } 190 191 @Override 192 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 193 if (mWifiDisplayStatus != null && mWifiDisplayStatus.getFeatureState() 194 != WifiDisplayStatus.FEATURE_STATE_UNAVAILABLE) { 195 MenuItem item = menu.add(Menu.NONE, MENU_ID_ENABLE_WIFI_DISPLAY, 0, 196 R.string.wifi_display_enable_menu_item); 197 item.setCheckable(true); 198 item.setChecked(mWifiDisplayOnSetting); 199 } 200 super.onCreateOptionsMenu(menu, inflater); 201 } 202 203 @Override 204 public boolean onOptionsItemSelected(MenuItem item) { 205 switch (item.getItemId()) { 206 case MENU_ID_ENABLE_WIFI_DISPLAY: 207 mWifiDisplayOnSetting = !item.isChecked(); 208 item.setChecked(mWifiDisplayOnSetting); 209 Settings.Global.putInt(getContentResolver(), 210 Settings.Global.WIFI_DISPLAY_ON, mWifiDisplayOnSetting ? 1 : 0); 211 return true; 212 } 213 return super.onOptionsItemSelected(item); 214 } 215 216 private void scheduleUpdate(int changes) { 217 if (mStarted) { 218 if (mPendingChanges == 0) { 219 mHandler.post(mUpdateRunnable); 220 } 221 mPendingChanges |= changes; 222 } 223 } 224 225 private void unscheduleUpdate() { 226 if (mPendingChanges != 0) { 227 mPendingChanges = 0; 228 mHandler.removeCallbacks(mUpdateRunnable); 229 } 230 } 231 232 private void update(int changes) { 233 boolean invalidateOptions = false; 234 235 // Update settings. 236 if ((changes & CHANGE_SETTINGS) != 0) { 237 mWifiDisplayOnSetting = Settings.Global.getInt(getContentResolver(), 238 Settings.Global.WIFI_DISPLAY_ON, 0) != 0; 239 mWifiDisplayCertificationOn = Settings.Global.getInt(getContentResolver(), 240 Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON, 0) != 0; 241 mWpsConfig = Settings.Global.getInt(getContentResolver(), 242 Settings.Global.WIFI_DISPLAY_WPS_CONFIG, WpsInfo.INVALID); 243 244 // The wifi display enabled setting may have changed. 245 invalidateOptions = true; 246 } 247 248 // Update wifi display state. 249 if ((changes & CHANGE_WIFI_DISPLAY_STATUS) != 0) { 250 mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus(); 251 252 // The wifi display feature state may have changed. 253 invalidateOptions = true; 254 } 255 256 // Rebuild the routes. 257 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 258 preferenceScreen.removeAll(); 259 260 // Add all known remote display routes. 261 final int routeCount = mRouter.getRouteCount(); 262 for (int i = 0; i < routeCount; i++) { 263 MediaRouter.RouteInfo route = mRouter.getRouteAt(i); 264 if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)) { 265 preferenceScreen.addPreference(createRoutePreference(route)); 266 } 267 } 268 269 // Additional features for wifi display routes. 270 if (mWifiDisplayStatus != null 271 && mWifiDisplayStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) { 272 // Add all unpaired wifi displays. 273 for (WifiDisplay display : mWifiDisplayStatus.getDisplays()) { 274 if (!display.isRemembered() && display.isAvailable() 275 && !display.equals(mWifiDisplayStatus.getActiveDisplay())) { 276 preferenceScreen.addPreference(new UnpairedWifiDisplayPreference( 277 getActivity(), display)); 278 } 279 } 280 281 // Add the certification menu if enabled in developer options. 282 if (mWifiDisplayCertificationOn) { 283 buildCertificationMenu(preferenceScreen); 284 } 285 } 286 287 // Invalidate menu options if needed. 288 if (invalidateOptions) { 289 getActivity().invalidateOptionsMenu(); 290 } 291 } 292 293 private RoutePreference createRoutePreference(MediaRouter.RouteInfo route) { 294 WifiDisplay display = findWifiDisplay(route.getDeviceAddress()); 295 if (display != null) { 296 return new WifiDisplayRoutePreference(getActivity(), route, display); 297 } else { 298 return new RoutePreference(getActivity(), route); 299 } 300 } 301 302 private WifiDisplay findWifiDisplay(String deviceAddress) { 303 if (mWifiDisplayStatus != null && deviceAddress != null) { 304 for (WifiDisplay display : mWifiDisplayStatus.getDisplays()) { 305 if (display.getDeviceAddress().equals(deviceAddress)) { 306 return display; 307 } 308 } 309 } 310 return null; 311 } 312 313 private void buildCertificationMenu(final PreferenceScreen preferenceScreen) { 314 if (mCertCategory == null) { 315 mCertCategory = new PreferenceCategory(getActivity()); 316 mCertCategory.setTitle(R.string.wifi_display_certification_heading); 317 mCertCategory.setOrder(ORDER_CERTIFICATION); 318 } else { 319 mCertCategory.removeAll(); 320 } 321 preferenceScreen.addPreference(mCertCategory); 322 323 // display session info if there is an active p2p session 324 if (!mWifiDisplayStatus.getSessionInfo().getGroupId().isEmpty()) { 325 Preference p = new Preference(getActivity()); 326 p.setTitle(R.string.wifi_display_session_info); 327 p.setSummary(mWifiDisplayStatus.getSessionInfo().toString()); 328 mCertCategory.addPreference(p); 329 330 // show buttons for Pause/Resume when a WFD session is established 331 if (mWifiDisplayStatus.getSessionInfo().getSessionId() != 0) { 332 mCertCategory.addPreference(new Preference(getActivity()) { 333 @Override 334 public View getView(View convertView, ViewGroup parent) { 335 final View v; 336 if (convertView == null) { 337 LayoutInflater li = (LayoutInflater) getActivity(). 338 getSystemService(Service.LAYOUT_INFLATER_SERVICE); 339 v = li.inflate(R.layout.two_buttons_panel, null); 340 } else { 341 v = convertView; 342 } 343 344 Button b = (Button)v.findViewById(R.id.left_button); 345 b.setText(R.string.wifi_display_pause); 346 b.setOnClickListener(new OnClickListener() { 347 @Override 348 public void onClick(View v) { 349 mDisplayManager.pauseWifiDisplay(); 350 } 351 }); 352 353 b = (Button)v.findViewById(R.id.right_button); 354 b.setText(R.string.wifi_display_resume); 355 b.setOnClickListener(new OnClickListener() { 356 @Override 357 public void onClick(View v) { 358 mDisplayManager.resumeWifiDisplay(); 359 } 360 }); 361 362 return v; 363 } 364 }); 365 } 366 } 367 368 // switch for Listen Mode 369 CheckBoxPreference cbp = new CheckBoxPreference(getActivity()) { 370 @Override 371 protected void onClick() { 372 mListen = !mListen; 373 setListenMode(mListen); 374 setChecked(mListen); 375 } 376 }; 377 cbp.setTitle(R.string.wifi_display_listen_mode); 378 cbp.setChecked(mListen); 379 mCertCategory.addPreference(cbp); 380 381 // switch for Autonomous GO 382 cbp = new CheckBoxPreference(getActivity()) { 383 @Override 384 protected void onClick() { 385 mAutoGO = !mAutoGO; 386 if (mAutoGO) { 387 startAutoGO(); 388 } else { 389 stopAutoGO(); 390 } 391 setChecked(mAutoGO); 392 } 393 }; 394 cbp.setTitle(R.string.wifi_display_autonomous_go); 395 cbp.setChecked(mAutoGO); 396 mCertCategory.addPreference(cbp); 397 398 // Drop down list for choosing WPS method (PBC/KEYPAD/DISPLAY) 399 ListPreference lp = new ListPreference(getActivity()) { 400 @Override 401 protected void onDialogClosed(boolean positiveResult) { 402 super.onDialogClosed(positiveResult); 403 if (positiveResult) { 404 mWpsConfig = Integer.parseInt(getValue()); 405 setSummary("%1$s"); 406 getActivity().invalidateOptionsMenu(); 407 Settings.Global.putInt(getActivity().getContentResolver(), 408 Settings.Global.WIFI_DISPLAY_WPS_CONFIG, mWpsConfig); 409 } 410 } 411 }; 412 mWpsConfig = Settings.Global.getInt(getActivity().getContentResolver(), 413 Settings.Global.WIFI_DISPLAY_WPS_CONFIG, WpsInfo.INVALID); 414 String[] wpsEntries = { "Default", "PBC", "KEYPAD", "DISPLAY" }; 415 String[] wpsValues = { 416 "" + WpsInfo.INVALID, 417 "" + WpsInfo.PBC, 418 "" + WpsInfo.KEYPAD, 419 "" + WpsInfo.DISPLAY }; 420 lp.setTitle(R.string.wifi_display_wps_config); 421 lp.setEntries(wpsEntries); 422 lp.setEntryValues(wpsValues); 423 lp.setValue("" + mWpsConfig); 424 lp.setSummary("%1$s"); 425 mCertCategory.addPreference(lp); 426 427 // Drop down list for choosing listen channel 428 lp = new ListPreference(getActivity()) { 429 @Override 430 protected void onDialogClosed(boolean positiveResult) { 431 super.onDialogClosed(positiveResult); 432 if (positiveResult) { 433 mListenChannel = Integer.parseInt(getValue()); 434 setSummary("%1$s"); 435 getActivity().invalidateOptionsMenu(); 436 setWifiP2pChannels(mListenChannel, mOperatingChannel); 437 } 438 } 439 }; 440 String[] lcEntries = { "Auto", "1", "6", "11" }; 441 String[] lcValues = { "0", "1", "6", "11" }; 442 lp.setTitle(R.string.wifi_display_listen_channel); 443 lp.setEntries(lcEntries); 444 lp.setEntryValues(lcValues); 445 lp.setValue("" + mListenChannel); 446 lp.setSummary("%1$s"); 447 mCertCategory.addPreference(lp); 448 449 // Drop down list for choosing operating channel 450 lp = new ListPreference(getActivity()) { 451 @Override 452 protected void onDialogClosed(boolean positiveResult) { 453 super.onDialogClosed(positiveResult); 454 if (positiveResult) { 455 mOperatingChannel = Integer.parseInt(getValue()); 456 setSummary("%1$s"); 457 getActivity().invalidateOptionsMenu(); 458 setWifiP2pChannels(mListenChannel, mOperatingChannel); 459 } 460 } 461 }; 462 String[] ocEntries = { "Auto", "1", "6", "11", "36" }; 463 String[] ocValues = { "0", "1", "6", "11", "36" }; 464 lp.setTitle(R.string.wifi_display_operating_channel); 465 lp.setEntries(ocEntries); 466 lp.setEntryValues(ocValues); 467 lp.setValue("" + mOperatingChannel); 468 lp.setSummary("%1$s"); 469 mCertCategory.addPreference(lp); 470 } 471 472 private void startAutoGO() { 473 if (DEBUG) { 474 Slog.d(TAG, "Starting Autonomous GO..."); 475 } 476 mWifiP2pManager.createGroup(mWifiP2pChannel, new ActionListener() { 477 @Override 478 public void onSuccess() { 479 if (DEBUG) { 480 Slog.d(TAG, "Successfully started AutoGO."); 481 } 482 } 483 484 @Override 485 public void onFailure(int reason) { 486 Slog.e(TAG, "Failed to start AutoGO with reason " + reason + "."); 487 } 488 }); 489 } 490 491 private void stopAutoGO() { 492 if (DEBUG) { 493 Slog.d(TAG, "Stopping Autonomous GO..."); 494 } 495 mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() { 496 @Override 497 public void onSuccess() { 498 if (DEBUG) { 499 Slog.d(TAG, "Successfully stopped AutoGO."); 500 } 501 } 502 503 @Override 504 public void onFailure(int reason) { 505 Slog.e(TAG, "Failed to stop AutoGO with reason " + reason + "."); 506 } 507 }); 508 } 509 510 private void setListenMode(final boolean enable) { 511 if (DEBUG) { 512 Slog.d(TAG, "Setting listen mode to: " + enable); 513 } 514 mWifiP2pManager.listen(mWifiP2pChannel, enable, new ActionListener() { 515 @Override 516 public void onSuccess() { 517 if (DEBUG) { 518 Slog.d(TAG, "Successfully " + (enable ? "entered" : "exited") 519 +" listen mode."); 520 } 521 } 522 523 @Override 524 public void onFailure(int reason) { 525 Slog.e(TAG, "Failed to " + (enable ? "entered" : "exited") 526 +" listen mode with reason " + reason + "."); 527 } 528 }); 529 } 530 531 private void setWifiP2pChannels(final int lc, final int oc) { 532 if (DEBUG) { 533 Slog.d(TAG, "Setting wifi p2p channel: lc=" + lc + ", oc=" + oc); 534 } 535 mWifiP2pManager.setWifiP2pChannels(mWifiP2pChannel, 536 lc, oc, new ActionListener() { 537 @Override 538 public void onSuccess() { 539 if (DEBUG) { 540 Slog.d(TAG, "Successfully set wifi p2p channels."); 541 } 542 } 543 544 @Override 545 public void onFailure(int reason) { 546 Slog.e(TAG, "Failed to set wifi p2p channels with reason " + reason + "."); 547 } 548 }); 549 } 550 551 private void toggleRoute(MediaRouter.RouteInfo route) { 552 if (route.isSelected()) { 553 MediaRouteDialogPresenter.showDialogFragment(getActivity(), 554 MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, null); 555 } else { 556 route.select(); 557 } 558 } 559 560 private void pairWifiDisplay(WifiDisplay display) { 561 if (display.canConnect()) { 562 mDisplayManager.connectWifiDisplay(display.getDeviceAddress()); 563 } 564 } 565 566 private void showWifiDisplayOptionsDialog(final WifiDisplay display) { 567 View view = getActivity().getLayoutInflater().inflate(R.layout.wifi_display_options, null); 568 final EditText nameEditText = (EditText)view.findViewById(R.id.name); 569 nameEditText.setText(display.getFriendlyDisplayName()); 570 571 DialogInterface.OnClickListener done = new DialogInterface.OnClickListener() { 572 @Override 573 public void onClick(DialogInterface dialog, int which) { 574 String name = nameEditText.getText().toString().trim(); 575 if (name.isEmpty() || name.equals(display.getDeviceName())) { 576 name = null; 577 } 578 mDisplayManager.renameWifiDisplay(display.getDeviceAddress(), name); 579 } 580 }; 581 DialogInterface.OnClickListener forget = new DialogInterface.OnClickListener() { 582 @Override 583 public void onClick(DialogInterface dialog, int which) { 584 mDisplayManager.forgetWifiDisplay(display.getDeviceAddress()); 585 } 586 }; 587 588 AlertDialog dialog = new AlertDialog.Builder(getActivity()) 589 .setCancelable(true) 590 .setTitle(R.string.wifi_display_options_title) 591 .setView(view) 592 .setPositiveButton(R.string.wifi_display_options_done, done) 593 .setNegativeButton(R.string.wifi_display_options_forget, forget) 594 .create(); 595 dialog.show(); 596 } 597 598 private final Runnable mUpdateRunnable = new Runnable() { 599 @Override 600 public void run() { 601 final int changes = mPendingChanges; 602 mPendingChanges = 0; 603 update(changes); 604 } 605 }; 606 607 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 608 @Override 609 public void onReceive(Context context, Intent intent) { 610 String action = intent.getAction(); 611 if (action.equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) { 612 scheduleUpdate(CHANGE_WIFI_DISPLAY_STATUS); 613 } 614 } 615 }; 616 617 private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) { 618 @Override 619 public void onChange(boolean selfChange, Uri uri) { 620 scheduleUpdate(CHANGE_SETTINGS); 621 } 622 }; 623 624 private final MediaRouter.Callback mRouterCallback = new MediaRouter.SimpleCallback() { 625 @Override 626 public void onRouteAdded(MediaRouter router, RouteInfo info) { 627 scheduleUpdate(CHANGE_ROUTES); 628 } 629 630 @Override 631 public void onRouteChanged(MediaRouter router, RouteInfo info) { 632 scheduleUpdate(CHANGE_ROUTES); 633 } 634 635 @Override 636 public void onRouteRemoved(MediaRouter router, RouteInfo info) { 637 scheduleUpdate(CHANGE_ROUTES); 638 } 639 640 @Override 641 public void onRouteSelected(MediaRouter router, int type, RouteInfo info) { 642 scheduleUpdate(CHANGE_ROUTES); 643 } 644 645 @Override 646 public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) { 647 scheduleUpdate(CHANGE_ROUTES); 648 } 649 }; 650 651 private class RoutePreference extends Preference 652 implements Preference.OnPreferenceClickListener { 653 private final MediaRouter.RouteInfo mRoute; 654 655 public RoutePreference(Context context, MediaRouter.RouteInfo route) { 656 super(context); 657 658 mRoute = route; 659 setTitle(route.getName()); 660 setSummary(route.getDescription()); 661 setEnabled(route.isEnabled()); 662 if (route.isSelected()) { 663 setOrder(ORDER_CONNECTED); 664 if (route.isConnecting()) { 665 setSummary(R.string.wifi_display_status_connecting); 666 } else { 667 setSummary(R.string.wifi_display_status_connected); 668 } 669 } else { 670 if (isEnabled()) { 671 setOrder(ORDER_AVAILABLE); 672 } else { 673 setOrder(ORDER_UNAVAILABLE); 674 if (route.getStatusCode() == MediaRouter.RouteInfo.STATUS_IN_USE) { 675 setSummary(R.string.wifi_display_status_in_use); 676 } else { 677 setSummary(R.string.wifi_display_status_not_available); 678 } 679 } 680 } 681 setOnPreferenceClickListener(this); 682 } 683 684 @Override 685 public boolean onPreferenceClick(Preference preference) { 686 toggleRoute(mRoute); 687 return true; 688 } 689 } 690 691 private class WifiDisplayRoutePreference extends RoutePreference 692 implements View.OnClickListener { 693 private final WifiDisplay mDisplay; 694 695 public WifiDisplayRoutePreference(Context context, MediaRouter.RouteInfo route, 696 WifiDisplay display) { 697 super(context, route); 698 699 mDisplay = display; 700 setWidgetLayoutResource(R.layout.wifi_display_preference); 701 } 702 703 @Override 704 protected void onBindView(View view) { 705 super.onBindView(view); 706 707 ImageView deviceDetails = (ImageView) view.findViewById(R.id.deviceDetails); 708 if (deviceDetails != null) { 709 deviceDetails.setOnClickListener(this); 710 if (!isEnabled()) { 711 TypedValue value = new TypedValue(); 712 getContext().getTheme().resolveAttribute(android.R.attr.disabledAlpha, 713 value, true); 714 deviceDetails.setImageAlpha((int)(value.getFloat() * 255)); 715 deviceDetails.setEnabled(true); // always allow button to be pressed 716 } 717 } 718 } 719 720 @Override 721 public void onClick(View v) { 722 showWifiDisplayOptionsDialog(mDisplay); 723 } 724 } 725 726 private class UnpairedWifiDisplayPreference extends Preference 727 implements Preference.OnPreferenceClickListener { 728 private final WifiDisplay mDisplay; 729 730 public UnpairedWifiDisplayPreference(Context context, WifiDisplay display) { 731 super(context); 732 733 mDisplay = display; 734 setTitle(display.getFriendlyDisplayName()); 735 setSummary(com.android.internal.R.string.wireless_display_route_description); 736 setEnabled(display.canConnect()); 737 if (isEnabled()) { 738 setOrder(ORDER_AVAILABLE); 739 } else { 740 setOrder(ORDER_UNAVAILABLE); 741 setSummary(R.string.wifi_display_status_in_use); 742 } 743 setOnPreferenceClickListener(this); 744 } 745 746 @Override 747 public boolean onPreferenceClick(Preference preference) { 748 pairWifiDisplay(mDisplay); 749 return true; 750 } 751 } 752 } 753