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