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