QuickSettings.java revision d4726d062e277b360046609f35e1aa8572e8e364
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.systemui.statusbar.phone;
18
19import android.app.Dialog;
20import android.app.PendingIntent;
21import android.content.BroadcastReceiver;
22import android.content.ComponentName;
23import android.content.Context;
24import android.content.CursorLoader;
25import android.content.DialogInterface;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.Loader;
29import android.content.res.Resources;
30import android.database.Cursor;
31import android.graphics.drawable.Drawable;
32import android.graphics.drawable.LevelListDrawable;
33import android.hardware.display.DisplayManager;
34import android.hardware.display.WifiDisplay;
35import android.hardware.display.WifiDisplayStatus;
36import android.net.Uri;
37import android.provider.ContactsContract;
38import android.provider.Settings;
39import android.view.LayoutInflater;
40import android.view.View;
41import android.view.ViewGroup;
42import android.view.Window;
43import android.view.WindowManager;
44import android.widget.AdapterView;
45import android.widget.ArrayAdapter;
46import android.widget.Button;
47import android.widget.ImageView;
48import android.widget.ListView;
49import android.widget.TextView;
50
51import com.android.internal.view.RotationPolicy;
52import com.android.systemui.R;
53import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
54import com.android.systemui.statusbar.phone.QuickSettingsModel.UserState;
55import com.android.systemui.statusbar.policy.BatteryController;
56import com.android.systemui.statusbar.policy.BluetoothController;
57import com.android.systemui.statusbar.policy.BrightnessController;
58import com.android.systemui.statusbar.policy.LocationController;
59import com.android.systemui.statusbar.policy.NetworkController;
60import com.android.systemui.statusbar.policy.ToggleSlider;
61
62import java.util.ArrayList;
63import java.util.Comparator;
64
65
66/**
67 *
68 */
69class QuickSettings {
70
71    private Context mContext;
72    private PanelBar mBar;
73    private QuickSettingsModel mModel;
74    private QuickSettingsContainerView mContainerView;
75
76    private DisplayManager mDisplayManager;
77    private WifiDisplayStatus mWifiDisplayStatus;
78    private WifiDisplayListAdapter mWifiDisplayListAdapter;
79
80    private BrightnessController mBrightnessController;
81    private Dialog mBrightnessDialog;
82
83    private CursorLoader mUserInfoLoader;
84
85    private LevelListDrawable mBatteryLevels;
86    private LevelListDrawable mChargingBatteryLevels;
87
88    // The set of QuickSettingsTiles that have dynamic spans (and need to be updated on
89    // configuration change)
90    private final ArrayList<QuickSettingsTileView> mDynamicSpannedTiles =
91            new ArrayList<QuickSettingsTileView>();
92
93    private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
94            new RotationPolicy.RotationPolicyListener() {
95        @Override
96        public void onChange() {
97            mModel.onRotationLockChanged();
98        }
99    };
100
101    public QuickSettings(Context context, QuickSettingsContainerView container) {
102        mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
103        mContext = context;
104        mContainerView = container;
105        mModel = new QuickSettingsModel(context);
106        mWifiDisplayStatus = new WifiDisplayStatus();
107        mWifiDisplayListAdapter = new WifiDisplayListAdapter(context);
108
109        Resources r = mContext.getResources();
110        mBatteryLevels = (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery);
111        mChargingBatteryLevels =
112                (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery_charging);
113
114        IntentFilter filter = new IntentFilter();
115        filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
116        mContext.registerReceiver(mReceiver, filter);
117
118        setupQuickSettings();
119        updateWifiDisplayStatus();
120        updateResources();
121    }
122
123    void setBar(PanelBar bar) {
124        mBar = bar;
125    }
126
127    public void setImeWindowStatus(boolean visible) {
128        mModel.onImeWindowStatusChanged(visible);
129    }
130
131    void setup(NetworkController networkController, BluetoothController bluetoothController,
132            BatteryController batteryController, LocationController locationController) {
133        networkController.addNetworkSignalChangedCallback(mModel);
134        bluetoothController.addStateChangedCallback(mModel);
135        batteryController.addStateChangedCallback(mModel);
136        locationController.addStateChangedCallback(mModel);
137        RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener);
138    }
139
140    private void queryForUserInformation() {
141        Uri userContactUri = Uri.withAppendedPath(
142            ContactsContract.Profile.CONTENT_URI,
143            ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
144
145        String[] selectArgs = {
146            ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
147            ContactsContract.CommonDataKinds.Photo.PHOTO
148        };
149        String where = String.format("(%s = ? OR %s = ?) AND %s IS NULL",
150            ContactsContract.Contacts.Data.MIMETYPE,
151            ContactsContract.Contacts.Data.MIMETYPE,
152            ContactsContract.RawContacts.ACCOUNT_TYPE);
153        String[] whereArgs = {
154            ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE,
155            ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
156        };
157
158        mUserInfoLoader = new CursorLoader(mContext, userContactUri, selectArgs, where, whereArgs,
159                null);
160        mUserInfoLoader.registerListener(0,
161                new Loader.OnLoadCompleteListener<Cursor>() {
162                    @Override
163                    public void onLoadComplete(Loader<Cursor> loader,
164                            Cursor cursor) {
165                        if (cursor != null && cursor.moveToFirst()) {
166                            String name = cursor.getString(0); // DISPLAY_NAME
167                            mModel.setUserTileInfo(name, null);
168                            /*
169                            byte[] photoData = cursor.getBlob(0);
170                            Bitmap b =
171                                BitmapFactory.decodeByteArray(photoData, 0, photoData.length);
172                             */
173                        }
174                        mUserInfoLoader.stopLoading();
175                    }
176                });
177        mUserInfoLoader.startLoading();
178    }
179
180    private void setupQuickSettings() {
181        // Setup the tiles that we are going to be showing (including the temporary ones)
182        LayoutInflater inflater = LayoutInflater.from(mContext);
183
184        addUserTiles(mContainerView, inflater);
185        addSystemTiles(mContainerView, inflater);
186        addTemporaryTiles(mContainerView, inflater);
187
188        queryForUserInformation();
189    }
190
191    private void startSettingsActivity(String action) {
192        Intent intent = new Intent(action);
193        startSettingsActivity(intent);
194    }
195    private void startSettingsActivity(Intent intent) {
196        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
197        mBar.collapseAllPanels(true);
198        mContext.startActivity(intent);
199    }
200
201    private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
202        QuickSettingsTileView userTile = (QuickSettingsTileView)
203                inflater.inflate(R.layout.quick_settings_tile, parent, false);
204        userTile.setContent(R.layout.quick_settings_tile_user, inflater);
205        mModel.addUserTile(userTile, new QuickSettingsModel.RefreshCallback() {
206            @Override
207            public void refreshView(QuickSettingsTileView view, State state) {
208                UserState us = (UserState) state;
209                TextView tv = (TextView) view.findViewById(R.id.user_textview);
210                tv.setText(state.label);
211                if (us.avatar != null) {
212                    tv.setCompoundDrawables(null, us.avatar, null, null);
213                }
214            }
215        });
216        parent.addView(userTile);
217        mDynamicSpannedTiles.add(userTile);
218
219        // Time tile
220        QuickSettingsTileView timeTile = (QuickSettingsTileView)
221                inflater.inflate(R.layout.quick_settings_tile, parent, false);
222        timeTile.setContent(R.layout.quick_settings_tile_time, inflater);
223        timeTile.setOnClickListener(new View.OnClickListener() {
224            @Override
225            public void onClick(View v) {
226                // TODO: Jump into the alarm application
227                Intent intent = new Intent();
228                intent.setComponent(new ComponentName(
229                        "com.google.android.deskclock",
230                        "com.android.deskclock.AlarmClock"));
231                startSettingsActivity(intent);
232            }
233        });
234        mModel.addTimeTile(timeTile, new QuickSettingsModel.RefreshCallback() {
235            @Override
236            public void refreshView(QuickSettingsTileView view, State alarmState) {
237                TextView tv = (TextView) view.findViewById(R.id.alarm_textview);
238                tv.setText(alarmState.label);
239                tv.setVisibility(alarmState.enabled ? View.VISIBLE : View.GONE);
240            }
241        });
242        parent.addView(timeTile);
243        mDynamicSpannedTiles.add(timeTile);
244
245        // Settings tile
246        QuickSettingsTileView settingsTile = (QuickSettingsTileView)
247                inflater.inflate(R.layout.quick_settings_tile, parent, false);
248        settingsTile.setContent(R.layout.quick_settings_tile_settings, inflater);
249        settingsTile.setOnClickListener(new View.OnClickListener() {
250            @Override
251            public void onClick(View v) {
252                startSettingsActivity(android.provider.Settings.ACTION_SETTINGS);
253            }
254        });
255        parent.addView(settingsTile);
256        mDynamicSpannedTiles.add(settingsTile);
257    }
258
259    private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
260        // Wi-fi
261        QuickSettingsTileView wifiTile = (QuickSettingsTileView)
262                inflater.inflate(R.layout.quick_settings_tile, parent, false);
263        wifiTile.setContent(R.layout.quick_settings_tile_wifi, inflater);
264        wifiTile.setOnClickListener(new View.OnClickListener() {
265            @Override
266            public void onClick(View v) {
267                startSettingsActivity(android.provider.Settings.ACTION_WIFI_SETTINGS);
268            }
269        });
270        mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() {
271            @Override
272            public void refreshView(QuickSettingsTileView view, State state) {
273                TextView tv = (TextView) view.findViewById(R.id.wifi_textview);
274                tv.setCompoundDrawablesRelativeWithIntrinsicBounds(0, state.iconId, 0, 0);
275                tv.setText(state.label);
276            }
277        });
278        parent.addView(wifiTile);
279
280        if (mModel.deviceSupportsTelephony()) {
281            // RSSI
282            QuickSettingsTileView rssiTile = (QuickSettingsTileView)
283                    inflater.inflate(R.layout.quick_settings_tile, parent, false);
284            rssiTile.setContent(R.layout.quick_settings_tile_rssi, inflater);
285            rssiTile.setOnClickListener(new View.OnClickListener() {
286                @Override
287                public void onClick(View v) {
288                    Intent intent = new Intent();
289                    intent.setComponent(new ComponentName(
290                            "com.android.settings",
291                            "com.android.settings.Settings$DataUsageSummaryActivity"));
292                    startSettingsActivity(intent);
293                }
294            });
295            mModel.addRSSITile(rssiTile, new QuickSettingsModel.RefreshCallback() {
296                @Override
297                public void refreshView(QuickSettingsTileView view, State state) {
298                    TextView tv = (TextView) view.findViewById(R.id.rssi_textview);
299                    tv.setCompoundDrawablesRelativeWithIntrinsicBounds(0, state.iconId, 0, 0);
300                    tv.setText(state.label);
301                }
302            });
303            parent.addView(rssiTile);
304        }
305
306        // Rotation Lock
307        if (mContext.getResources().getBoolean(R.bool.quick_settings_show_rotation_lock)) {
308            QuickSettingsTileView rotationLockTile = (QuickSettingsTileView)
309                    inflater.inflate(R.layout.quick_settings_tile, parent, false);
310            rotationLockTile.setContent(R.layout.quick_settings_tile_rotation_lock, inflater);
311            rotationLockTile.setOnClickListener(new View.OnClickListener() {
312                @Override
313                public void onClick(View v) {
314                    boolean locked = RotationPolicy.isRotationLocked(mContext);
315                    RotationPolicy.setRotationLock(mContext, !locked);
316                }
317            });
318            mModel.addRotationLockTile(rotationLockTile, new QuickSettingsModel.RefreshCallback() {
319                @Override
320                public void refreshView(QuickSettingsTileView view, State state) {
321                    TextView tv = (TextView) view.findViewById(R.id.rotation_lock_textview);
322                    tv.setCompoundDrawablesRelativeWithIntrinsicBounds(0, state.iconId, 0, 0);
323                    tv.setText(state.label);
324                }
325            });
326            parent.addView(rotationLockTile);
327        }
328
329        // Battery
330        QuickSettingsTileView batteryTile = (QuickSettingsTileView)
331                inflater.inflate(R.layout.quick_settings_tile, parent, false);
332        batteryTile.setContent(R.layout.quick_settings_tile_battery, inflater);
333        batteryTile.setOnClickListener(new View.OnClickListener() {
334            @Override
335            public void onClick(View v) {
336                startSettingsActivity(Intent.ACTION_POWER_USAGE_SUMMARY);
337            }
338        });
339        mModel.addBatteryTile(batteryTile, new QuickSettingsModel.RefreshCallback() {
340            @Override
341            public void refreshView(QuickSettingsTileView view, State state) {
342                QuickSettingsModel.BatteryState batteryState =
343                        (QuickSettingsModel.BatteryState) state;
344                TextView tv = (TextView) view.findViewById(R.id.battery_textview);
345                ImageView iv = (ImageView) view.findViewById(R.id.battery_image);
346                Drawable d = batteryState.pluggedIn
347                        ? mChargingBatteryLevels
348                        : mBatteryLevels;
349                String t;
350                if (batteryState.batteryLevel == 100) {
351                    t = mContext.getString(R.string.quick_settings_battery_charged_label);
352                } else {
353                    t = batteryState.pluggedIn
354                        ? mContext.getString(R.string.quick_settings_battery_charging_label,
355                                batteryState.batteryLevel)
356                        : mContext.getString(R.string.status_bar_settings_battery_meter_format,
357                                batteryState.batteryLevel);
358                }
359                iv.setImageDrawable(d);
360                iv.setImageLevel(batteryState.batteryLevel);
361                tv.setText(t);
362            }
363        });
364        parent.addView(batteryTile);
365
366        // Airplane Mode
367        QuickSettingsTileView airplaneTile = (QuickSettingsTileView)
368                inflater.inflate(R.layout.quick_settings_tile, parent, false);
369        airplaneTile.setContent(R.layout.quick_settings_tile_airplane, inflater);
370        mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() {
371            @Override
372            public void refreshView(QuickSettingsTileView view, State state) {
373                TextView tv = (TextView) view.findViewById(R.id.airplane_mode_textview);
374                tv.setCompoundDrawablesRelativeWithIntrinsicBounds(0, state.iconId, 0, 0);
375            }
376        });
377        parent.addView(airplaneTile);
378
379        // Bluetooth
380        if (mModel.deviceSupportsBluetooth()) {
381            QuickSettingsTileView bluetoothTile = (QuickSettingsTileView)
382                    inflater.inflate(R.layout.quick_settings_tile, parent, false);
383            bluetoothTile.setContent(R.layout.quick_settings_tile_bluetooth, inflater);
384            bluetoothTile.setOnClickListener(new View.OnClickListener() {
385                @Override
386                public void onClick(View v) {
387                    startSettingsActivity(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
388                }
389            });
390            mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() {
391                @Override
392                public void refreshView(QuickSettingsTileView view, State state) {
393                    TextView tv = (TextView) view.findViewById(R.id.bluetooth_textview);
394                    tv.setCompoundDrawablesRelativeWithIntrinsicBounds(0, state.iconId, 0, 0);
395                }
396            });
397            parent.addView(bluetoothTile);
398        }
399
400        // Brightness
401        QuickSettingsTileView brightnessTile = (QuickSettingsTileView)
402                inflater.inflate(R.layout.quick_settings_tile, parent, false);
403        brightnessTile.setContent(R.layout.quick_settings_tile_brightness, inflater);
404        brightnessTile.setOnClickListener(new View.OnClickListener() {
405            @Override
406            public void onClick(View v) {
407                // startSettingsActivity(android.provider.Settings.ACTION_DISPLAY_SETTINGS);
408                mBar.collapseAllPanels(true);
409                showBrightnessDialog();
410            }
411        });
412        parent.addView(brightnessTile);
413    }
414
415    private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) {
416        // Location
417        QuickSettingsTileView locationTile = (QuickSettingsTileView)
418                inflater.inflate(R.layout.quick_settings_tile, parent, false);
419        locationTile.setContent(R.layout.quick_settings_tile_location, inflater);
420        locationTile.setOnClickListener(new View.OnClickListener() {
421            @Override
422            public void onClick(View v) {
423                startSettingsActivity(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
424            }
425        });
426        mModel.addLocationTile(locationTile, new QuickSettingsModel.RefreshCallback() {
427            @Override
428            public void refreshView(QuickSettingsTileView view, State state) {
429                TextView tv = (TextView) view.findViewById(R.id.location_textview);
430                tv.setText(state.label);
431                view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
432            }
433        });
434        parent.addView(locationTile);
435
436        // Wifi Display
437        QuickSettingsTileView wifiDisplayTile = (QuickSettingsTileView)
438                inflater.inflate(R.layout.quick_settings_tile, parent, false);
439        wifiDisplayTile.setContent(R.layout.quick_settings_tile_wifi_display, inflater);
440        wifiDisplayTile.setOnClickListener(new View.OnClickListener() {
441            @Override
442            public void onClick(View v) {
443                mBar.collapseAllPanels(true);
444                showWifiDisplayDialog();
445            }
446        });
447        mModel.addWifiDisplayTile(wifiDisplayTile, new QuickSettingsModel.RefreshCallback() {
448            @Override
449            public void refreshView(QuickSettingsTileView view, State state) {
450                TextView tv = (TextView) view.findViewById(R.id.wifi_display_textview);
451                tv.setText(state.label);
452                view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
453            }
454        });
455        parent.addView(wifiDisplayTile);
456
457        // IME
458        QuickSettingsTileView imeTile = (QuickSettingsTileView)
459                inflater.inflate(R.layout.quick_settings_tile, parent, false);
460        imeTile.setContent(R.layout.quick_settings_tile_ime, inflater);
461        imeTile.setOnClickListener(new View.OnClickListener() {
462            @Override
463            public void onClick(View v) {
464                try {
465                    mBar.collapseAllPanels(true);
466                    Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
467                    PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
468                    pendingIntent.send();
469                } catch (Exception e) {}
470            }
471        });
472        mModel.addImeTile(imeTile, new QuickSettingsModel.RefreshCallback() {
473            @Override
474            public void refreshView(QuickSettingsTileView view, State state) {
475                TextView tv = (TextView) view.findViewById(R.id.ime_textview);
476                if (state.label != null) {
477                    tv.setText(state.label);
478                }
479                view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
480            }
481        });
482        parent.addView(imeTile);
483
484        /*
485        QuickSettingsTileView mediaTile = (QuickSettingsTileView)
486                inflater.inflate(R.layout.quick_settings_tile, parent, false);
487        mediaTile.setContent(R.layout.quick_settings_tile_media, inflater);
488        parent.addView(mediaTile);
489        QuickSettingsTileView imeTile = (QuickSettingsTileView)
490                inflater.inflate(R.layout.quick_settings_tile, parent, false);
491        imeTile.setContent(R.layout.quick_settings_tile_ime, inflater);
492        imeTile.setOnClickListener(new View.OnClickListener() {
493            @Override
494            public void onClick(View v) {
495                parent.removeViewAt(0);
496            }
497        });
498        parent.addView(imeTile);
499        */
500    }
501
502    void updateResources() {
503        Resources r = mContext.getResources();
504
505        // Update the User, Time, and Settings tiles spans, and reset everything else
506        int span = r.getInteger(R.integer.quick_settings_user_time_settings_tile_span);
507        for (QuickSettingsTileView v : mDynamicSpannedTiles) {
508            v.setColumnSpan(span);
509        }
510        mContainerView.requestLayout();
511    }
512
513    private void showBrightnessDialog() {
514        if (mBrightnessDialog == null) {
515            mBrightnessDialog = new Dialog(mContext);
516            mBrightnessDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
517            mBrightnessDialog.setContentView(R.layout.quick_settings_brightness_dialog);
518            mBrightnessDialog.setCanceledOnTouchOutside(true);
519
520            mBrightnessController = new BrightnessController(mContext,
521                    (ToggleSlider) mBrightnessDialog.findViewById(R.id.brightness_slider));
522            mBrightnessDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
523                @Override
524                public void onDismiss(DialogInterface dialog) {
525                    mBrightnessController = null;
526                }
527            });
528
529            mBrightnessDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
530            mBrightnessDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
531        }
532        if (!mBrightnessDialog.isShowing()) {
533            mBrightnessDialog.show();
534        }
535    }
536
537    // Wifi Display
538    private void showWifiDisplayDialog() {
539        mDisplayManager.scanWifiDisplays();
540        updateWifiDisplayStatus();
541
542        Dialog dialog = new Dialog(mContext);
543        dialog.setContentView(R.layout.wifi_display_dialog);
544        dialog.setCanceledOnTouchOutside(true);
545        dialog.setTitle(R.string.wifi_display_dialog_title);
546
547        Button scanButton = (Button)dialog.findViewById(R.id.scan);
548        scanButton.setOnClickListener(new View.OnClickListener() {
549            @Override
550            public void onClick(View v) {
551                mDisplayManager.scanWifiDisplays();
552            }
553        });
554
555        Button disconnectButton = (Button)dialog.findViewById(R.id.disconnect);
556        disconnectButton.setOnClickListener(new View.OnClickListener() {
557            @Override
558            public void onClick(View v) {
559                mDisplayManager.disconnectWifiDisplay();
560            }
561        });
562
563        ListView list = (ListView)dialog.findViewById(R.id.list);
564        list.setAdapter(mWifiDisplayListAdapter);
565        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
566            @Override
567            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
568                WifiDisplay display = mWifiDisplayListAdapter.getItem(position);
569                mDisplayManager.connectWifiDisplay(display.getDeviceAddress());
570            }
571        });
572
573        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
574        dialog.show();
575    }
576
577    private void updateWifiDisplayStatus() {
578        applyWifiDisplayStatus(mDisplayManager.getWifiDisplayStatus());
579    }
580
581    private void applyWifiDisplayStatus(WifiDisplayStatus status) {
582        mWifiDisplayStatus = status;
583
584        mWifiDisplayListAdapter.clear();
585        mWifiDisplayListAdapter.addAll(status.getKnownDisplays());
586        if (status.getActiveDisplay() != null
587                && !contains(status.getKnownDisplays(), status.getActiveDisplay())) {
588            mWifiDisplayListAdapter.add(status.getActiveDisplay());
589        }
590        mWifiDisplayListAdapter.sort(mWifiDisplayComparator);
591
592        mModel.onWifiDisplayStateChanged(status);
593    }
594
595    private static boolean contains(WifiDisplay[] displays, WifiDisplay display) {
596        for (WifiDisplay d : displays) {
597            if (d.equals(display)) {
598                return true;
599            }
600        }
601        return false;
602    }
603
604    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
605        @Override
606        public void onReceive(Context context, Intent intent) {
607            if (intent.getAction().equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
608                WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
609                        DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
610                applyWifiDisplayStatus(status);
611            }
612        }
613    };
614
615    private final class WifiDisplayListAdapter extends ArrayAdapter<WifiDisplay> {
616        private final LayoutInflater mInflater;
617
618        public WifiDisplayListAdapter(Context context) {
619            super(context, android.R.layout.simple_list_item_2);
620            mInflater = LayoutInflater.from(context);
621        }
622
623        @Override
624        public View getView(int position, View convertView, ViewGroup parent) {
625            WifiDisplay item = getItem(position);
626            View view = convertView;
627            if (view == null) {
628                view = mInflater.inflate(android.R.layout.simple_list_item_2,
629                        parent, false);
630            }
631            TextView headline = (TextView) view.findViewById(android.R.id.text1);
632            TextView subText = (TextView) view.findViewById(android.R.id.text2);
633            headline.setText(item.getDeviceName());
634
635            int state = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
636            if (item.equals(mWifiDisplayStatus.getActiveDisplay())) {
637                state = mWifiDisplayStatus.getActiveDisplayState();
638            }
639            switch (state) {
640                case WifiDisplayStatus.DISPLAY_STATE_CONNECTING:
641                    subText.setText(R.string.wifi_display_state_connecting);
642                    break;
643                case WifiDisplayStatus.DISPLAY_STATE_CONNECTED:
644                    subText.setText(R.string.wifi_display_state_connected);
645                    break;
646                case WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED:
647                default:
648                    subText.setText(R.string.wifi_display_state_available);
649                    break;
650            }
651            return view;
652        }
653    }
654
655    private final Comparator<WifiDisplay> mWifiDisplayComparator = new Comparator<WifiDisplay>() {
656        @Override
657        public int compare(WifiDisplay lhs, WifiDisplay rhs) {
658            int c = lhs.getDeviceName().compareToIgnoreCase(rhs.getDeviceName());
659            if (c == 0) {
660                c = lhs.getDeviceAddress().compareToIgnoreCase(rhs.getDeviceAddress());
661            }
662            return c;
663        }
664    };
665}