2 * Copyright (C) 2012 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.wfd;
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.os.ServiceManager;
40 import android.provider.Settings;
41 import android.support.v14.preference.SwitchPreference;
42 import android.support.v7.preference.ListPreference;
43 import android.support.v7.preference.Preference;
44 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
45 import android.support.v7.preference.PreferenceCategory;
46 import android.support.v7.preference.PreferenceGroup;
47 import android.support.v7.preference.PreferenceScreen;
48 import android.support.v7.preference.PreferenceViewHolder;
49 import android.util.Slog;
50 import android.util.TypedValue;
51 import android.view.Menu;
52 import android.view.MenuInflater;
53 import android.view.MenuItem;
54 import android.view.View;
55 import android.view.View.OnClickListener;
56 import android.widget.Button;
57 import android.widget.EditText;
58 import android.widget.ImageView;
59 import android.widget.TextView;
61 import com.android.internal.app.MediaRouteDialogPresenter;
62 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
63 import com.android.settings.R;
64 import com.android.settings.SettingsPreferenceFragment;
65 import com.android.settings.dashboard.SummaryLoader;
68 * The Settings screen for WifiDisplay configuration and connection management.
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.
75 public final class WifiDisplaySettings extends SettingsPreferenceFragment {
76 private static final String TAG = "WifiDisplaySettings";
77 private static final boolean DEBUG = false;
79 private static final int MENU_ID_ENABLE_WIFI_DISPLAY = Menu.FIRST;
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;
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;
91 private final Handler mHandler;
93 private MediaRouter mRouter;
94 private DisplayManager mDisplayManager;
96 private boolean mStarted;
97 private int mPendingChanges;
99 private boolean mWifiDisplayOnSetting;
100 private WifiDisplayStatus mWifiDisplayStatus;
102 private TextView mEmptyView;
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;
115 public WifiDisplaySettings() {
116 mHandler = new Handler();
120 public int getMetricsCategory() {
121 return MetricsEvent.WFD_WIFI_DISPLAY;
125 public void onCreate(Bundle icicle) {
126 super.onCreate(icicle);
128 final Context context = getActivity();
129 mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
130 mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
131 mWifiP2pManager = (WifiP2pManager) context.getSystemService(Context.WIFI_P2P_SERVICE);
132 mWifiP2pChannel = mWifiP2pManager.initialize(context, Looper.getMainLooper(), null);
134 addPreferencesFromResource(R.xml.wifi_display_settings);
135 setHasOptionsMenu(true);
139 protected int getHelpResource() {
140 return R.string.help_url_remote_display;
144 public void onActivityCreated(Bundle savedInstanceState) {
145 super.onActivityCreated(savedInstanceState);
147 mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
148 mEmptyView.setText(R.string.wifi_display_no_devices_found);
149 setEmptyView(mEmptyView);
153 public void onStart() {
157 final Context context = getActivity();
158 IntentFilter filter = new IntentFilter();
159 filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
160 context.registerReceiver(mReceiver, filter);
162 getContentResolver().registerContentObserver(Settings.Global.getUriFor(
163 Settings.Global.WIFI_DISPLAY_ON), false, mSettingsObserver);
164 getContentResolver().registerContentObserver(Settings.Global.getUriFor(
165 Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON), false, mSettingsObserver);
166 getContentResolver().registerContentObserver(Settings.Global.getUriFor(
167 Settings.Global.WIFI_DISPLAY_WPS_CONFIG), false, mSettingsObserver);
169 mRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mRouterCallback,
170 MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
176 public void onStop() {
180 final Context context = getActivity();
181 context.unregisterReceiver(mReceiver);
183 getContentResolver().unregisterContentObserver(mSettingsObserver);
185 mRouter.removeCallback(mRouterCallback);
191 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
192 if (mWifiDisplayStatus != null && mWifiDisplayStatus.getFeatureState()
193 != WifiDisplayStatus.FEATURE_STATE_UNAVAILABLE) {
194 MenuItem item = menu.add(Menu.NONE, MENU_ID_ENABLE_WIFI_DISPLAY, 0,
195 R.string.wifi_display_enable_menu_item);
196 item.setCheckable(true);
197 item.setChecked(mWifiDisplayOnSetting);
199 super.onCreateOptionsMenu(menu, inflater);
203 public boolean onOptionsItemSelected(MenuItem item) {
204 switch (item.getItemId()) {
205 case MENU_ID_ENABLE_WIFI_DISPLAY:
206 mWifiDisplayOnSetting = !item.isChecked();
207 item.setChecked(mWifiDisplayOnSetting);
208 Settings.Global.putInt(getContentResolver(),
209 Settings.Global.WIFI_DISPLAY_ON, mWifiDisplayOnSetting ? 1 : 0);
212 return super.onOptionsItemSelected(item);
215 public static boolean isAvailable(Context context) {
217 return context.getSystemService(Context.DISPLAY_SERVICE) != null
218 && context.getSystemService(Context.WIFI_P2P_SERVICE) != null;
219 } catch (Exception e) {
220 // Service is not registered, so this is definitely not available.
225 private void scheduleUpdate(int changes) {
227 if (mPendingChanges == 0) {
228 mHandler.post(mUpdateRunnable);
230 mPendingChanges |= changes;
234 private void unscheduleUpdate() {
235 if (mPendingChanges != 0) {
237 mHandler.removeCallbacks(mUpdateRunnable);
241 private void update(int changes) {
242 boolean invalidateOptions = false;
245 if ((changes & CHANGE_SETTINGS) != 0) {
246 mWifiDisplayOnSetting = Settings.Global.getInt(getContentResolver(),
247 Settings.Global.WIFI_DISPLAY_ON, 0) != 0;
248 mWifiDisplayCertificationOn = Settings.Global.getInt(getContentResolver(),
249 Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON, 0) != 0;
250 mWpsConfig = Settings.Global.getInt(getContentResolver(),
251 Settings.Global.WIFI_DISPLAY_WPS_CONFIG, WpsInfo.INVALID);
253 // The wifi display enabled setting may have changed.
254 invalidateOptions = true;
257 // Update wifi display state.
258 if ((changes & CHANGE_WIFI_DISPLAY_STATUS) != 0) {
259 mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
261 // The wifi display feature state may have changed.
262 invalidateOptions = true;
265 // Rebuild the routes.
266 final PreferenceScreen preferenceScreen = getPreferenceScreen();
267 preferenceScreen.removeAll();
269 // Add all known remote display routes.
270 final int routeCount = mRouter.getRouteCount();
271 for (int i = 0; i < routeCount; i++) {
272 MediaRouter.RouteInfo route = mRouter.getRouteAt(i);
273 if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)) {
274 preferenceScreen.addPreference(createRoutePreference(route));
278 // Additional features for wifi display routes.
279 if (mWifiDisplayStatus != null
280 && mWifiDisplayStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) {
281 // Add all unpaired wifi displays.
282 for (WifiDisplay display : mWifiDisplayStatus.getDisplays()) {
283 if (!display.isRemembered() && display.isAvailable()
284 && !display.equals(mWifiDisplayStatus.getActiveDisplay())) {
285 preferenceScreen.addPreference(new UnpairedWifiDisplayPreference(
286 getPrefContext(), display));
290 // Add the certification menu if enabled in developer options.
291 if (mWifiDisplayCertificationOn) {
292 buildCertificationMenu(preferenceScreen);
296 // Invalidate menu options if needed.
297 if (invalidateOptions) {
298 getActivity().invalidateOptionsMenu();
302 private RoutePreference createRoutePreference(MediaRouter.RouteInfo route) {
303 WifiDisplay display = findWifiDisplay(route.getDeviceAddress());
304 if (display != null) {
305 return new WifiDisplayRoutePreference(getPrefContext(), route, display);
307 return new RoutePreference(getPrefContext(), route);
311 private WifiDisplay findWifiDisplay(String deviceAddress) {
312 if (mWifiDisplayStatus != null && deviceAddress != null) {
313 for (WifiDisplay display : mWifiDisplayStatus.getDisplays()) {
314 if (display.getDeviceAddress().equals(deviceAddress)) {
322 private void buildCertificationMenu(final PreferenceScreen preferenceScreen) {
323 if (mCertCategory == null) {
324 mCertCategory = new PreferenceCategory(getPrefContext());
325 mCertCategory.setTitle(R.string.wifi_display_certification_heading);
326 mCertCategory.setOrder(ORDER_CERTIFICATION);
328 mCertCategory.removeAll();
330 preferenceScreen.addPreference(mCertCategory);
332 // display session info if there is an active p2p session
333 if (!mWifiDisplayStatus.getSessionInfo().getGroupId().isEmpty()) {
334 Preference p = new Preference(getPrefContext());
335 p.setTitle(R.string.wifi_display_session_info);
336 p.setSummary(mWifiDisplayStatus.getSessionInfo().toString());
337 mCertCategory.addPreference(p);
339 // show buttons for Pause/Resume when a WFD session is established
340 if (mWifiDisplayStatus.getSessionInfo().getSessionId() != 0) {
341 mCertCategory.addPreference(new Preference(getPrefContext()) {
343 public void onBindViewHolder(PreferenceViewHolder view) {
344 super.onBindViewHolder(view);
346 Button b = (Button) view.findViewById(R.id.left_button);
347 b.setText(R.string.wifi_display_pause);
348 b.setOnClickListener(new OnClickListener() {
350 public void onClick(View v) {
351 mDisplayManager.pauseWifiDisplay();
355 b = (Button) view.findViewById(R.id.right_button);
356 b.setText(R.string.wifi_display_resume);
357 b.setOnClickListener(new OnClickListener() {
359 public void onClick(View v) {
360 mDisplayManager.resumeWifiDisplay();
365 mCertCategory.setLayoutResource(R.layout.two_buttons_panel);
369 // switch for Listen Mode
370 SwitchPreference pref = new SwitchPreference(getPrefContext()) {
372 protected void onClick() {
374 setListenMode(mListen);
378 pref.setTitle(R.string.wifi_display_listen_mode);
379 pref.setChecked(mListen);
380 mCertCategory.addPreference(pref);
382 // switch for Autonomous GO
383 pref = new SwitchPreference(getPrefContext()) {
385 protected void onClick() {
395 pref.setTitle(R.string.wifi_display_autonomous_go);
396 pref.setChecked(mAutoGO);
397 mCertCategory.addPreference(pref);
399 // Drop down list for choosing WPS method (PBC/KEYPAD/DISPLAY)
400 ListPreference lp = new ListPreference(getPrefContext());
401 lp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
403 public boolean onPreferenceChange(Preference preference, Object value) {
404 int wpsConfig = Integer.parseInt((String) value);
405 if (wpsConfig != mWpsConfig) {
406 mWpsConfig = wpsConfig;
407 getActivity().invalidateOptionsMenu();
408 Settings.Global.putInt(getActivity().getContentResolver(),
409 Settings.Global.WIFI_DISPLAY_WPS_CONFIG, mWpsConfig);
414 mWpsConfig = Settings.Global.getInt(getActivity().getContentResolver(),
415 Settings.Global.WIFI_DISPLAY_WPS_CONFIG, WpsInfo.INVALID);
416 String[] wpsEntries = {"Default", "PBC", "KEYPAD", "DISPLAY"};
417 String[] wpsValues = {
418 "" + WpsInfo.INVALID,
421 "" + WpsInfo.DISPLAY};
423 lp.setTitle(R.string.wifi_display_wps_config);
424 lp.setEntries(wpsEntries);
425 lp.setEntryValues(wpsValues);
426 lp.setValue("" + mWpsConfig);
427 lp.setSummary("%1$s");
428 mCertCategory.addPreference(lp);
430 // Drop down list for choosing listen channel
431 lp = new ListPreference(getPrefContext());
432 lp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
434 public boolean onPreferenceChange(Preference preference, Object value) {
435 int channel = Integer.parseInt((String) value);
436 if (channel != mListenChannel) {
437 mListenChannel = channel;
438 getActivity().invalidateOptionsMenu();
439 setWifiP2pChannels(mListenChannel, mOperatingChannel);
444 String[] lcEntries = {"Auto", "1", "6", "11"};
445 String[] lcValues = {"0", "1", "6", "11"};
446 lp.setKey("listening_channel");
447 lp.setTitle(R.string.wifi_display_listen_channel);
448 lp.setEntries(lcEntries);
449 lp.setEntryValues(lcValues);
450 lp.setValue("" + mListenChannel);
451 lp.setSummary("%1$s");
452 mCertCategory.addPreference(lp);
454 // Drop down list for choosing operating channel
455 lp = new ListPreference(getPrefContext());
456 lp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
458 public boolean onPreferenceChange(Preference preference, Object value) {
459 int channel = Integer.parseInt((String) value);
460 if (channel != mOperatingChannel) {
461 mOperatingChannel = channel;
462 getActivity().invalidateOptionsMenu();
463 setWifiP2pChannels(mListenChannel, mOperatingChannel);
468 String[] ocEntries = {"Auto", "1", "6", "11", "36"};
469 String[] ocValues = {"0", "1", "6", "11", "36"};
470 lp.setKey("operating_channel");
471 lp.setTitle(R.string.wifi_display_operating_channel);
472 lp.setEntries(ocEntries);
473 lp.setEntryValues(ocValues);
474 lp.setValue("" + mOperatingChannel);
475 lp.setSummary("%1$s");
476 mCertCategory.addPreference(lp);
479 private void startAutoGO() {
481 Slog.d(TAG, "Starting Autonomous GO...");
483 mWifiP2pManager.createGroup(mWifiP2pChannel, new ActionListener() {
485 public void onSuccess() {
487 Slog.d(TAG, "Successfully started AutoGO.");
492 public void onFailure(int reason) {
493 Slog.e(TAG, "Failed to start AutoGO with reason " + reason + ".");
498 private void stopAutoGO() {
500 Slog.d(TAG, "Stopping Autonomous GO...");
502 mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() {
504 public void onSuccess() {
506 Slog.d(TAG, "Successfully stopped AutoGO.");
511 public void onFailure(int reason) {
512 Slog.e(TAG, "Failed to stop AutoGO with reason " + reason + ".");
517 private void setListenMode(final boolean enable) {
519 Slog.d(TAG, "Setting listen mode to: " + enable);
521 mWifiP2pManager.listen(mWifiP2pChannel, enable, new ActionListener() {
523 public void onSuccess() {
525 Slog.d(TAG, "Successfully " + (enable ? "entered" : "exited")
531 public void onFailure(int reason) {
532 Slog.e(TAG, "Failed to " + (enable ? "entered" : "exited")
533 + " listen mode with reason " + reason + ".");
538 private void setWifiP2pChannels(final int lc, final int oc) {
540 Slog.d(TAG, "Setting wifi p2p channel: lc=" + lc + ", oc=" + oc);
542 mWifiP2pManager.setWifiP2pChannels(mWifiP2pChannel,
543 lc, oc, new ActionListener() {
545 public void onSuccess() {
547 Slog.d(TAG, "Successfully set wifi p2p channels.");
552 public void onFailure(int reason) {
553 Slog.e(TAG, "Failed to set wifi p2p channels with reason " + reason + ".");
558 private void toggleRoute(MediaRouter.RouteInfo route) {
559 if (route.isSelected()) {
560 MediaRouteDialogPresenter.showDialogFragment(getActivity(),
561 MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, null);
567 private void pairWifiDisplay(WifiDisplay display) {
568 if (display.canConnect()) {
569 mDisplayManager.connectWifiDisplay(display.getDeviceAddress());
573 private void showWifiDisplayOptionsDialog(final WifiDisplay display) {
574 View view = getActivity().getLayoutInflater().inflate(R.layout.wifi_display_options, null);
575 final EditText nameEditText = (EditText) view.findViewById(R.id.name);
576 nameEditText.setText(display.getFriendlyDisplayName());
578 DialogInterface.OnClickListener done = new DialogInterface.OnClickListener() {
580 public void onClick(DialogInterface dialog, int which) {
581 String name = nameEditText.getText().toString().trim();
582 if (name.isEmpty() || name.equals(display.getDeviceName())) {
585 mDisplayManager.renameWifiDisplay(display.getDeviceAddress(), name);
588 DialogInterface.OnClickListener forget = new DialogInterface.OnClickListener() {
590 public void onClick(DialogInterface dialog, int which) {
591 mDisplayManager.forgetWifiDisplay(display.getDeviceAddress());
595 AlertDialog dialog = new AlertDialog.Builder(getActivity())
597 .setTitle(R.string.wifi_display_options_title)
599 .setPositiveButton(R.string.wifi_display_options_done, done)
600 .setNegativeButton(R.string.wifi_display_options_forget, forget)
605 private final Runnable mUpdateRunnable = new Runnable() {
608 final int changes = mPendingChanges;
614 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
616 public void onReceive(Context context, Intent intent) {
617 String action = intent.getAction();
618 if (action.equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
619 scheduleUpdate(CHANGE_WIFI_DISPLAY_STATUS);
624 private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
626 public void onChange(boolean selfChange, Uri uri) {
627 scheduleUpdate(CHANGE_SETTINGS);
631 private final MediaRouter.Callback mRouterCallback = new MediaRouter.SimpleCallback() {
633 public void onRouteAdded(MediaRouter router, RouteInfo info) {
634 scheduleUpdate(CHANGE_ROUTES);
638 public void onRouteChanged(MediaRouter router, RouteInfo info) {
639 scheduleUpdate(CHANGE_ROUTES);
643 public void onRouteRemoved(MediaRouter router, RouteInfo info) {
644 scheduleUpdate(CHANGE_ROUTES);
648 public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
649 scheduleUpdate(CHANGE_ROUTES);
653 public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
654 scheduleUpdate(CHANGE_ROUTES);
658 private class RoutePreference extends Preference
659 implements Preference.OnPreferenceClickListener {
660 private final MediaRouter.RouteInfo mRoute;
662 public RoutePreference(Context context, MediaRouter.RouteInfo route) {
666 setTitle(route.getName());
667 setSummary(route.getDescription());
668 setEnabled(route.isEnabled());
669 if (route.isSelected()) {
670 setOrder(ORDER_CONNECTED);
671 if (route.isConnecting()) {
672 setSummary(R.string.wifi_display_status_connecting);
674 setSummary(R.string.wifi_display_status_connected);
678 setOrder(ORDER_AVAILABLE);
680 setOrder(ORDER_UNAVAILABLE);
681 if (route.getStatusCode() == MediaRouter.RouteInfo.STATUS_IN_USE) {
682 setSummary(R.string.wifi_display_status_in_use);
684 setSummary(R.string.wifi_display_status_not_available);
688 setOnPreferenceClickListener(this);
692 public boolean onPreferenceClick(Preference preference) {
698 private class WifiDisplayRoutePreference extends RoutePreference
699 implements View.OnClickListener {
700 private final WifiDisplay mDisplay;
702 public WifiDisplayRoutePreference(Context context, MediaRouter.RouteInfo route,
703 WifiDisplay display) {
704 super(context, route);
707 setWidgetLayoutResource(R.layout.wifi_display_preference);
711 public void onBindViewHolder(PreferenceViewHolder view) {
712 super.onBindViewHolder(view);
714 ImageView deviceDetails = (ImageView) view.findViewById(R.id.deviceDetails);
715 if (deviceDetails != null) {
716 deviceDetails.setOnClickListener(this);
718 TypedValue value = new TypedValue();
719 getContext().getTheme().resolveAttribute(android.R.attr.disabledAlpha,
721 deviceDetails.setImageAlpha((int) (value.getFloat() * 255));
722 deviceDetails.setEnabled(true); // always allow button to be pressed
728 public void onClick(View v) {
729 showWifiDisplayOptionsDialog(mDisplay);
733 private class UnpairedWifiDisplayPreference extends Preference
734 implements Preference.OnPreferenceClickListener {
735 private final WifiDisplay mDisplay;
737 public UnpairedWifiDisplayPreference(Context context, WifiDisplay display) {
741 setTitle(display.getFriendlyDisplayName());
742 setSummary(com.android.internal.R.string.wireless_display_route_description);
743 setEnabled(display.canConnect());
745 setOrder(ORDER_AVAILABLE);
747 setOrder(ORDER_UNAVAILABLE);
748 setSummary(R.string.wifi_display_status_in_use);
750 setOnPreferenceClickListener(this);
754 public boolean onPreferenceClick(Preference preference) {
755 pairWifiDisplay(mDisplay);
760 private static class SummaryProvider implements SummaryLoader.SummaryProvider {
762 private final Context mContext;
763 private final SummaryLoader mSummaryLoader;
764 private final MediaRouter mRouter;
765 private final MediaRouter.Callback mRouterCallback = new MediaRouter.SimpleCallback() {
767 public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
772 public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
777 public void onRouteAdded(MediaRouter router, RouteInfo info) {
782 public void onRouteRemoved(MediaRouter router, RouteInfo info) {
787 public void onRouteChanged(MediaRouter router, RouteInfo info) {
792 public SummaryProvider(Context context, SummaryLoader summaryLoader) {
794 mSummaryLoader = summaryLoader;
795 mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
799 public void setListening(boolean listening) {
801 mRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mRouterCallback);
804 mRouter.removeCallback(mRouterCallback);
808 private void updateSummary() {
809 String summary = mContext.getString(R.string.disconnected);
811 final int routeCount = mRouter.getRouteCount();
812 for (int i = 0; i < routeCount; i++) {
813 final MediaRouter.RouteInfo route = mRouter.getRouteAt(i);
814 if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)
815 && route.isSelected() && !route.isConnecting()) {
816 summary = mContext.getString(R.string.wifi_display_status_connected);
820 mSummaryLoader.setSummary(this, summary);
824 public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
825 = (activity, summaryLoader) -> new SummaryProvider(activity, summaryLoader);