WifiDisplaySettings.java revision 4e54c2a17765aed01ba23c9b0ec4d41e66c698b7
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.ActionBar;
20import android.app.Activity;
21import android.app.AlertDialog;
22import android.app.Service;
23import android.content.BroadcastReceiver;
24import android.content.Context;
25import android.content.DialogInterface;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.database.ContentObserver;
29import android.hardware.display.DisplayManager;
30import android.hardware.display.WifiDisplay;
31import android.hardware.display.WifiDisplayStatus;
32import android.media.MediaRouter;
33import android.media.MediaRouter.RouteInfo;
34import android.net.Uri;
35import android.net.wifi.p2p.WifiP2pManager;
36import android.net.wifi.p2p.WifiP2pManager.ActionListener;
37import android.net.wifi.p2p.WifiP2pManager.Channel;
38import android.net.wifi.WpsInfo;
39import android.os.Bundle;
40import android.os.Handler;
41import android.os.Looper;
42import android.preference.CheckBoxPreference;
43import android.preference.ListPreference;
44import android.preference.Preference;
45import android.preference.PreferenceActivity;
46import android.preference.PreferenceCategory;
47import android.preference.PreferenceGroup;
48import android.preference.PreferenceScreen;
49import android.provider.Settings;
50import android.text.Html;
51import android.util.Slog;
52import android.util.TypedValue;
53import android.view.Gravity;
54import android.view.LayoutInflater;
55import android.view.Menu;
56import android.view.MenuInflater;
57import android.view.MenuItem;
58import android.view.View;
59import android.view.View.OnClickListener;
60import android.view.ViewGroup;
61import android.widget.Button;
62import android.widget.CompoundButton;
63import android.widget.EditText;
64import android.widget.ImageView;
65import android.widget.Switch;
66import android.widget.TextView;
67
68import com.android.internal.app.MediaRouteDialogPresenter;
69import com.android.settings.ProgressCategory;
70import com.android.settings.R;
71import com.android.settings.SettingsPreferenceFragment;
72
73/**
74 * The Settings screen for WifiDisplay configuration and connection management.
75 *
76 * The wifi display routes are integrated together with other remote display routes
77 * from the media router.  It may happen that wifi display isn't actually available
78 * on the system.  In that case, the enable option will not be shown but other
79 * remote display routes will continue to be made available.
80 */
81public final class WifiDisplaySettings extends SettingsPreferenceFragment {
82    private static final String TAG = "WifiDisplaySettings";
83    private static final boolean DEBUG = false;
84
85    private static final int MENU_ID_ENABLE_WIFI_DISPLAY = Menu.FIRST;
86
87    private static final int CHANGE_SETTINGS = 1 << 0;
88    private static final int CHANGE_ROUTES = 1 << 1;
89    private static final int CHANGE_WIFI_DISPLAY_STATUS = 1 << 2;
90    private static final int CHANGE_ALL = -1;
91
92    private static final int ORDER_CERTIFICATION = 1;
93    private static final int ORDER_CONNECTED = 2;
94    private static final int ORDER_AVAILABLE = 3;
95    private static final int ORDER_UNAVAILABLE = 4;
96
97    private final Handler mHandler;
98
99    private MediaRouter mRouter;
100    private DisplayManager mDisplayManager;
101
102    private boolean mStarted;
103    private int mPendingChanges;
104
105    private boolean mWifiDisplayOnSetting;
106    private WifiDisplayStatus mWifiDisplayStatus;
107
108    private TextView mEmptyView;
109
110    /* certification */
111    private boolean mWifiDisplayCertificationOn;
112    private WifiP2pManager mWifiP2pManager;
113    private Channel mWifiP2pChannel;
114    private PreferenceGroup mCertCategory;
115    private boolean mListen;
116    private boolean mAutoGO;
117    private int mWpsConfig = WpsInfo.INVALID;
118    private int mListenChannel;
119    private int mOperatingChannel;
120
121    public WifiDisplaySettings() {
122        mHandler = new Handler();
123    }
124
125    @Override
126    public void onCreate(Bundle icicle) {
127        super.onCreate(icicle);
128
129        final Context context = getActivity();
130        mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
131        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
132        mWifiP2pManager = (WifiP2pManager)context.getSystemService(Context.WIFI_P2P_SERVICE);
133        mWifiP2pChannel = mWifiP2pManager.initialize(context, Looper.getMainLooper(), null);
134
135        addPreferencesFromResource(R.xml.wifi_display_settings);
136        setHasOptionsMenu(true);
137    }
138
139    @Override
140    public void onActivityCreated(Bundle savedInstanceState) {
141        super.onActivityCreated(savedInstanceState);
142
143        mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
144        mEmptyView.setText(R.string.wifi_display_no_devices_found);
145        getListView().setEmptyView(mEmptyView);
146    }
147
148    @Override
149    public void onStart() {
150        super.onStart();
151        mStarted = true;
152
153        final Context context = getActivity();
154        IntentFilter filter = new IntentFilter();
155        filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
156        context.registerReceiver(mReceiver, filter);
157
158        getContentResolver().registerContentObserver(Settings.Global.getUriFor(
159                Settings.Global.WIFI_DISPLAY_ON), false, mSettingsObserver);
160        getContentResolver().registerContentObserver(Settings.Global.getUriFor(
161                Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON), false, mSettingsObserver);
162        getContentResolver().registerContentObserver(Settings.Global.getUriFor(
163                Settings.Global.WIFI_DISPLAY_WPS_CONFIG), false, mSettingsObserver);
164
165        mRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mRouterCallback,
166                MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
167
168        update(CHANGE_ALL);
169    }
170
171    @Override
172    public void onStop() {
173        super.onStop();
174        mStarted = false;
175
176        final Context context = getActivity();
177        context.unregisterReceiver(mReceiver);
178
179        getContentResolver().unregisterContentObserver(mSettingsObserver);
180
181        mRouter.removeCallback(mRouterCallback);
182
183        unscheduleUpdate();
184    }
185
186    @Override
187    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
188        if (mWifiDisplayStatus != null && mWifiDisplayStatus.getFeatureState()
189                != WifiDisplayStatus.FEATURE_STATE_UNAVAILABLE) {
190            MenuItem item = menu.add(Menu.NONE, MENU_ID_ENABLE_WIFI_DISPLAY, 0,
191                    R.string.wifi_display_enable_menu_item);
192            item.setCheckable(true);
193            item.setChecked(mWifiDisplayOnSetting);
194        }
195        super.onCreateOptionsMenu(menu, inflater);
196    }
197
198    @Override
199    public boolean onOptionsItemSelected(MenuItem item) {
200        switch (item.getItemId()) {
201            case MENU_ID_ENABLE_WIFI_DISPLAY:
202                mWifiDisplayOnSetting = !item.isChecked();
203                item.setChecked(mWifiDisplayOnSetting);
204                Settings.Global.putInt(getContentResolver(),
205                        Settings.Global.WIFI_DISPLAY_ON, mWifiDisplayOnSetting ? 1 : 0);
206                return true;
207        }
208        return super.onOptionsItemSelected(item);
209    }
210
211    private void scheduleUpdate(int changes) {
212        if (mStarted) {
213            if (mPendingChanges == 0) {
214                mHandler.post(mUpdateRunnable);
215            }
216            mPendingChanges |= changes;
217        }
218    }
219
220    private void unscheduleUpdate() {
221        if (mPendingChanges != 0) {
222            mPendingChanges = 0;
223            mHandler.removeCallbacks(mUpdateRunnable);
224        }
225    }
226
227    private void update(int changes) {
228        boolean invalidateOptions = false;
229
230        // Update settings.
231        if ((changes & CHANGE_SETTINGS) != 0) {
232            mWifiDisplayOnSetting = Settings.Global.getInt(getContentResolver(),
233                    Settings.Global.WIFI_DISPLAY_ON, 0) != 0;
234            mWifiDisplayCertificationOn = Settings.Global.getInt(getContentResolver(),
235                    Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON, 0) != 0;
236            mWpsConfig = Settings.Global.getInt(getContentResolver(),
237                Settings.Global.WIFI_DISPLAY_WPS_CONFIG, WpsInfo.INVALID);
238
239            // The wifi display enabled setting may have changed.
240            invalidateOptions = true;
241        }
242
243        // Update wifi display state.
244        if ((changes & CHANGE_WIFI_DISPLAY_STATUS) != 0) {
245            mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
246
247            // The wifi display feature state may have changed.
248            invalidateOptions = true;
249        }
250
251        // Rebuild the routes.
252        final PreferenceScreen preferenceScreen = getPreferenceScreen();
253        preferenceScreen.removeAll();
254
255        // Add all known remote display routes.
256        final int routeCount = mRouter.getRouteCount();
257        for (int i = 0; i < routeCount; i++) {
258            MediaRouter.RouteInfo route = mRouter.getRouteAt(i);
259            if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)) {
260                preferenceScreen.addPreference(createRoutePreference(route));
261            }
262        }
263
264        // Additional features for wifi display routes.
265        if (mWifiDisplayStatus != null
266                && mWifiDisplayStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) {
267            // Add all unpaired wifi displays.
268            for (WifiDisplay display : mWifiDisplayStatus.getDisplays()) {
269                if (!display.isRemembered() && display.isAvailable()
270                        && !display.equals(mWifiDisplayStatus.getActiveDisplay())) {
271                    preferenceScreen.addPreference(new UnpairedWifiDisplayPreference(
272                            getActivity(), display));
273                }
274            }
275
276            // Add the certification menu if enabled in developer options.
277            if (mWifiDisplayCertificationOn) {
278                buildCertificationMenu(preferenceScreen);
279            }
280        }
281
282        // Invalidate menu options if needed.
283        if (invalidateOptions) {
284            getActivity().invalidateOptionsMenu();
285        }
286    }
287
288    private RoutePreference createRoutePreference(MediaRouter.RouteInfo route) {
289        WifiDisplay display = findWifiDisplay(route.getDeviceAddress());
290        if (display != null) {
291            return new WifiDisplayRoutePreference(getActivity(), route, display);
292        } else {
293            return new RoutePreference(getActivity(), route);
294        }
295    }
296
297    private WifiDisplay findWifiDisplay(String deviceAddress) {
298        if (mWifiDisplayStatus != null && deviceAddress != null) {
299            for (WifiDisplay display : mWifiDisplayStatus.getDisplays()) {
300                if (display.getDeviceAddress().equals(deviceAddress)) {
301                    return display;
302                }
303            }
304        }
305        return null;
306    }
307
308    private void buildCertificationMenu(final PreferenceScreen preferenceScreen) {
309        if (mCertCategory == null) {
310            mCertCategory = new PreferenceCategory(getActivity());
311            mCertCategory.setTitle(R.string.wifi_display_certification_heading);
312            mCertCategory.setOrder(ORDER_CERTIFICATION);
313        } else {
314            mCertCategory.removeAll();
315        }
316        preferenceScreen.addPreference(mCertCategory);
317
318        // display session info if there is an active p2p session
319        if (!mWifiDisplayStatus.getSessionInfo().getGroupId().isEmpty()) {
320            Preference p = new Preference(getActivity());
321            p.setTitle(R.string.wifi_display_session_info);
322            p.setSummary(mWifiDisplayStatus.getSessionInfo().toString());
323            mCertCategory.addPreference(p);
324
325            // show buttons for Pause/Resume when a WFD session is established
326            if (mWifiDisplayStatus.getSessionInfo().getSessionId() != 0) {
327                mCertCategory.addPreference(new Preference(getActivity()) {
328                    @Override
329                    public View getView(View convertView, ViewGroup parent) {
330                        final View v;
331                        if (convertView == null) {
332                            LayoutInflater li = (LayoutInflater) getActivity().
333                                    getSystemService(Service.LAYOUT_INFLATER_SERVICE);
334                            v = li.inflate(R.layout.two_buttons_panel, null);
335                        } else {
336                            v = convertView;
337                        }
338
339                        Button b = (Button)v.findViewById(R.id.left_button);
340                        b.setText(R.string.wifi_display_pause);
341                        b.setOnClickListener(new OnClickListener() {
342                            @Override
343                            public void onClick(View v) {
344                                mDisplayManager.pauseWifiDisplay();
345                            }
346                        });
347
348                        b = (Button)v.findViewById(R.id.right_button);
349                        b.setText(R.string.wifi_display_resume);
350                        b.setOnClickListener(new OnClickListener() {
351                            @Override
352                            public void onClick(View v) {
353                                mDisplayManager.resumeWifiDisplay();
354                            }
355                        });
356
357                        return v;
358                    }
359                });
360            }
361        }
362
363        // switch for Listen Mode
364        CheckBoxPreference cbp = new CheckBoxPreference(getActivity()) {
365            @Override
366            protected void onClick() {
367                mListen = !mListen;
368                setListenMode(mListen);
369                setChecked(mListen);
370            }
371        };
372        cbp.setTitle(R.string.wifi_display_listen_mode);
373        cbp.setChecked(mListen);
374        mCertCategory.addPreference(cbp);
375
376        // switch for Autonomous GO
377        cbp = new CheckBoxPreference(getActivity()) {
378            @Override
379            protected void onClick() {
380                mAutoGO = !mAutoGO;
381                if (mAutoGO) {
382                    startAutoGO();
383                } else {
384                    stopAutoGO();
385                }
386                setChecked(mAutoGO);
387            }
388        };
389        cbp.setTitle(R.string.wifi_display_autonomous_go);
390        cbp.setChecked(mAutoGO);
391        mCertCategory.addPreference(cbp);
392
393        // Drop down list for choosing WPS method (PBC/KEYPAD/DISPLAY)
394        ListPreference lp = new ListPreference(getActivity()) {
395            @Override
396            protected void onDialogClosed(boolean positiveResult) {
397                super.onDialogClosed(positiveResult);
398                if (positiveResult) {
399                    mWpsConfig = Integer.parseInt(getValue());
400                    setSummary("%1$s");
401                    getActivity().invalidateOptionsMenu();
402                    Settings.Global.putInt(getActivity().getContentResolver(),
403                            Settings.Global.WIFI_DISPLAY_WPS_CONFIG, mWpsConfig);
404                }
405            }
406        };
407        mWpsConfig = Settings.Global.getInt(getActivity().getContentResolver(),
408                Settings.Global.WIFI_DISPLAY_WPS_CONFIG, WpsInfo.INVALID);
409        String[] wpsEntries = { "Default", "PBC", "KEYPAD", "DISPLAY" };
410        String[] wpsValues = {
411            "" + WpsInfo.INVALID,
412            "" + WpsInfo.PBC,
413            "" + WpsInfo.KEYPAD,
414            "" + WpsInfo.DISPLAY };
415        lp.setTitle(R.string.wifi_display_wps_config);
416        lp.setEntries(wpsEntries);
417        lp.setEntryValues(wpsValues);
418        lp.setValue("" + mWpsConfig);
419        lp.setSummary("%1$s");
420        mCertCategory.addPreference(lp);
421
422        // Drop down list for choosing listen channel
423        lp = new ListPreference(getActivity()) {
424            @Override
425            protected void onDialogClosed(boolean positiveResult) {
426                super.onDialogClosed(positiveResult);
427                if (positiveResult) {
428                    mListenChannel = Integer.parseInt(getValue());
429                    setSummary("%1$s");
430                    getActivity().invalidateOptionsMenu();
431                    setWifiP2pChannels(mListenChannel, mOperatingChannel);
432                }
433            }
434        };
435        String[] lcEntries = { "Auto", "1", "6", "11" };
436        String[] lcValues = { "0", "1", "6", "11" };
437        lp.setTitle(R.string.wifi_display_listen_channel);
438        lp.setEntries(lcEntries);
439        lp.setEntryValues(lcValues);
440        lp.setValue("" + mListenChannel);
441        lp.setSummary("%1$s");
442        mCertCategory.addPreference(lp);
443
444        // Drop down list for choosing operating channel
445        lp = new ListPreference(getActivity()) {
446            @Override
447            protected void onDialogClosed(boolean positiveResult) {
448                super.onDialogClosed(positiveResult);
449                if (positiveResult) {
450                    mOperatingChannel = Integer.parseInt(getValue());
451                    setSummary("%1$s");
452                    getActivity().invalidateOptionsMenu();
453                    setWifiP2pChannels(mListenChannel, mOperatingChannel);
454                }
455            }
456        };
457        String[] ocEntries = { "Auto", "1", "6", "11", "36" };
458        String[] ocValues = { "0", "1", "6", "11", "36" };
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        protected void onBindView(View view) {
700            super.onBindView(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