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