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