WifiDisplaySettings.java revision 9d1bfd1e8de6e46137a9571507c03526880d6a46
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
17package com.android.settings.wfd;
18
19import android.app.AlertDialog;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.DialogInterface;
23import android.content.Intent;
24import android.content.IntentFilter;
25import android.database.ContentObserver;
26import android.hardware.display.DisplayManager;
27import android.hardware.display.WifiDisplay;
28import android.hardware.display.WifiDisplayStatus;
29import android.media.MediaRouter;
30import android.media.MediaRouter.RouteInfo;
31import android.net.Uri;
32import android.net.wifi.WpsInfo;
33import android.net.wifi.p2p.WifiP2pManager;
34import android.net.wifi.p2p.WifiP2pManager.ActionListener;
35import android.net.wifi.p2p.WifiP2pManager.Channel;
36import android.os.Bundle;
37import android.os.Handler;
38import android.os.Looper;
39import android.provider.Settings;
40import android.support.v14.preference.SwitchPreference;
41import android.support.v7.preference.ListPreference;
42import android.support.v7.preference.Preference;
43import android.support.v7.preference.Preference.OnPreferenceChangeListener;
44import android.support.v7.preference.PreferenceCategory;
45import android.support.v7.preference.PreferenceGroup;
46import android.support.v7.preference.PreferenceScreen;
47import android.support.v7.preference.PreferenceViewHolder;
48import android.util.Slog;
49import android.util.TypedValue;
50import android.view.Menu;
51import android.view.MenuInflater;
52import android.view.MenuItem;
53import android.view.View;
54import android.view.View.OnClickListener;
55import android.widget.Button;
56import android.widget.EditText;
57import android.widget.ImageView;
58import android.widget.TextView;
59
60import com.android.internal.app.MediaRouteDialogPresenter;
61import com.android.internal.logging.MetricsProto.MetricsEvent;
62import com.android.settings.R;
63import 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 */
73public 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