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.content.BroadcastReceiver;
     23 import android.content.Context;
     24 import android.content.DialogInterface;
     25 import android.content.Intent;
     26 import android.content.IntentFilter;
     27 import android.database.ContentObserver;
     28 import android.hardware.display.DisplayManager;
     29 import android.hardware.display.WifiDisplay;
     30 import android.hardware.display.WifiDisplayStatus;
     31 import android.net.Uri;
     32 import android.os.Bundle;
     33 import android.os.Handler;
     34 import android.preference.Preference;
     35 import android.preference.PreferenceActivity;
     36 import android.preference.PreferenceCategory;
     37 import android.preference.PreferenceGroup;
     38 import android.preference.PreferenceScreen;
     39 import android.provider.Settings;
     40 import android.text.Html;
     41 import android.util.TypedValue;
     42 import android.view.Gravity;
     43 import android.view.Menu;
     44 import android.view.MenuInflater;
     45 import android.view.MenuItem;
     46 import android.view.View;
     47 import android.widget.CompoundButton;
     48 import android.widget.EditText;
     49 import android.widget.ImageView;
     50 import android.widget.Switch;
     51 import android.widget.TextView;
     52 
     53 import com.android.settings.ProgressCategory;
     54 import com.android.settings.R;
     55 import com.android.settings.SettingsPreferenceFragment;
     56 
     57 /**
     58  * The Settings screen for WifiDisplay configuration and connection management.
     59  */
     60 public final class WifiDisplaySettings extends SettingsPreferenceFragment {
     61     private static final String TAG = "WifiDisplaySettings";
     62 
     63     private static final int MENU_ID_SCAN = Menu.FIRST;
     64 
     65     private DisplayManager mDisplayManager;
     66 
     67     private boolean mWifiDisplayOnSetting;
     68     private WifiDisplayStatus mWifiDisplayStatus;
     69 
     70     private PreferenceGroup mPairedDevicesCategory;
     71     private ProgressCategory mAvailableDevicesCategory;
     72 
     73     private TextView mEmptyView;
     74 
     75     private Switch mActionBarSwitch;
     76 
     77     public WifiDisplaySettings() {
     78     }
     79 
     80     @Override
     81     public void onCreate(Bundle icicle) {
     82         super.onCreate(icicle);
     83 
     84         mDisplayManager = (DisplayManager)getActivity().getSystemService(Context.DISPLAY_SERVICE);
     85 
     86         addPreferencesFromResource(R.xml.wifi_display_settings);
     87         setHasOptionsMenu(true);
     88     }
     89 
     90     @Override
     91     public void onActivityCreated(Bundle savedInstanceState) {
     92         super.onActivityCreated(savedInstanceState);
     93 
     94         Activity activity = getActivity();
     95         mActionBarSwitch = new Switch(activity);
     96         mActionBarSwitch.setOnCheckedChangeListener(mSwitchOnCheckedChangedListener);
     97 
     98         final int padding = activity.getResources().getDimensionPixelSize(
     99                 R.dimen.action_bar_switch_padding);
    100         mActionBarSwitch.setPaddingRelative(0, 0, padding, 0);
    101         activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
    102                 ActionBar.DISPLAY_SHOW_CUSTOM);
    103         activity.getActionBar().setCustomView(mActionBarSwitch,
    104                 new ActionBar.LayoutParams(
    105                         ActionBar.LayoutParams.WRAP_CONTENT,
    106                         ActionBar.LayoutParams.WRAP_CONTENT,
    107                         Gravity.CENTER_VERTICAL | Gravity.END));
    108 
    109         mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
    110         getListView().setEmptyView(mEmptyView);
    111 
    112         update();
    113 
    114         if (mWifiDisplayStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_UNAVAILABLE) {
    115             activity.finish();
    116         }
    117     }
    118 
    119     @Override
    120     public void onDestroyView() {
    121         getActivity().getActionBar().setCustomView(null);
    122         super.onDestroyView();
    123     }
    124 
    125     @Override
    126     public void onResume() {
    127         super.onResume();
    128 
    129         Context context = getActivity();
    130         IntentFilter filter = new IntentFilter();
    131         filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
    132         context.registerReceiver(mReceiver, filter);
    133 
    134         getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
    135                 Settings.Global.WIFI_DISPLAY_ON), false, mSettingsObserver);
    136 
    137         mDisplayManager.scanWifiDisplays();
    138 
    139         update();
    140     }
    141 
    142     @Override
    143     public void onPause() {
    144         super.onPause();
    145 
    146         Context context = getActivity();
    147         context.unregisterReceiver(mReceiver);
    148 
    149         getContentResolver().unregisterContentObserver(mSettingsObserver);
    150     }
    151 
    152     @Override
    153     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    154         MenuItem item = menu.add(Menu.NONE, MENU_ID_SCAN, 0,
    155                 mWifiDisplayStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING ?
    156                         R.string.wifi_display_searching_for_devices :
    157                                 R.string.wifi_display_search_for_devices);
    158         item.setEnabled(mWifiDisplayStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON
    159                 && mWifiDisplayStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_NOT_SCANNING);
    160         item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    161         super.onCreateOptionsMenu(menu, inflater);
    162     }
    163 
    164     @Override
    165     public boolean onOptionsItemSelected(MenuItem item) {
    166         switch (item.getItemId()) {
    167             case MENU_ID_SCAN:
    168                 if (mWifiDisplayStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) {
    169                     mDisplayManager.scanWifiDisplays();
    170                 }
    171                 return true;
    172         }
    173         return super.onOptionsItemSelected(item);
    174     }
    175 
    176     @Override
    177     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
    178             Preference preference) {
    179         if (preference instanceof WifiDisplayPreference) {
    180             WifiDisplayPreference p = (WifiDisplayPreference)preference;
    181             WifiDisplay display = p.getDisplay();
    182 
    183             if (display.equals(mWifiDisplayStatus.getActiveDisplay())) {
    184                 showDisconnectDialog(display);
    185             } else {
    186                 mDisplayManager.connectWifiDisplay(display.getDeviceAddress());
    187             }
    188         }
    189 
    190         return super.onPreferenceTreeClick(preferenceScreen, preference);
    191     }
    192 
    193     private void update() {
    194         mWifiDisplayOnSetting = Settings.Global.getInt(getContentResolver(),
    195                 Settings.Global.WIFI_DISPLAY_ON, 0) != 0;
    196         mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
    197 
    198         applyState();
    199     }
    200 
    201     private void applyState() {
    202         final int featureState = mWifiDisplayStatus.getFeatureState();
    203         mActionBarSwitch.setEnabled(featureState != WifiDisplayStatus.FEATURE_STATE_DISABLED);
    204         mActionBarSwitch.setChecked(mWifiDisplayOnSetting);
    205 
    206         final PreferenceScreen preferenceScreen = getPreferenceScreen();
    207         preferenceScreen.removeAll();
    208 
    209         if (featureState == WifiDisplayStatus.FEATURE_STATE_ON) {
    210             final WifiDisplay[] pairedDisplays = mWifiDisplayStatus.getRememberedDisplays();
    211             final WifiDisplay[] availableDisplays = mWifiDisplayStatus.getAvailableDisplays();
    212 
    213             if (mPairedDevicesCategory == null) {
    214                 mPairedDevicesCategory = new PreferenceCategory(getActivity());
    215                 mPairedDevicesCategory.setTitle(R.string.wifi_display_paired_devices);
    216             } else {
    217                 mPairedDevicesCategory.removeAll();
    218             }
    219             preferenceScreen.addPreference(mPairedDevicesCategory);
    220 
    221             for (WifiDisplay d : pairedDisplays) {
    222                 mPairedDevicesCategory.addPreference(createWifiDisplayPreference(d, true));
    223             }
    224             if (mPairedDevicesCategory.getPreferenceCount() == 0) {
    225                 preferenceScreen.removePreference(mPairedDevicesCategory);
    226             }
    227 
    228             if (mAvailableDevicesCategory == null) {
    229                 mAvailableDevicesCategory = new ProgressCategory(getActivity(), null,
    230                         R.string.wifi_display_no_devices_found);
    231                 mAvailableDevicesCategory.setTitle(R.string.wifi_display_available_devices);
    232             } else {
    233                 mAvailableDevicesCategory.removeAll();
    234             }
    235             preferenceScreen.addPreference(mAvailableDevicesCategory);
    236 
    237             for (WifiDisplay d : availableDisplays) {
    238                 if (!contains(pairedDisplays, d.getDeviceAddress())) {
    239                     mAvailableDevicesCategory.addPreference(createWifiDisplayPreference(d, false));
    240                 }
    241             }
    242             if (mWifiDisplayStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING) {
    243                 mAvailableDevicesCategory.setProgress(true);
    244             } else {
    245                 mAvailableDevicesCategory.setProgress(false);
    246             }
    247         } else {
    248             mEmptyView.setText(featureState == WifiDisplayStatus.FEATURE_STATE_OFF ?
    249                     R.string.wifi_display_settings_empty_list_wifi_display_off :
    250                             R.string.wifi_display_settings_empty_list_wifi_display_disabled);
    251         }
    252 
    253         getActivity().invalidateOptionsMenu();
    254     }
    255 
    256     private Preference createWifiDisplayPreference(final WifiDisplay d, boolean paired) {
    257         WifiDisplayPreference p = new WifiDisplayPreference(getActivity(), d);
    258         if (d.equals(mWifiDisplayStatus.getActiveDisplay())) {
    259             switch (mWifiDisplayStatus.getActiveDisplayState()) {
    260                 case WifiDisplayStatus.DISPLAY_STATE_CONNECTED:
    261                     p.setSummary(R.string.wifi_display_status_connected);
    262                     break;
    263                 case WifiDisplayStatus.DISPLAY_STATE_CONNECTING:
    264                     p.setSummary(R.string.wifi_display_status_connecting);
    265                     break;
    266             }
    267         } else if (paired && contains(mWifiDisplayStatus.getAvailableDisplays(),
    268                 d.getDeviceAddress())) {
    269             p.setSummary(R.string.wifi_display_status_available);
    270         }
    271         if (paired) {
    272             p.setWidgetLayoutResource(R.layout.wifi_display_preference);
    273         }
    274         return p;
    275     }
    276 
    277     private void showDisconnectDialog(final WifiDisplay display) {
    278         DialogInterface.OnClickListener ok = new DialogInterface.OnClickListener() {
    279             @Override
    280             public void onClick(DialogInterface dialog, int which) {
    281                 if (display.equals(mWifiDisplayStatus.getActiveDisplay())) {
    282                     mDisplayManager.disconnectWifiDisplay();
    283                 }
    284             }
    285         };
    286 
    287         AlertDialog dialog = new AlertDialog.Builder(getActivity())
    288                 .setCancelable(true)
    289                 .setTitle(R.string.wifi_display_disconnect_title)
    290                 .setMessage(Html.fromHtml(getResources().getString(
    291                         R.string.wifi_display_disconnect_text, display.getFriendlyDisplayName())))
    292                 .setPositiveButton(android.R.string.ok, ok)
    293                 .setNegativeButton(android.R.string.cancel, null)
    294                 .create();
    295         dialog.show();
    296     }
    297 
    298     private void showOptionsDialog(final WifiDisplay display) {
    299         View view = getActivity().getLayoutInflater().inflate(R.layout.wifi_display_options, null);
    300         final EditText nameEditText = (EditText)view.findViewById(R.id.name);
    301         nameEditText.setText(display.getFriendlyDisplayName());
    302 
    303         DialogInterface.OnClickListener done = new DialogInterface.OnClickListener() {
    304             @Override
    305             public void onClick(DialogInterface dialog, int which) {
    306                 String name = nameEditText.getText().toString().trim();
    307                 if (name.isEmpty() || name.equals(display.getDeviceName())) {
    308                     name = null;
    309                 }
    310                 mDisplayManager.renameWifiDisplay(display.getDeviceAddress(), name);
    311             }
    312         };
    313         DialogInterface.OnClickListener forget = new DialogInterface.OnClickListener() {
    314             @Override
    315             public void onClick(DialogInterface dialog, int which) {
    316                 mDisplayManager.forgetWifiDisplay(display.getDeviceAddress());
    317             }
    318         };
    319 
    320         AlertDialog dialog = new AlertDialog.Builder(getActivity())
    321                 .setCancelable(true)
    322                 .setTitle(R.string.wifi_display_options_title)
    323                 .setView(view)
    324                 .setPositiveButton(R.string.wifi_display_options_done, done)
    325                 .setNegativeButton(R.string.wifi_display_options_forget, forget)
    326                 .create();
    327         dialog.show();
    328     }
    329 
    330     private static boolean contains(WifiDisplay[] displays, String address) {
    331         for (WifiDisplay d : displays) {
    332             if (d.getDeviceAddress().equals(address)) {
    333                 return true;
    334             }
    335         }
    336         return false;
    337     }
    338 
    339     private final CompoundButton.OnCheckedChangeListener mSwitchOnCheckedChangedListener =
    340             new CompoundButton.OnCheckedChangeListener() {
    341         @Override
    342         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    343             mWifiDisplayOnSetting = isChecked;
    344             Settings.Global.putInt(getContentResolver(),
    345                     Settings.Global.WIFI_DISPLAY_ON, isChecked ? 1 : 0);
    346         }
    347     };
    348 
    349     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    350         @Override
    351         public void onReceive(Context context, Intent intent) {
    352             String action = intent.getAction();
    353             if (action.equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
    354                 WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
    355                         DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
    356                 mWifiDisplayStatus = status;
    357                 applyState();
    358             }
    359         }
    360     };
    361 
    362     private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
    363         @Override
    364         public void onChange(boolean selfChange, Uri uri) {
    365             update();
    366         }
    367     };
    368 
    369     private final class WifiDisplayPreference extends Preference
    370             implements View.OnClickListener {
    371         private final WifiDisplay mDisplay;
    372 
    373         public WifiDisplayPreference(Context context, WifiDisplay display) {
    374             super(context);
    375 
    376             mDisplay = display;
    377             setTitle(display.getFriendlyDisplayName());
    378         }
    379 
    380         public WifiDisplay getDisplay() {
    381             return mDisplay;
    382         }
    383 
    384         @Override
    385         protected void onBindView(View view) {
    386             super.onBindView(view);
    387 
    388             ImageView deviceDetails = (ImageView) view.findViewById(R.id.deviceDetails);
    389             if (deviceDetails != null) {
    390                 deviceDetails.setOnClickListener(this);
    391 
    392                 if (!isEnabled()) {
    393                     TypedValue value = new TypedValue();
    394                     getContext().getTheme().resolveAttribute(android.R.attr.disabledAlpha,
    395                             value, true);
    396                     deviceDetails.setImageAlpha((int)(value.getFloat() * 255));
    397                 }
    398             }
    399         }
    400 
    401         @Override
    402         public void onClick(View v) {
    403             showOptionsDialog(mDisplay);
    404         }
    405     }
    406 }
    407