Skip to content

Commit e168edb

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Add skeleton Wifi-Display tile in QS." into jb-mr1-dev
2 parents 20ec8ac + 508257b commit e168edb

File tree

5 files changed

+280
-8
lines changed

5 files changed

+280
-8
lines changed

packages/SystemUI/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<uses-permission android:name="android.permission.MANAGE_USERS" />
1919
<uses-permission android:name="android.permission.READ_PROFILE" />
2020
<uses-permission android:name="android.permission.READ_CONTACTS" />
21+
<uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
2122

2223
<!-- Networking and telephony -->
2324
<uses-permission android:name="android.permission.BLUETOOTH" />

packages/SystemUI/res/layout/quick_settings_tile_wifi_display.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
-->
1616
<TextView
1717
xmlns:android="http://schemas.android.com/apk/res/android"
18+
android:id="@+id/wifi_display_textview"
1819
android:layout_width="match_parent"
1920
android:layout_height="match_parent"
21+
android:layout_gravity="center"
2022
android:gravity="center"
23+
android:drawableTop="@drawable/ic_qs_wifi_normal"
2124
android:text="@string/quick_settings_wifi_display_label"
22-
android:singleLine="true"
23-
android:ellipsize="marquee"
24-
android:fadingEdge="horizontal"
25+
android:textAppearance="@style/TextAppearance.QuickSettings.TileView"
2526
/>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="utf-8"?>
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+
17+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
18+
android:layout_width="match_parent"
19+
android:layout_height="wrap_content"
20+
android:orientation="vertical">
21+
22+
<ListView android:id="@+id/list"
23+
android:layout_width="match_parent"
24+
android:layout_height="0dp"
25+
android:layout_weight="2" />
26+
27+
<Button android:id="@+id/scan"
28+
android:layout_width="match_parent"
29+
android:layout_height="wrap_content"
30+
android:layout_weight="1"
31+
android:text="@string/wifi_display_scan" />
32+
33+
<Button android:id="@+id/disconnect"
34+
android:layout_width="match_parent"
35+
android:layout_height="wrap_content"
36+
android:layout_weight="1"
37+
android:text="@string/wifi_display_disconnect" />
38+
</LinearLayout>

packages/SystemUI/res/values/strings.xml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,5 +430,25 @@
430430
<!-- QuickSettings: Wifi (No network) [CHAR LIMIT=NONE] -->
431431
<string name="quick_settings_wifi_no_network">No Network</string>
432432
<!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] -->
433-
<string name="quick_settings_wifi_display_label">Wifi display</string>
433+
<string name="quick_settings_wifi_display_label">Wifi Display</string>
434+
<!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] -->
435+
<string name="quick_settings_wifi_display_no_connection_label">No Wifi Display Connection</string>
436+
437+
<!-- Wifi display: Scan button text [CHAR LIMIT=15] -->
438+
<string name="wifi_display_scan">Scan</string>
439+
440+
<!-- Wifi display: Disconnect button text [CHAR LIMIT=15] -->
441+
<string name="wifi_display_disconnect">Disconnect</string>
442+
443+
<!-- Wifi display: Quick setting dialog title [CHAR LIMIT=30] -->
444+
<string name="wifi_display_dialog_title">Wifi Display</string>
445+
446+
<!-- Wifi display: Subtitle text shown to indicate that a display is available [CHAR LIMIT=30] -->
447+
<string name="wifi_display_state_available">Available</string>
448+
449+
<!-- Wifi display: Subtitle text shown to indicate that a display is connecting [CHAR LIMIT=30] -->
450+
<string name="wifi_display_state_connecting">Connecting</string>
451+
452+
<!-- Wifi display: Subtitle text shown to indicate that a display is connected [CHAR LIMIT=30] -->
453+
<string name="wifi_display_state_connected">Connected</string>
434454
</resources>

packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java

Lines changed: 216 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,36 +16,58 @@
1616

1717
package com.android.systemui.statusbar.phone;
1818

19+
import android.app.Dialog;
1920
import android.bluetooth.BluetoothAdapter;
2021
import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback;
22+
import android.content.BroadcastReceiver;
2123
import android.content.Context;
2224
import android.content.CursorLoader;
25+
import android.content.DialogInterface;
2326
import android.content.Intent;
27+
import android.content.IntentFilter;
2428
import android.content.Loader;
2529
import android.content.res.Resources;
2630
import android.database.Cursor;
31+
import android.database.DataSetObserver;
2732
import 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;
2837
import android.net.Uri;
2938
import android.provider.ContactsContract;
3039
import android.provider.Settings;
3140
import android.view.LayoutInflater;
3241
import android.view.View;
3342
import 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;
3450
import android.widget.TextView;
51+
import android.widget.Toast;
52+
import android.widget.ListAdapter;
3553

3654
import java.util.ArrayList;
55+
import java.util.Comparator;
3756

3857
import com.android.systemui.R;
3958
import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
4059
import com.android.systemui.statusbar.policy.BatteryController;
60+
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
4161
import com.android.systemui.statusbar.policy.BluetoothController;
4262
import com.android.systemui.statusbar.policy.LocationController;
63+
import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback;
4364
import com.android.systemui.statusbar.policy.NetworkController;
65+
import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
4466

4567
class 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

Comments
 (0)