Merge "Add support for remembering Wifi display devices." into jb-mr1-dev
This commit is contained in:
@@ -160,6 +160,10 @@ public final class DisplayManager {
|
||||
/**
|
||||
* Connects to a Wifi display.
|
||||
* The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
|
||||
* <p>
|
||||
* Automatically remembers the display after a successful connection, if not
|
||||
* already remembered.
|
||||
* </p>
|
||||
*
|
||||
* @param deviceAddress The MAC address of the device to which we should connect.
|
||||
* @hide
|
||||
@@ -177,6 +181,36 @@ public final class DisplayManager {
|
||||
mGlobal.disconnectWifiDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a Wifi display.
|
||||
* <p>
|
||||
* The display must already be remembered for this call to succeed. In other words,
|
||||
* we must already have successfully connected to the display at least once and then
|
||||
* not forgotten it.
|
||||
* </p>
|
||||
*
|
||||
* @param deviceAddress The MAC address of the device to rename.
|
||||
* @param alias The alias name by which to remember the device, or null
|
||||
* or empty if no alias should be used.
|
||||
* @hide
|
||||
*/
|
||||
public void renameWifiDisplay(String deviceAddress, String alias) {
|
||||
mGlobal.renameWifiDisplay(deviceAddress, alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forgets a previously remembered Wifi display.
|
||||
* <p>
|
||||
* Automatically disconnects from the display if currently connected to it.
|
||||
* </p>
|
||||
*
|
||||
* @param deviceAddress The MAC address of the device to forget.
|
||||
* @hide
|
||||
*/
|
||||
public void forgetWifiDisplay(String deviceAddress) {
|
||||
mGlobal.forgetWifiDisplay(deviceAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current Wifi display status.
|
||||
* Watch for changes in the status by registering a broadcast receiver for
|
||||
|
||||
@@ -281,6 +281,31 @@ public final class DisplayManagerGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
public void renameWifiDisplay(String deviceAddress, String alias) {
|
||||
if (deviceAddress == null) {
|
||||
throw new IllegalArgumentException("deviceAddress must not be null");
|
||||
}
|
||||
|
||||
try {
|
||||
mDm.renameWifiDisplay(deviceAddress, alias);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Failed to rename Wifi display " + deviceAddress
|
||||
+ " with alias " + alias + ".", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void forgetWifiDisplay(String deviceAddress) {
|
||||
if (deviceAddress == null) {
|
||||
throw new IllegalArgumentException("deviceAddress must not be null");
|
||||
}
|
||||
|
||||
try {
|
||||
mDm.forgetWifiDisplay(deviceAddress);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Failed to forget Wifi display.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public WifiDisplayStatus getWifiDisplayStatus() {
|
||||
try {
|
||||
return mDm.getWifiDisplayStatus();
|
||||
|
||||
@@ -37,6 +37,12 @@ interface IDisplayManager {
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
void disconnectWifiDisplay();
|
||||
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
void renameWifiDisplay(String address, String alias);
|
||||
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
void forgetWifiDisplay(String address);
|
||||
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
WifiDisplayStatus getWifiDisplayStatus();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package android.hardware.display;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import libcore.util.Objects;
|
||||
|
||||
/**
|
||||
* Describes the properties of a Wifi display.
|
||||
* <p>
|
||||
@@ -30,6 +32,7 @@ import android.os.Parcelable;
|
||||
public final class WifiDisplay implements Parcelable {
|
||||
private final String mDeviceAddress;
|
||||
private final String mDeviceName;
|
||||
private final String mDeviceAlias;
|
||||
|
||||
public static final WifiDisplay[] EMPTY_ARRAY = new WifiDisplay[0];
|
||||
|
||||
@@ -37,7 +40,8 @@ public final class WifiDisplay implements Parcelable {
|
||||
public WifiDisplay createFromParcel(Parcel in) {
|
||||
String deviceAddress = in.readString();
|
||||
String deviceName = in.readString();
|
||||
return new WifiDisplay(deviceAddress, deviceName);
|
||||
String deviceAlias = in.readString();
|
||||
return new WifiDisplay(deviceAddress, deviceName, deviceAlias);
|
||||
}
|
||||
|
||||
public WifiDisplay[] newArray(int size) {
|
||||
@@ -45,7 +49,7 @@ public final class WifiDisplay implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
public WifiDisplay(String deviceAddress, String deviceName) {
|
||||
public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias) {
|
||||
if (deviceAddress == null) {
|
||||
throw new IllegalArgumentException("deviceAddress must not be null");
|
||||
}
|
||||
@@ -55,6 +59,7 @@ public final class WifiDisplay implements Parcelable {
|
||||
|
||||
mDeviceAddress = deviceAddress;
|
||||
mDeviceName = deviceName;
|
||||
mDeviceAlias = deviceAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,6 +76,25 @@ public final class WifiDisplay implements Parcelable {
|
||||
return mDeviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user-specified alias of the Wifi display device, or null if none.
|
||||
* <p>
|
||||
* The alias should be used in the UI whenever available. It is the value
|
||||
* provided by the user when renaming the device.
|
||||
* </p>
|
||||
*/
|
||||
public String getDeviceAlias() {
|
||||
return mDeviceAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name to show in the UI.
|
||||
* Uses the device alias if available, otherwise uses the device name.
|
||||
*/
|
||||
public String getFriendlyDisplayName() {
|
||||
return mDeviceAlias != null ? mDeviceAlias : mDeviceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof WifiDisplay && equals((WifiDisplay)o);
|
||||
@@ -79,7 +103,8 @@ public final class WifiDisplay implements Parcelable {
|
||||
public boolean equals(WifiDisplay other) {
|
||||
return other != null
|
||||
&& mDeviceAddress.equals(other.mDeviceAddress)
|
||||
&& mDeviceName.equals(other.mDeviceName);
|
||||
&& mDeviceName.equals(other.mDeviceName)
|
||||
&& Objects.equal(mDeviceAlias, other.mDeviceAlias);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,6 +117,7 @@ public final class WifiDisplay implements Parcelable {
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mDeviceAddress);
|
||||
dest.writeString(mDeviceName);
|
||||
dest.writeString(mDeviceAlias);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,6 +128,10 @@ public final class WifiDisplay implements Parcelable {
|
||||
// For debugging purposes only.
|
||||
@Override
|
||||
public String toString() {
|
||||
return mDeviceName + " (" + mDeviceAddress + ")";
|
||||
String result = mDeviceName + " (" + mDeviceAddress + ")";
|
||||
if (mDeviceAlias != null) {
|
||||
result += ", alias " + mDeviceAlias;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Describes the current global state of Wifi display connectivity, including the
|
||||
* currently connected display and all known displays.
|
||||
* currently connected display and all available or remembered displays.
|
||||
* <p>
|
||||
* This object is immutable.
|
||||
* </p>
|
||||
@@ -31,22 +31,37 @@ import java.util.Arrays;
|
||||
* @hide
|
||||
*/
|
||||
public final class WifiDisplayStatus implements Parcelable {
|
||||
private final boolean mEnabled;
|
||||
private final int mFeatureState;
|
||||
private final int mScanState;
|
||||
private final int mActiveDisplayState;
|
||||
private final WifiDisplay mActiveDisplay;
|
||||
private final WifiDisplay[] mKnownDisplays;
|
||||
private final WifiDisplay[] mAvailableDisplays;
|
||||
private final WifiDisplay[] mRememberedDisplays;
|
||||
|
||||
/** Feature state: Wifi display is not available on this device. */
|
||||
public static final int FEATURE_STATE_UNAVAILABLE = 0;
|
||||
/** Feature state: Wifi display is disabled, probably because Wifi is disabled. */
|
||||
public static final int FEATURE_STATE_DISABLED = 1;
|
||||
/** Feature state: Wifi display is turned off in settings. */
|
||||
public static final int FEATURE_STATE_OFF = 2;
|
||||
/** Feature state: Wifi display is turned on in settings. */
|
||||
public static final int FEATURE_STATE_ON = 3;
|
||||
|
||||
/** Scan state: Not currently scanning. */
|
||||
public static final int SCAN_STATE_NOT_SCANNING = 0;
|
||||
/** Scan state: Currently scanning. */
|
||||
public static final int SCAN_STATE_SCANNING = 1;
|
||||
|
||||
/** Display state: Not connected. */
|
||||
public static final int DISPLAY_STATE_NOT_CONNECTED = 0;
|
||||
/** Display state: Connecting to active display. */
|
||||
public static final int DISPLAY_STATE_CONNECTING = 1;
|
||||
/** Display state: Connected to active display. */
|
||||
public static final int DISPLAY_STATE_CONNECTED = 2;
|
||||
|
||||
public static final Creator<WifiDisplayStatus> CREATOR = new Creator<WifiDisplayStatus>() {
|
||||
public WifiDisplayStatus createFromParcel(Parcel in) {
|
||||
boolean enabled = (in.readInt() != 0);
|
||||
int featureState = in.readInt();
|
||||
int scanState = in.readInt();
|
||||
int activeDisplayState= in.readInt();
|
||||
|
||||
@@ -55,13 +70,18 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
activeDisplay = WifiDisplay.CREATOR.createFromParcel(in);
|
||||
}
|
||||
|
||||
WifiDisplay[] knownDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
|
||||
for (int i = 0; i < knownDisplays.length; i++) {
|
||||
knownDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
|
||||
WifiDisplay[] availableDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
|
||||
for (int i = 0; i < availableDisplays.length; i++) {
|
||||
availableDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
|
||||
}
|
||||
|
||||
return new WifiDisplayStatus(enabled, scanState, activeDisplayState,
|
||||
activeDisplay, knownDisplays);
|
||||
WifiDisplay[] rememberedDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
|
||||
for (int i = 0; i < rememberedDisplays.length; i++) {
|
||||
rememberedDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
|
||||
}
|
||||
|
||||
return new WifiDisplayStatus(featureState, scanState, activeDisplayState,
|
||||
activeDisplay, availableDisplays, rememberedDisplays);
|
||||
}
|
||||
|
||||
public WifiDisplayStatus[] newArray(int size) {
|
||||
@@ -70,33 +90,38 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
};
|
||||
|
||||
public WifiDisplayStatus() {
|
||||
this(false, SCAN_STATE_NOT_SCANNING, DISPLAY_STATE_NOT_CONNECTED,
|
||||
null, WifiDisplay.EMPTY_ARRAY);
|
||||
this(FEATURE_STATE_UNAVAILABLE, SCAN_STATE_NOT_SCANNING, DISPLAY_STATE_NOT_CONNECTED,
|
||||
null, WifiDisplay.EMPTY_ARRAY, WifiDisplay.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
public WifiDisplayStatus(boolean enabled, int scanState, int activeDisplayState,
|
||||
WifiDisplay activeDisplay, WifiDisplay[] knownDisplays) {
|
||||
if (knownDisplays == null) {
|
||||
throw new IllegalArgumentException("knownDisplays must not be null");
|
||||
public WifiDisplayStatus(int featureState, int scanState,
|
||||
int activeDisplayState, WifiDisplay activeDisplay,
|
||||
WifiDisplay[] availableDisplays, WifiDisplay[] rememberedDisplays) {
|
||||
if (availableDisplays == null) {
|
||||
throw new IllegalArgumentException("availableDisplays must not be null");
|
||||
}
|
||||
if (rememberedDisplays == null) {
|
||||
throw new IllegalArgumentException("rememberedDisplays must not be null");
|
||||
}
|
||||
|
||||
mEnabled = enabled;
|
||||
mFeatureState = featureState;
|
||||
mScanState = scanState;
|
||||
mActiveDisplayState = activeDisplayState;
|
||||
mActiveDisplay = activeDisplay;
|
||||
mKnownDisplays = knownDisplays;
|
||||
mAvailableDisplays = availableDisplays;
|
||||
mRememberedDisplays = rememberedDisplays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Wifi display feature is enabled and available for use.
|
||||
* Returns the state of the Wifi display feature on this device.
|
||||
* <p>
|
||||
* The value of this property reflects whether Wifi and Wifi P2P functions
|
||||
* are enabled. Enablement is not directly controllable by the user at this
|
||||
* time, except indirectly such as by turning off Wifi altogether.
|
||||
* The value of this property reflects whether the device supports the Wifi display,
|
||||
* whether it has been enabled by the user and whether the prerequisites for
|
||||
* connecting to displays have been met.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return mEnabled;
|
||||
public int getFeatureState() {
|
||||
return mFeatureState;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,15 +152,29 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all known Wifi displays, never null.
|
||||
* Gets the list of all available Wifi displays as reported by the most recent
|
||||
* scan, never null.
|
||||
* <p>
|
||||
* Some of these displays may already be remembered, others may be unknown.
|
||||
* </p>
|
||||
*/
|
||||
public WifiDisplay[] getKnownDisplays() {
|
||||
return mKnownDisplays;
|
||||
public WifiDisplay[] getAvailableDisplays() {
|
||||
return mAvailableDisplays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all remembered Wifi displays, never null.
|
||||
* <p>
|
||||
* Not all remembered displays will necessarily be available.
|
||||
* </p>
|
||||
*/
|
||||
public WifiDisplay[] getRememberedDisplays() {
|
||||
return mRememberedDisplays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mEnabled ? 1 : 0);
|
||||
dest.writeInt(mFeatureState);
|
||||
dest.writeInt(mScanState);
|
||||
dest.writeInt(mActiveDisplayState);
|
||||
|
||||
@@ -146,8 +185,13 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
|
||||
dest.writeInt(mKnownDisplays.length);
|
||||
for (WifiDisplay display : mKnownDisplays) {
|
||||
dest.writeInt(mAvailableDisplays.length);
|
||||
for (WifiDisplay display : mAvailableDisplays) {
|
||||
display.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
dest.writeInt(mRememberedDisplays.length);
|
||||
for (WifiDisplay display : mRememberedDisplays) {
|
||||
display.writeToParcel(dest, flags);
|
||||
}
|
||||
}
|
||||
@@ -160,11 +204,12 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
// For debugging purposes only.
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WifiDisplayStatus{enabled=" + mEnabled
|
||||
return "WifiDisplayStatus{featureState=" + mFeatureState
|
||||
+ ", scanState=" + mScanState
|
||||
+ ", activeDisplayState=" + mActiveDisplayState
|
||||
+ ", activeDisplay=" + mActiveDisplay
|
||||
+ ", knownDisplays=" + Arrays.toString(mKnownDisplays)
|
||||
+ ", availableDisplays=" + Arrays.toString(mAvailableDisplays)
|
||||
+ ", rememberedDisplays=" + Arrays.toString(mRememberedDisplays)
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +213,21 @@ public final class Settings {
|
||||
public static final String ACTION_BLUETOOTH_SETTINGS =
|
||||
"android.settings.BLUETOOTH_SETTINGS";
|
||||
|
||||
/**
|
||||
* Activity Action: Show settings to allow configuration of Wifi Displays.
|
||||
* <p>
|
||||
* In some cases, a matching Activity may not exist, so ensure you
|
||||
* safeguard against this.
|
||||
* <p>
|
||||
* Input: Nothing.
|
||||
* <p>
|
||||
* Output: Nothing.
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public static final String ACTION_WIFI_DISPLAY_SETTINGS =
|
||||
"android.settings.WIFI_DISPLAY_SETTINGS";
|
||||
|
||||
/**
|
||||
* Activity Action: Show settings to allow configuration of date and time.
|
||||
* <p>
|
||||
@@ -5539,6 +5554,13 @@ public final class Settings {
|
||||
public static final String WEB_AUTOFILL_QUERY_URL =
|
||||
"web_autofill_query_url";
|
||||
|
||||
/**
|
||||
* Whether Wifi display is enabled/disabled
|
||||
* 0=disabled. 1=enabled.
|
||||
* @hide
|
||||
*/
|
||||
public static final String WIFI_DISPLAY_ON = "wifi_display_on";
|
||||
|
||||
/**
|
||||
* Whether to notify the user of open networks.
|
||||
* <p>
|
||||
|
||||
@@ -946,4 +946,18 @@
|
||||
players. -->
|
||||
<integer name="config_safe_media_volume_index">10</integer>
|
||||
|
||||
<!-- Whether WiFi display is supported by this device.
|
||||
There are many prerequisites for this feature to work correctly.
|
||||
Here are a few of them:
|
||||
* The WiFi radio must support WiFi P2P.
|
||||
* The WiFi radio must support concurrent connections to the WiFi display and
|
||||
to an access point.
|
||||
* The Audio Flinger audio_policy.conf file must specify a rule for the "r_submix"
|
||||
remote submix module. This module is used to record and stream system
|
||||
audio output to the WiFi display encoder in the media server.
|
||||
* The remote submix module "audio.r_submix.default" must be installed on the device.
|
||||
* The device must be provisioned with HDCP keys (for protected content).
|
||||
-->
|
||||
<bool name="config_enableWifiDisplay">false</bool>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -268,6 +268,7 @@
|
||||
<java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
|
||||
<java-symbol type="bool" name="config_enableScreenshotChord" />
|
||||
<java-symbol type="bool" name="config_bluetooth_default_profiles" />
|
||||
<java-symbol type="bool" name="config_enableWifiDisplay" />
|
||||
|
||||
<java-symbol type="integer" name="config_cursorWindowSize" />
|
||||
<java-symbol type="integer" name="config_longPressOnPowerBehavior" />
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
<bool name="def_haptic_feedback">true</bool>
|
||||
|
||||
<bool name="def_bluetooth_on">false</bool>
|
||||
<bool name="def_wifi_display_on">false</bool>
|
||||
<bool name="def_install_non_market_apps">false</bool>
|
||||
<bool name="def_package_verifier_enable">true</bool>
|
||||
<!-- Comma-separated list of location providers.
|
||||
|
||||
@@ -1995,6 +1995,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
||||
loadIntegerSetting(stmt, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
|
||||
R.integer.def_max_dhcp_retries);
|
||||
|
||||
loadBooleanSetting(stmt, Settings.Global.WIFI_DISPLAY_ON,
|
||||
R.bool.def_wifi_display_on);
|
||||
|
||||
// --- New global settings start here
|
||||
} finally {
|
||||
if (stmt != null) stmt.close();
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2012 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ListView android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="2" />
|
||||
|
||||
<Button android:id="@+id/scan"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/wifi_display_scan" />
|
||||
|
||||
<Button android:id="@+id/disconnect"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/wifi_display_disconnect" />
|
||||
</LinearLayout>
|
||||
@@ -445,22 +445,4 @@
|
||||
<string name="quick_settings_brightness_dialog_title">Brightness</string>
|
||||
<!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
|
||||
<string name="quick_settings_brightness_dialog_auto_brightness_label">AUTO</string>
|
||||
|
||||
<!-- Wifi display: Scan button text [CHAR LIMIT=15] -->
|
||||
<string name="wifi_display_scan">Scan</string>
|
||||
|
||||
<!-- Wifi display: Disconnect button text [CHAR LIMIT=15] -->
|
||||
<string name="wifi_display_disconnect">Disconnect</string>
|
||||
|
||||
<!-- Wifi display: Quick setting dialog title [CHAR LIMIT=30] -->
|
||||
<string name="wifi_display_dialog_title">Wifi Display</string>
|
||||
|
||||
<!-- Wifi display: Subtitle text shown to indicate that a display is available [CHAR LIMIT=30] -->
|
||||
<string name="wifi_display_state_available">Available</string>
|
||||
|
||||
<!-- Wifi display: Subtitle text shown to indicate that a display is connecting [CHAR LIMIT=30] -->
|
||||
<string name="wifi_display_state_connecting">Connecting</string>
|
||||
|
||||
<!-- Wifi display: Subtitle text shown to indicate that a display is connected [CHAR LIMIT=30] -->
|
||||
<string name="wifi_display_state_connected">Connected</string>
|
||||
</resources>
|
||||
|
||||
@@ -81,8 +81,7 @@ class QuickSettings {
|
||||
|
||||
private DisplayManager mDisplayManager;
|
||||
private WifiDisplayStatus mWifiDisplayStatus;
|
||||
private WifiDisplayListAdapter mWifiDisplayListAdapter;
|
||||
|
||||
|
||||
private BrightnessController mBrightnessController;
|
||||
private BluetoothController mBluetoothController;
|
||||
private Dialog mBrightnessDialog;
|
||||
@@ -111,7 +110,6 @@ class QuickSettings {
|
||||
mContainerView = container;
|
||||
mModel = new QuickSettingsModel(context);
|
||||
mWifiDisplayStatus = new WifiDisplayStatus();
|
||||
mWifiDisplayListAdapter = new WifiDisplayListAdapter(context);
|
||||
|
||||
Resources r = mContext.getResources();
|
||||
mBatteryLevels = (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery);
|
||||
@@ -483,8 +481,7 @@ class QuickSettings {
|
||||
wifiDisplayTile.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mBar.collapseAllPanels(true);
|
||||
showWifiDisplayDialog();
|
||||
startSettingsActivity(android.provider.Settings.ACTION_WIFI_DISPLAY_SETTINGS);
|
||||
}
|
||||
});
|
||||
mModel.addWifiDisplayTile(wifiDisplayTile, new QuickSettingsModel.RefreshCallback() {
|
||||
@@ -578,71 +575,13 @@ class QuickSettings {
|
||||
}
|
||||
}
|
||||
|
||||
// Wifi Display
|
||||
private void showWifiDisplayDialog() {
|
||||
mDisplayManager.scanWifiDisplays();
|
||||
updateWifiDisplayStatus();
|
||||
|
||||
Dialog dialog = new Dialog(mContext);
|
||||
dialog.setContentView(R.layout.wifi_display_dialog);
|
||||
dialog.setCanceledOnTouchOutside(true);
|
||||
dialog.setTitle(R.string.wifi_display_dialog_title);
|
||||
|
||||
Button scanButton = (Button)dialog.findViewById(R.id.scan);
|
||||
scanButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mDisplayManager.scanWifiDisplays();
|
||||
}
|
||||
});
|
||||
|
||||
Button disconnectButton = (Button)dialog.findViewById(R.id.disconnect);
|
||||
disconnectButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mDisplayManager.disconnectWifiDisplay();
|
||||
}
|
||||
});
|
||||
|
||||
ListView list = (ListView)dialog.findViewById(R.id.list);
|
||||
list.setAdapter(mWifiDisplayListAdapter);
|
||||
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
WifiDisplay display = mWifiDisplayListAdapter.getItem(position);
|
||||
mDisplayManager.connectWifiDisplay(display.getDeviceAddress());
|
||||
}
|
||||
});
|
||||
|
||||
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void updateWifiDisplayStatus() {
|
||||
applyWifiDisplayStatus(mDisplayManager.getWifiDisplayStatus());
|
||||
mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
|
||||
applyWifiDisplayStatus();
|
||||
}
|
||||
|
||||
private void applyWifiDisplayStatus(WifiDisplayStatus status) {
|
||||
mWifiDisplayStatus = status;
|
||||
|
||||
mWifiDisplayListAdapter.clear();
|
||||
mWifiDisplayListAdapter.addAll(status.getKnownDisplays());
|
||||
if (status.getActiveDisplay() != null
|
||||
&& !contains(status.getKnownDisplays(), status.getActiveDisplay())) {
|
||||
mWifiDisplayListAdapter.add(status.getActiveDisplay());
|
||||
}
|
||||
mWifiDisplayListAdapter.sort(mWifiDisplayComparator);
|
||||
|
||||
mModel.onWifiDisplayStateChanged(status);
|
||||
}
|
||||
|
||||
private static boolean contains(WifiDisplay[] displays, WifiDisplay display) {
|
||||
for (WifiDisplay d : displays) {
|
||||
if (d.equals(display)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
private void applyWifiDisplayStatus() {
|
||||
mModel.onWifiDisplayStateChanged(mWifiDisplayStatus);
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@@ -651,59 +590,9 @@ class QuickSettings {
|
||||
if (intent.getAction().equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
|
||||
WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
|
||||
DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
|
||||
applyWifiDisplayStatus(status);
|
||||
mWifiDisplayStatus = status;
|
||||
applyWifiDisplayStatus();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final class WifiDisplayListAdapter extends ArrayAdapter<WifiDisplay> {
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
public WifiDisplayListAdapter(Context context) {
|
||||
super(context, android.R.layout.simple_list_item_2);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
WifiDisplay item = getItem(position);
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = mInflater.inflate(android.R.layout.simple_list_item_2,
|
||||
parent, false);
|
||||
}
|
||||
TextView headline = (TextView) view.findViewById(android.R.id.text1);
|
||||
TextView subText = (TextView) view.findViewById(android.R.id.text2);
|
||||
headline.setText(item.getDeviceName());
|
||||
|
||||
int state = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
|
||||
if (item.equals(mWifiDisplayStatus.getActiveDisplay())) {
|
||||
state = mWifiDisplayStatus.getActiveDisplayState();
|
||||
}
|
||||
switch (state) {
|
||||
case WifiDisplayStatus.DISPLAY_STATE_CONNECTING:
|
||||
subText.setText(R.string.wifi_display_state_connecting);
|
||||
break;
|
||||
case WifiDisplayStatus.DISPLAY_STATE_CONNECTED:
|
||||
subText.setText(R.string.wifi_display_state_connected);
|
||||
break;
|
||||
case WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED:
|
||||
default:
|
||||
subText.setText(R.string.wifi_display_state_available);
|
||||
break;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
private final Comparator<WifiDisplay> mWifiDisplayComparator = new Comparator<WifiDisplay>() {
|
||||
@Override
|
||||
public int compare(WifiDisplay lhs, WifiDisplay rhs) {
|
||||
int c = lhs.getDeviceName().compareToIgnoreCase(rhs.getDeviceName());
|
||||
if (c == 0) {
|
||||
c = lhs.getDeviceAddress().compareToIgnoreCase(rhs.getDeviceAddress());
|
||||
}
|
||||
return c;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -347,9 +347,10 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
|
||||
mWifiDisplayCallback = cb;
|
||||
}
|
||||
public void onWifiDisplayStateChanged(WifiDisplayStatus status) {
|
||||
mWifiDisplayState.enabled = status.isEnabled();
|
||||
mWifiDisplayState.enabled =
|
||||
(status.getFeatureState() != WifiDisplayStatus.FEATURE_STATE_UNAVAILABLE);
|
||||
if (status.getActiveDisplay() != null) {
|
||||
mWifiDisplayState.label = status.getActiveDisplay().getDeviceName();
|
||||
mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName();
|
||||
} else {
|
||||
mWifiDisplayState.label = mContext.getString(
|
||||
R.string.quick_settings_wifi_display_no_connection_label);
|
||||
|
||||
@@ -189,7 +189,7 @@ class ServerThread extends Thread {
|
||||
|
||||
// For debug builds, log event loop stalls to dropbox for analysis.
|
||||
if (StrictMode.conditionallyEnableDebugLogging()) {
|
||||
Slog.i(TAG, "Enabled StrictMode logging for UI Looper");
|
||||
Slog.i(TAG, "Enabled StrictMode logging for WM Looper");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -148,6 +148,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
|
||||
private final DisplayViewport mDefaultViewport = new DisplayViewport();
|
||||
private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
|
||||
|
||||
// Persistent data store for all internal settings maintained by the display manager service.
|
||||
private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
|
||||
|
||||
// Temporary callback list, used when sending display events to applications.
|
||||
// May be used outside of the lock but only on the handler thread.
|
||||
private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
|
||||
@@ -402,6 +405,50 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void renameWifiDisplay(String address, String alias) {
|
||||
if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
|
||||
}
|
||||
if (address == null) {
|
||||
throw new IllegalArgumentException("address must not be null");
|
||||
}
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mSyncRoot) {
|
||||
if (mWifiDisplayAdapter != null) {
|
||||
mWifiDisplayAdapter.requestRenameLocked(address, alias);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void forgetWifiDisplay(String address) {
|
||||
if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
|
||||
}
|
||||
if (address == null) {
|
||||
throw new IllegalArgumentException("address must not be null");
|
||||
}
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mSyncRoot) {
|
||||
if (mWifiDisplayAdapter != null) {
|
||||
mWifiDisplayAdapter.requestForgetLocked(address);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public WifiDisplayStatus getWifiDisplayStatus() {
|
||||
if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
|
||||
@@ -439,15 +486,27 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
|
||||
private void registerAdditionalDisplayAdapters() {
|
||||
synchronized (mSyncRoot) {
|
||||
if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
|
||||
registerDisplayAdapterLocked(new OverlayDisplayAdapter(
|
||||
mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
|
||||
mWifiDisplayAdapter = new WifiDisplayAdapter(
|
||||
mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
|
||||
registerDisplayAdapterLocked(mWifiDisplayAdapter);
|
||||
registerOverlayDisplayAdapterLocked();
|
||||
registerWifiDisplayAdapterLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerOverlayDisplayAdapterLocked() {
|
||||
registerDisplayAdapterLocked(new OverlayDisplayAdapter(
|
||||
mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
|
||||
}
|
||||
|
||||
private void registerWifiDisplayAdapterLocked() {
|
||||
if (mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_enableWifiDisplay)) {
|
||||
mWifiDisplayAdapter = new WifiDisplayAdapter(
|
||||
mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
|
||||
mPersistentDataStore);
|
||||
registerDisplayAdapterLocked(mWifiDisplayAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
|
||||
// In safe mode, we disable non-essential display adapters to give the user
|
||||
// an opportunity to fix broken settings or other problems that might affect
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.display;
|
||||
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import android.hardware.display.WifiDisplay;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Slog;
|
||||
import android.util.Xml;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
import libcore.util.Objects;
|
||||
|
||||
/**
|
||||
* Manages persistent state recorded by the display manager service as an XML file.
|
||||
* Caller must acquire lock on the data store before accessing it.
|
||||
*
|
||||
* File format:
|
||||
* <code>
|
||||
* <display-manager-state>
|
||||
* <remembered-wifi-displays>
|
||||
* <wifi-display deviceAddress="00:00:00:00:00:00" deviceName="XXXX" deviceAlias="YYYY" />
|
||||
* >remembered-wifi-displays>
|
||||
* >/display-manager-state>
|
||||
* </code>
|
||||
*
|
||||
* TODO: refactor this to extract common code shared with the input manager's data store
|
||||
*/
|
||||
final class PersistentDataStore {
|
||||
static final String TAG = "DisplayManager";
|
||||
|
||||
// Remembered Wifi display devices.
|
||||
private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>();
|
||||
|
||||
// The atomic file used to safely read or write the file.
|
||||
private final AtomicFile mAtomicFile;
|
||||
|
||||
// True if the data has been loaded.
|
||||
private boolean mLoaded;
|
||||
|
||||
// True if there are changes to be saved.
|
||||
private boolean mDirty;
|
||||
|
||||
public PersistentDataStore() {
|
||||
mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml"));
|
||||
}
|
||||
|
||||
public void saveIfNeeded() {
|
||||
if (mDirty) {
|
||||
save();
|
||||
mDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
public WifiDisplay[] getRememberedWifiDisplays() {
|
||||
loadIfNeeded();
|
||||
return mRememberedWifiDisplays.toArray(new WifiDisplay[mRememberedWifiDisplays.size()]);
|
||||
}
|
||||
|
||||
public WifiDisplay applyWifiDisplayAlias(WifiDisplay display) {
|
||||
if (display != null) {
|
||||
loadIfNeeded();
|
||||
|
||||
int index = findRememberedWifiDisplay(display.getDeviceAddress());
|
||||
if (index >= 0) {
|
||||
return mRememberedWifiDisplays.get(index);
|
||||
}
|
||||
}
|
||||
return display;
|
||||
}
|
||||
|
||||
public WifiDisplay[] applyWifiDisplayAliases(WifiDisplay[] displays) {
|
||||
WifiDisplay[] results = displays;
|
||||
if (results != null) {
|
||||
int count = displays.length;
|
||||
for (int i = 0; i < count; i++) {
|
||||
WifiDisplay result = applyWifiDisplayAlias(displays[i]);
|
||||
if (result != displays[i]) {
|
||||
if (results == displays) {
|
||||
results = new WifiDisplay[count];
|
||||
System.arraycopy(displays, 0, results, 0, count);
|
||||
}
|
||||
results[i] = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public boolean rememberWifiDisplay(WifiDisplay display) {
|
||||
loadIfNeeded();
|
||||
|
||||
int index = findRememberedWifiDisplay(display.getDeviceAddress());
|
||||
if (index >= 0) {
|
||||
WifiDisplay other = mRememberedWifiDisplays.get(index);
|
||||
if (other.equals(display)) {
|
||||
return false; // already remembered without change
|
||||
}
|
||||
mRememberedWifiDisplays.set(index, display);
|
||||
} else {
|
||||
mRememberedWifiDisplays.add(display);
|
||||
}
|
||||
setDirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean renameWifiDisplay(String deviceAddress, String alias) {
|
||||
int index = findRememberedWifiDisplay(deviceAddress);
|
||||
if (index >= 0) {
|
||||
WifiDisplay display = mRememberedWifiDisplays.get(index);
|
||||
if (Objects.equal(display.getDeviceAlias(), alias)) {
|
||||
return false; // already has this alias
|
||||
}
|
||||
WifiDisplay renamedDisplay = new WifiDisplay(deviceAddress,
|
||||
display.getDeviceName(), alias);
|
||||
mRememberedWifiDisplays.set(index, renamedDisplay);
|
||||
setDirty();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean forgetWifiDisplay(String deviceAddress) {
|
||||
int index = findRememberedWifiDisplay(deviceAddress);
|
||||
if (index >= 0) {
|
||||
mRememberedWifiDisplays.remove(index);
|
||||
setDirty();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int findRememberedWifiDisplay(String deviceAddress) {
|
||||
int count = mRememberedWifiDisplays.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (mRememberedWifiDisplays.get(i).getDeviceAddress().equals(deviceAddress)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void loadIfNeeded() {
|
||||
if (!mLoaded) {
|
||||
load();
|
||||
mLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void setDirty() {
|
||||
mDirty = true;
|
||||
}
|
||||
|
||||
private void clearState() {
|
||||
mRememberedWifiDisplays.clear();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
clearState();
|
||||
|
||||
final InputStream is;
|
||||
try {
|
||||
is = mAtomicFile.openRead();
|
||||
} catch (FileNotFoundException ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
XmlPullParser parser;
|
||||
try {
|
||||
parser = Xml.newPullParser();
|
||||
parser.setInput(new BufferedInputStream(is), null);
|
||||
loadFromXml(parser);
|
||||
} catch (IOException ex) {
|
||||
Slog.w(TAG, "Failed to load display manager persistent store data.", ex);
|
||||
clearState();
|
||||
} catch (XmlPullParserException ex) {
|
||||
Slog.w(TAG, "Failed to load display manager persistent store data.", ex);
|
||||
clearState();
|
||||
} finally {
|
||||
IoUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
private void save() {
|
||||
final FileOutputStream os;
|
||||
try {
|
||||
os = mAtomicFile.startWrite();
|
||||
boolean success = false;
|
||||
try {
|
||||
XmlSerializer serializer = new FastXmlSerializer();
|
||||
serializer.setOutput(new BufferedOutputStream(os), "utf-8");
|
||||
saveToXml(serializer);
|
||||
serializer.flush();
|
||||
success = true;
|
||||
} finally {
|
||||
if (success) {
|
||||
mAtomicFile.finishWrite(os);
|
||||
} else {
|
||||
mAtomicFile.failWrite(os);
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Slog.w(TAG, "Failed to save display manager persistent store data.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadFromXml(XmlPullParser parser)
|
||||
throws IOException, XmlPullParserException {
|
||||
XmlUtils.beginDocument(parser, "display-manager-state");
|
||||
final int outerDepth = parser.getDepth();
|
||||
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
|
||||
if (parser.getName().equals("remembered-wifi-displays")) {
|
||||
loadRememberedWifiDisplaysFromXml(parser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadRememberedWifiDisplaysFromXml(XmlPullParser parser)
|
||||
throws IOException, XmlPullParserException {
|
||||
final int outerDepth = parser.getDepth();
|
||||
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
|
||||
if (parser.getName().equals("wifi-display")) {
|
||||
String deviceAddress = parser.getAttributeValue(null, "deviceAddress");
|
||||
String deviceName = parser.getAttributeValue(null, "deviceName");
|
||||
String deviceAlias = parser.getAttributeValue(null, "deviceAlias");
|
||||
if (deviceAddress == null || deviceName == null) {
|
||||
throw new XmlPullParserException(
|
||||
"Missing deviceAddress or deviceName attribute on wifi-display.");
|
||||
}
|
||||
if (findRememberedWifiDisplay(deviceAddress) >= 0) {
|
||||
throw new XmlPullParserException(
|
||||
"Found duplicate wifi display device address.");
|
||||
}
|
||||
|
||||
mRememberedWifiDisplays.add(
|
||||
new WifiDisplay(deviceAddress, deviceName, deviceAlias));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveToXml(XmlSerializer serializer) throws IOException {
|
||||
serializer.startDocument(null, true);
|
||||
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
|
||||
serializer.startTag(null, "display-manager-state");
|
||||
serializer.startTag(null, "remembered-wifi-displays");
|
||||
for (WifiDisplay display : mRememberedWifiDisplays) {
|
||||
serializer.startTag(null, "wifi-display");
|
||||
serializer.attribute(null, "deviceAddress", display.getDeviceAddress());
|
||||
serializer.attribute(null, "deviceName", display.getDeviceName());
|
||||
if (display.getDeviceAlias() != null) {
|
||||
serializer.attribute(null, "deviceAlias", display.getDeviceAlias());
|
||||
}
|
||||
serializer.endTag(null, "wifi-display");
|
||||
}
|
||||
serializer.endTag(null, "remembered-wifi-displays");
|
||||
serializer.endTag(null, "display-manager-state");
|
||||
serializer.endDocument();
|
||||
}
|
||||
}
|
||||
@@ -49,21 +49,26 @@ import java.util.Arrays;
|
||||
final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
private static final String TAG = "WifiDisplayAdapter";
|
||||
|
||||
private PersistentDataStore mPersistentDataStore;
|
||||
|
||||
private WifiDisplayController mDisplayController;
|
||||
private WifiDisplayDevice mDisplayDevice;
|
||||
|
||||
private WifiDisplayStatus mCurrentStatus;
|
||||
private boolean mEnabled;
|
||||
private int mFeatureState;
|
||||
private int mScanState;
|
||||
private int mActiveDisplayState;
|
||||
private WifiDisplay mActiveDisplay;
|
||||
private WifiDisplay[] mKnownDisplays = WifiDisplay.EMPTY_ARRAY;
|
||||
private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY;
|
||||
private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY;
|
||||
|
||||
private boolean mPendingStatusChangeBroadcast;
|
||||
|
||||
public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
|
||||
Context context, Handler handler, Listener listener) {
|
||||
Context context, Handler handler, Listener listener,
|
||||
PersistentDataStore persistentDataStore) {
|
||||
super(syncRoot, context, handler, listener, TAG);
|
||||
mPersistentDataStore = persistentDataStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,11 +76,12 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
super.dumpLocked(pw);
|
||||
|
||||
pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked());
|
||||
pw.println("mEnabled=" + mEnabled);
|
||||
pw.println("mFeatureState=" + mFeatureState);
|
||||
pw.println("mScanState=" + mScanState);
|
||||
pw.println("mActiveDisplayState=" + mActiveDisplayState);
|
||||
pw.println("mActiveDisplay=" + mActiveDisplay);
|
||||
pw.println("mKnownDisplays=" + Arrays.toString(mKnownDisplays));
|
||||
pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
|
||||
pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
|
||||
pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
|
||||
|
||||
// Try to dump the controller state.
|
||||
@@ -93,6 +99,8 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
public void registerLocked() {
|
||||
super.registerLocked();
|
||||
|
||||
updateRememberedDisplaysLocked();
|
||||
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -135,18 +143,58 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
public void requestRenameLocked(String address, String alias) {
|
||||
if (alias != null) {
|
||||
alias = alias.trim();
|
||||
if (alias.isEmpty()) {
|
||||
alias = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (mPersistentDataStore.renameWifiDisplay(address, alias)) {
|
||||
mPersistentDataStore.saveIfNeeded();
|
||||
updateRememberedDisplaysLocked();
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
|
||||
public void requestForgetLocked(String address) {
|
||||
if (mPersistentDataStore.forgetWifiDisplay(address)) {
|
||||
mPersistentDataStore.saveIfNeeded();
|
||||
updateRememberedDisplaysLocked();
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
|
||||
if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
|
||||
requestDisconnectLocked();
|
||||
}
|
||||
}
|
||||
|
||||
public WifiDisplayStatus getWifiDisplayStatusLocked() {
|
||||
if (mCurrentStatus == null) {
|
||||
mCurrentStatus = new WifiDisplayStatus(mEnabled, mScanState, mActiveDisplayState,
|
||||
mActiveDisplay, mKnownDisplays);
|
||||
mCurrentStatus = new WifiDisplayStatus(
|
||||
mFeatureState, mScanState, mActiveDisplayState,
|
||||
mActiveDisplay, mAvailableDisplays, mRememberedDisplays);
|
||||
}
|
||||
return mCurrentStatus;
|
||||
}
|
||||
|
||||
private void updateRememberedDisplaysLocked() {
|
||||
mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays();
|
||||
mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay);
|
||||
mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
|
||||
}
|
||||
|
||||
private void handleConnectLocked(WifiDisplay display,
|
||||
Surface surface, int width, int height, int flags) {
|
||||
handleDisconnectLocked();
|
||||
|
||||
if (mPersistentDataStore.rememberWifiDisplay(display)) {
|
||||
mPersistentDataStore.saveIfNeeded();
|
||||
updateRememberedDisplaysLocked();
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
|
||||
int deviceFlags = 0;
|
||||
if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) {
|
||||
deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
|
||||
@@ -154,7 +202,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
|
||||
float refreshRate = 60.0f; // TODO: get this for real
|
||||
|
||||
String name = display.getDeviceName();
|
||||
String name = display.getFriendlyDisplayName();
|
||||
IBinder displayToken = Surface.createDisplay(name);
|
||||
mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
|
||||
refreshRate, deviceFlags, surface);
|
||||
@@ -170,6 +218,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
}
|
||||
|
||||
private void scheduleStatusChangedBroadcastLocked() {
|
||||
mCurrentStatus = null;
|
||||
if (!mPendingStatusChangeBroadcast) {
|
||||
mPendingStatusChangeBroadcast = true;
|
||||
getHandler().post(mStatusChangeBroadcast);
|
||||
@@ -202,11 +251,10 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
private final WifiDisplayController.Listener mWifiDisplayListener =
|
||||
new WifiDisplayController.Listener() {
|
||||
@Override
|
||||
public void onEnablementChanged(boolean enabled) {
|
||||
public void onFeatureStateChanged(int featureState) {
|
||||
synchronized (getSyncRoot()) {
|
||||
if (mEnabled != enabled) {
|
||||
mCurrentStatus = null;
|
||||
mEnabled = enabled;
|
||||
if (mFeatureState != featureState) {
|
||||
mFeatureState = featureState;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
@@ -216,20 +264,21 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
public void onScanStarted() {
|
||||
synchronized (getSyncRoot()) {
|
||||
if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) {
|
||||
mCurrentStatus = null;
|
||||
mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onScanFinished(WifiDisplay[] knownDisplays) {
|
||||
public void onScanFinished(WifiDisplay[] availableDisplays) {
|
||||
synchronized (getSyncRoot()) {
|
||||
availableDisplays = mPersistentDataStore.applyWifiDisplayAliases(
|
||||
availableDisplays);
|
||||
|
||||
if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING
|
||||
|| !Arrays.equals(mKnownDisplays, knownDisplays)) {
|
||||
mCurrentStatus = null;
|
||||
|| !Arrays.equals(mAvailableDisplays, availableDisplays)) {
|
||||
mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
|
||||
mKnownDisplays = knownDisplays;
|
||||
mAvailableDisplays = availableDisplays;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
@@ -238,10 +287,11 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
@Override
|
||||
public void onDisplayConnecting(WifiDisplay display) {
|
||||
synchronized (getSyncRoot()) {
|
||||
display = mPersistentDataStore.applyWifiDisplayAlias(display);
|
||||
|
||||
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING
|
||||
|| mActiveDisplay == null
|
||||
|| !mActiveDisplay.equals(display)) {
|
||||
mCurrentStatus = null;
|
||||
mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING;
|
||||
mActiveDisplay = display;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
@@ -254,7 +304,6 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
synchronized (getSyncRoot()) {
|
||||
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
|
||||
|| mActiveDisplay != null) {
|
||||
mCurrentStatus = null;
|
||||
mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
|
||||
mActiveDisplay = null;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
@@ -266,12 +315,12 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
public void onDisplayConnected(WifiDisplay display, Surface surface,
|
||||
int width, int height, int flags) {
|
||||
synchronized (getSyncRoot()) {
|
||||
display = mPersistentDataStore.applyWifiDisplayAlias(display);
|
||||
handleConnectLocked(display, surface, width, height, flags);
|
||||
|
||||
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
|
||||
|| mActiveDisplay == null
|
||||
|| !mActiveDisplay.equals(display)) {
|
||||
mCurrentStatus = null;
|
||||
mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED;
|
||||
mActiveDisplay = display;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
@@ -287,7 +336,6 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
|
||||
if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
|
||||
|| mActiveDisplay != null) {
|
||||
mCurrentStatus = null;
|
||||
mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
|
||||
mActiveDisplay = null;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
|
||||
@@ -19,13 +19,17 @@ package com.android.server.display;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.display.WifiDisplay;
|
||||
import android.hardware.display.WifiDisplayStatus;
|
||||
import android.media.AudioManager;
|
||||
import android.media.RemoteDisplay;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.p2p.WifiP2pConfig;
|
||||
import android.net.wifi.p2p.WifiP2pDevice;
|
||||
import android.net.wifi.p2p.WifiP2pDeviceList;
|
||||
@@ -37,6 +41,7 @@ import android.net.wifi.p2p.WifiP2pManager.Channel;
|
||||
import android.net.wifi.p2p.WifiP2pManager.GroupInfoListener;
|
||||
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.util.Slog;
|
||||
import android.view.Surface;
|
||||
|
||||
@@ -94,9 +99,12 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
private boolean mWfdEnabling;
|
||||
private NetworkInfo mNetworkInfo;
|
||||
|
||||
private final ArrayList<WifiP2pDevice> mKnownWifiDisplayPeers =
|
||||
private final ArrayList<WifiP2pDevice> mAvailableWifiDisplayPeers =
|
||||
new ArrayList<WifiP2pDevice>();
|
||||
|
||||
// True if Wifi display is enabled by the user.
|
||||
private boolean mWifiDisplayOnSetting;
|
||||
|
||||
// True if there is a call to discoverPeers in progress.
|
||||
private boolean mDiscoverPeersInProgress;
|
||||
|
||||
@@ -146,10 +154,31 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
|
||||
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
|
||||
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
|
||||
context.registerReceiver(mWifiP2pReceiver, intentFilter);
|
||||
context.registerReceiver(mWifiP2pReceiver, intentFilter, null, mHandler);
|
||||
|
||||
ContentObserver settingsObserver = new ContentObserver(mHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
updateSettings();
|
||||
}
|
||||
};
|
||||
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
resolver.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.WIFI_DISPLAY_ON), false, settingsObserver);
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
private void updateSettings() {
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
mWifiDisplayOnSetting = Settings.Global.getInt(resolver,
|
||||
Settings.Global.WIFI_DISPLAY_ON, 0) != 0;
|
||||
|
||||
updateWfdEnableState();
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw) {
|
||||
pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting);
|
||||
pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled);
|
||||
pw.println("mWfdEnabled=" + mWfdEnabled);
|
||||
pw.println("mWfdEnabling=" + mWfdEnabling);
|
||||
@@ -165,8 +194,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
pw.println("mRemoteDisplayConnected=" + mRemoteDisplayConnected);
|
||||
pw.println("mRemoteSubmixOn=" + mRemoteSubmixOn);
|
||||
|
||||
pw.println("mKnownWifiDisplayPeers: size=" + mKnownWifiDisplayPeers.size());
|
||||
for (WifiP2pDevice device : mKnownWifiDisplayPeers) {
|
||||
pw.println("mAvailableWifiDisplayPeers: size=" + mAvailableWifiDisplayPeers.size());
|
||||
for (WifiP2pDevice device : mAvailableWifiDisplayPeers) {
|
||||
pw.println(" " + describeWifiP2pDevice(device));
|
||||
}
|
||||
}
|
||||
@@ -176,7 +205,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
|
||||
public void requestConnect(String address) {
|
||||
for (WifiP2pDevice device : mKnownWifiDisplayPeers) {
|
||||
for (WifiP2pDevice device : mAvailableWifiDisplayPeers) {
|
||||
if (device.deviceAddress.equals(address)) {
|
||||
connect(device);
|
||||
}
|
||||
@@ -187,49 +216,65 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
private void enableWfd() {
|
||||
if (!mWfdEnabled && !mWfdEnabling) {
|
||||
mWfdEnabling = true;
|
||||
private void updateWfdEnableState() {
|
||||
if (mWifiDisplayOnSetting && mWifiP2pEnabled) {
|
||||
// WFD should be enabled.
|
||||
if (!mWfdEnabled && !mWfdEnabling) {
|
||||
mWfdEnabling = true;
|
||||
|
||||
WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo();
|
||||
wfdInfo.setWfdEnabled(true);
|
||||
wfdInfo.setDeviceType(WifiP2pWfdInfo.WFD_SOURCE);
|
||||
wfdInfo.setSessionAvailable(true);
|
||||
wfdInfo.setControlPort(DEFAULT_CONTROL_PORT);
|
||||
wfdInfo.setMaxThroughput(MAX_THROUGHPUT);
|
||||
mWifiP2pManager.setWFDInfo(mWifiP2pChannel, wfdInfo, new ActionListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Successfully set WFD info.");
|
||||
WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo();
|
||||
wfdInfo.setWfdEnabled(true);
|
||||
wfdInfo.setDeviceType(WifiP2pWfdInfo.WFD_SOURCE);
|
||||
wfdInfo.setSessionAvailable(true);
|
||||
wfdInfo.setControlPort(DEFAULT_CONTROL_PORT);
|
||||
wfdInfo.setMaxThroughput(MAX_THROUGHPUT);
|
||||
mWifiP2pManager.setWFDInfo(mWifiP2pChannel, wfdInfo, new ActionListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Successfully set WFD info.");
|
||||
}
|
||||
if (mWfdEnabling) {
|
||||
mWfdEnabling = false;
|
||||
mWfdEnabled = true;
|
||||
reportFeatureState();
|
||||
}
|
||||
}
|
||||
if (mWfdEnabling) {
|
||||
|
||||
@Override
|
||||
public void onFailure(int reason) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Failed to set WFD info with reason " + reason + ".");
|
||||
}
|
||||
mWfdEnabling = false;
|
||||
setWfdEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int reason) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Failed to set WFD info with reason " + reason + ".");
|
||||
}
|
||||
mWfdEnabling = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// WFD should be disabled.
|
||||
mWfdEnabling = false;
|
||||
mWfdEnabled = false;
|
||||
reportFeatureState();
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private void setWfdEnabled(final boolean enabled) {
|
||||
if (mWfdEnabled != enabled) {
|
||||
mWfdEnabled = enabled;
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onEnablementChanged(enabled);
|
||||
}
|
||||
});
|
||||
private void reportFeatureState() {
|
||||
final int featureState = computeFeatureState();
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onFeatureStateChanged(featureState);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private int computeFeatureState() {
|
||||
if (!mWifiP2pEnabled) {
|
||||
return WifiDisplayStatus.FEATURE_STATE_DISABLED;
|
||||
}
|
||||
return mWifiDisplayOnSetting ? WifiDisplayStatus.FEATURE_STATE_ON :
|
||||
WifiDisplayStatus.FEATURE_STATE_OFF;
|
||||
}
|
||||
|
||||
private void discoverPeers() {
|
||||
@@ -296,14 +341,14 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
Slog.d(TAG, "Received list of peers.");
|
||||
}
|
||||
|
||||
mKnownWifiDisplayPeers.clear();
|
||||
mAvailableWifiDisplayPeers.clear();
|
||||
for (WifiP2pDevice device : peers.getDeviceList()) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, " " + describeWifiP2pDevice(device));
|
||||
}
|
||||
|
||||
if (isWifiDisplay(device)) {
|
||||
mKnownWifiDisplayPeers.add(device);
|
||||
mAvailableWifiDisplayPeers.add(device);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,10 +367,10 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
|
||||
private void handleScanFinished() {
|
||||
final int count = mKnownWifiDisplayPeers.size();
|
||||
final int count = mAvailableWifiDisplayPeers.size();
|
||||
final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
displays[i] = createWifiDisplay(mKnownWifiDisplayPeers.get(i));
|
||||
displays[i] = createWifiDisplay(mAvailableWifiDisplayPeers.get(i));
|
||||
}
|
||||
|
||||
mHandler.post(new Runnable() {
|
||||
@@ -368,18 +413,11 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
|
||||
private void retryConnection() {
|
||||
if (mDesiredDevice != null && mConnectedDevice != mDesiredDevice
|
||||
&& mConnectionRetriesLeft > 0) {
|
||||
mConnectionRetriesLeft -= 1;
|
||||
Slog.i(TAG, "Retrying Wifi display connection. Retries left: "
|
||||
+ mConnectionRetriesLeft);
|
||||
|
||||
// Cheap hack. Make a new instance of the device object so that we
|
||||
// can distinguish it from the previous connection attempt.
|
||||
// This will cause us to tear everything down before we try again.
|
||||
mDesiredDevice = new WifiP2pDevice(mDesiredDevice);
|
||||
updateConnection();
|
||||
}
|
||||
// Cheap hack. Make a new instance of the device object so that we
|
||||
// can distinguish it from the previous connection attempt.
|
||||
// This will cause us to tear everything down before we try again.
|
||||
mDesiredDevice = new WifiP2pDevice(mDesiredDevice);
|
||||
updateConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -513,6 +551,13 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
if (mConnectingDevice == newDevice) {
|
||||
Slog.i(TAG, "Failed to initiate connection to Wifi display: "
|
||||
+ newDevice.deviceName + ", reason=" + reason);
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onDisplayDisconnected();
|
||||
}
|
||||
});
|
||||
|
||||
mConnectingDevice = null;
|
||||
handleConnectionFailure(false);
|
||||
}
|
||||
@@ -595,26 +640,13 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
|
||||
private void handleStateChanged(boolean enabled) {
|
||||
if (mWifiP2pEnabled != enabled) {
|
||||
mWifiP2pEnabled = enabled;
|
||||
if (enabled) {
|
||||
if (!mWfdEnabled) {
|
||||
enableWfd();
|
||||
}
|
||||
} else {
|
||||
setWfdEnabled(false);
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
mWifiP2pEnabled = enabled;
|
||||
updateWfdEnableState();
|
||||
}
|
||||
|
||||
private void handlePeersChanged() {
|
||||
if (mWifiP2pEnabled) {
|
||||
if (mWfdEnabled) {
|
||||
requestPeers();
|
||||
} else {
|
||||
enableWfd();
|
||||
}
|
||||
if (mWfdEnabled) {
|
||||
requestPeers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,7 +664,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
if (mConnectingDevice != null && !info.contains(mConnectingDevice)) {
|
||||
Slog.i(TAG, "Aborting connection to Wifi display because "
|
||||
+ "the current P2P group does not contain the device "
|
||||
+ "we expected to find: " + mConnectingDevice.deviceName);
|
||||
+ "we expected to find: " + mConnectingDevice.deviceName
|
||||
+ ", group info was: " + describeWifiP2pGroup(info));
|
||||
handleConnectionFailure(false);
|
||||
return;
|
||||
}
|
||||
@@ -704,10 +737,16 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
|
||||
if (mDesiredDevice != null) {
|
||||
if (mConnectionRetriesLeft > 0) {
|
||||
final WifiP2pDevice oldDevice = mDesiredDevice;
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
retryConnection();
|
||||
if (mDesiredDevice == oldDevice && mConnectionRetriesLeft > 0) {
|
||||
mConnectionRetriesLeft -= 1;
|
||||
Slog.i(TAG, "Retrying Wifi display connection. Retries left: "
|
||||
+ mConnectionRetriesLeft);
|
||||
retryConnection();
|
||||
}
|
||||
}
|
||||
}, timeoutOccurred ? 0 : CONNECT_RETRY_DELAY_MILLIS);
|
||||
} else {
|
||||
@@ -768,7 +807,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
|
||||
private static WifiDisplay createWifiDisplay(WifiP2pDevice device) {
|
||||
return new WifiDisplay(device.deviceAddress, device.deviceName);
|
||||
return new WifiDisplay(device.deviceAddress, device.deviceName, null);
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mWifiP2pReceiver = new BroadcastReceiver() {
|
||||
@@ -776,6 +815,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)) {
|
||||
// This broadcast is sticky so we'll always get the initial Wifi P2P state
|
||||
// on startup.
|
||||
boolean enabled = (intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE,
|
||||
WifiP2pManager.WIFI_P2P_STATE_DISABLED)) ==
|
||||
WifiP2pManager.WIFI_P2P_STATE_ENABLED;
|
||||
@@ -808,10 +849,10 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
* Called on the handler thread when displays are connected or disconnected.
|
||||
*/
|
||||
public interface Listener {
|
||||
void onEnablementChanged(boolean enabled);
|
||||
void onFeatureStateChanged(int featureState);
|
||||
|
||||
void onScanStarted();
|
||||
void onScanFinished(WifiDisplay[] knownDisplays);
|
||||
void onScanFinished(WifiDisplay[] availableDisplays);
|
||||
|
||||
void onDisplayConnecting(WifiDisplay display);
|
||||
void onDisplayConnectionFailed();
|
||||
|
||||
Reference in New Issue
Block a user