diff options
4 files changed, 221 insertions, 52 deletions
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java index 59fe1ee6bc80..156c3fdf336c 100644 --- a/wifi/java/android/net/wifi/aware/DiscoverySession.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java @@ -116,6 +116,7 @@ public class DiscoverySession { Log.w(TAG, "terminate: already terminated."); return; } + mTerminated = true; mMgr.clear(); mCloseGuard.close(); @@ -172,15 +173,15 @@ public class DiscoverySession { if (mTerminated) { Log.w(TAG, "sendMessage: called on terminated session"); return; - } else { - WifiAwareManager mgr = mMgr.get(); - if (mgr == null) { - Log.w(TAG, "sendMessage: called post GC on WifiAwareManager"); - return; - } + } - mgr.sendMessage(mClientId, mSessionId, peerHandle, message, messageId, retryCount); + WifiAwareManager mgr = mMgr.get(); + if (mgr == null) { + Log.w(TAG, "sendMessage: called post GC on WifiAwareManager"); + return; } + + mgr.sendMessage(mClientId, mSessionId, peerHandle, message, messageId, retryCount); } /** @@ -235,15 +236,15 @@ public class DiscoverySession { if (mTerminated) { Log.w(TAG, "startRanging: called on terminated session"); return; - } else { - WifiAwareManager mgr = mMgr.get(); - if (mgr == null) { - Log.w(TAG, "startRanging: called post GC on WifiAwareManager"); - return; - } + } - mgr.startRanging(mClientId, mSessionId, params, listener); + WifiAwareManager mgr = mMgr.get(); + if (mgr == null) { + Log.w(TAG, "startRanging: called post GC on WifiAwareManager"); + return; } + + mgr.startRanging(mClientId, mSessionId, params, listener); } /** @@ -261,6 +262,9 @@ public class DiscoverySession { * <p> * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR * and a Publisher is a RESPONDER. + * <p> + * To set up an encrypted link use the {@link #createNetworkSpecifierPmk(PeerHandle, byte[])} + * or {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} APIs. * * @param peerHandle The peer's handle obtained through * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)} @@ -282,19 +286,81 @@ public class DiscoverySession { if (mTerminated) { Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session"); return null; - } else { - WifiAwareManager mgr = mMgr.get(); - if (mgr == null) { - Log.w(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager"); - return null; - } + } + + WifiAwareManager mgr = mMgr.get(); + if (mgr == null) { + Log.w(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager"); + return null; + } + + int role = this instanceof SubscribeDiscoverySession + ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR + : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; + + return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null, null); + } + + /** + * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an + * encrypted WiFi Aware connection (link) to the specified peer. The + * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to + * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}. + * <p> + * This method should be used when setting up a connection with a peer discovered through Aware + * discovery or communication (in such scenarios the MAC address of the peer is shielded by + * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other + * OOB (out-of-band) mechanism then use the alternative + * {@link WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)} method - + * which uses the peer's MAC address. + * <p> + * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR + * and a Publisher is a RESPONDER. + * + * @param peerHandle The peer's handle obtained through + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, + * byte[], java.util.List)} or + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, + * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request + * from only that peer. A RESPONDER may specify a null - indicating that + * it will accept connection requests from any device. + * @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from + * the passphrase. Use the + * {@link #createNetworkSpecifierPmk(PeerHandle, byte[])} to specify the + * PMK directly or {@link #createNetworkSpecifierOpen(PeerHandle)} to + * specify an open (unencrypted) link. + * + * @return A string to be used to construct + * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to + * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, + * android.net.ConnectivityManager.NetworkCallback)} + * [or other varieties of that API]. + * + * * @hide + */ + public String createNetworkSpecifierPassphrase(@Nullable PeerHandle peerHandle, + @NonNull String passphrase) { + if (passphrase == null || passphrase.length() == 0) { + throw new IllegalArgumentException("Passphrase must not be null or empty"); + } - int role = this instanceof SubscribeDiscoverySession - ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR - : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; + if (mTerminated) { + Log.w(TAG, "createNetworkSpecifierPassphrase: called on terminated session"); + return null; + } - return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null); + WifiAwareManager mgr = mMgr.get(); + if (mgr == null) { + Log.w(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager"); + return null; } + + int role = this instanceof SubscribeDiscoverySession + ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR + : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; + + return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null, + passphrase); } /** @@ -307,8 +373,8 @@ public class DiscoverySession { * discovery or communication (in such scenarios the MAC address of the peer is shielded by * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other * OOB (out-of-band) mechanism then use the alternative - * {@link WifiAwareSession#createNetworkSpecifierPmk(int, byte[], byte[])} method - which uses the - * peer's MAC address. + * {@link WifiAwareSession#createNetworkSpecifierPmk(int, byte[], byte[])} method - which uses + * the peer's MAC address. * <p> * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR * and a Publisher is a RESPONDER. @@ -322,8 +388,9 @@ public class DiscoverySession { * it will accept connection requests from any device. * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for * encrypting the data-path. Use the - * {@link #createNetworkSpecifierOpen(PeerHandle)} to specify an open (unencrypted) - * link. + * {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} to specify a + * Passphrase or {@link #createNetworkSpecifierOpen(PeerHandle)} to specify an + * open (unencrypted) link. * * @return A string to be used to construct * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to @@ -342,19 +409,19 @@ public class DiscoverySession { if (mTerminated) { Log.w(TAG, "createNetworkSpecifierPmk: called on terminated session"); return null; - } else { - WifiAwareManager mgr = mMgr.get(); - if (mgr == null) { - Log.w(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager"); - return null; - } - - int role = this instanceof SubscribeDiscoverySession - ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR - : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; + } - return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, pmk); + WifiAwareManager mgr = mMgr.get(); + if (mgr == null) { + Log.w(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager"); + return null; } + + int role = this instanceof SubscribeDiscoverySession + ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR + : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; + + return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, pmk, null); } /** diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java index 3d784ba02fd6..7b6805c3da92 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java @@ -130,26 +130,26 @@ public class WifiAwareManager { */ /** - * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk optional + * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional * @hide */ public static final int NETWORK_SPECIFIER_TYPE_IB = 0; /** - * TYPE: in band, any peer: role, client_id, session_id, pmk optional + * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional * [only permitted for RESPONDER] * @hide */ public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1; /** - * TYPE: out-of-band: role, client_id, peer_mac, pmk optional + * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional * @hide */ public static final int NETWORK_SPECIFIER_TYPE_OOB = 2; /** - * TYPE: out-of-band, any peer: role, client_id, pmk optional + * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional * [only permitted for RESPONDER] * @hide */ @@ -180,6 +180,9 @@ public class WifiAwareManager { /** @hide */ public static final String NETWORK_SPECIFIER_KEY_PMK = "pmk"; + /** @hide */ + public static final String NETWORK_SPECIFIER_KEY_PASSPHRASE = "passphrase"; + /** * Broadcast intent action to indicate that the state of Wi-Fi Aware availability has changed. * Use the {@link #isAvailable()} to query the current status. @@ -473,11 +476,12 @@ public class WifiAwareManager { /** @hide */ public String createNetworkSpecifier(int clientId, int role, int sessionId, - PeerHandle peerHandle, @Nullable byte[] pmk) { + PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) { if (VDBG) { Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId + ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId) - + ", pmk=" + ((pmk == null) ? "null" : "non-null")); + + ", pmk=" + ((pmk == null) ? "null" : "non-null") + + ", passphrase=" + ((passphrase == null) ? "null" : "non-null")); } int type = (peerHandle == null) ? NETWORK_SPECIFIER_TYPE_IB_ANY_PEER @@ -512,6 +516,11 @@ public class WifiAwareManager { } json.put(NETWORK_SPECIFIER_KEY_PMK, Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT)); + if (passphrase == null) { + passphrase = new String(); + } + json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase); + } catch (JSONException e) { return ""; } @@ -521,10 +530,11 @@ public class WifiAwareManager { /** @hide */ public String createNetworkSpecifier(int clientId, @DataPathRole int role, - @Nullable byte[] peer, @Nullable byte[] pmk) { + @Nullable byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) { if (VDBG) { Log.v(TAG, "createNetworkSpecifier: role=" + role - + ", pmk=" + ((pmk == null) ? "null" : "non-null")); + + ", pmk=" + ((pmk == null) ? "null" : "non-null") + + ", passphrase=" + ((passphrase == null) ? "null" : "non-null")); } int type = (peer == null) ? @@ -560,6 +570,10 @@ public class WifiAwareManager { } json.put(NETWORK_SPECIFIER_KEY_PMK, Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT)); + if (passphrase == null) { + passphrase = new String(); + } + json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase); } catch (JSONException e) { return ""; } diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java index 856066efff62..f48f64184bfb 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java @@ -192,6 +192,9 @@ public class WifiAwareSession { * (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer - * when using Aware discovery use the alternative network specifier method - * {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)}. + * <p> + * To set up an encrypted link use the {@link #createNetworkSpecifierPmk(int, byte[], byte[])} + * or {@link #createNetworkSpecifierPassphrase(int, byte[], String)} APIs. * * @param role The role of this device: * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or @@ -220,7 +223,56 @@ public class WifiAwareSession { Log.e(TAG, "createNetworkSpecifierOpen: called after termination"); return ""; } - return mgr.createNetworkSpecifier(mClientId, role, peer, null); + return mgr.createNetworkSpecifier(mClientId, role, peer, null, null); + } + + /** + * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an + * encrypted WiFi Aware connection (link) to the specified peer. The + * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to + * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}. + * <p> + * This API is targeted for applications which can obtain the peer MAC address using OOB + * (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer - + * when using Aware discovery use the alternative network specifier method - + * {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}. + * + * @param role The role of this device: + * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or + * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER} + * @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this + * value is used to gate the acceptance of a connection request from only that + * peer. A RESPONDER may specify a null - indicating that it will accept + * connection requests from any device. + * @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from + * the passphrase. Use the + * {@link #createNetworkSpecifierPmk(int, byte[], byte[])} to specify the + * PMK directly or {@link #createNetworkSpecifierOpen(int, byte[])} to + * specify an open (unencrypted) link. + * + * @return A string to be used to construct + * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to + * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, + * android.net.ConnectivityManager.NetworkCallback)} + * [or other varieties of that API]. + * + * @hide + */ + public String createNetworkSpecifierPassphrase(@WifiAwareManager.DataPathRole int role, + @Nullable byte[] peer, @NonNull String passphrase) { + WifiAwareManager mgr = mMgr.get(); + if (mgr == null) { + Log.e(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager"); + return ""; + } + if (mTerminated) { + Log.e(TAG, "createNetworkSpecifierPassphrase: called after termination"); + return ""; + } + if (passphrase == null || passphrase.length() == 0) { + throw new IllegalArgumentException("Passphrase must not be null or empty"); + } + return mgr.createNetworkSpecifier(mClientId, role, peer, null, passphrase); } /** @@ -232,7 +284,7 @@ public class WifiAwareSession { * This API is targeted for applications which can obtain the peer MAC address using OOB * (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer - * when using Aware discovery use the alternative network specifier method - - * {@link DiscoverySession#createNetworkSpecifierPmk(PeerHandle, byte[])}}. + * {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}. * * @param role The role of this device: * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or @@ -242,8 +294,10 @@ public class WifiAwareSession { * peer. A RESPONDER may specify a null - indicating that it will accept * connection requests from any device. * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for - * encrypting the data-path. Use the {@link #createNetworkSpecifierOpen(int, byte[])} - * to specify an open (unencrypted) link. + * encrypting the data-path. Use the + * {@link #createNetworkSpecifierPassphrase(int, byte[], String)} to specify a + * Passphrase or {@link #createNetworkSpecifierOpen(int, byte[])} to specify an + * open (unencrypted) link. * * @return A string to be used to construct * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to @@ -267,7 +321,7 @@ public class WifiAwareSession { if (pmk == null || pmk.length == 0) { throw new IllegalArgumentException("PMK must not be null or empty"); } - return mgr.createNetworkSpecifier(mClientId, role, peer, pmk); + return mgr.createNetworkSpecifier(mClientId, role, peer, pmk, null); } /** diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java index 992958b84e1a..eceb3658d1d6 100644 --- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java @@ -974,6 +974,7 @@ public class WifiAwareManagerTest { final PeerHandle peerHandle = new PeerHandle(123412); final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; final byte[] pmk = "Some arbitrary byte array".getBytes(); + final String passphrase = "A really bad password"; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final PublishConfig publishConfig = new PublishConfig.Builder().build(); @@ -1038,6 +1039,23 @@ public class WifiAwareManagerTest { collector.checkThat("pmk", pmkB64 , equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK))); + // (5) request an encrypted (Passphrase) network specifier from the session + networkSpecifier = publishSession.getValue().createNetworkSpecifierPassphrase(peerHandle, + passphrase); + + // validate format + jsonObject = new JSONObject(networkSpecifier); + collector.checkThat("role", role, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE))); + collector.checkThat("client_id", clientId, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID))); + collector.checkThat("session_id", sessionId, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID))); + collector.checkThat("peer_id", peerHandle.peerId, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID))); + collector.checkThat("passphrase", passphrase, + equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE))); + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService, mockPublishSession, mockRttListener); } @@ -1053,6 +1071,7 @@ public class WifiAwareManagerTest { final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false); final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR; final byte[] pmk = "Some arbitrary pmk data".getBytes(); + final String passphrase = "A really bad password"; String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT); @@ -1101,6 +1120,21 @@ public class WifiAwareManagerTest { collector.checkThat("pmk", pmkB64, equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK))); + // (4) request an encrypted (Passphrase) direct network specifier + networkSpecifier = session.createNetworkSpecifierPassphrase(role, someMac, passphrase); + + // validate format + jsonObject = new JSONObject(networkSpecifier); + collector.checkThat("role", role, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE))); + collector.checkThat("client_id", clientId, + equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID))); + collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode( + jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(), + false))); + collector.checkThat("passphrase", passphrase, + equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE))); + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService, mockPublishSession, mockRttListener); } |