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