Merge "Add new wifi display discovery API." into jb-mr1-dev
This commit is contained in:
@@ -40,6 +40,28 @@ public final class DisplayManager {
|
||||
private final Object mLock = new Object();
|
||||
private final SparseArray<Display> mDisplays = new SparseArray<Display>();
|
||||
|
||||
/**
|
||||
* Broadcast receiver that indicates when the Wifi display status changes.
|
||||
* <p>
|
||||
* The status is provided as a {@link WifiDisplayStatus} object in the
|
||||
* {@link #EXTRA_WIFI_DISPLAY_STATUS} extra.
|
||||
* </p><p>
|
||||
* This broadcast is only sent to registered receivers with the
|
||||
* {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} permission and can
|
||||
* only be sent by the system.
|
||||
* </p>
|
||||
* @hide
|
||||
*/
|
||||
public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED =
|
||||
"android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED";
|
||||
|
||||
/**
|
||||
* Contains a {@link WifiDisplayStatus} object.
|
||||
* @hide
|
||||
*/
|
||||
public static final String EXTRA_WIFI_DISPLAY_STATUS =
|
||||
"android.hardware.display.extra.WIFI_DISPLAY_STATUS";
|
||||
|
||||
/** @hide */
|
||||
public DisplayManager(Context context) {
|
||||
mContext = context;
|
||||
@@ -126,6 +148,47 @@ public final class DisplayManager {
|
||||
mGlobal.unregisterDisplayListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates a fresh scan of availble Wifi displays.
|
||||
* The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
|
||||
* @hide
|
||||
*/
|
||||
public void scanWifiDisplays() {
|
||||
mGlobal.scanWifiDisplays();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to a Wifi display.
|
||||
* The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
|
||||
*
|
||||
* @param deviceAddress The MAC address of the device to which we should connect.
|
||||
* @hide
|
||||
*/
|
||||
public void connectWifiDisplay(String deviceAddress) {
|
||||
mGlobal.connectWifiDisplay(deviceAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from the current Wifi display.
|
||||
* The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
|
||||
* @hide
|
||||
*/
|
||||
public void disconnectWifiDisplay() {
|
||||
mGlobal.disconnectWifiDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current Wifi display status.
|
||||
* Watch for changes in the status by registering a broadcast receiver for
|
||||
* {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED}.
|
||||
*
|
||||
* @return The current Wifi display status.
|
||||
* @hide
|
||||
*/
|
||||
public WifiDisplayStatus getWifiDisplayStatus() {
|
||||
return mGlobal.getWifiDisplayStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for changes in available display devices.
|
||||
*/
|
||||
|
||||
@@ -253,6 +253,43 @@ public final class DisplayManagerGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
public void scanWifiDisplays() {
|
||||
try {
|
||||
mDm.scanWifiDisplays();
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Failed to scan for Wifi displays.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void connectWifiDisplay(String deviceAddress) {
|
||||
if (deviceAddress == null) {
|
||||
throw new IllegalArgumentException("deviceAddress must not be null");
|
||||
}
|
||||
|
||||
try {
|
||||
mDm.connectWifiDisplay(deviceAddress);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Failed to connect to Wifi display " + deviceAddress + ".", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnectWifiDisplay() {
|
||||
try {
|
||||
mDm.disconnectWifiDisplay();
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Failed to disconnect from Wifi display.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public WifiDisplayStatus getWifiDisplayStatus() {
|
||||
try {
|
||||
return mDm.getWifiDisplayStatus();
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Failed to get Wifi display status.", ex);
|
||||
return new WifiDisplayStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
|
||||
@Override
|
||||
public void onDisplayEvent(int displayId, int event) {
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package android.hardware.display;
|
||||
|
||||
import android.hardware.display.IDisplayManagerCallback;
|
||||
import android.hardware.display.WifiDisplay;
|
||||
import android.hardware.display.WifiDisplayStatus;
|
||||
import android.view.DisplayInfo;
|
||||
|
||||
/** @hide */
|
||||
@@ -25,4 +27,16 @@ interface IDisplayManager {
|
||||
int[] getDisplayIds();
|
||||
|
||||
void registerCallback(in IDisplayManagerCallback callback);
|
||||
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
void scanWifiDisplays();
|
||||
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
void connectWifiDisplay(String address);
|
||||
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
void disconnectWifiDisplay();
|
||||
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
WifiDisplayStatus getWifiDisplayStatus();
|
||||
}
|
||||
|
||||
19
core/java/android/hardware/display/WifiDisplay.aidl
Normal file
19
core/java/android/hardware/display/WifiDisplay.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 android.hardware.display;
|
||||
|
||||
parcelable WifiDisplay;
|
||||
107
core/java/android/hardware/display/WifiDisplay.java
Normal file
107
core/java/android/hardware/display/WifiDisplay.java
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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 android.hardware.display;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Describes the properties of a Wifi display.
|
||||
* <p>
|
||||
* This object is immutable.
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class WifiDisplay implements Parcelable {
|
||||
private final String mDeviceAddress;
|
||||
private final String mDeviceName;
|
||||
|
||||
public static final WifiDisplay[] EMPTY_ARRAY = new WifiDisplay[0];
|
||||
|
||||
public static final Creator<WifiDisplay> CREATOR = new Creator<WifiDisplay>() {
|
||||
public WifiDisplay createFromParcel(Parcel in) {
|
||||
String deviceAddress = in.readString();
|
||||
String deviceName = in.readString();
|
||||
return new WifiDisplay(deviceAddress, deviceName);
|
||||
}
|
||||
|
||||
public WifiDisplay[] newArray(int size) {
|
||||
return size == 0 ? EMPTY_ARRAY : new WifiDisplay[size];
|
||||
}
|
||||
};
|
||||
|
||||
public WifiDisplay(String deviceAddress, String deviceName) {
|
||||
if (deviceAddress == null) {
|
||||
throw new IllegalArgumentException("deviceAddress must not be null");
|
||||
}
|
||||
if (deviceName == null) {
|
||||
throw new IllegalArgumentException("deviceName must not be null");
|
||||
}
|
||||
|
||||
mDeviceAddress = deviceAddress;
|
||||
mDeviceName = deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MAC address of the Wifi display device.
|
||||
*/
|
||||
public String getDeviceAddress() {
|
||||
return mDeviceAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the Wifi display device.
|
||||
*/
|
||||
public String getDeviceName() {
|
||||
return mDeviceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof WifiDisplay && equals((WifiDisplay)o);
|
||||
}
|
||||
|
||||
public boolean equals(WifiDisplay other) {
|
||||
return other != null
|
||||
&& mDeviceAddress.equals(other.mDeviceAddress)
|
||||
&& mDeviceName.equals(other.mDeviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// The address on its own should be sufficiently unique for hashing purposes.
|
||||
return mDeviceAddress.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mDeviceAddress);
|
||||
dest.writeString(mDeviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For debugging purposes only.
|
||||
@Override
|
||||
public String toString() {
|
||||
return mDeviceName + " (" + mDeviceAddress + ")";
|
||||
}
|
||||
}
|
||||
19
core/java/android/hardware/display/WifiDisplayStatus.aidl
Normal file
19
core/java/android/hardware/display/WifiDisplayStatus.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 android.hardware.display;
|
||||
|
||||
parcelable WifiDisplayStatus;
|
||||
159
core/java/android/hardware/display/WifiDisplayStatus.java
Normal file
159
core/java/android/hardware/display/WifiDisplayStatus.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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 android.hardware.display;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Describes the current global state of Wifi display connectivity, including the
|
||||
* currently connected display and all known displays.
|
||||
* <p>
|
||||
* This object is immutable.
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class WifiDisplayStatus implements Parcelable {
|
||||
private final boolean mEnabled;
|
||||
private final WifiDisplay mConnectedDisplay;
|
||||
private final WifiDisplay[] mKnownDisplays;
|
||||
private final boolean mScanInProgress;
|
||||
private final boolean mConnectionInProgress;
|
||||
|
||||
public static final Creator<WifiDisplayStatus> CREATOR = new Creator<WifiDisplayStatus>() {
|
||||
public WifiDisplayStatus createFromParcel(Parcel in) {
|
||||
boolean enabled = (in.readInt() != 0);
|
||||
|
||||
WifiDisplay connectedDisplay = null;
|
||||
if (in.readInt() != 0) {
|
||||
connectedDisplay = 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);
|
||||
}
|
||||
|
||||
boolean scanInProgress = (in.readInt() != 0);
|
||||
boolean connectionInProgress = (in.readInt() != 0);
|
||||
|
||||
return new WifiDisplayStatus(enabled, connectedDisplay, knownDisplays,
|
||||
scanInProgress, connectionInProgress);
|
||||
}
|
||||
|
||||
public WifiDisplayStatus[] newArray(int size) {
|
||||
return new WifiDisplayStatus[size];
|
||||
}
|
||||
};
|
||||
|
||||
public WifiDisplayStatus() {
|
||||
this(false, null, WifiDisplay.EMPTY_ARRAY, false, false);
|
||||
}
|
||||
|
||||
public WifiDisplayStatus(boolean enabled,
|
||||
WifiDisplay connectedDisplay, WifiDisplay[] knownDisplays,
|
||||
boolean scanInProgress, boolean connectionInProgress) {
|
||||
if (knownDisplays == null) {
|
||||
throw new IllegalArgumentException("knownDisplays must not be null");
|
||||
}
|
||||
|
||||
mEnabled = enabled;
|
||||
mConnectedDisplay = connectedDisplay;
|
||||
mKnownDisplays = knownDisplays;
|
||||
mScanInProgress = scanInProgress;
|
||||
mConnectionInProgress = connectionInProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Wifi display feature is enabled and available for use.
|
||||
* <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.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently connected Wifi display or null if none.
|
||||
*/
|
||||
public WifiDisplay getConnectedDisplay() {
|
||||
return mConnectedDisplay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all known Wifi displays, never null.
|
||||
*/
|
||||
public WifiDisplay[] getKnownDisplays() {
|
||||
return mKnownDisplays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is currently a Wifi display scan in progress.
|
||||
*/
|
||||
public boolean isScanInProgress() {
|
||||
return mScanInProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is currently a Wifi display connection in progress.
|
||||
*/
|
||||
public boolean isConnectionInProgress() {
|
||||
return mConnectionInProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mEnabled ? 1 : 0);
|
||||
|
||||
if (mConnectedDisplay != null) {
|
||||
dest.writeInt(1);
|
||||
mConnectedDisplay.writeToParcel(dest, flags);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
|
||||
dest.writeInt(mKnownDisplays.length);
|
||||
for (WifiDisplay display : mKnownDisplays) {
|
||||
display.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
dest.writeInt(mScanInProgress ? 1 : 0);
|
||||
dest.writeInt(mConnectionInProgress ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For debugging purposes only.
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WifiDisplayStatus{enabled=" + mEnabled
|
||||
+ ", connectedDisplay=" + mConnectedDisplay
|
||||
+ ", knownDisplays=" + Arrays.toString(mKnownDisplays)
|
||||
+ ", scanInProgress=" + mScanInProgress
|
||||
+ ", connectionInProgress=" + mConnectionInProgress
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,8 @@
|
||||
<protected-broadcast
|
||||
android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
|
||||
|
||||
<protected-broadcast android:name="android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED" />
|
||||
|
||||
<protected-broadcast android:name="android.hardware.usb.action.USB_STATE" />
|
||||
<protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
|
||||
<protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
|
||||
|
||||
@@ -486,7 +486,6 @@
|
||||
<java-symbol type="string" name="display_manager_hdmi_display_name" />
|
||||
<java-symbol type="string" name="display_manager_overlay_display_name" />
|
||||
<java-symbol type="string" name="display_manager_overlay_display_title" />
|
||||
<java-symbol type="string" name="display_manager_wifi_display_name" />
|
||||
<java-symbol type="string" name="double_tap_toast" />
|
||||
<java-symbol type="string" name="elapsed_time_short_format_h_mm_ss" />
|
||||
<java-symbol type="string" name="elapsed_time_short_format_mm_ss" />
|
||||
|
||||
@@ -3688,9 +3688,6 @@
|
||||
<!-- Title text to show within the overlay. [CHAR LIMIT=50] -->
|
||||
<string name="display_manager_overlay_display_title"><xliff:g id="name">%1$s</xliff:g>: <xliff:g id="width">%2$d</xliff:g>x<xliff:g id="height">%3$d</xliff:g>, <xliff:g id="dpi">%4$d</xliff:g> dpi</string>
|
||||
|
||||
<!-- Name of a wifi display. [CHAR LIMIT=50] -->
|
||||
<string name="display_manager_wifi_display_name">Wifi display: <xliff:g id="device">%1$s</xliff:g></string>
|
||||
|
||||
<!-- Keyguard strings -->
|
||||
<!-- Label shown on emergency call button in keyguard -->
|
||||
<string name="kg_emergency_call_label">Emergency call</string>
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.pm.PackageManager;
|
||||
import android.hardware.display.DisplayManagerGlobal;
|
||||
import android.hardware.display.IDisplayManager;
|
||||
import android.hardware.display.IDisplayManagerCallback;
|
||||
import android.hardware.display.WifiDisplayStatus;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -137,6 +138,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
|
||||
// to the surface flinger state.
|
||||
private boolean mPendingTraversal;
|
||||
|
||||
// The Wifi display adapter, or null if not registered.
|
||||
private WifiDisplayAdapter mWifiDisplayAdapter;
|
||||
|
||||
// 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>();
|
||||
@@ -315,6 +319,77 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void scanWifiDisplays() {
|
||||
if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
|
||||
}
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mSyncRoot) {
|
||||
mWifiDisplayAdapter.requestScanLocked();
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void connectWifiDisplay(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) {
|
||||
mWifiDisplayAdapter.requestConnectLocked(address);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void disconnectWifiDisplay() {
|
||||
if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
|
||||
}
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mSyncRoot) {
|
||||
mWifiDisplayAdapter.requestDisconnectLocked();
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public WifiDisplayStatus getWifiDisplayStatus() {
|
||||
if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
|
||||
}
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mSyncRoot) {
|
||||
return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerDefaultDisplayAdapter() {
|
||||
// Register default display adapter.
|
||||
synchronized (mSyncRoot) {
|
||||
@@ -333,8 +408,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
|
||||
if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
|
||||
registerDisplayAdapterLocked(new OverlayDisplayAdapter(
|
||||
mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
|
||||
registerDisplayAdapterLocked(new WifiDisplayAdapter(
|
||||
mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
|
||||
mWifiDisplayAdapter = new WifiDisplayAdapter(
|
||||
mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
|
||||
registerDisplayAdapterLocked(mWifiDisplayAdapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.WifiDisplay;
|
||||
import android.hardware.display.WifiDisplayStatus;
|
||||
import android.media.RemoteDisplay;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -27,6 +31,7 @@ import android.util.Slog;
|
||||
import android.view.Surface;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Connects to Wifi displays that implement the Miracast protocol.
|
||||
@@ -48,6 +53,15 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
private WifiDisplayHandle mDisplayHandle;
|
||||
private WifiDisplayController mDisplayController;
|
||||
|
||||
private WifiDisplayStatus mCurrentStatus;
|
||||
private boolean mEnabled;
|
||||
private WifiDisplay mConnectedDisplay;
|
||||
private WifiDisplay[] mKnownDisplays = WifiDisplay.EMPTY_ARRAY;
|
||||
private boolean mScanInProgress;
|
||||
private boolean mConnectionInProgress;
|
||||
|
||||
private boolean mPendingStatusChangeBroadcast;
|
||||
|
||||
public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
|
||||
Context context, Handler handler, Listener listener) {
|
||||
super(syncRoot, context, handler, listener, TAG);
|
||||
@@ -64,6 +78,14 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
mDisplayHandle.dumpLocked(pw);
|
||||
}
|
||||
|
||||
pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked());
|
||||
pw.println("mEnabled=" + mEnabled);
|
||||
pw.println("mConnectedDisplay=" + mConnectedDisplay);
|
||||
pw.println("mKnownDisplays=" + Arrays.toString(mKnownDisplays));
|
||||
pw.println("mScanInProgress=" + mScanInProgress);
|
||||
pw.println("mConnectionInProgress=" + mConnectionInProgress);
|
||||
pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
|
||||
|
||||
// Try to dump the controller state.
|
||||
if (mDisplayController == null) {
|
||||
pw.println("mDisplayController=null");
|
||||
@@ -88,28 +110,160 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
private void connectLocked(String deviceName, String iface) {
|
||||
disconnectLocked();
|
||||
|
||||
String name = getContext().getResources().getString(
|
||||
com.android.internal.R.string.display_manager_wifi_display_name,
|
||||
deviceName);
|
||||
mDisplayHandle = new WifiDisplayHandle(name, iface);
|
||||
public void requestScanLocked() {
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mDisplayController != null) {
|
||||
mDisplayController.requestScan();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void disconnectLocked() {
|
||||
public void requestConnectLocked(final String address) {
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mDisplayController != null) {
|
||||
mDisplayController.requestConnect(address);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void requestDisconnectLocked() {
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mDisplayController != null) {
|
||||
mDisplayController.requestDisconnect();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public WifiDisplayStatus getWifiDisplayStatusLocked() {
|
||||
if (mCurrentStatus == null) {
|
||||
mCurrentStatus = new WifiDisplayStatus(mEnabled,
|
||||
mConnectedDisplay, mKnownDisplays,
|
||||
mScanInProgress, mConnectionInProgress);
|
||||
}
|
||||
return mCurrentStatus;
|
||||
}
|
||||
|
||||
private void handleConnectLocked(WifiDisplay display, String iface) {
|
||||
handleDisconnectLocked();
|
||||
|
||||
mDisplayHandle = new WifiDisplayHandle(display.getDeviceName(), iface);
|
||||
}
|
||||
|
||||
private void handleDisconnectLocked() {
|
||||
if (mDisplayHandle != null) {
|
||||
mDisplayHandle.disposeLocked();
|
||||
mDisplayHandle = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleStatusChangedBroadcastLocked() {
|
||||
if (!mPendingStatusChangeBroadcast) {
|
||||
mPendingStatusChangeBroadcast = true;
|
||||
getHandler().post(mStatusChangeBroadcast);
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable mStatusChangeBroadcast = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Intent intent;
|
||||
synchronized (getSyncRoot()) {
|
||||
if (!mPendingStatusChangeBroadcast) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPendingStatusChangeBroadcast = false;
|
||||
intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
|
||||
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
|
||||
intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
|
||||
getWifiDisplayStatusLocked());
|
||||
}
|
||||
|
||||
// Send protected broadcast about wifi display status to receivers that
|
||||
// have the required permission.
|
||||
getContext().sendBroadcast(intent,
|
||||
android.Manifest.permission.CONFIGURE_WIFI_DISPLAY);
|
||||
}
|
||||
};
|
||||
|
||||
private final WifiDisplayController.Listener mWifiDisplayListener =
|
||||
new WifiDisplayController.Listener() {
|
||||
@Override
|
||||
public void onDisplayConnected(String deviceName, String iface) {
|
||||
public void onEnablementChanged(boolean enabled) {
|
||||
synchronized (getSyncRoot()) {
|
||||
connectLocked(deviceName, iface);
|
||||
if (mEnabled != enabled) {
|
||||
mCurrentStatus = null;
|
||||
mEnabled = enabled;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScanStarted() {
|
||||
synchronized (getSyncRoot()) {
|
||||
if (!mScanInProgress) {
|
||||
mCurrentStatus = null;
|
||||
mScanInProgress = true;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onScanFinished(WifiDisplay[] knownDisplays) {
|
||||
synchronized (getSyncRoot()) {
|
||||
if (!Arrays.equals(mKnownDisplays, knownDisplays) || mScanInProgress) {
|
||||
mCurrentStatus = null;
|
||||
mKnownDisplays = knownDisplays;
|
||||
mScanInProgress = false;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayConnecting(WifiDisplay display) {
|
||||
synchronized (getSyncRoot()) {
|
||||
if (!mConnectionInProgress) {
|
||||
mCurrentStatus = null;
|
||||
mConnectionInProgress = true;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayConnectionFailed() {
|
||||
synchronized (getSyncRoot()) {
|
||||
if (mConnectionInProgress) {
|
||||
mCurrentStatus = null;
|
||||
mConnectionInProgress = false;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayConnected(WifiDisplay display, String iface) {
|
||||
synchronized (getSyncRoot()) {
|
||||
handleConnectLocked(display, iface);
|
||||
|
||||
if (mConnectedDisplay == null || !mConnectedDisplay.equals(display)
|
||||
|| mConnectionInProgress) {
|
||||
mCurrentStatus = null;
|
||||
mConnectedDisplay = display;
|
||||
mConnectionInProgress = false;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +271,14 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
public void onDisplayDisconnected() {
|
||||
// Stop listening.
|
||||
synchronized (getSyncRoot()) {
|
||||
disconnectLocked();
|
||||
handleDisconnectLocked();
|
||||
|
||||
if (mConnectedDisplay != null || mConnectionInProgress) {
|
||||
mCurrentStatus = null;
|
||||
mConnectedDisplay = null;
|
||||
mConnectionInProgress = false;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.display.WifiDisplay;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.p2p.WifiP2pConfig;
|
||||
import android.net.wifi.p2p.WifiP2pDevice;
|
||||
@@ -143,6 +144,22 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestScan() {
|
||||
discoverPeers();
|
||||
}
|
||||
|
||||
public void requestConnect(String address) {
|
||||
for (WifiP2pDevice device : mKnownWifiDisplayPeers) {
|
||||
if (device.deviceAddress.equals(address)) {
|
||||
connect(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void requestDisconnect() {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
private void enableWfd() {
|
||||
if (!mWfdEnabled && !mWfdEnabling) {
|
||||
mWfdEnabling = true;
|
||||
@@ -160,8 +177,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
Slog.d(TAG, "Successfully set WFD info.");
|
||||
}
|
||||
if (mWfdEnabling) {
|
||||
mWfdEnabled = true;
|
||||
mWfdEnabling = false;
|
||||
setWfdEnabled(true);
|
||||
discoverPeers();
|
||||
}
|
||||
}
|
||||
@@ -177,10 +194,23 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
}
|
||||
|
||||
private void setWfdEnabled(final boolean enabled) {
|
||||
if (mWfdEnabled != enabled) {
|
||||
mWfdEnabled = enabled;
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onEnablementChanged(enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void discoverPeers() {
|
||||
if (!mDiscoverPeersInProgress) {
|
||||
mDiscoverPeersInProgress = true;
|
||||
mDiscoverPeersRetriesLeft = DISCOVER_PEERS_MAX_RETRIES;
|
||||
handleScanStarted();
|
||||
tryDiscoverPeers();
|
||||
}
|
||||
}
|
||||
@@ -217,12 +247,14 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
tryDiscoverPeers();
|
||||
} else {
|
||||
handleScanFinished();
|
||||
mDiscoverPeersInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, DISCOVER_PEERS_RETRY_DELAY_MILLIS);
|
||||
} else {
|
||||
handleScanFinished();
|
||||
mDiscoverPeersInProgress = false;
|
||||
}
|
||||
}
|
||||
@@ -249,16 +281,31 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: shouldn't auto-connect like this, let UI do it explicitly
|
||||
if (!mKnownWifiDisplayPeers.isEmpty()) {
|
||||
final WifiP2pDevice device = mKnownWifiDisplayPeers.get(0);
|
||||
handleScanFinished();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (device.status == WifiP2pDevice.AVAILABLE) {
|
||||
connect(device);
|
||||
}
|
||||
}
|
||||
private void handleScanStarted() {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onScanStarted();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: publish this information to applications
|
||||
private void handleScanFinished() {
|
||||
final int count = mKnownWifiDisplayPeers.size();
|
||||
final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
displays[i] = createWifiDisplay(mKnownWifiDisplayPeers.get(i));
|
||||
}
|
||||
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onScanFinished(displays);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -403,6 +450,14 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
WifiP2pConfig config = new WifiP2pConfig();
|
||||
config.deviceAddress = mConnectingDevice.deviceAddress;
|
||||
|
||||
final WifiDisplay display = createWifiDisplay(mConnectingDevice);
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onDisplayConnecting(display);
|
||||
}
|
||||
});
|
||||
|
||||
final WifiP2pDevice newDevice = mDesiredDevice;
|
||||
mWifiP2pManager.connect(mWifiP2pChannel, config, new ActionListener() {
|
||||
@Override
|
||||
@@ -440,14 +495,14 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
|
||||
WifiP2pWfdInfo wfdInfo = mConnectedDevice.wfdInfo;
|
||||
int port = (wfdInfo != null ? wfdInfo.getControlPort() : DEFAULT_CONTROL_PORT);
|
||||
final String name = mConnectedDevice.deviceName;
|
||||
final WifiDisplay display = createWifiDisplay(mConnectedDevice);
|
||||
final String iface = addr.getHostAddress() + ":" + port;
|
||||
|
||||
mPublishedDevice = mConnectedDevice;
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onDisplayConnected(name, iface);
|
||||
mListener.onDisplayConnected(display, iface);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -463,7 +518,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
enableWfd();
|
||||
}
|
||||
} else {
|
||||
mWfdEnabled = false;
|
||||
setWfdEnabled(false);
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
@@ -537,6 +592,13 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
if (mDesiredDevice != null) {
|
||||
Slog.i(TAG, "Wifi display connection failed!");
|
||||
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onDisplayConnectionFailed();
|
||||
}
|
||||
});
|
||||
|
||||
if (mConnectionRetriesLeft > 0) {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
@@ -575,12 +637,10 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
|
||||
private static boolean isWifiDisplay(WifiP2pDevice device) {
|
||||
// FIXME: the wfdInfo API doesn't work yet
|
||||
return false;
|
||||
//return device.deviceName.equals("DWD-300-22ACC2");
|
||||
//return device.deviceName.startsWith("DWD-")
|
||||
// || device.deviceName.startsWith("DIRECT-")
|
||||
// || device.deviceName.startsWith("CAVM-");
|
||||
//return device.wfdInfo != null && device.wfdInfo.isWfdEnabled();
|
||||
return device.deviceName.startsWith("DWD-")
|
||||
|| device.deviceName.startsWith("DIRECT-")
|
||||
|| device.deviceName.startsWith("CAVM-");
|
||||
//device.wfdInfo != null && device.wfdInfo.isWfdEnabled();
|
||||
}
|
||||
|
||||
private static String describeWifiP2pDevice(WifiP2pDevice device) {
|
||||
@@ -591,6 +651,10 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
return group != null ? group.toString().replace('\n', ',') : "null";
|
||||
}
|
||||
|
||||
private static WifiDisplay createWifiDisplay(WifiP2pDevice device) {
|
||||
return new WifiDisplay(device.deviceAddress, device.deviceName);
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mWifiP2pReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@@ -628,7 +692,14 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
* Called on the handler thread when displays are connected or disconnected.
|
||||
*/
|
||||
public interface Listener {
|
||||
void onDisplayConnected(String deviceName, String iface);
|
||||
void onEnablementChanged(boolean enabled);
|
||||
|
||||
void onScanStarted();
|
||||
void onScanFinished(WifiDisplay[] knownDisplays);
|
||||
|
||||
void onDisplayConnecting(WifiDisplay display);
|
||||
void onDisplayConnectionFailed();
|
||||
void onDisplayConnected(WifiDisplay display, String iface);
|
||||
void onDisplayDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user