WifiDisplaySettings.java revision 94417b41c0090d6da5ae982259f69deb6c99d3d1
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[] displays = mWifiDisplayStatus.getDisplays();
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            if (mAvailableDevicesCategory == null) {
221                mAvailableDevicesCategory = new ProgressCategory(getActivity(), null,
222                        R.string.wifi_display_no_devices_found);
223                mAvailableDevicesCategory.setTitle(R.string.wifi_display_available_devices);
224            } else {
225                mAvailableDevicesCategory.removeAll();
226            }
227            preferenceScreen.addPreference(mAvailableDevicesCategory);
228
229            for (WifiDisplay d : displays) {
230                if (d.isRemembered()) {
231                    mPairedDevicesCategory.addPreference(createWifiDisplayPreference(d));
232                } else if (d.isAvailable()){
233                    mAvailableDevicesCategory.addPreference(createWifiDisplayPreference(d));
234                }
235            }
236            if (mPairedDevicesCategory.getPreferenceCount() == 0) {
237                preferenceScreen.removePreference(mPairedDevicesCategory);
238            }
239            if (mWifiDisplayStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING) {
240                mAvailableDevicesCategory.setProgress(true);
241            } else {
242                mAvailableDevicesCategory.setProgress(false);
243            }
244        } else {
245            mEmptyView.setText(featureState == WifiDisplayStatus.FEATURE_STATE_OFF ?
246                    R.string.wifi_display_settings_empty_list_wifi_display_off :
247                            R.string.wifi_display_settings_empty_list_wifi_display_disabled);
248        }
249
250        getActivity().invalidateOptionsMenu();
251    }
252
253    private Preference createWifiDisplayPreference(final WifiDisplay d) {
254        WifiDisplayPreference p = new WifiDisplayPreference(getActivity(), d);
255        if (d.equals(mWifiDisplayStatus.getActiveDisplay())) {
256            switch (mWifiDisplayStatus.getActiveDisplayState()) {
257                case WifiDisplayStatus.DISPLAY_STATE_CONNECTED:
258                    p.setSummary(R.string.wifi_display_status_connected);
259                    break;
260                case WifiDisplayStatus.DISPLAY_STATE_CONNECTING:
261                    p.setSummary(R.string.wifi_display_status_connecting);
262                    break;
263            }
264        } else if (d.isAvailable()) {
265            if (!d.canConnect()) {
266                p.setSummary(R.string.wifi_display_status_in_use);
267                p.setEnabled(false);
268            } else if (d.isRemembered()) {
269                p.setSummary(R.string.wifi_display_status_available);
270            }
271        }
272        if (d.isRemembered()) {
273            p.setWidgetLayoutResource(R.layout.wifi_display_preference);
274        }
275        return p;
276    }
277
278    private void showDisconnectDialog(final WifiDisplay display) {
279        DialogInterface.OnClickListener ok = new DialogInterface.OnClickListener() {
280            @Override
281            public void onClick(DialogInterface dialog, int which) {
282                if (display.equals(mWifiDisplayStatus.getActiveDisplay())) {
283                    mDisplayManager.disconnectWifiDisplay();
284                }
285            }
286        };
287
288        AlertDialog dialog = new AlertDialog.Builder(getActivity())
289                .setCancelable(true)
290                .setTitle(R.string.wifi_display_disconnect_title)
291                .setMessage(Html.fromHtml(getResources().getString(
292                        R.string.wifi_display_disconnect_text, display.getFriendlyDisplayName())))
293                .setPositiveButton(android.R.string.ok, ok)
294                .setNegativeButton(android.R.string.cancel, null)
295                .create();
296        dialog.show();
297    }
298
299    private void showOptionsDialog(final WifiDisplay display) {
300        View view = getActivity().getLayoutInflater().inflate(R.layout.wifi_display_options, null);
301        final EditText nameEditText = (EditText)view.findViewById(R.id.name);
302        nameEditText.setText(display.getFriendlyDisplayName());
303
304        DialogInterface.OnClickListener done = new DialogInterface.OnClickListener() {
305            @Override
306            public void onClick(DialogInterface dialog, int which) {
307                String name = nameEditText.getText().toString().trim();
308                if (name.isEmpty() || name.equals(display.getDeviceName())) {
309                    name = null;
310                }
311                mDisplayManager.renameWifiDisplay(display.getDeviceAddress(), name);
312            }
313        };
314        DialogInterface.OnClickListener forget = new DialogInterface.OnClickListener() {
315            @Override
316            public void onClick(DialogInterface dialog, int which) {
317                mDisplayManager.forgetWifiDisplay(display.getDeviceAddress());
318            }
319        };
320
321        AlertDialog dialog = new AlertDialog.Builder(getActivity())
322                .setCancelable(true)
323                .setTitle(R.string.wifi_display_options_title)
324                .setView(view)
325                .setPositiveButton(R.string.wifi_display_options_done, done)
326                .setNegativeButton(R.string.wifi_display_options_forget, forget)
327                .create();
328        dialog.show();
329    }
330
331    private static boolean contains(WifiDisplay[] displays, String address) {
332        for (WifiDisplay d : displays) {
333            if (d.getDeviceAddress().equals(address)) {
334                return true;
335            }
336        }
337        return false;
338    }
339
340    private final CompoundButton.OnCheckedChangeListener mSwitchOnCheckedChangedListener =
341            new CompoundButton.OnCheckedChangeListener() {
342        @Override
343        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
344            mWifiDisplayOnSetting = isChecked;
345            Settings.Global.putInt(getContentResolver(),
346                    Settings.Global.WIFI_DISPLAY_ON, isChecked ? 1 : 0);
347        }
348    };
349
350    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
351        @Override
352        public void onReceive(Context context, Intent intent) {
353            String action = intent.getAction();
354            if (action.equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
355                WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
356                        DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
357                mWifiDisplayStatus = status;
358                applyState();
359            }
360        }
361    };
362
363    private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
364        @Override
365        public void onChange(boolean selfChange, Uri uri) {
366            update();
367        }
368    };
369
370    private final class WifiDisplayPreference extends Preference
371            implements View.OnClickListener {
372        private final WifiDisplay mDisplay;
373
374        public WifiDisplayPreference(Context context, WifiDisplay display) {
375            super(context);
376
377            mDisplay = display;
378            setTitle(display.getFriendlyDisplayName());
379        }
380
381        public WifiDisplay getDisplay() {
382            return mDisplay;
383        }
384
385        @Override
386        protected void onBindView(View view) {
387            super.onBindView(view);
388
389            ImageView deviceDetails = (ImageView) view.findViewById(R.id.deviceDetails);
390            if (deviceDetails != null) {
391                deviceDetails.setOnClickListener(this);
392
393                if (!isEnabled()) {
394                    TypedValue value = new TypedValue();
395                    getContext().getTheme().resolveAttribute(android.R.attr.disabledAlpha,
396                            value, true);
397                    deviceDetails.setImageAlpha((int)(value.getFloat() * 255));
398                }
399            }
400        }
401
402        @Override
403        public void onClick(View v) {
404            showOptionsDialog(mDisplay);
405        }
406    }
407}
408