WifiDisplaySettings.java revision 9e143f5e9d836d2d3dd0b2f59f7d14327ade0193
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.content.BroadcastReceiver;
23import android.content.Context;
24import android.content.DialogInterface;
25import android.content.Intent;
26import android.content.IntentFilter;
27import android.database.ContentObserver;
28import android.hardware.display.DisplayManager;
29import android.hardware.display.WifiDisplay;
30import android.hardware.display.WifiDisplayStatus;
31import android.net.Uri;
32import android.os.Bundle;
33import android.os.Handler;
34import android.preference.Preference;
35import android.preference.PreferenceActivity;
36import android.preference.PreferenceCategory;
37import android.preference.PreferenceGroup;
38import android.preference.PreferenceScreen;
39import android.provider.Settings;
40import android.text.Html;
41import android.util.TypedValue;
42import android.view.Gravity;
43import android.view.Menu;
44import android.view.MenuInflater;
45import android.view.MenuItem;
46import android.view.View;
47import android.widget.CompoundButton;
48import android.widget.EditText;
49import android.widget.ImageView;
50import android.widget.Switch;
51import android.widget.TextView;
52
53import com.android.settings.ProgressCategory;
54import com.android.settings.R;
55import com.android.settings.SettingsPreferenceFragment;
56
57/**
58 * The Settings screen for WifiDisplay configuration and connection management.
59 */
60public 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