summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sunil Ravi <sunilravi@google.com> 2024-11-25 06:23:25 +0000
committer Sunil Ravi <sunilravi@google.com> 2024-12-03 20:13:20 +0000
commit4805ca200f1d5b63e3f6c5fddcd78fc487b4224b (patch)
tree8e71a9241d3d78c47cae6597012e5c41364f8dd6
parentdb6a1f64880dcf3d59c99a7ecf8f6d7cae7edad8 (diff)
Support for BLE assisted P2P discovery and pairing
This CL includes, 1. An interface to generate a DIR info and to validate a received DIR info. 2. Added a new bootstrapping method which will be set for bootsrapping done over BLE. 3. Added authorize flag in WifiP2pConfig for the device to authorize a connection request from Peer. 4. Added API to get the BSSID of group owner. Bug: 341971059 Flag: com.android.wifi.flags.wifi_direct_r2 Test: Manual - Basic P2P connect/disconnect tests Test: TH Presubmit tests Test: atest com.android.server.wifi.p2p Change-Id: I2f602f4ea1cb383501967d0bfae8e3b2fa55ec95
-rw-r--r--framework/api/current.txt17
-rw-r--r--framework/java/android/net/wifi/p2p/WifiP2pConfig.java55
-rw-r--r--framework/java/android/net/wifi/p2p/WifiP2pDirInfo.java146
-rw-r--r--framework/java/android/net/wifi/p2p/WifiP2pGroup.java25
-rw-r--r--framework/java/android/net/wifi/p2p/WifiP2pManager.java237
-rw-r--r--framework/java/android/net/wifi/p2p/WifiP2pPairingBootstrappingConfig.java7
-rw-r--r--framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java23
-rw-r--r--framework/tests/src/android/net/wifi/p2p/WifiP2pDirInfoTest.java48
-rw-r--r--framework/tests/src/android/net/wifi/p2p/WifiP2pGroupTest.java15
-rw-r--r--service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java48
-rw-r--r--service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java45
11 files changed, 661 insertions, 5 deletions
diff --git a/framework/api/current.txt b/framework/api/current.txt
index a4982793a5..451f907e19 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -1280,6 +1280,7 @@ package android.net.wifi.p2p {
method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @Nullable public android.net.wifi.p2p.WifiP2pPairingBootstrappingConfig getPairingBootstrappingConfig();
method @Nullable public String getPassphrase();
method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public int getPccModeConnectionType();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public boolean isAuthorizeConnectionFromPeer();
method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public void setGroupOwnerVersion(int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pConfig> CREATOR;
@@ -1306,6 +1307,7 @@ package android.net.wifi.p2p {
ctor public WifiP2pConfig.Builder();
method @NonNull public android.net.wifi.p2p.WifiP2pConfig build();
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder enablePersistentMode(boolean);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setAuthorizeConnectionFromPeer(boolean);
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setDeviceAddress(@Nullable android.net.MacAddress);
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupClientIpProvisioningMode(int);
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingBand(int);
@@ -1358,6 +1360,16 @@ package android.net.wifi.p2p {
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pDeviceList> CREATOR;
}
+ @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public final class WifiP2pDirInfo implements android.os.Parcelable {
+ ctor public WifiP2pDirInfo(@NonNull android.net.MacAddress, @NonNull byte[], @NonNull byte[]);
+ method public int describeContents();
+ method @NonNull public byte[] getDirTag();
+ method @NonNull public android.net.MacAddress getMacAddress();
+ method @NonNull public byte[] getNonce();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pDirInfo> CREATOR;
+ }
+
@FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public final class WifiP2pDiscoveryConfig implements android.os.Parcelable {
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public int describeContents();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public int getFrequencyMhz();
@@ -1378,6 +1390,7 @@ package android.net.wifi.p2p {
method public int describeContents();
method public java.util.Collection<android.net.wifi.p2p.WifiP2pDevice> getClientList();
method public int getFrequency();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @Nullable public android.net.MacAddress getGroupOwnerBssid();
method public String getInterface();
method public int getNetworkId();
method public String getNetworkName();
@@ -1438,6 +1451,7 @@ package android.net.wifi.p2p {
method public void removeServiceRequest(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceRequest, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void requestConnectionInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener);
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void requestDeviceInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.DeviceInfoListener);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void requestDirInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.net.wifi.p2p.WifiP2pDirInfo,java.lang.Exception>);
method public void requestDiscoveryState(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.DiscoveryStateListener);
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void requestGroupInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.GroupInfoListener);
method public void requestNetworkInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.NetworkInfoListener);
@@ -1456,6 +1470,7 @@ package android.net.wifi.p2p {
method public void stopListening(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void stopPeerDiscovery(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public void unregisterWifiP2pListener(@NonNull android.net.wifi.p2p.WifiP2pManager.WifiP2pListener);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void validateDirInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pDirInfo, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,java.lang.Exception>);
field public static final String ACTION_WIFI_P2P_LISTEN_STATE_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_LISTEN_STATE_CHANGED";
field public static final String ACTION_WIFI_P2P_REQUEST_RESPONSE_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_REQUEST_RESPONSE_CHANGED";
field public static final int BUSY = 2; // 0x2
@@ -1480,6 +1495,7 @@ package android.net.wifi.p2p {
field @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public static final int GROUP_CREATION_FAILURE_REASON_PROVISION_DISCOVERY_FAILED = 3; // 0x3
field @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public static final int GROUP_CREATION_FAILURE_REASON_TIMED_OUT = 1; // 0x1
field @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public static final int GROUP_CREATION_FAILURE_REASON_USER_REJECTED = 2; // 0x2
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int NO_PERMISSION = 4; // 0x4
field public static final int NO_SERVICE_REQUESTS = 3; // 0x3
field public static final int P2P_UNSUPPORTED = 1; // 0x1
field public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION = "android.net.wifi.p2p.CONNECTION_STATE_CHANGE";
@@ -1596,6 +1612,7 @@ package android.net.wifi.p2p {
field public static final int PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PASSPHRASE = 16; // 0x10
field public static final int PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PINCODE = 8; // 0x8
field public static final int PAIRING_BOOTSTRAPPING_METHOD_OPPORTUNISTIC = 1; // 0x1
+ field public static final int PAIRING_BOOTSTRAPPING_METHOD_OUT_OF_BAND = 32; // 0x20
}
@FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public final class WifiP2pUsdBasedLocalServiceAdvertisementConfig implements android.os.Parcelable {
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pConfig.java b/framework/java/android/net/wifi/p2p/WifiP2pConfig.java
index d1bed9dc96..67f1e6cd3a 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -394,6 +394,27 @@ public class WifiP2pConfig implements Parcelable {
return mPairingBootstrappingConfig;
}
+ /**
+ * Used to authorize a connection request from the peer device.
+ */
+ private boolean mAuthorizeConnectionFromPeer = false;
+
+ /**
+ * Query to check if the configuration is for authorizing a connection request
+ * from the peer device. @see {@link Builder#setAuthorizeConnectionFromPeer(boolean)}
+ *
+ * @return true if configured to authorize a connection request from the Peer device,
+ * False otherwise.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public boolean isAuthorizeConnectionFromPeer() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return mAuthorizeConnectionFromPeer;
+ }
+
public WifiP2pConfig() {
//set defaults
wps = new WpsInfo();
@@ -477,6 +498,7 @@ public class WifiP2pConfig implements Parcelable {
.append((mPairingBootstrappingConfig == null)
? "<null>" : mPairingBootstrappingConfig.toString());
}
+ sbuf.append("\n authorizeConnectionFromPeer: ").append(mAuthorizeConnectionFromPeer);
return sbuf.toString();
}
@@ -501,6 +523,7 @@ public class WifiP2pConfig implements Parcelable {
mVendorData = new ArrayList<>(source.mVendorData);
mGroupOwnerVersion = source.mGroupOwnerVersion;
mPairingBootstrappingConfig = source.mPairingBootstrappingConfig;
+ mAuthorizeConnectionFromPeer = source.mAuthorizeConnectionFromPeer;
}
}
@@ -521,6 +544,7 @@ public class WifiP2pConfig implements Parcelable {
if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
dest.writeParcelable(mPairingBootstrappingConfig, flags);
}
+ dest.writeBoolean(mAuthorizeConnectionFromPeer);
}
/** Implement the Parcelable interface */
@@ -545,6 +569,7 @@ public class WifiP2pConfig implements Parcelable {
config.mPairingBootstrappingConfig = in.readParcelable(
WifiP2pPairingBootstrappingConfig.class.getClassLoader());
}
+ config.mAuthorizeConnectionFromPeer = in.readBoolean();
return config;
}
@@ -585,6 +610,7 @@ public class WifiP2pConfig implements Parcelable {
@PccModeConnectionType
private int mPccModeConnectionType = PCC_MODE_DEFAULT_CONNECTION_TYPE_LEGACY_ONLY;
private @Nullable WifiP2pPairingBootstrappingConfig mPairingBootstrappingConfig;
+ private boolean mAuthorizeConnectionFromPeer = false;
/**
* Specify the peer's MAC address. If not set, the device will
@@ -913,6 +939,34 @@ public class WifiP2pConfig implements Parcelable {
}
/**
+ * Specify that the configuration is to authorize a connection request from a peer device.
+ * The MAC address of the peer device is specified using
+ * {@link WifiP2pConfig.Builder#setDeviceAddress(MacAddress)}.
+ * <p>
+ * Optional. false by default. The default configuration is to join a group or to initiate
+ * a group formation.
+ * <p>
+ * This configuration is typically used in Bluetooth LE assisted P2P pairing protocol
+ * defined in Wi-Fi Direct R2 specification, section 3.9. The collocated Bluetooth Provider
+ * sends the pairing password to the peer device (Seeker) and direct the system to
+ * authorize the connection request from the peer device using {@link
+ * WifiP2pManager#connect(WifiP2pManager.Channel, WifiP2pConfig,
+ * WifiP2pManager.ActionListener)}. The device will then wait for the connection request
+ * from the peer device.
+ *
+ * @param authorize true to authorize a connection request from the peer device, false to
+ * let the device join a group or form a group.
+ * @return The builder to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @NonNull
+ public Builder setAuthorizeConnectionFromPeer(boolean authorize) {
+ mAuthorizeConnectionFromPeer = authorize;
+ return this;
+ }
+
+ /**
* Build {@link WifiP2pConfig} given the current requests made on the builder.
* @return {@link WifiP2pConfig} constructed based on builder method calls.
*/
@@ -963,6 +1017,7 @@ public class WifiP2pConfig implements Parcelable {
config.mGroupClientIpProvisioningMode = mGroupClientIpProvisioningMode;
config.mJoinExistingGroup = mJoinExistingGroup;
config.mPairingBootstrappingConfig = mPairingBootstrappingConfig;
+ config.mAuthorizeConnectionFromPeer = mAuthorizeConnectionFromPeer;
return config;
}
}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pDirInfo.java b/framework/java/android/net/wifi/p2p/WifiP2pDirInfo.java
new file mode 100644
index 0000000000..0292628154
--- /dev/null
+++ b/framework/java/android/net/wifi/p2p/WifiP2pDirInfo.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 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.net.wifi.p2p;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.RequiresApi;
+import android.net.MacAddress;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.wifi.flags.Flags;
+
+import java.util.Arrays;
+
+/**
+ * This object contains the Device Identity Resolution (DIR) Info to check if the device is a
+ * previously paired device.
+ * The device advertises this information in Bluetooth LE advertising packets
+ * and Unsynchronized Service Discovery (USD) frames. The device receiving DIR
+ * Info uses this information to identify that the peer device is a previously paired device.
+ * For Details, refer Wi-Fi Alliance Wi-Fi Direct R2 specification section 3.8.2 Pairing Identity
+ * and section 3.9.2.3.2 Optional Advertising Data Elements.
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+public final class WifiP2pDirInfo implements Parcelable {
+ /**
+ * The MAC address of the P2P device interface.
+ */
+ private MacAddress mMacAddress;
+
+ /**
+ * Random number of 8 octets.
+ */
+ private byte[] mNonce;
+
+ /**
+ * A resolvable identity value of 8 octets.
+ */
+ private byte[] mDirTag;
+
+ /**
+ * @return the MAC address of the P2P device interface.
+ */
+ @NonNull
+ public MacAddress getMacAddress() {
+ return mMacAddress;
+ }
+
+ /**
+ * Get the nonce value used to derive DIR Tag.
+ * See {@link WifiP2pDirInfo}
+ *
+ * @return A byte-array of random number of size 8 octets.
+ */
+ @NonNull
+ public byte[] getNonce() {
+ return mNonce;
+ }
+
+ /**
+ * Get the DIR Tag value.
+ * See {@link WifiP2pDirInfo}
+ *
+ * @return A byte-array of Tag value of size 8 octets.
+ */
+ @NonNull
+ public byte[] getDirTag() {
+ return mDirTag;
+ }
+
+ /**
+ * Constructor for Device Identity Resolution (DIR) Info generated based on the 128 bit Device
+ * Identity key. For details, refer Wi-Fi Alliance Wi-Fi Direct R2 specification Table 8.
+ *
+ * @param macAddress The MAC address of the P2P device interface.
+ * @param nonce Random number of 8 octets.
+ * @param dirTag Resolvable identity value of 8 octets derived based on the device MAC address,
+ * device identity key and P2P device MAC address.
+ * Tag = Truncate-64(HMAC-SHA-256(DevIk, "DIR" || P2P Device Address || Nonce))
+ *
+ */
+ public WifiP2pDirInfo(@NonNull MacAddress macAddress, @NonNull byte[] nonce,
+ @NonNull byte[] dirTag) {
+ mMacAddress = macAddress;
+ mNonce = nonce;
+ mDirTag = dirTag;
+ }
+
+ /**
+ * Generates a string of all the defined elements.
+ *
+ * @return a compiled string representing all elements
+ */
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder("WifiP2pDirInfo:");
+ sbuf.append("\n Mac Address: ").append(mMacAddress);
+ sbuf.append("\n Nonce : ").append((mNonce == null)
+ ? "<null>" : Arrays.toString(mNonce));
+ sbuf.append("\n DIR Tag : ").append((mDirTag == null)
+ ? "<null>" : Arrays.toString(mDirTag));
+ return sbuf.toString();
+ }
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ mMacAddress.writeToParcel(dest, flags);
+ dest.writeByteArray(mNonce);
+ dest.writeByteArray(mDirTag);
+ }
+
+ /** Implement the Parcelable interface */
+ @NonNull
+ public static final Creator<WifiP2pDirInfo> CREATOR =
+ new Creator<WifiP2pDirInfo>() {
+ public WifiP2pDirInfo createFromParcel(Parcel in) {
+ return new WifiP2pDirInfo(MacAddress.CREATOR.createFromParcel(in),
+ in.createByteArray(), in.createByteArray());
+ }
+
+ public WifiP2pDirInfo[] newArray(int size) {
+ return new WifiP2pDirInfo[size];
+ }
+ };
+}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pGroup.java b/framework/java/android/net/wifi/p2p/WifiP2pGroup.java
index eb51cc0fdd..43dc26fa04 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -500,6 +500,31 @@ public class WifiP2pGroup implements Parcelable {
mVendorData = new ArrayList<>(vendorData);
}
+ /**
+ * Returns the BSSID, if this device is the group owner of the P2P group supporting Wi-Fi
+ * Direct R2 protocol.
+ * <p>
+ * The interface address of a Wi-Fi Direct R2 supported device is randomized. So for every
+ * group owner session a randomized interface address will be returned.
+ * <p>
+ * The BSSID returned will be {@code null}, if this device is a client device or a group owner
+ * which doesn't support Wi-Fi Direct R2 protocol.
+ * @return the BSSID.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @Nullable
+ public MacAddress getGroupOwnerBssid() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ if (isGroupOwner() && getSecurityType() == SECURITY_TYPE_WPA3_SAE
+ && interfaceAddress != null) {
+ return MacAddress.fromBytes(interfaceAddress);
+ }
+ return null;
+ }
+
public String toString() {
StringBuffer sbuf = new StringBuffer();
sbuf.append("network: ").append(mNetworkName);
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pManager.java b/framework/java/android/net/wifi/p2p/WifiP2pManager.java
index 80ec9631f1..717bde6a80 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -51,6 +51,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
+import android.os.OutcomeReceiver;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.CloseGuard;
@@ -629,6 +630,13 @@ public class WifiP2pManager {
*/
public static final int WIFI_P2P_USD_BASED_ADD_LOCAL_SERVICE = 1;
+ /**
+ * Extra for transporting DIR Information.
+ * @hide
+ */
+ public static final String EXTRA_PARAM_KEY_DIR_INFO =
+ "android.net.wifi.p2p.EXTRA_PARAM_KEY_DIR_INFO";
+
private Context mContext;
IWifiP2pManager mService;
@@ -904,6 +912,20 @@ public class WifiP2pManager {
/** @hide */
public static final int RESPONSE_GET_LISTEN_STATE = BASE + 118;
+ /** @hide */
+ public static final int GET_DIR_INFO = BASE + 119;
+ /** @hide */
+ public static final int GET_DIR_INFO_FAILED = BASE + 120;
+ /** @hide */
+ public static final int RESPONSE_GET_DIR_INFO = BASE + 121;
+
+ /** @hide */
+ public static final int VALIDATE_DIR_INFO = BASE + 122;
+ /** @hide */
+ public static final int VALIDATE_DIR_INFO_FAILED = BASE + 123;
+ /** @hide */
+ public static final int RESPONSE_VALIDATE_DIR_INFO = BASE + 124;
+
private static final SparseArray<IWifiP2pListener> sWifiP2pListenerMap = new SparseArray<>();
/**
* Create a new WifiP2pManager instance. Applications use
@@ -945,6 +967,14 @@ public class WifiP2pManager {
*/
public static final int NO_SERVICE_REQUESTS = 3;
+ /**
+ * Passed with {@link ActionListener#onFailure}.
+ * Indicates that the operation failed due to calling app doesn't have permission to call the
+ * API.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int NO_PERMISSION = 4;
+
/** Interface for callback invocation when framework channel is lost */
public interface ChannelListener {
/**
@@ -1950,6 +1980,31 @@ public class WifiP2pManager {
.onPinGenerated(deviceAddress, pin);
}
break;
+ case RESPONSE_GET_DIR_INFO:
+ if (listener != null) {
+ if (Flags.wifiDirectR2()) {
+ ((WifiP2pDirInfoListener) listener)
+ .onDirInfoReceived((WifiP2pDirInfo) message.obj);
+ }
+ }
+ break;
+ case GET_DIR_INFO_FAILED:
+ if (listener != null) {
+ ((WifiP2pDirInfoListener) listener)
+ .onFailure(message.arg1);
+ }
+ break;
+ case RESPONSE_VALIDATE_DIR_INFO:
+ if (listener != null) {
+ ((WifiP2pDirInfoValidationListener) listener)
+ .onDirInfoValidation(message.arg1 == 1);
+ }
+ break;
+ case VALIDATE_DIR_INFO_FAILED:
+ if (listener != null) {
+ ((WifiP2pDirInfoValidationListener) listener)
+ .onFailure(message.arg1);
+ }
default:
Log.d(TAG, "Ignored " + message);
break;
@@ -3835,4 +3890,186 @@ public class WifiP2pManager {
public static int getP2pMaxAllowedVendorElementsLengthBytes() {
return WIFI_P2P_VENDOR_ELEMENTS_MAXIMUM_LENGTH;
}
+
+ private static Exception reasonCodeToException(int reason) {
+ if (reason == ERROR) {
+ return new IllegalStateException("Internal error");
+ } else if (reason == BUSY) {
+ return new IllegalStateException("Framework is busy");
+ } else if (Flags.wifiDirectR2() && reason == NO_PERMISSION) {
+ return new SecurityException("Application doesn't have required permission");
+ } else {
+ return new IllegalStateException();
+ }
+ }
+
+ /**
+ * Interface for callback invocation in response to {@link #requestDirInfo}.
+ * @hide
+ */
+ public interface WifiP2pDirInfoListener {
+ /**
+ * The callback to indicate that the system searched for DIR information.
+ * @param dirInfo {@link WifiP2pDirInfo} if exists, otherwise null.
+ */
+ void onDirInfoReceived(@Nullable WifiP2pDirInfo dirInfo);
+
+ /**
+ * The operation failed.
+ * @param reason The reason for failure.
+ */
+ void onFailure(int reason);
+ }
+
+ /**
+ * Get the Device Identity Resolution (DIR) Information.
+ * See {@link WifiP2pDirInfo} for details
+ *
+ * Note: The results callback returns null if the device doesn't have any persistent group
+ * with device identity key information.
+ *
+ * <p>
+ * Use {@link #isWiFiDirectR2Supported()} to determine whether the device supports
+ * this feature. If {@link #isWiFiDirectR2Supported()} return {@code false} then
+ * this method will throw {@link UnsupportedOperationException}.
+ * <p>
+ * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
+ * android:usesPermissionFlags="neverForLocation". If the application does not declare
+ * android:usesPermissionFlags="neverForLocation", then it must also have
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ *
+ * @param c It is the channel created at {@link #initialize}.
+ * @param executor The executor on which callback will be invoked.
+ * @param callback An OutcomeReceiver callback for receiving {@link WifiP2pDirInfo} via
+ * {@link OutcomeReceiver#onResult(Object)}. This callback will return
+ * null when DIR info doesn't exist.
+ * When this API call fails due to permission issues, state machine
+ * is busy etc., {@link OutcomeReceiver#onError(Throwable)} is called.
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.NEARBY_WIFI_DEVICES,
+ android.Manifest.permission.ACCESS_FINE_LOCATION
+ }, conditional = true)
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public void requestDirInfo(@NonNull Channel c, @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<WifiP2pDirInfo, Exception> callback) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ if (!isWiFiDirectR2Supported()) {
+ throw new UnsupportedOperationException();
+ }
+ Objects.requireNonNull(c, "channel cannot be null and needs to be initialized)");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
+ Bundle extras = prepareExtrasBundle(c);
+ c.mAsyncChannel.sendMessage(prepareMessage(GET_DIR_INFO, 0,
+ c.putListener(new WifiP2pDirInfoListener() {
+ @Override
+ public void onDirInfoReceived(WifiP2pDirInfo result) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ callback.onResult(result);
+ });
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ callback.onError(reasonCodeToException(reason));
+ });
+ }
+ }), extras, c.mContext));
+ }
+
+ /**
+ * Interface for callback invocation when the received DIR information is validated
+ * in response to {@link #validateDirInfo}.
+ * @hide
+ */
+ public interface WifiP2pDirInfoValidationListener {
+ /**
+ * The requested DIR information is validated.
+ * @param result True if a match is found, false otherwise.
+ */
+ void onDirInfoValidation(boolean result);
+
+ /**
+ * The operation failed.
+ * @param reason The reason for failure.
+ */
+ void onFailure(int reason);
+ }
+
+ /**
+ * Validate the Device Identity Resolution (DIR) Information of a P2P device.
+ * See {@link WifiP2pDirInfo} for details.
+ * Framework takes the {@link WifiP2pDirInfo} and derives a set of Tag values based on
+ * the cached Device Identity Keys (DevIK) of all paired peers saved in the device.
+ * If a derived Tag value matches the Tag value received in the {@link WifiP2pDirInfo}, the
+ * device is identified as a paired peer and returns true.
+ *
+ * <p>
+ * Use {@link #isWiFiDirectR2Supported()} to determine whether the device supports
+ * this feature. If {@link #isWiFiDirectR2Supported()} return {@code false} then
+ * this method will throw {@link UnsupportedOperationException}.
+ * <p>
+ * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
+ * android:usesPermissionFlags="neverForLocation". If the application does not declare
+ * android:usesPermissionFlags="neverForLocation", then it must also have
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ *
+ * @param c It is the channel created at {@link #initialize}.
+ * @param dirInfo {@link WifiP2pDirInfo} to validate.
+ * @param executor The executor on which callback will be invoked.
+ * @param callback An OutcomeReceiver callback for receiving the result via
+ * {@link OutcomeReceiver#onResult(Object)} indicating whether the DIR
+ * info of P2P device is of a paired device. {code true} for paired,
+ * {@code false} for not paired.
+ * When this API call fails due to permission issues, state machine
+ * is busy etc., {@link OutcomeReceiver#onError(Throwable)} is called.
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.NEARBY_WIFI_DEVICES,
+ android.Manifest.permission.ACCESS_FINE_LOCATION
+ }, conditional = true)
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public void validateDirInfo(@NonNull Channel c, @NonNull WifiP2pDirInfo dirInfo,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Boolean, Exception> callback) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ if (!isWiFiDirectR2Supported()) {
+ throw new UnsupportedOperationException();
+ }
+ Objects.requireNonNull(c, "channel cannot be null and needs to be initialized)");
+ Objects.requireNonNull(dirInfo, "dirInfo cannot be null");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(callback, "resultsCallback cannot be null");
+ Bundle extras = prepareExtrasBundle(c);
+
+ extras.putParcelable(EXTRA_PARAM_KEY_DIR_INFO, dirInfo);
+ c.mAsyncChannel.sendMessage(prepareMessage(VALIDATE_DIR_INFO, 0,
+ c.putListener(new WifiP2pDirInfoValidationListener() {
+ @Override
+ public void onDirInfoValidation(boolean result) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ callback.onResult(result);
+ });
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ callback.onError(reasonCodeToException(reason));
+ });
+ }
+ }), extras, c.mContext));
+ }
}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pPairingBootstrappingConfig.java b/framework/java/android/net/wifi/p2p/WifiP2pPairingBootstrappingConfig.java
index 80d0fb14d4..4579cd2261 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pPairingBootstrappingConfig.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pPairingBootstrappingConfig.java
@@ -69,6 +69,12 @@ public final class WifiP2pPairingBootstrappingConfig implements Parcelable {
*/
public static final int PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PASSPHRASE = 1 << 4;
+ /**
+ * Pairing bootstrapping done out of band (For example: Over Bluetooth LE.
+ * Refer Wi-Fi Alliance Wi-Fi Direct R2 specification Section 3.9 for the details).
+ */
+ public static final int PAIRING_BOOTSTRAPPING_METHOD_OUT_OF_BAND = 1 << 5;
+
/** @hide */
@IntDef(flag = true, prefix = {"PAIRING_BOOTSTRAPPING_METHOD_"}, value = {
@@ -77,6 +83,7 @@ public final class WifiP2pPairingBootstrappingConfig implements Parcelable {
PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PASSPHRASE,
PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PINCODE,
PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PASSPHRASE,
+ PAIRING_BOOTSTRAPPING_METHOD_OUT_OF_BAND,
})
@Retention(RetentionPolicy.SOURCE)
public @interface PairingBootstrappingMethod {
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
index 3317d1e2ab..b11daabac5 100644
--- a/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
@@ -462,4 +462,27 @@ public class WifiP2pConfigTest {
assertNotNull(pairingBootstrappingConfig);
assertEquals(expectedPairingBootstrappingConfig, pairingBootstrappingConfig);
}
+
+ /**
+ * Verify that a config with the request to authorize a connection request from a peer device
+ * can be built.
+ */
+ @Test
+ public void testBuildConfigWithAuthorizeConnectionFromPeer() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pPairingBootstrappingConfig expectedPairingBootstrappingConfig =
+ new WifiP2pPairingBootstrappingConfig(WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_OUT_OF_BAND, "1234");
+ WifiP2pConfig c = new WifiP2pConfig.Builder()
+ .setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setPairingBootstrappingConfig(expectedPairingBootstrappingConfig)
+ .setGroupOperatingFrequency(2437)
+ .setAuthorizeConnectionFromPeer(true)
+ .build();
+ WifiP2pPairingBootstrappingConfig pairingBootstrappingConfig =
+ c.getPairingBootstrappingConfig();
+ assertNotNull(pairingBootstrappingConfig);
+ assertEquals(expectedPairingBootstrappingConfig, pairingBootstrappingConfig);
+ assertTrue(c.isAuthorizeConnectionFromPeer());
+ }
}
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pDirInfoTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pDirInfoTest.java
new file mode 100644
index 0000000000..f032fbeaba
--- /dev/null
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pDirInfoTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 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.net.wifi.p2p;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.net.MacAddress;
+import android.net.wifi.util.Environment;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+/**
+ * Unit tests for {@link WifiP2pDirInfo}
+ */
+@SmallTest
+public final class WifiP2pDirInfoTest {
+ private static final String TEST_MAC_ADDRESS_STRING = "00:11:22:33:44:55";
+ private static final byte[] TEST_NONCE = {10, 20, 30, 40, 50, 60, 70, 80};
+ private static final byte[] TEST_DIR_TAG = {11, 22, 33, 44, 55, 66, 77, 88};
+ @Test
+ public void testWifiP2pDirInfo() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pDirInfo dirInfo = new WifiP2pDirInfo(
+ MacAddress.fromString(TEST_MAC_ADDRESS_STRING), TEST_NONCE, TEST_DIR_TAG);
+ assertNotNull(dirInfo);
+ assertEquals(MacAddress.fromString(TEST_MAC_ADDRESS_STRING), dirInfo.getMacAddress());
+ assertArrayEquals(TEST_NONCE, dirInfo.getNonce());
+ assertArrayEquals(TEST_DIR_TAG, dirInfo.getDirTag());
+ }
+}
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pGroupTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pGroupTest.java
index c617606891..4cb9785fa1 100644
--- a/framework/tests/src/android/net/wifi/p2p/WifiP2pGroupTest.java
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pGroupTest.java
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.net.InetAddresses;
import android.net.MacAddress;
@@ -52,6 +53,8 @@ public class WifiP2pGroupTest {
private static final int FREQUENCY = 5300;
private static final String CLIENT_1_DEV_ADDRESS = "aa:bb:cc:dd:ee:01";
private static final String CLIENT_2_DEV_ADDRESS = "aa:bb:cc:dd:ee:02";
+ private static final byte[] GROUP_OWNER_INTERFACE_ADDRESS =
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
private static final WifiP2pDevice CLIENT_1 = new WifiP2pDevice(CLIENT_1_DEV_ADDRESS);
private static final WifiP2pDevice CLIENT_2 = new WifiP2pDevice(CLIENT_2_DEV_ADDRESS);
private static final MacAddress CLIENT_1_INTERFACE_MAC_ADDRESS =
@@ -144,4 +147,16 @@ public class WifiP2pGroupTest {
assertEquals(group.toString(), fromParcel.toString());
}
+
+ /** Verify {@link WifiP2pGroup#getGroupOwnerBssid()} */
+ @Test
+ public void testGetGroupOwnerBssid() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pGroup group = new WifiP2pGroup();
+ group.setIsGroupOwner(true);
+ group.interfaceAddress = GROUP_OWNER_INTERFACE_ADDRESS;
+ group.setSecurityType(WifiP2pGroup.SECURITY_TYPE_WPA3_SAE);
+ assertEquals(MacAddress.fromBytes(GROUP_OWNER_INTERFACE_ADDRESS),
+ group.getGroupOwnerBssid());
+ }
}
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index eb082213ce..19456d644d 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
@@ -664,6 +664,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
case WifiP2pManager.REMOVE_EXTERNAL_APPROVER:
case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT:
case WifiP2pManager.SET_VENDOR_ELEMENTS:
+ case WifiP2pManager.GET_DIR_INFO:
+ case WifiP2pManager.VALIDATE_DIR_INFO:
mP2pStateMachine.sendMessage(Message.obtain(msg));
break;
default:
@@ -1917,6 +1919,10 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
return "WifiP2pManager.SET_VENDOR_ELEMENTS";
case P2P_REJECTION_RESUME_AFTER_DELAY:
return "P2P_REJECTION_RESUME_AFTER_DELAY";
+ case WifiP2pManager.GET_DIR_INFO:
+ return "WifiP2pManager.GET_DIR_INFO";
+ case WifiP2pManager.VALIDATE_DIR_INFO:
+ return "WifiP2pManager.VALIDATE_DIR_INFO";
case RunnerState.STATE_ENTER_CMD:
return "Enter";
case RunnerState.STATE_EXIT_CMD:
@@ -3562,7 +3568,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
case SET_MIRACAST_MODE:
mWifiNative.setMiracastMode(message.arg1);
break;
- case WifiP2pManager.START_LISTEN:
+ case WifiP2pManager.START_LISTEN: {
String packageName = getCallingPkgName(message.sendingUid, message.replyTo);
if (packageName == null) {
replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
@@ -3579,10 +3585,10 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
.getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE);
WifiP2pExtListenParams extListenParams = SdkLevel.isAtLeastV()
&& (listenType == WifiP2pManager.WIFI_P2P_EXT_LISTEN_WITH_PARAMS)
- ? extras.getParcelable(
- WifiP2pManager.EXTRA_PARAM_KEY_EXT_LISTEN_PARAMS,
- WifiP2pExtListenParams.class)
- : null;
+ ? extras.getParcelable(
+ WifiP2pManager.EXTRA_PARAM_KEY_EXT_LISTEN_PARAMS,
+ WifiP2pExtListenParams.class)
+ : null;
boolean hasPermission;
if (isPlatformOrTargetSdkLessThanT(packageName, uid)) {
hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect(
@@ -3613,6 +3619,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
}
break;
+ }
case WifiP2pManager.STOP_LISTEN:
mLastCallerInfoManager.put(WifiManager.API_P2P_STOP_LISTENING,
Process.myTid(), message.sendingUid, 0,
@@ -3673,6 +3680,37 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
}
updateP2pChannels();
break;
+ case WifiP2pManager.GET_DIR_INFO: {
+ String packageName = getCallingPkgName(message.sendingUid, message.replyTo);
+ if (packageName == null) {
+ replyToMessage(message, WifiP2pManager.GET_DIR_INFO_FAILED);
+ break;
+ }
+ if (!Environment.isSdkAtLeastB()
+ || !checkNearbyDevicesPermission(message, "GET_DIR_INFO")) {
+ replyToMessage(message, WifiP2pManager.GET_DIR_INFO_FAILED);
+ break;
+ }
+ // TODO implementation
+ replyToMessage(message, WifiP2pManager.RESPONSE_GET_DIR_INFO, null);
+ break;
+ }
+ case WifiP2pManager.VALIDATE_DIR_INFO: {
+ String packageName = getCallingPkgName(message.sendingUid, message.replyTo);
+ if (packageName == null) {
+ replyToMessage(message, WifiP2pManager.VALIDATE_DIR_INFO_FAILED);
+ break;
+ }
+ if (!Environment.isSdkAtLeastB()
+ || !checkNearbyDevicesPermission(message,
+ "VALIDATE_DIR_INFO")) {
+ replyToMessage(message, WifiP2pManager.VALIDATE_DIR_INFO_FAILED);
+ break;
+ }
+ // TODO implementation
+ replyToMessage(message, WifiP2pManager.RESPONSE_VALIDATE_DIR_INFO, 0);
+ break;
+ }
default:
return NOT_HANDLED;
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
index 6b2b59eb8a..1298be08b0 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
@@ -109,6 +109,7 @@ import android.net.wifi.p2p.WifiP2pProvDiscEvent;
import android.net.wifi.p2p.WifiP2pWfdInfo;
import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
+import android.net.wifi.util.Environment;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -8636,4 +8637,48 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
verify(mWifiNative).teardownInterface();
verify(mWifiMonitor).stopMonitoring(anyString());
}
+
+ /**
+ * Verify {@link WifiP2pManager#GET_DIR_INFO} message.
+ */
+ @Test
+ public void testGetDirInfo() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ forceP2pEnabled(mClient1);
+ when(mWifiPermissionsUtil.checkNearbyDevicesPermission(any(), anyBoolean(), any()))
+ .thenReturn(false);
+ sendSimpleMsg(mClientMessenger, WifiP2pManager.GET_DIR_INFO);
+ assertTrue(mClientHandler.hasMessages(WifiP2pManager.GET_DIR_INFO_FAILED));
+
+ when(mWifiPermissionsUtil.checkNearbyDevicesPermission(any(), anyBoolean(), any()))
+ .thenReturn(true);
+ sendSimpleMsg(mClientMessenger, WifiP2pManager.GET_DIR_INFO);
+
+ verify(mClientHandler, times(2)).sendMessage(mMessageCaptor.capture());
+ List<Message> messages = mMessageCaptor.getAllValues();
+ assertEquals(WifiP2pManager.GET_DIR_INFO_FAILED, messages.get(0).what);
+ assertEquals(WifiP2pManager.RESPONSE_GET_DIR_INFO, messages.get(1).what);
+ }
+
+ /**
+ * Verify {@link WifiP2pManager#VALIDATE_DIR_INFO} message.
+ */
+ @Test
+ public void testValidateDirInfo() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ forceP2pEnabled(mClient1);
+ when(mWifiPermissionsUtil.checkNearbyDevicesPermission(any(), anyBoolean(), any()))
+ .thenReturn(false);
+ sendSimpleMsg(mClientMessenger, WifiP2pManager.VALIDATE_DIR_INFO);
+ assertTrue(mClientHandler.hasMessages(WifiP2pManager.VALIDATE_DIR_INFO_FAILED));
+
+ when(mWifiPermissionsUtil.checkNearbyDevicesPermission(any(), anyBoolean(), any()))
+ .thenReturn(true);
+ sendSimpleMsg(mClientMessenger, WifiP2pManager.VALIDATE_DIR_INFO);
+
+ verify(mClientHandler, times(2)).sendMessage(mMessageCaptor.capture());
+ List<Message> messages = mMessageCaptor.getAllValues();
+ assertEquals(WifiP2pManager.VALIDATE_DIR_INFO_FAILED, messages.get(0).what);
+ assertEquals(WifiP2pManager.RESPONSE_VALIDATE_DIR_INFO, messages.get(1).what);
+ }
}