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