WifiDisplaySettings.java revision 017d82af8a978cf20a848f5698840f4661aae3ea
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        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 if (display.canConnect()){
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            for (WifiDisplay display : mWifiDisplayStatus.getAvailableDisplays()) {
271                if (display.getDeviceAddress().equals(d.getDeviceAddress()) &&
272                        !display.canConnect()) {
273                    p.setSummary(R.string.wifi_display_status_busy);
274                    p.setEnabled(false);
275                    break;
276                }
277            }
278        } else if (!paired && !d.canConnect()) {
279            p.setSummary(R.string.wifi_display_status_busy);
280            p.setEnabled(false);
281        }
282        if (paired) {
283            p.setWidgetLayoutResource(R.layout.wifi_display_preference);
284        }
285        return p;
286    }
287
288    private void showDisconnectDialog(final WifiDisplay display) {
289        DialogInterface.OnClickListener ok = new DialogInterface.OnClickListener() {
290            @Override
291            public void onClick(DialogInterface dialog, int which) {
292                if (display.equals(mWifiDisplayStatus.getActiveDisplay())) {
293                    mDisplayManager.disconnectWifiDisplay();
294                }
295            }
296        };
297
298        AlertDialog dialog = new AlertDialog.Builder(getActivity())
299                .setCancelable(true)
300                .setTitle(R.string.wifi_display_disconnect_title)
301                .setMessage(Html.fromHtml(getResources().getString(
302                        R.string.wifi_display_disconnect_text, display.getFriendlyDisplayName())))
303                .setPositiveButton(android.R.string.ok, ok)
304                .setNegativeButton(android.R.string.cancel, null)
305                .create();
306        dialog.show();
307    }
308
309    private void showOptionsDialog(final WifiDisplay display) {
310        View view = getActivity().getLayoutInflater().inflate(R.layout.wifi_display_options, null);
311        final EditText nameEditText = (EditText)view.findViewById(R.id.name);
312        nameEditText.setText(display.getFriendlyDisplayName());
313
314        DialogInterface.OnClickListener done = new DialogInterface.OnClickListener() {
315            @Override
316            public void onClick(DialogInterface dialog, int which) {
317                String name = nameEditText.getText().toString().trim();
318                if (name.isEmpty() || name.equals(display.getDeviceName())) {
319                    name = null;
320                }
321                mDisplayManager.renameWifiDisplay(display.getDeviceAddress(), name);
322            }
323        };
324        DialogInterface.OnClickListener forget = new DialogInterface.OnClickListener() {
325            @Override
326            public void onClick(DialogInterface dialog, int which) {
327                mDisplayManager.forgetWifiDisplay(display.getDeviceAddress());
328            }
329        };
330
331        AlertDialog dialog = new AlertDialog.Builder(getActivity())
332                .setCancelable(true)
333                .setTitle(R.string.wifi_display_options_title)
334                .setView(view)
335                .setPositiveButton(R.string.wifi_display_options_done, done)
336                .setNegativeButton(R.string.wifi_display_options_forget, forget)
337                .create();
338        dialog.show();
339    }
340
341    private static boolean contains(WifiDisplay[] displays, String address) {
342        for (WifiDisplay d : displays) {
343            if (d.getDeviceAddress().equals(address)) {
344                return true;
345            }
346        }
347        return false;
348    }
349
350    private final CompoundButton.OnCheckedChangeListener mSwitchOnCheckedChangedListener =
351            new CompoundButton.OnCheckedChangeListener() {
352        @Override
353        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
354            mWifiDisplayOnSetting = isChecked;
355            Settings.Global.putInt(getContentResolver(),
356                    Settings.Global.WIFI_DISPLAY_ON, isChecked ? 1 : 0);
357        }
358    };
359
360    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
361        @Override
362        public void onReceive(Context context, Intent intent) {
363            String action = intent.getAction();
364            if (action.equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
365                WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
366                        DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
367                mWifiDisplayStatus = status;
368                applyState();
369            }
370        }
371    };
372
373    private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
374        @Override
375        public void onChange(boolean selfChange, Uri uri) {
376            update();
377        }
378    };
379
380    private final class WifiDisplayPreference extends Preference
381            implements View.OnClickListener {
382        private final WifiDisplay mDisplay;
383
384        public WifiDisplayPreference(Context context, WifiDisplay display) {
385            super(context);
386
387            mDisplay = display;
388            setTitle(display.getFriendlyDisplayName());
389        }
390
391        public WifiDisplay getDisplay() {
392            return mDisplay;
393        }
394
395        @Override
396        protected void onBindView(View view) {
397            super.onBindView(view);
398
399            ImageView deviceDetails = (ImageView) view.findViewById(R.id.deviceDetails);
400            if (deviceDetails != null) {
401                deviceDetails.setOnClickListener(this);
402
403                if (!isEnabled()) {
404                    TypedValue value = new TypedValue();
405                    getContext().getTheme().resolveAttribute(android.R.attr.disabledAlpha,
406                            value, true);
407                    deviceDetails.setImageAlpha((int)(value.getFloat() * 255));
408                }
409            }
410        }
411
412        @Override
413        public void onClick(View v) {
414            showOptionsDialog(mDisplay);
415        }
416    }
417}
418