1616
1717package com .android .systemui .statusbar .phone ;
1818
19+ import android .app .Dialog ;
1920import android .bluetooth .BluetoothAdapter ;
2021import android .bluetooth .BluetoothAdapter .BluetoothStateChangeCallback ;
22+ import android .content .BroadcastReceiver ;
2123import android .content .Context ;
2224import android .content .CursorLoader ;
25+ import android .content .DialogInterface ;
2326import android .content .Intent ;
27+ import android .content .IntentFilter ;
2428import android .content .Loader ;
2529import android .content .res .Resources ;
2630import android .database .Cursor ;
31+ import android .database .DataSetObserver ;
2732import android .graphics .drawable .ClipDrawable ;
33+ import android .hardware .display .DisplayManager ;
34+ import android .hardware .display .WifiDisplay ;
35+ import android .hardware .display .WifiDisplayStatus ;
36+ import android .hardware .input .KeyboardLayout ;
2837import android .net .Uri ;
2938import android .provider .ContactsContract ;
3039import android .provider .Settings ;
3140import android .view .LayoutInflater ;
3241import android .view .View ;
3342import android .view .ViewGroup ;
43+ import android .view .WindowManager ;
44+ import android .widget .AdapterView ;
45+ import android .widget .ArrayAdapter ;
46+ import android .widget .Button ;
47+ import android .widget .CheckedTextView ;
48+ import android .widget .ListView ;
49+ import android .widget .RadioButton ;
3450import android .widget .TextView ;
51+ import android .widget .Toast ;
52+ import android .widget .ListAdapter ;
3553
3654import java .util .ArrayList ;
55+ import java .util .Comparator ;
3756
3857import com .android .systemui .R ;
3958import com .android .systemui .statusbar .phone .QuickSettingsModel .State ;
4059import com .android .systemui .statusbar .policy .BatteryController ;
60+ import com .android .systemui .statusbar .policy .BatteryController .BatteryStateChangeCallback ;
4161import com .android .systemui .statusbar .policy .BluetoothController ;
4262import com .android .systemui .statusbar .policy .LocationController ;
63+ import com .android .systemui .statusbar .policy .LocationController .LocationGpsStateChangeCallback ;
4364import com .android .systemui .statusbar .policy .NetworkController ;
65+ import com .android .systemui .statusbar .policy .NetworkController .NetworkSignalChangedCallback ;
4466
4567class QuickSettingsModel implements BluetoothStateChangeCallback ,
46- NetworkController . NetworkSignalChangedCallback ,
47- BatteryController . BatteryStateChangeCallback ,
48- LocationController . LocationGpsStateChangeCallback {
68+ NetworkSignalChangedCallback ,
69+ BatteryStateChangeCallback ,
70+ LocationGpsStateChangeCallback {
4971
5072 /** Represents the state of a given attribute. */
5173 static class State {
@@ -77,6 +99,10 @@ interface RefreshCallback {
7799 private RefreshCallback mWifiCallback ;
78100 private State mWifiState = new State ();
79101
102+ private QuickSettingsTileView mWifiDisplayTile ;
103+ private RefreshCallback mWifiDisplayCallback ;
104+ private State mWifiDisplayState = new State ();
105+
80106 private QuickSettingsTileView mRSSITile ;
81107 private RefreshCallback mRSSICallback ;
82108 private State mRSSIState = new State ();
@@ -282,6 +308,32 @@ public void onLocationGpsStateChanged(boolean inUse, String description) {
282308 }
283309 }
284310
311+ // Wifi Display
312+ void addWifiDisplayTile (QuickSettingsTileView view , RefreshCallback cb ) {
313+ mWifiDisplayTile = view ;
314+ mWifiDisplayCallback = cb ;
315+ }
316+ private void enableWifiDisplayTile () {
317+ mWifiDisplayTile .setVisibility (View .VISIBLE );
318+ }
319+ private void disableWifiDisplayTile () {
320+ mWifiDisplayTile .setVisibility (View .GONE );
321+ }
322+ public void onWifiDisplayStateChanged (WifiDisplayStatus status ) {
323+ if (status .isEnabled ()) {
324+ if (status .getActiveDisplay () != null ) {
325+ mWifiDisplayState .label = status .getActiveDisplay ().getDeviceName ();
326+ } else {
327+ mWifiDisplayState .label = mContext .getString (
328+ R .string .quick_settings_wifi_display_no_connection_label );
329+ }
330+ mWifiDisplayCallback .refreshView (mWifiDisplayTile , mWifiDisplayState );
331+ enableWifiDisplayTile ();
332+ } else {
333+ disableWifiDisplayTile ();
334+ }
335+ }
336+
285337}
286338
287339/**
@@ -294,6 +346,10 @@ class QuickSettings {
294346 private QuickSettingsModel mModel ;
295347 private QuickSettingsContainerView mContainerView ;
296348
349+ private DisplayManager mDisplayManager ;
350+ private WifiDisplayStatus mWifiDisplayStatus ;
351+ private WifiDisplayListAdapter mWifiDisplayListAdapter ;
352+
297353 private CursorLoader mUserInfoLoader ;
298354
299355 // The set of QuickSettingsTiles that have dynamic spans (and need to be updated on
@@ -302,11 +358,19 @@ class QuickSettings {
302358 new ArrayList <QuickSettingsTileView >();
303359
304360 public QuickSettings (Context context , QuickSettingsContainerView container ) {
361+ mDisplayManager = (DisplayManager ) context .getSystemService (Context .DISPLAY_SERVICE );
305362 mContext = context ;
306- mModel = new QuickSettingsModel (context );
307363 mContainerView = container ;
364+ mModel = new QuickSettingsModel (context );
365+ mWifiDisplayStatus = new WifiDisplayStatus ();
366+ mWifiDisplayListAdapter = new WifiDisplayListAdapter (context );
367+
368+ IntentFilter filter = new IntentFilter ();
369+ filter .addAction (DisplayManager .ACTION_WIFI_DISPLAY_STATUS_CHANGED );
370+ mContext .registerReceiver (mReceiver , filter );
308371
309372 setupQuickSettings ();
373+ updateWifiDisplayStatus ();
310374 updateResources ();
311375 }
312376
@@ -551,6 +615,26 @@ public void refreshView(QuickSettingsTileView view, State state) {
551615 });
552616 parent .addView (locationTile );
553617
618+ // Wifi Display
619+ QuickSettingsTileView wifiDisplayTile = (QuickSettingsTileView )
620+ inflater .inflate (R .layout .quick_settings_tile , parent , false );
621+ wifiDisplayTile .setContent (R .layout .quick_settings_tile_wifi_display , inflater );
622+ wifiDisplayTile .setOnClickListener (new View .OnClickListener () {
623+ @ Override
624+ public void onClick (View v ) {
625+ showWifiDisplayDialog ();
626+ mBar .collapseAllPanels (true );
627+ }
628+ });
629+ mModel .addWifiDisplayTile (wifiDisplayTile , new QuickSettingsModel .RefreshCallback () {
630+ @ Override
631+ public void refreshView (QuickSettingsTileView view , State state ) {
632+ TextView tv = (TextView ) view .findViewById (R .id .wifi_display_textview );
633+ tv .setText (state .label );
634+ }
635+ });
636+ parent .addView (wifiDisplayTile );
637+
554638 /*
555639 QuickSettingsTileView mediaTile = (QuickSettingsTileView)
556640 inflater.inflate(R.layout.quick_settings_tile, parent, false);
@@ -579,4 +663,132 @@ void updateResources() {
579663 }
580664 mContainerView .requestLayout ();
581665 }
666+
667+ private void showWifiDisplayDialog () {
668+ mDisplayManager .scanWifiDisplays ();
669+ updateWifiDisplayStatus ();
670+
671+ Dialog dialog = new Dialog (mContext );
672+ dialog .setContentView (R .layout .wifi_display_dialog );
673+ dialog .setCanceledOnTouchOutside (true );
674+ dialog .setTitle (R .string .wifi_display_dialog_title );
675+
676+ Button scanButton = (Button )dialog .findViewById (R .id .scan );
677+ scanButton .setOnClickListener (new View .OnClickListener () {
678+ @ Override
679+ public void onClick (View v ) {
680+ mDisplayManager .scanWifiDisplays ();
681+ }
682+ });
683+
684+ Button disconnectButton = (Button )dialog .findViewById (R .id .disconnect );
685+ disconnectButton .setOnClickListener (new View .OnClickListener () {
686+ @ Override
687+ public void onClick (View v ) {
688+ mDisplayManager .disconnectWifiDisplay ();
689+ }
690+ });
691+
692+ ListView list = (ListView )dialog .findViewById (R .id .list );
693+ list .setAdapter (mWifiDisplayListAdapter );
694+ list .setOnItemClickListener (new AdapterView .OnItemClickListener () {
695+ @ Override
696+ public void onItemClick (AdapterView <?> parent , View view , int position , long id ) {
697+ WifiDisplay display = mWifiDisplayListAdapter .getItem (position );
698+ mDisplayManager .connectWifiDisplay (display .getDeviceAddress ());
699+ }
700+ });
701+
702+ dialog .getWindow ().setType (WindowManager .LayoutParams .TYPE_SYSTEM_ALERT );
703+ dialog .show ();
704+ }
705+
706+ private void updateWifiDisplayStatus () {
707+ applyWifiDisplayStatus (mDisplayManager .getWifiDisplayStatus ());
708+ }
709+
710+ private void applyWifiDisplayStatus (WifiDisplayStatus status ) {
711+ mWifiDisplayStatus = status ;
712+
713+ mWifiDisplayListAdapter .clear ();
714+ mWifiDisplayListAdapter .addAll (status .getKnownDisplays ());
715+ if (status .getActiveDisplay () != null
716+ && !contains (status .getKnownDisplays (), status .getActiveDisplay ())) {
717+ mWifiDisplayListAdapter .add (status .getActiveDisplay ());
718+ }
719+ mWifiDisplayListAdapter .sort (mWifiDisplayComparator );
720+
721+ mModel .onWifiDisplayStateChanged (status );
722+ }
723+
724+ private static boolean contains (WifiDisplay [] displays , WifiDisplay display ) {
725+ for (WifiDisplay d : displays ) {
726+ if (d .equals (display )) {
727+ return true ;
728+ }
729+ }
730+ return false ;
731+ }
732+
733+ private final BroadcastReceiver mReceiver = new BroadcastReceiver () {
734+ @ Override
735+ public void onReceive (Context context , Intent intent ) {
736+ if (intent .getAction ().equals (DisplayManager .ACTION_WIFI_DISPLAY_STATUS_CHANGED )) {
737+ WifiDisplayStatus status = (WifiDisplayStatus )intent .getParcelableExtra (
738+ DisplayManager .EXTRA_WIFI_DISPLAY_STATUS );
739+ applyWifiDisplayStatus (status );
740+ }
741+ }
742+ };
743+
744+ private final class WifiDisplayListAdapter extends ArrayAdapter <WifiDisplay > {
745+ private final LayoutInflater mInflater ;
746+
747+ public WifiDisplayListAdapter (Context context ) {
748+ super (context , android .R .layout .simple_list_item_2 );
749+ mInflater = LayoutInflater .from (context );
750+ }
751+
752+ @ Override
753+ public View getView (int position , View convertView , ViewGroup parent ) {
754+ WifiDisplay item = getItem (position );
755+ View view = convertView ;
756+ if (view == null ) {
757+ view = mInflater .inflate (android .R .layout .simple_list_item_2 ,
758+ parent , false );
759+ }
760+ TextView headline = (TextView ) view .findViewById (android .R .id .text1 );
761+ TextView subText = (TextView ) view .findViewById (android .R .id .text2 );
762+ headline .setText (item .getDeviceName ());
763+
764+ int state = WifiDisplayStatus .DISPLAY_STATE_NOT_CONNECTED ;
765+ if (item .equals (mWifiDisplayStatus .getActiveDisplay ())) {
766+ state = mWifiDisplayStatus .getActiveDisplayState ();
767+ }
768+ switch (state ) {
769+ case WifiDisplayStatus .DISPLAY_STATE_CONNECTING :
770+ subText .setText (R .string .wifi_display_state_connecting );
771+ break ;
772+ case WifiDisplayStatus .DISPLAY_STATE_CONNECTED :
773+ subText .setText (R .string .wifi_display_state_connected );
774+ break ;
775+ case WifiDisplayStatus .DISPLAY_STATE_NOT_CONNECTED :
776+ default :
777+ subText .setText (R .string .wifi_display_state_available );
778+ break ;
779+ }
780+ return view ;
781+ }
782+ }
783+
784+ private final Comparator <WifiDisplay > mWifiDisplayComparator = new Comparator <WifiDisplay >() {
785+ @ Override
786+ public int compare (WifiDisplay lhs , WifiDisplay rhs ) {
787+ int c = lhs .getDeviceName ().compareToIgnoreCase (rhs .getDeviceName ());
788+ if (c == 0 ) {
789+ c = lhs .getDeviceAddress ().compareToIgnoreCase (rhs .getDeviceAddress ());
790+ }
791+ return c ;
792+ }
793+ };
582794}
0 commit comments