am 5de1faca: Merge "wifi-display: add certification options" into klp-dev
* commit '5de1faca166e2241cf9ad1981007caa947a1fc1b': wifi-display: add certification options
This commit is contained in:
@@ -325,6 +325,16 @@ public final class DisplayManager {
|
||||
mGlobal.connectWifiDisplay(deviceAddress);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void pauseWifiDisplay() {
|
||||
mGlobal.pauseWifiDisplay();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void resumeWifiDisplay() {
|
||||
mGlobal.resumeWifiDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from the current Wifi display.
|
||||
* The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
|
||||
|
||||
@@ -287,6 +287,22 @@ public final class DisplayManagerGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
public void pauseWifiDisplay() {
|
||||
try {
|
||||
mDm.pauseWifiDisplay();
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Failed to pause Wifi display.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void resumeWifiDisplay() {
|
||||
try {
|
||||
mDm.resumeWifiDisplay();
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Failed to resume Wifi display.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnectWifiDisplay() {
|
||||
try {
|
||||
mDm.disconnectWifiDisplay();
|
||||
|
||||
@@ -55,4 +55,10 @@ interface IDisplayManager {
|
||||
|
||||
// No permissions required but must be same Uid as the creator.
|
||||
void releaseVirtualDisplay(in IBinder token);
|
||||
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
void pauseWifiDisplay();
|
||||
|
||||
// Requires CONFIGURE_WIFI_DISPLAY permission.
|
||||
void resumeWifiDisplay();
|
||||
}
|
||||
|
||||
116
core/java/android/hardware/display/WifiDisplaySessionInfo.java
Normal file
116
core/java/android/hardware/display/WifiDisplaySessionInfo.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* This class contains information regarding a wifi display session
|
||||
* (such as session id, source ip address, etc.). This is needed for
|
||||
* Wifi Display Certification process.
|
||||
* <p>
|
||||
* This object is immutable.
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class WifiDisplaySessionInfo implements Parcelable {
|
||||
private final boolean mClient;
|
||||
private final int mSessionId;
|
||||
private final String mGroupId;
|
||||
private final String mPassphrase;
|
||||
private final String mIP;
|
||||
|
||||
public static final Creator<WifiDisplaySessionInfo> CREATOR =
|
||||
new Creator<WifiDisplaySessionInfo>() {
|
||||
@Override
|
||||
public WifiDisplaySessionInfo createFromParcel(Parcel in) {
|
||||
boolean client = (in.readInt() != 0);
|
||||
int session = in.readInt();
|
||||
String group = in.readString();
|
||||
String pp = in.readString();
|
||||
String ip = in.readString();
|
||||
|
||||
return new WifiDisplaySessionInfo(client, session, group, pp, ip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WifiDisplaySessionInfo[] newArray(int size) {
|
||||
return new WifiDisplaySessionInfo[size];
|
||||
}
|
||||
};
|
||||
|
||||
public WifiDisplaySessionInfo() {
|
||||
this(true, 0, "", "", "");
|
||||
}
|
||||
|
||||
public WifiDisplaySessionInfo(
|
||||
boolean client, int session, String group, String pp, String ip) {
|
||||
mClient = client;
|
||||
mSessionId = session;
|
||||
mGroupId = group;
|
||||
mPassphrase = pp;
|
||||
mIP = ip;
|
||||
}
|
||||
|
||||
public boolean isClient() {
|
||||
return mClient;
|
||||
}
|
||||
|
||||
public int getSessionId() {
|
||||
return mSessionId;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return mGroupId;
|
||||
}
|
||||
|
||||
public String getPassphrase() {
|
||||
return mPassphrase;
|
||||
}
|
||||
|
||||
public String getIP() {
|
||||
return mIP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mClient ? 1 : 0);
|
||||
dest.writeInt(mSessionId);
|
||||
dest.writeString(mGroupId);
|
||||
dest.writeString(mPassphrase);
|
||||
dest.writeString(mIP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For debugging purposes only.
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WifiDisplaySessionInfo:"
|
||||
+"\n Client/Owner: " + (mClient ? "Client":"Owner")
|
||||
+"\n GroupId: " + mGroupId
|
||||
+"\n Passphrase: " + mPassphrase
|
||||
+"\n SessionId: " + mSessionId
|
||||
+"\n IP Address: " + mIP
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,9 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
private final WifiDisplay mActiveDisplay;
|
||||
private final WifiDisplay[] mDisplays;
|
||||
|
||||
/** Session info needed for Miracast Certification */
|
||||
private final WifiDisplaySessionInfo mSessionInfo;
|
||||
|
||||
/** 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. */
|
||||
@@ -76,8 +79,11 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
displays[i] = WifiDisplay.CREATOR.createFromParcel(in);
|
||||
}
|
||||
|
||||
WifiDisplaySessionInfo sessionInfo =
|
||||
WifiDisplaySessionInfo.CREATOR.createFromParcel(in);
|
||||
|
||||
return new WifiDisplayStatus(featureState, scanState, activeDisplayState,
|
||||
activeDisplay, displays);
|
||||
activeDisplay, displays, sessionInfo);
|
||||
}
|
||||
|
||||
public WifiDisplayStatus[] newArray(int size) {
|
||||
@@ -87,11 +93,11 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
|
||||
public WifiDisplayStatus() {
|
||||
this(FEATURE_STATE_UNAVAILABLE, SCAN_STATE_NOT_SCANNING, DISPLAY_STATE_NOT_CONNECTED,
|
||||
null, WifiDisplay.EMPTY_ARRAY);
|
||||
null, WifiDisplay.EMPTY_ARRAY, null);
|
||||
}
|
||||
|
||||
public WifiDisplayStatus(int featureState, int scanState,
|
||||
int activeDisplayState, WifiDisplay activeDisplay, WifiDisplay[] displays) {
|
||||
public WifiDisplayStatus(int featureState, int scanState, int activeDisplayState,
|
||||
WifiDisplay activeDisplay, WifiDisplay[] displays, WifiDisplaySessionInfo sessionInfo) {
|
||||
if (displays == null) {
|
||||
throw new IllegalArgumentException("displays must not be null");
|
||||
}
|
||||
@@ -101,6 +107,8 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
mActiveDisplayState = activeDisplayState;
|
||||
mActiveDisplay = activeDisplay;
|
||||
mDisplays = displays;
|
||||
|
||||
mSessionInfo = (sessionInfo != null) ? sessionInfo : new WifiDisplaySessionInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,13 +152,20 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
|
||||
/**
|
||||
* Gets the list of Wifi displays, returns a combined list of all available
|
||||
* Wifi displays as reported by the most recent scan, and all remembered
|
||||
* Wifi displays as reported by the most recent scan, and all remembered
|
||||
* Wifi displays (not necessarily available at the time).
|
||||
*/
|
||||
public WifiDisplay[] getDisplays() {
|
||||
return mDisplays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Wifi display session info (required for certification only)
|
||||
*/
|
||||
public WifiDisplaySessionInfo getSessionInfo() {
|
||||
return mSessionInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mFeatureState);
|
||||
@@ -168,6 +183,8 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
for (WifiDisplay display : mDisplays) {
|
||||
display.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
mSessionInfo.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -183,6 +200,7 @@ public final class WifiDisplayStatus implements Parcelable {
|
||||
+ ", activeDisplayState=" + mActiveDisplayState
|
||||
+ ", activeDisplay=" + mActiveDisplay
|
||||
+ ", displays=" + Arrays.toString(mDisplays)
|
||||
+ ", sessionInfo=" + mSessionInfo
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5074,6 +5074,14 @@ public final class Settings {
|
||||
*/
|
||||
public static final String WIFI_DISPLAY_ON = "wifi_display_on";
|
||||
|
||||
/**
|
||||
* Whether Wifi display certification mode is enabled/disabled
|
||||
* 0=disabled. 1=enabled.
|
||||
* @hide
|
||||
*/
|
||||
public static final String WIFI_DISPLAY_CERTIFICATION_ON =
|
||||
"wifi_display_certification_on";
|
||||
|
||||
/**
|
||||
* Whether to notify the user of open networks.
|
||||
* <p>
|
||||
|
||||
@@ -61,7 +61,7 @@ protected:
|
||||
|
||||
public:
|
||||
virtual void onDisplayConnected(const sp<IGraphicBufferProducer>& bufferProducer,
|
||||
uint32_t width, uint32_t height, uint32_t flags) {
|
||||
uint32_t width, uint32_t height, uint32_t flags, uint32_t session) {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
|
||||
jobject surfaceObj = android_view_Surface_createFromIGraphicBufferProducer(env, bufferProducer);
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
|
||||
env->CallVoidMethod(mRemoteDisplayObjGlobal,
|
||||
gRemoteDisplayClassInfo.notifyDisplayConnected,
|
||||
surfaceObj, width, height, flags);
|
||||
surfaceObj, width, height, flags, session);
|
||||
env->DeleteLocalRef(surfaceObj);
|
||||
checkAndClearExceptionFromCallback(env, "notifyDisplayConnected");
|
||||
}
|
||||
@@ -117,6 +117,14 @@ public:
|
||||
mDisplay->dispose();
|
||||
}
|
||||
|
||||
void pause() {
|
||||
mDisplay->pause();
|
||||
}
|
||||
|
||||
void resume() {
|
||||
mDisplay->resume();
|
||||
}
|
||||
|
||||
private:
|
||||
sp<IRemoteDisplay> mDisplay;
|
||||
sp<NativeRemoteDisplayClient> mClient;
|
||||
@@ -149,6 +157,16 @@ static jint nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr
|
||||
return reinterpret_cast<jint>(wrapper);
|
||||
}
|
||||
|
||||
static void nativePause(JNIEnv* env, jobject remoteDisplayObj, jint ptr) {
|
||||
NativeRemoteDisplay* wrapper = reinterpret_cast<NativeRemoteDisplay*>(ptr);
|
||||
wrapper->pause();
|
||||
}
|
||||
|
||||
static void nativeResume(JNIEnv* env, jobject remoteDisplayObj, jint ptr) {
|
||||
NativeRemoteDisplay* wrapper = reinterpret_cast<NativeRemoteDisplay*>(ptr);
|
||||
wrapper->resume();
|
||||
}
|
||||
|
||||
static void nativeDispose(JNIEnv* env, jobject remoteDisplayObj, jint ptr) {
|
||||
NativeRemoteDisplay* wrapper = reinterpret_cast<NativeRemoteDisplay*>(ptr);
|
||||
delete wrapper;
|
||||
@@ -161,6 +179,10 @@ static JNINativeMethod gMethods[] = {
|
||||
(void*)nativeListen },
|
||||
{"nativeDispose", "(I)V",
|
||||
(void*)nativeDispose },
|
||||
{"nativePause", "(I)V",
|
||||
(void*)nativePause },
|
||||
{"nativeResume", "(I)V",
|
||||
(void*)nativeResume },
|
||||
};
|
||||
|
||||
int register_android_media_RemoteDisplay(JNIEnv* env)
|
||||
@@ -171,7 +193,7 @@ int register_android_media_RemoteDisplay(JNIEnv* env)
|
||||
jclass clazz = env->FindClass("android/media/RemoteDisplay");
|
||||
gRemoteDisplayClassInfo.notifyDisplayConnected =
|
||||
env->GetMethodID(clazz, "notifyDisplayConnected",
|
||||
"(Landroid/view/Surface;III)V");
|
||||
"(Landroid/view/Surface;IIII)V");
|
||||
gRemoteDisplayClassInfo.notifyDisplayDisconnected =
|
||||
env->GetMethodID(clazz, "notifyDisplayDisconnected", "()V");
|
||||
gRemoteDisplayClassInfo.notifyDisplayError =
|
||||
|
||||
@@ -42,6 +42,8 @@ public final class RemoteDisplay {
|
||||
|
||||
private native int nativeListen(String iface);
|
||||
private native void nativeDispose(int ptr);
|
||||
private native void nativePause(int ptr);
|
||||
private native void nativeResume(int ptr);
|
||||
|
||||
private RemoteDisplay(Listener listener, Handler handler) {
|
||||
mListener = listener;
|
||||
@@ -87,6 +89,14 @@ public final class RemoteDisplay {
|
||||
dispose(false);
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
nativePause(mPtr);
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
nativeResume(mPtr);
|
||||
}
|
||||
|
||||
private void dispose(boolean finalized) {
|
||||
if (mPtr != 0) {
|
||||
if (mGuard != null) {
|
||||
@@ -113,11 +123,11 @@ public final class RemoteDisplay {
|
||||
|
||||
// Called from native.
|
||||
private void notifyDisplayConnected(final Surface surface,
|
||||
final int width, final int height, final int flags) {
|
||||
final int width, final int height, final int flags, final int session) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onDisplayConnected(surface, width, height, flags);
|
||||
mListener.onDisplayConnected(surface, width, height, flags, session);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -146,7 +156,8 @@ public final class RemoteDisplay {
|
||||
* Listener invoked when the remote display connection changes state.
|
||||
*/
|
||||
public interface Listener {
|
||||
void onDisplayConnected(Surface surface, int width, int height, int flags);
|
||||
void onDisplayConnected(Surface surface,
|
||||
int width, int height, int flags, int session);
|
||||
void onDisplayDisconnected();
|
||||
void onDisplayError(int error);
|
||||
}
|
||||
|
||||
@@ -497,6 +497,48 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseWifiDisplay() {
|
||||
if (mContext.checkCallingPermission(
|
||||
android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY"
|
||||
+ "permission to pause a wifi display session.");
|
||||
}
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mSyncRoot) {
|
||||
if (mWifiDisplayAdapter != null) {
|
||||
mWifiDisplayAdapter.requestPauseLocked();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeWifiDisplay() {
|
||||
if (mContext.checkCallingPermission(
|
||||
android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY"
|
||||
+ "permission to resume a wifi display session.");
|
||||
}
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mSyncRoot) {
|
||||
if (mWifiDisplayAdapter != null) {
|
||||
mWifiDisplayAdapter.requestResumeLocked();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void disconnectWifiDisplay() {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.WifiDisplay;
|
||||
import android.hardware.display.WifiDisplaySessionInfo;
|
||||
import android.hardware.display.WifiDisplayStatus;
|
||||
import android.media.RemoteDisplay;
|
||||
import android.os.Handler;
|
||||
@@ -93,6 +94,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
private WifiDisplay[] mDisplays = WifiDisplay.EMPTY_ARRAY;
|
||||
private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY;
|
||||
private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY;
|
||||
private WifiDisplaySessionInfo mSessionInfo;
|
||||
|
||||
private boolean mPendingStatusChangeBroadcast;
|
||||
private boolean mPendingNotificationUpdate;
|
||||
@@ -204,6 +206,36 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void requestPauseLocked() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "requestPauseLocked");
|
||||
}
|
||||
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mDisplayController != null) {
|
||||
mDisplayController.requestPause();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void requestResumeLocked() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "requestResumeLocked");
|
||||
}
|
||||
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mDisplayController != null) {
|
||||
mDisplayController.requestResume();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void requestDisconnectLocked() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "requestDisconnectedLocked");
|
||||
@@ -267,7 +299,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
if (mCurrentStatus == null) {
|
||||
mCurrentStatus = new WifiDisplayStatus(
|
||||
mFeatureState, mScanState, mActiveDisplayState,
|
||||
mActiveDisplay, mDisplays);
|
||||
mActiveDisplay, mDisplays, mSessionInfo);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
@@ -579,6 +611,14 @@ final class WifiDisplayAdapter extends DisplayAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplaySessionInfo(WifiDisplaySessionInfo sessionInfo) {
|
||||
synchronized (getSyncRoot()) {
|
||||
mSessionInfo = sessionInfo;
|
||||
scheduleStatusChangedBroadcastLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayChanged(WifiDisplay display) {
|
||||
synchronized (getSyncRoot()) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.display.WifiDisplay;
|
||||
import android.hardware.display.WifiDisplaySessionInfo;
|
||||
import android.hardware.display.WifiDisplayStatus;
|
||||
import android.media.AudioManager;
|
||||
import android.media.RemoteDisplay;
|
||||
@@ -76,6 +77,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
private static final int MAX_THROUGHPUT = 50;
|
||||
private static final int CONNECTION_TIMEOUT_SECONDS = 60;
|
||||
private static final int RTSP_TIMEOUT_SECONDS = 15;
|
||||
private static final int RTSP_TIMEOUT_SECONDS_CERT_MODE = 120;
|
||||
|
||||
private static final int DISCOVER_PEERS_MAX_RETRIES = 10;
|
||||
private static final int DISCOVER_PEERS_RETRY_DELAY_MILLIS = 500;
|
||||
@@ -146,6 +148,10 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
private int mAdvertisedDisplayHeight;
|
||||
private int mAdvertisedDisplayFlags;
|
||||
|
||||
// Certification
|
||||
private boolean mWifiDisplayCertMode;
|
||||
private WifiP2pDevice mThisDevice;
|
||||
|
||||
public WifiDisplayController(Context context, Handler handler, Listener listener) {
|
||||
mContext = context;
|
||||
mHandler = handler;
|
||||
@@ -158,6 +164,7 @@ 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);
|
||||
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
|
||||
context.registerReceiver(mWifiP2pReceiver, intentFilter, null, mHandler);
|
||||
|
||||
ContentObserver settingsObserver = new ContentObserver(mHandler) {
|
||||
@@ -170,6 +177,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
resolver.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.WIFI_DISPLAY_ON), false, settingsObserver);
|
||||
resolver.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON), false, settingsObserver);
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
@@ -177,6 +186,8 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
mWifiDisplayOnSetting = Settings.Global.getInt(resolver,
|
||||
Settings.Global.WIFI_DISPLAY_ON, 0) != 0;
|
||||
mWifiDisplayCertMode = Settings.Global.getInt(resolver,
|
||||
Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON, 0) != 0;
|
||||
|
||||
updateWfdEnableState();
|
||||
}
|
||||
@@ -223,6 +234,18 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestPause() {
|
||||
if (mRemoteDisplay != null) {
|
||||
mRemoteDisplay.pause();
|
||||
}
|
||||
}
|
||||
|
||||
public void requestResume() {
|
||||
if (mRemoteDisplay != null) {
|
||||
mRemoteDisplay.resume();
|
||||
}
|
||||
}
|
||||
|
||||
public void requestDisconnect() {
|
||||
disconnect();
|
||||
}
|
||||
@@ -482,6 +505,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName);
|
||||
mDisconnectingDevice = mConnectedDevice;
|
||||
mConnectedDevice = null;
|
||||
mConnectedDeviceGroupInfo = null;
|
||||
|
||||
unadvertiseDisplay();
|
||||
|
||||
@@ -548,8 +572,12 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
return; // wait for asynchronous callback
|
||||
}
|
||||
|
||||
// Step 4. If we wanted to disconnect, then mission accomplished.
|
||||
// Step 4. If we wanted to disconnect, or we're updating after starting an
|
||||
// autonomous GO, then mission accomplished.
|
||||
if (mDesiredDevice == null) {
|
||||
if (mWifiDisplayCertMode) {
|
||||
mListener.onDisplaySessionInfo(getSessionInfo(mConnectedDeviceGroupInfo, 0));
|
||||
}
|
||||
unadvertiseDisplay();
|
||||
return; // done
|
||||
}
|
||||
@@ -625,13 +653,18 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
mRemoteDisplay = RemoteDisplay.listen(iface, new RemoteDisplay.Listener() {
|
||||
@Override
|
||||
public void onDisplayConnected(Surface surface,
|
||||
int width, int height, int flags) {
|
||||
int width, int height, int flags, int session) {
|
||||
if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) {
|
||||
Slog.i(TAG, "Opened RTSP connection with Wifi display: "
|
||||
+ mConnectedDevice.deviceName);
|
||||
mRemoteDisplayConnected = true;
|
||||
mHandler.removeCallbacks(mRtspTimeout);
|
||||
|
||||
if (mWifiDisplayCertMode) {
|
||||
mListener.onDisplaySessionInfo(
|
||||
getSessionInfo(mConnectedDeviceGroupInfo, session));
|
||||
}
|
||||
|
||||
final WifiDisplay display = createWifiDisplay(mConnectedDevice);
|
||||
advertiseDisplay(display, surface, width, height, flags);
|
||||
}
|
||||
@@ -658,10 +691,31 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
}, mHandler);
|
||||
|
||||
mHandler.postDelayed(mRtspTimeout, RTSP_TIMEOUT_SECONDS * 1000);
|
||||
// Use extended timeout value for certification, as some tests require user inputs
|
||||
int rtspTimeout = mWifiDisplayCertMode ?
|
||||
RTSP_TIMEOUT_SECONDS_CERT_MODE : RTSP_TIMEOUT_SECONDS;
|
||||
|
||||
mHandler.postDelayed(mRtspTimeout, rtspTimeout * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
private WifiDisplaySessionInfo getSessionInfo(WifiP2pGroup info, int session) {
|
||||
if (info == null) {
|
||||
return null;
|
||||
}
|
||||
Inet4Address addr = getInterfaceAddress(info);
|
||||
WifiDisplaySessionInfo sessionInfo = new WifiDisplaySessionInfo(
|
||||
!info.getOwner().deviceAddress.equals(mThisDevice.deviceAddress),
|
||||
session,
|
||||
info.getOwner().deviceAddress + " " + info.getNetworkName(),
|
||||
info.getPassphrase(),
|
||||
(addr != null) ? addr.getHostAddress() : "");
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, sessionInfo.toString());
|
||||
}
|
||||
return sessionInfo;
|
||||
}
|
||||
|
||||
private void handleStateChanged(boolean enabled) {
|
||||
mWifiP2pEnabled = enabled;
|
||||
updateWfdEnableState();
|
||||
@@ -676,7 +730,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
private void handleConnectionChanged(NetworkInfo networkInfo) {
|
||||
mNetworkInfo = networkInfo;
|
||||
if (mWfdEnabled && networkInfo.isConnected()) {
|
||||
if (mDesiredDevice != null) {
|
||||
if (mDesiredDevice != null || mWifiDisplayCertMode) {
|
||||
mWifiP2pManager.requestGroupInfo(mWifiP2pChannel, new GroupInfoListener() {
|
||||
@Override
|
||||
public void onGroupInfoAvailable(WifiP2pGroup info) {
|
||||
@@ -698,6 +752,25 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mWifiDisplayCertMode) {
|
||||
boolean owner = info.getOwner().deviceAddress
|
||||
.equals(mThisDevice.deviceAddress);
|
||||
if (owner && info.getClientList().isEmpty()) {
|
||||
// this is the case when we started Autonomous GO,
|
||||
// and no client has connected, save group info
|
||||
// and updateConnection()
|
||||
mConnectingDevice = mDesiredDevice = null;
|
||||
mConnectedDeviceGroupInfo = info;
|
||||
updateConnection();
|
||||
} else if (mConnectingDevice == null && mDesiredDevice == null) {
|
||||
// this is the case when we received an incoming connection
|
||||
// from the sink, update both mConnectingDevice and mDesiredDevice
|
||||
// then proceed to updateConnection() below
|
||||
mConnectingDevice = mDesiredDevice = owner ?
|
||||
info.getClientList().iterator().next() : info.getOwner();
|
||||
}
|
||||
}
|
||||
|
||||
if (mConnectingDevice != null && mConnectingDevice == mDesiredDevice) {
|
||||
Slog.i(TAG, "Connected to Wifi display: "
|
||||
+ mConnectingDevice.deviceName);
|
||||
@@ -712,6 +785,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
mConnectedDeviceGroupInfo = null;
|
||||
disconnect();
|
||||
|
||||
// After disconnection for a group, for some reason we have a tendency
|
||||
@@ -910,6 +984,13 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
}
|
||||
|
||||
handleConnectionChanged(networkInfo);
|
||||
} else if (action.equals(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION)) {
|
||||
mThisDevice = (WifiP2pDevice) intent.getParcelableExtra(
|
||||
WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Received WIFI_P2P_THIS_DEVICE_CHANGED_ACTION: mThisDevice= "
|
||||
+ mThisDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -928,6 +1009,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
|
||||
void onDisplayChanged(WifiDisplay display);
|
||||
void onDisplayConnected(WifiDisplay display,
|
||||
Surface surface, int width, int height, int flags);
|
||||
void onDisplaySessionInfo(WifiDisplaySessionInfo sessionInfo);
|
||||
void onDisplayDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,6 +619,37 @@ public class WifiNative {
|
||||
return doBooleanCommand("P2P_LISTEN " + timeout);
|
||||
}
|
||||
|
||||
public boolean p2pExtListen(boolean enable, int period, int interval) {
|
||||
if (enable && interval < period) {
|
||||
return false;
|
||||
}
|
||||
return doBooleanCommand("P2P_EXT_LISTEN"
|
||||
+ (enable ? (" " + period + " " + interval) : ""));
|
||||
}
|
||||
|
||||
public boolean p2pSetChannel(int lc, int oc) {
|
||||
if (DBG) Log.d(mTAG, "p2pSetChannel: lc="+lc+", oc="+oc);
|
||||
|
||||
if (lc >=1 && lc <= 11) {
|
||||
if (!doBooleanCommand("P2P_SET listen_channel " + lc)) {
|
||||
return false;
|
||||
}
|
||||
} else if (lc != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (oc >= 1 && oc <= 165 ) {
|
||||
int freq = (oc <= 14 ? 2407 : 5000) + oc * 5;
|
||||
return doBooleanCommand("P2P_SET disallow_freq 1000-"
|
||||
+ (freq - 5) + "," + (freq + 5) + "-6000");
|
||||
} else if (oc == 0) {
|
||||
/* oc==0 disables "P2P_SET disallow_freq" (enables all freqs) */
|
||||
return doBooleanCommand("P2P_SET disallow_freq \"\"");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean p2pFlush() {
|
||||
return doBooleanCommand("P2P_FLUSH");
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
|
||||
import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo;
|
||||
import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceResponse;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -430,6 +431,28 @@ public class WifiP2pManager {
|
||||
/** @hide */
|
||||
public static final int START_WPS_SUCCEEDED = BASE + 64;
|
||||
|
||||
/** @hide */
|
||||
public static final int START_LISTEN = BASE + 65;
|
||||
/** @hide */
|
||||
public static final int START_LISTEN_FAILED = BASE + 66;
|
||||
/** @hide */
|
||||
public static final int START_LISTEN_SUCCEEDED = BASE + 67;
|
||||
|
||||
/** @hide */
|
||||
public static final int STOP_LISTEN = BASE + 68;
|
||||
/** @hide */
|
||||
public static final int STOP_LISTEN_FAILED = BASE + 69;
|
||||
/** @hide */
|
||||
public static final int STOP_LISTEN_SUCCEEDED = BASE + 70;
|
||||
|
||||
/** @hide */
|
||||
public static final int SET_CHANNEL = BASE + 71;
|
||||
/** @hide */
|
||||
public static final int SET_CHANNEL_FAILED = BASE + 72;
|
||||
/** @hide */
|
||||
public static final int SET_CHANNEL_SUCCEEDED = BASE + 73;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new WifiP2pManager instance. Applications use
|
||||
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
|
||||
@@ -667,6 +690,9 @@ public class WifiP2pManager {
|
||||
case DELETE_PERSISTENT_GROUP_FAILED:
|
||||
case SET_WFD_INFO_FAILED:
|
||||
case START_WPS_FAILED:
|
||||
case START_LISTEN_FAILED:
|
||||
case STOP_LISTEN_FAILED:
|
||||
case SET_CHANNEL_FAILED:
|
||||
if (listener != null) {
|
||||
((ActionListener) listener).onFailure(message.arg1);
|
||||
}
|
||||
@@ -689,6 +715,9 @@ public class WifiP2pManager {
|
||||
case DELETE_PERSISTENT_GROUP_SUCCEEDED:
|
||||
case SET_WFD_INFO_SUCCEEDED:
|
||||
case START_WPS_SUCCEEDED:
|
||||
case START_LISTEN_SUCCEEDED:
|
||||
case STOP_LISTEN_SUCCEEDED:
|
||||
case SET_CHANNEL_SUCCEEDED:
|
||||
if (listener != null) {
|
||||
((ActionListener) listener).onSuccess();
|
||||
}
|
||||
@@ -955,6 +984,22 @@ public class WifiP2pManager {
|
||||
c.mAsyncChannel.sendMessage(REMOVE_GROUP, 0, c.putListener(listener));
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void listen(Channel c, boolean enable, ActionListener listener) {
|
||||
checkChannel(c);
|
||||
c.mAsyncChannel.sendMessage(enable ? START_LISTEN : STOP_LISTEN,
|
||||
0, c.putListener(listener));
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void setWifiP2pChannels(Channel c, int lc, int oc, ActionListener listener) {
|
||||
checkChannel(c);
|
||||
Bundle p2pChannels = new Bundle();
|
||||
p2pChannels.putInt("lc", lc);
|
||||
p2pChannels.putInt("oc", oc);
|
||||
c.mAsyncChannel.sendMessage(SET_CHANNEL, 0, c.putListener(listener), p2pChannels);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a Wi-Fi Protected Setup (WPS) session.
|
||||
*
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
|
||||
import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
|
||||
import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.INetworkManagementService;
|
||||
import android.os.Handler;
|
||||
@@ -628,6 +629,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
|
||||
case DhcpStateMachine.CMD_ON_QUIT:
|
||||
case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT:
|
||||
case SET_MIRACAST_MODE:
|
||||
case WifiP2pManager.START_LISTEN:
|
||||
case WifiP2pManager.STOP_LISTEN:
|
||||
case WifiP2pManager.SET_CHANNEL:
|
||||
break;
|
||||
case WifiStateMachine.CMD_ENABLE_P2P:
|
||||
// Enable is lazy and has no response
|
||||
@@ -729,7 +733,16 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
|
||||
replyToMessage(message, WifiP2pManager.START_WPS_FAILED,
|
||||
WifiP2pManager.P2P_UNSUPPORTED);
|
||||
break;
|
||||
default:
|
||||
case WifiP2pManager.START_LISTEN:
|
||||
replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED,
|
||||
WifiP2pManager.P2P_UNSUPPORTED);
|
||||
break;
|
||||
case WifiP2pManager.STOP_LISTEN:
|
||||
replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED,
|
||||
WifiP2pManager.P2P_UNSUPPORTED);
|
||||
break;
|
||||
|
||||
default:
|
||||
return NOT_HANDLED;
|
||||
}
|
||||
return HANDLED;
|
||||
@@ -1022,6 +1035,35 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
|
||||
case SET_MIRACAST_MODE:
|
||||
mWifiNative.setMiracastMode(message.arg1);
|
||||
break;
|
||||
case WifiP2pManager.START_LISTEN:
|
||||
if (DBG) logd(getName() + " start listen mode");
|
||||
mWifiNative.p2pFlush();
|
||||
if (mWifiNative.p2pExtListen(true, 500, 500)) {
|
||||
replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED);
|
||||
} else {
|
||||
replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
|
||||
}
|
||||
break;
|
||||
case WifiP2pManager.STOP_LISTEN:
|
||||
if (DBG) logd(getName() + " stop listen mode");
|
||||
if (mWifiNative.p2pExtListen(false, 0, 0)) {
|
||||
replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED);
|
||||
} else {
|
||||
replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED);
|
||||
}
|
||||
mWifiNative.p2pFlush();
|
||||
break;
|
||||
case WifiP2pManager.SET_CHANNEL:
|
||||
Bundle p2pChannels = (Bundle) message.obj;
|
||||
int lc = p2pChannels.getInt("lc", 0);
|
||||
int oc = p2pChannels.getInt("oc", 0);
|
||||
if (DBG) logd(getName() + " set listen and operating channel");
|
||||
if (mWifiNative.p2pSetChannel(lc, oc)) {
|
||||
replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED);
|
||||
} else {
|
||||
replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NOT_HANDLED;
|
||||
}
|
||||
@@ -1171,6 +1213,35 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
|
||||
mWifiNative.p2pGroupRemove(mGroup.getInterface());
|
||||
}
|
||||
break;
|
||||
case WifiP2pManager.START_LISTEN:
|
||||
if (DBG) logd(getName() + " start listen mode");
|
||||
mWifiNative.p2pFlush();
|
||||
if (mWifiNative.p2pExtListen(true, 500, 500)) {
|
||||
replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED);
|
||||
} else {
|
||||
replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
|
||||
}
|
||||
break;
|
||||
case WifiP2pManager.STOP_LISTEN:
|
||||
if (DBG) logd(getName() + " stop listen mode");
|
||||
if (mWifiNative.p2pExtListen(false, 0, 0)) {
|
||||
replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED);
|
||||
} else {
|
||||
replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED);
|
||||
}
|
||||
mWifiNative.p2pFlush();
|
||||
break;
|
||||
case WifiP2pManager.SET_CHANNEL:
|
||||
Bundle p2pChannels = (Bundle) message.obj;
|
||||
int lc = p2pChannels.getInt("lc", 0);
|
||||
int oc = p2pChannels.getInt("oc", 0);
|
||||
if (DBG) logd(getName() + " set listen and operating channel");
|
||||
if (mWifiNative.p2pSetChannel(lc, oc)) {
|
||||
replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED);
|
||||
} else {
|
||||
replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NOT_HANDLED;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user