diff options
9 files changed, 326 insertions, 311 deletions
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanDiscoverySessionCallback.aidl b/wifi/java/android/net/wifi/nan/IWifiNanDiscoverySessionCallback.aidl index 8c1b892f6730..f2e371dd74f9 100644 --- a/wifi/java/android/net/wifi/nan/IWifiNanDiscoverySessionCallback.aidl +++ b/wifi/java/android/net/wifi/nan/IWifiNanDiscoverySessionCallback.aidl @@ -23,7 +23,7 @@ package android.net.wifi.nan; */ oneway interface IWifiNanDiscoverySessionCallback { - void onSessionStarted(int sessionId); + void onSessionStarted(int discoverySessionId); void onSessionConfigSuccess(); void onSessionConfigFail(int reason); void onSessionTerminated(int reason); diff --git a/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl b/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl index a4e590beca59..9ac7bf24e18e 100644 --- a/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl +++ b/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl @@ -26,7 +26,7 @@ import android.net.wifi.RttManager; */ oneway interface IWifiNanEventCallback { - void onConnectSuccess(); + void onConnectSuccess(int clientId); void onConnectFail(int reason); void onIdentityChanged(in byte[] mac); diff --git a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl index 4711bad31f12..4e1f607e0902 100644 --- a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl +++ b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl @@ -38,7 +38,7 @@ interface IWifiNanManager boolean isUsageEnabled(); // client API - int connect(in IBinder binder, in String callingPackage, in IWifiNanEventCallback callback, + void connect(in IBinder binder, in String callingPackage, in IWifiNanEventCallback callback, in ConfigRequest configRequest); void disconnect(int clientId, in IBinder binder); @@ -48,10 +48,10 @@ interface IWifiNanManager in IWifiNanDiscoverySessionCallback callback); // session API - void updatePublish(int clientId, int sessionId, in PublishConfig publishConfig); - void updateSubscribe(int clientId, int sessionId, in SubscribeConfig subscribeConfig); - void sendMessage(int clientId, int sessionId, int peerId, in byte[] message, int messageId, + void updatePublish(int clientId, int discoverySessionId, in PublishConfig publishConfig); + void updateSubscribe(int clientId, int discoverySessionId, in SubscribeConfig subscribeConfig); + void sendMessage(int clientId, int discoverySessionId, int peerId, in byte[] message, int messageId, int retryCount); - void terminateSession(int clientId, int sessionId); - int startRanging(int clientId, int sessionId, in RttManager.ParcelableRttParams parms); + void terminateSession(int clientId, int discoverySessionId); + int startRanging(int clientId, int discoverySessionId, in RttManager.ParcelableRttParams parms); } diff --git a/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java b/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java index 58971dbdae28..c2f373595ff5 100644 --- a/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java +++ b/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java @@ -50,6 +50,8 @@ public class WifiNanDiscoveryBaseSession { /** @hide */ protected WeakReference<WifiNanManager> mMgr; /** @hide */ + protected final int mClientId; + /** @hide */ protected final int mSessionId; /** @hide */ protected boolean mTerminated = false; @@ -67,10 +69,14 @@ public class WifiNanDiscoveryBaseSession { } /** @hide */ - public WifiNanDiscoveryBaseSession(WifiNanManager manager, int sessionId) { - if (VDBG) Log.v(TAG, "New client created: manager=" + manager + ", sessionId=" + sessionId); + public WifiNanDiscoveryBaseSession(WifiNanManager manager, int clientId, int sessionId) { + if (VDBG) { + Log.v(TAG, "New discovery session created: manager=" + manager + ", clientId=" + + clientId + ", sessionId=" + sessionId); + } mMgr = new WeakReference<>(manager); + mClientId = clientId; mSessionId = sessionId; mCloseGuard.open("terminate"); @@ -93,7 +99,7 @@ public class WifiNanDiscoveryBaseSession { Log.w(TAG, "terminate: called post GC on WifiNanManager"); return; } - mgr.terminateSession(mSessionId); + mgr.terminateSession(mClientId, mSessionId); mTerminated = true; mMgr.clear(); mCloseGuard.close(); @@ -166,7 +172,7 @@ public class WifiNanDiscoveryBaseSession { return; } - mgr.sendMessage(mSessionId, peerId, message, messageId, retryCount); + mgr.sendMessage(mClientId, mSessionId, peerId, message, messageId, retryCount); } } @@ -223,7 +229,7 @@ public class WifiNanDiscoveryBaseSession { return; } - mgr.startRanging(mSessionId, params, listener); + mgr.startRanging(mClientId, mSessionId, params, listener); } } @@ -237,7 +243,7 @@ public class WifiNanDiscoveryBaseSession { * discovery or communication (in such scenarios the MAC address of the peer is shielded by * an opaque peer ID handle). If a NAN connection is needed to a peer discovered using other * OOB (out-of-band) mechanism then use the alternative - * {@link WifiNanManager#createNetworkSpecifier(int, byte[], byte[])} method - which uses the + * {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])} method - which uses the * peer's MAC address. * * @param role The role of this device: @@ -272,7 +278,7 @@ public class WifiNanDiscoveryBaseSession { return null; } - return mgr.createNetworkSpecifier(role, mSessionId, peerId, token); + return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerId, token); } } } diff --git a/wifi/java/android/net/wifi/nan/WifiNanEventCallback.java b/wifi/java/android/net/wifi/nan/WifiNanEventCallback.java index a66afc189c4c..28c5ca29ea43 100644 --- a/wifi/java/android/net/wifi/nan/WifiNanEventCallback.java +++ b/wifi/java/android/net/wifi/nan/WifiNanEventCallback.java @@ -62,8 +62,11 @@ public class WifiNanEventCallback { * Called when NAN connect operation * {@link WifiNanManager#connect(android.os.Handler, WifiNanEventCallback)} * is completed and that we can now start discovery sessions or connections. + * + * @param session The NAN connection on which we can execute further NAN operations - e.g. + * discovery, connections. */ - public void onConnectSuccess() { + public void onConnectSuccess(WifiNanSession session) { /* empty */ } diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java index 6eb476d229ad..b300d81db4cb 100644 --- a/wifi/java/android/net/wifi/nan/WifiNanManager.java +++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java @@ -28,7 +28,6 @@ import android.net.wifi.RttManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; -import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.RemoteException; @@ -38,8 +37,6 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; -import dalvik.system.CloseGuard; - import libcore.util.HexEncoding; import org.json.JSONException; @@ -59,15 +56,15 @@ import java.util.Arrays; * The class provides access to: * <ul> * <li>Initialize a NAN cluster (peer-to-peer synchronization). Refer to - * {@link #connect(Handler, WifiNanEventCallback)}. - * <li>Create discovery sessions (publish or subscribe sessions). - * Refer to {@link #publish(PublishConfig, WifiNanDiscoverySessionCallback)} and - * {@link #subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)}. - * <li>Create a NAN network specifier to be used with + * {@link #connect(Handler, WifiNanEventCallback)}. <li>Create discovery sessions (publish or + * subscribe sessions). Refer to + * {@link WifiNanSession#publish(PublishConfig, WifiNanDiscoverySessionCallback)} and + * {@link WifiNanSession#subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)}. <li>Create + * a NAN network specifier to be used with * {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)} * to set-up a NAN connection with a peer. Refer to * {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])} and - * {@link #createNetworkSpecifier(int, byte[], byte[])}. + * {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])}. * </ul> * <p> * NAN may not be usable when Wi-Fi is disabled (and other conditions). To validate that @@ -82,16 +79,16 @@ import java.util.Arrays; * starts one if none can be found). Information about connection success (or failure) are * returned in callbacks of {@link WifiNanEventCallback}. Proceed with NAN discovery or * connection setup only after receiving confirmation that NAN connection succeeded - - * {@link WifiNanEventCallback#onConnectSuccess()}. - * When an application is finished using NAN it <b>must</b> use the {@link #disconnect()} API + * {@link WifiNanEventCallback#onConnectSuccess(WifiNanSession)}. When an application is + * finished using NAN it <b>must</b> use the {@link WifiNanSession#disconnect()} API * to indicate to the NAN service that the device may disconnect from the NAN cluster. The * device will actually disconnect from the NAN cluster once the last application disconnects. * <p> * Once a NAN connection is confirmed use the - * {@link #publish(PublishConfig, WifiNanDiscoverySessionCallback)} or - * {@link #subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)} to create publish or - * subscribe NAN discovery sessions. Events are called on the provided callback object - * {@link WifiNanDiscoverySessionCallback}. Specifically, the + * {@link WifiNanSession#publish(PublishConfig, WifiNanDiscoverySessionCallback)} or + * {@link WifiNanSession#subscribe(SubscribeConfig, WifiNanDiscoverySessionCallback)} to + * create publish or subscribe NAN discovery sessions. Events are called on the provided + * callback object {@link WifiNanDiscoverySessionCallback}. Specifically, the * {@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)} * and * {@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)} @@ -111,7 +108,7 @@ import java.util.Arrays; * <li>{@link NetworkRequest.Builder#addTransportType(int)} of * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_NAN}. * <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using - * {@link #createNetworkSpecifier(int, byte[], byte[])} or + * {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])} or * {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])}. * </ul> * @@ -122,8 +119,6 @@ public class WifiNanManager { private static final boolean DBG = false; private static final boolean VDBG = false; // STOPSHIP if true - private static final int INVALID_CLIENT_ID = 0; - /** * Keys used to generate a Network Specifier for the NAN network request. The network specifier * is formatted as a JSON string. @@ -251,7 +246,7 @@ public class WifiNanManager { * when requesting a NAN network. * * @see WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[]) - * @see #createNetworkSpecifier(int, byte[], byte[]) + * @see WifiNanSession#createNetworkSpecifier(int, byte[], byte[]) */ public static final int WIFI_NAN_DATA_PATH_ROLE_INITIATOR = 0; @@ -260,26 +255,16 @@ public class WifiNanManager { * when requesting a NAN network. * * @see WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[]) - * @see #createNetworkSpecifier(int, byte[], byte[]) + * @see WifiNanSession#createNetworkSpecifier(int, byte[], byte[]) */ public static final int WIFI_NAN_DATA_PATH_ROLE_RESPONDER = 1; private final Context mContext; private final IWifiNanManager mService; - private final CloseGuard mCloseGuard = CloseGuard.get(); private final Object mLock = new Object(); // lock access to the following vars @GuardedBy("mLock") - private final IBinder mBinder = new Binder(); - - @GuardedBy("mLock") - private int mClientId = INVALID_CLIENT_ID; - - @GuardedBy("mLock") - private Looper mLooper; - - @GuardedBy("mLock") private SparseArray<RttManager.RttListener> mRangingListeners = new SparseArray<>(); /** @hide */ @@ -338,8 +323,8 @@ public class WifiNanManager { * create connection to peers. The device will connect to an existing cluster if it can find * one or create a new cluster (if it is the first to enable NAN in its vicinity). Results * (e.g. successful connection to a cluster) are provided to the {@code callback} object. - * An application <b>must</b> call {@link #disconnect()} when done with the Wi-Fi NAN - * connection. + * An application <b>must</b> call {@link WifiNanSession#disconnect()} when done with the + * Wi-Fi NAN connection. * <p> * Note: a NAN cluster is a shared resource - if the device is already connected to a cluster * than this function will simply indicate success immediately. @@ -358,10 +343,10 @@ public class WifiNanManager { * create connection to peers. The device will connect to an existing cluster if it can find * one or create a new cluster (if it is the first to enable NAN in its vicinity). Results * (e.g. successful connection to a cluster) are provided to the {@code callback} object. - * An application <b>must</b> call {@link #disconnect()} when done with the Wi-Fi NAN - * connection. Allows requesting a specific configuration using {@link ConfigRequest}. If not - * necessary (default configuration should usually work) use the - * {@link #connect(Handler, WifiNanEventCallback)} method instead. + * An application <b>must</b> call {@link WifiNanSession#disconnect()} when done with the + * Wi-Fi NAN connection. Allows requesting a specific configuration using + * {@link ConfigRequest}. If not necessary (default configuration should usually work) use + * the {@link #connect(Handler, WifiNanEventCallback)} method instead. * <p> * Note: a NAN cluster is a shared resource - if the device is already connected to a cluster * than this function will simply indicate success immediately. @@ -381,50 +366,23 @@ public class WifiNanManager { } synchronized (mLock) { - mLooper = (handler == null) ? Looper.getMainLooper() : handler.getLooper(); + Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper(); try { - mClientId = mService.connect(mBinder, mContext.getOpPackageName(), - new WifiNanEventCallbackProxy(this, mLooper, callback), configRequest); + Binder binder = new Binder(); + mService.connect(binder, mContext.getOpPackageName(), + new WifiNanEventCallbackProxy(this, looper, binder, callback), + configRequest); } catch (RemoteException e) { - mClientId = INVALID_CLIENT_ID; - mLooper = null; throw e.rethrowFromSystemServer(); } } - - mCloseGuard.open("disconnect"); } - /** - * Disconnect from the Wi-Fi NAN service and, if no other applications are connected to NAN, - * also disconnect from the NAN cluster. This method destroys all outstanding operations - - * i.e. all publish and subscribes are terminated, and any outstanding data-links are - * shut-down. However, it is good practice to terminate these discovery sessions and - * connections explicitly before a disconnect. - * <p> - * An application may re-connect after a disconnect using - * {@link WifiNanManager#connect(Handler, WifiNanEventCallback)} . - */ - public void disconnect() { + /** @hide */ + public void disconnect(int clientId, Binder binder) { if (VDBG) Log.v(TAG, "disconnect()"); - IBinder binder; - int clientId; - synchronized (mLock) { - if (mClientId == INVALID_CLIENT_ID) { - Log.w(TAG, "disconnect(): called with invalid client ID - not connected first?"); - return; - } - - binder = mBinder; - clientId = mClientId; - - mLooper = null; - mClientId = INVALID_CLIENT_ID; - } - - mCloseGuard.close(); try { mService.disconnect(clientId, binder); } catch (RemoteException e) { @@ -433,78 +391,26 @@ public class WifiNanManager { } /** @hide */ - @Override - protected void finalize() throws Throwable { - try { - mCloseGuard.warnIfOpen(); - disconnect(); - } finally { - super.finalize(); - } - } + public void publish(int clientId, Looper looper, PublishConfig publishConfig, + WifiNanDiscoverySessionCallback callback) { + if (VDBG) Log.v(TAG, "publish(): clientId=" + clientId + ", config=" + publishConfig); - /** - * Issue a request to the NAN service to create a new NAN publish discovery session, using - * the specified {@code publishConfig} configuration. The results of the publish operation - * are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}: - * <ul> - * <li>{@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)} - * is called when the publish session is created and provides a handle to the session. - * Further operations on the publish session can be executed on that object. - * <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFail(int)} is called if the - * publish operation failed. - * </ul> - * <p> - * Other results of the publish session operations will also be routed to callbacks - * on the {@code callback} object. The resulting publish session can be modified using - * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)}. - * <p> - * An application must use the {@link WifiNanDiscoveryBaseSession#terminate()} to - * terminate the publish discovery session once it isn't needed. This will free - * resources as well terminate any on-air transmissions. - * - * @param publishConfig The {@link PublishConfig} specifying the - * configuration of the requested publish session. - * @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for - * session event callbacks. - */ - public void publish(@NonNull PublishConfig publishConfig, - @NonNull WifiNanDiscoverySessionCallback callback) { - if (VDBG) Log.v(TAG, "publish(): config=" + publishConfig); - - int clientId; - Looper looper; - synchronized (mLock) { - if (mLooper == null || mClientId == INVALID_CLIENT_ID) { - Log.e(TAG, "publish(): called with null looper or invalid client ID - " - + "not connected first?"); - return; - } - - clientId = mClientId; - looper = mLooper; - } try { mService.publish(clientId, publishConfig, - new WifiNanDiscoverySessionCallbackProxy(this, looper, true, callback)); + new WifiNanDiscoverySessionCallbackProxy(this, looper, true, callback, + clientId)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @hide */ - public void updatePublish(int sessionId, PublishConfig publishConfig) { - if (VDBG) Log.v(TAG, "updatePublish(): config=" + publishConfig); - - int clientId; - synchronized (mLock) { - if (mClientId == INVALID_CLIENT_ID) { - Log.e(TAG, "updatePublish(): called with invalid client ID - not connected first?"); - return; - } - - clientId = mClientId; + public void updatePublish(int clientId, int sessionId, PublishConfig publishConfig) { + if (VDBG) { + Log.v(TAG, "updatePublish(): clientId=" + clientId + ",sessionId=" + sessionId + + ", config=" + publishConfig); } + try { mService.updatePublish(clientId, sessionId, publishConfig); } catch (RemoteException e) { @@ -512,73 +418,30 @@ public class WifiNanManager { } } - /** - * Issue a request to the NAN service to create a new NAN subscribe discovery session, using - * the specified {@code subscribeConfig} configuration. The results of the subscribe - * operation are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}: - * <ul> - * <li>{@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)} - * is called when the subscribe session is created and provides a handle to the session. - * Further operations on the subscribe session can be executed on that object. - * <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFail(int)} is called if the - * subscribe operation failed. - * </ul> - * <p> - * Other results of the subscribe session operations will also be routed to callbacks - * on the {@code callback} object. The resulting subscribe session can be modified using - * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. - * <p> - * An application must use the {@link WifiNanDiscoveryBaseSession#terminate()} to - * terminate the subscribe discovery session once it isn't needed. This will free - * resources as well terminate any on-air transmissions. - * - * @param subscribeConfig The {@link SubscribeConfig} specifying the - * configuration of the requested subscribe session. - * @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for - * session event callbacks. - */ - public void subscribe(@NonNull SubscribeConfig subscribeConfig, - @NonNull WifiNanDiscoverySessionCallback callback) { + /** @hide */ + public void subscribe(int clientId, Looper looper, SubscribeConfig subscribeConfig, + WifiNanDiscoverySessionCallback callback) { if (VDBG) { - Log.v(TAG, "subscribe(): config=" + subscribeConfig); - } - - int clientId; - Looper looper; - synchronized (mLock) { - if (mLooper == null || mClientId == INVALID_CLIENT_ID) { - Log.e(TAG, "subscribe(): called with null looper or invalid client ID - " - + "not connected first?"); - return; + if (VDBG) { + Log.v(TAG, + "subscribe(): clientId=" + clientId + ", config=" + subscribeConfig); } - - clientId = mClientId; - looper = mLooper; } try { mService.subscribe(clientId, subscribeConfig, - new WifiNanDiscoverySessionCallbackProxy(this, looper, false, callback)); + new WifiNanDiscoverySessionCallbackProxy(this, looper, false, callback, + clientId)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @hide */ - public void updateSubscribe(int sessionId, SubscribeConfig subscribeConfig) { + public void updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig) { if (VDBG) { - Log.v(TAG, "subscribe(): config=" + subscribeConfig); - } - - int clientId; - synchronized (mLock) { - if (mClientId == INVALID_CLIENT_ID) { - Log.e(TAG, - "updateSubscribe(): called with invalid client ID - not connected first?"); - return; - } - - clientId = mClientId; + Log.v(TAG, "updateSubscribe(): clientId=" + clientId + ",sessionId=" + sessionId + + ", config=" + subscribeConfig); } try { @@ -589,18 +452,10 @@ public class WifiNanManager { } /** @hide */ - public void terminateSession(int sessionId) { - if (DBG) Log.d(TAG, "Terminate NAN session #" + sessionId); - - int clientId; - synchronized (mLock) { - if (mClientId == INVALID_CLIENT_ID) { - Log.e(TAG, - "terminateSession(): called with invalid client ID - not connected first?"); - return; - } - - clientId = mClientId; + public void terminateSession(int clientId, int sessionId) { + if (VDBG) { + Log.d(TAG, + "terminateSession(): clientId=" + clientId + ", sessionId=" + sessionId); } try { @@ -611,21 +466,12 @@ public class WifiNanManager { } /** @hide */ - public void sendMessage(int sessionId, int peerId, byte[] message, int messageId, + public void sendMessage(int clientId, int sessionId, int peerId, byte[] message, int messageId, int retryCount) { if (VDBG) { - Log.v(TAG, "sendMessage(): sessionId=" + sessionId + ", peerId=" + peerId - + ", messageId=" + messageId + ", retryCount=" + retryCount); - } - - int clientId; - synchronized (mLock) { - if (mClientId == INVALID_CLIENT_ID) { - Log.e(TAG, "sendMessage(): called with invalid client ID - not connected first?"); - return; - } - - clientId = mClientId; + Log.v(TAG, + "sendMessage(): clientId=" + clientId + ", sessionId=" + sessionId + ", peerId=" + + peerId + ", messageId=" + messageId + ", retryCount=" + retryCount); } try { @@ -636,21 +482,11 @@ public class WifiNanManager { } /** @hide */ - public void startRanging(int sessionId, RttManager.RttParams[] params, + public void startRanging(int clientId, int sessionId, RttManager.RttParams[] params, RttManager.RttListener listener) { if (VDBG) { - Log.v(TAG, "startRanging: sessionId=" + sessionId + ", " + "params=" - + Arrays.toString(params) + ", listener=" + listener); - } - - int clientId; - synchronized (mLock) { - if (mClientId == INVALID_CLIENT_ID) { - Log.e(TAG, "startRanging(): called with invalid client ID - not connected first?"); - return; - } - - clientId = mClientId; + Log.v(TAG, "startRanging: clientId=" + clientId + ", sessionId=" + sessionId + ", " + + "params=" + Arrays.toString(params) + ", listener=" + listener); } int rangingKey = 0; @@ -667,7 +503,7 @@ public class WifiNanManager { } /** @hide */ - public String createNetworkSpecifier(@DataPathRole int role, int sessionId, int peerId, + public String createNetworkSpecifier(int clientId, int role, int sessionId, int peerId, byte[] token) { if (VDBG) { Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId @@ -703,18 +539,6 @@ public class WifiNanManager { } } - int clientId; - synchronized (mLock) { - if (mClientId == INVALID_CLIENT_ID) { - Log.e(TAG, - "createNetworkSpecifier: called with invalid client ID - not connected " - + "first?"); - return null; - } - - clientId = mClientId; - } - JSONObject json; try { json = new JSONObject(); @@ -736,36 +560,8 @@ public class WifiNanManager { return json.toString(); } - /** - * Create a {@link NetworkRequest.Builder#setNetworkSpecifier(String)} for a - * WiFi NAN connection to the specified peer. The - * {@link NetworkRequest.Builder#addTransportType(int)} should be set to - * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_NAN}. - * <p> - * This API is targeted for applications which can obtain the peer MAC address using OOB - * (out-of-band) discovery. NAN discovery does not provide the MAC address of the peer - - * when using NAN discovery use the alternative network specifier method - - * {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])}. - * - * @param role The role of this device: - * {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_INITIATOR} or - * {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_RESPONDER} - * @param peer The MAC address of the peer's NAN discovery interface. On a RESPONDER this - * value is used to gate the acceptance of a connection request from only that - * peer. A RESPONDER may specified a null - indicating that it will accept - * connection requests from any device. - * @param token An arbitrary token (message) to be used to match connection initiation request - * to a responder setup. A RESPONDER is set up with a {@code token} which must - * be matched by the token provided by the INITIATOR. A null token is permitted - * on the RESPONDER and matches any peer token. An empty ({@code ""}) token is - * not the same as a null token and requires the peer token to be empty as well. - * - * @return A string to be used to construct - * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to - * {@link android.net.ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)} - * [or other varieties of that API]. - */ - public String createNetworkSpecifier(@DataPathRole int role, @Nullable byte[] peer, + /** @hide */ + public String createNetworkSpecifier(int clientId, @DataPathRole int role, @Nullable byte[] peer, @Nullable byte[] token) { if (VDBG) { Log.v(TAG, "createNetworkSpecifier: role=" + role + ", token=" + token); @@ -804,18 +600,6 @@ public class WifiNanManager { } } - int clientId; - synchronized (mLock) { - if (mClientId == INVALID_CLIENT_ID) { - Log.e(TAG, - "createNetworkSpecifier: called with invalid client ID - not connected " - + "first?"); - return null; - } - - clientId = mClientId; - } - JSONObject json; try { json = new JSONObject(); @@ -846,6 +630,8 @@ public class WifiNanManager { private final Handler mHandler; private final WeakReference<WifiNanManager> mNanManager; + private final Binder mBinder; + private final Looper mLooper; RttManager.RttListener getAndRemoveRangingListener(int rangingId) { WifiNanManager mgr = mNanManager.get(); @@ -867,9 +653,11 @@ public class WifiNanManager { * * @param looper The looper on which to execute the callbacks. */ - WifiNanEventCallbackProxy(WifiNanManager mgr, Looper looper, + WifiNanEventCallbackProxy(WifiNanManager mgr, Looper looper, Binder binder, final WifiNanEventCallback originalCallback) { mNanManager = new WeakReference<>(mgr); + mLooper = looper; + mBinder = binder; if (VDBG) Log.v(TAG, "WifiNanEventCallbackProxy ctor: looper=" + looper); mHandler = new Handler(looper) { @@ -887,13 +675,10 @@ public class WifiNanManager { switch (msg.what) { case CALLBACK_CONNECT_SUCCESS: - originalCallback.onConnectSuccess(); + originalCallback.onConnectSuccess( + new WifiNanSession(mgr, mBinder, mLooper, msg.arg1)); break; case CALLBACK_CONNECT_FAIL: - synchronized (mgr.mLock) { - mgr.mLooper = null; - mgr.mClientId = INVALID_CLIENT_ID; - } mNanManager.clear(); originalCallback.onConnectFail(msg.arg1); break; @@ -937,10 +722,11 @@ public class WifiNanManager { } @Override - public void onConnectSuccess() { + public void onConnectSuccess(int clientId) { if (VDBG) Log.v(TAG, "onConnectSuccess"); Message msg = mHandler.obtainMessage(CALLBACK_CONNECT_SUCCESS); + msg.arg1 = clientId; mHandler.sendMessage(msg); } @@ -1017,15 +803,17 @@ public class WifiNanManager { private final WeakReference<WifiNanManager> mNanManager; private final boolean mIsPublish; private final WifiNanDiscoverySessionCallback mOriginalCallback; + private final int mClientId; private final Handler mHandler; private WifiNanDiscoveryBaseSession mSession; WifiNanDiscoverySessionCallbackProxy(WifiNanManager mgr, Looper looper, boolean isPublish, - WifiNanDiscoverySessionCallback originalCallback) { + WifiNanDiscoverySessionCallback originalCallback, int clientId) { mNanManager = new WeakReference<>(mgr); mIsPublish = isPublish; mOriginalCallback = originalCallback; + mClientId = clientId; if (VDBG) { Log.v(TAG, "WifiNanDiscoverySessionCallbackProxy ctor: isPublish=" + isPublish); @@ -1181,12 +969,12 @@ public class WifiNanManager { if (mIsPublish) { WifiNanPublishDiscoverySession session = new WifiNanPublishDiscoverySession(mgr, - sessionId); + mClientId, sessionId); mSession = session; mOriginalCallback.onPublishStarted(session); } else { WifiNanSubscribeDiscoverySession - session = new WifiNanSubscribeDiscoverySession(mgr, sessionId); + session = new WifiNanSubscribeDiscoverySession(mgr, mClientId, sessionId); mSession = session; mOriginalCallback.onSubscribeStarted(session); } diff --git a/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java b/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java index cacbdbf751d8..c1731bbfd817 100644 --- a/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java +++ b/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java @@ -34,8 +34,8 @@ public class WifiNanPublishDiscoverySession extends WifiNanDiscoveryBaseSession private static final String TAG = "WifiNanPublishDiscSsn"; /** @hide */ - public WifiNanPublishDiscoverySession(WifiNanManager manager, int sessionId) { - super(manager, sessionId); + public WifiNanPublishDiscoverySession(WifiNanManager manager, int clientId, int sessionId) { + super(manager, clientId, sessionId); } /** @@ -64,7 +64,7 @@ public class WifiNanPublishDiscoverySession extends WifiNanDiscoveryBaseSession return; } - mgr.updatePublish(mSessionId, publishConfig); + mgr.updatePublish(mClientId, mSessionId, publishConfig); } } } diff --git a/wifi/java/android/net/wifi/nan/WifiNanSession.java b/wifi/java/android/net/wifi/nan/WifiNanSession.java new file mode 100644 index 000000000000..f9e601795552 --- /dev/null +++ b/wifi/java/android/net/wifi/nan/WifiNanSession.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2016 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.nan; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.NetworkRequest; +import android.os.Binder; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; + +import dalvik.system.CloseGuard; + +import java.lang.ref.WeakReference; + +/** + * This class represents a Wi-Fi NAN session - an attachment to the Wi-Fi NAN service through + * which the app can execute discovery operations. + * + * @hide PROPOSED_NAN_API + */ +public class WifiNanSession { + private static final String TAG = "WifiNanSession"; + private static final boolean DBG = false; + private static final boolean VDBG = false; // STOPSHIP if true + + private final WeakReference<WifiNanManager> mMgr; + private final Binder mBinder; + private final Looper mLooper; + private final int mClientId; + + private boolean mTerminated = true; + private final CloseGuard mCloseGuard = CloseGuard.get(); + + /** @hide */ + public WifiNanSession(WifiNanManager manager, Binder binder, Looper looper, int clientId) { + if (VDBG) Log.v(TAG, "New session created: manager=" + manager + ", clientId=" + clientId); + + mMgr = new WeakReference<>(manager); + mBinder = binder; + mLooper = looper; + mClientId = clientId; + mTerminated = false; + + mCloseGuard.open("disconnect"); + } + + /** + * Disconnect from the Wi-Fi NAN service and, if no other applications are connected to NAN, + * also disconnect from the NAN cluster. This method destroys all outstanding operations - + * i.e. all publish and subscribes are terminated, and any outstanding data-links are + * shut-down. However, it is good practice to terminate these discovery sessions and + * connections explicitly before a disconnect. + * <p> + * An application may re-connect after a disconnect using + * {@link WifiNanManager#connect(Handler, WifiNanEventCallback)} . + */ + public void disconnect() { + WifiNanManager mgr = mMgr.get(); + if (mgr == null) { + Log.w(TAG, "disconnect: called post GC on WifiNanManager"); + return; + } + mgr.disconnect(mClientId, mBinder); + mTerminated = true; + mMgr.clear(); + mCloseGuard.close(); + } + + /** @hide */ + @Override + protected void finalize() throws Throwable { + try { + if (!mTerminated) { + mCloseGuard.warnIfOpen(); + disconnect(); + } + } finally { + super.finalize(); + } + } + + /** + * Issue a request to the NAN service to create a new NAN publish discovery session, using + * the specified {@code publishConfig} configuration. The results of the publish operation + * are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}: + * <ul> + * <li>{@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)} + * is called when the publish session is created and provides a handle to the session. + * Further operations on the publish session can be executed on that object. + * <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFail(int)} is called if the + * publish operation failed. + * </ul> + * <p> + * Other results of the publish session operations will also be routed to callbacks + * on the {@code callback} object. The resulting publish session can be modified using + * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)}. + * <p> + * An application must use the {@link WifiNanDiscoveryBaseSession#terminate()} to + * terminate the publish discovery session once it isn't needed. This will free + * resources as well terminate any on-air transmissions. + * + * @param publishConfig The {@link PublishConfig} specifying the + * configuration of the requested publish session. + * @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for + * session event callbacks. + */ + public void publish(@NonNull PublishConfig publishConfig, + @NonNull WifiNanDiscoverySessionCallback callback) { + WifiNanManager mgr = mMgr.get(); + if (mgr == null) { + Log.e(TAG, "publish: called post GC on WifiNanManager"); + return; + } + if (mTerminated) { + Log.e(TAG, "publish: called after termination"); + return; + } + mgr.publish(mClientId, mLooper, publishConfig, callback); + } + + /** + * Issue a request to the NAN service to create a new NAN subscribe discovery session, using + * the specified {@code subscribeConfig} configuration. The results of the subscribe + * operation are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}: + * <ul> + * <li>{@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)} + * is called when the subscribe session is created and provides a handle to the session. + * Further operations on the subscribe session can be executed on that object. + * <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFail(int)} is called if the + * subscribe operation failed. + * </ul> + * <p> + * Other results of the subscribe session operations will also be routed to callbacks + * on the {@code callback} object. The resulting subscribe session can be modified using + * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. + * <p> + * An application must use the {@link WifiNanDiscoveryBaseSession#terminate()} to + * terminate the subscribe discovery session once it isn't needed. This will free + * resources as well terminate any on-air transmissions. + * + * @param subscribeConfig The {@link SubscribeConfig} specifying the + * configuration of the requested subscribe session. + * @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for + * session event callbacks. + */ + public void subscribe(@NonNull SubscribeConfig subscribeConfig, + @NonNull WifiNanDiscoverySessionCallback callback) { + WifiNanManager mgr = mMgr.get(); + if (mgr == null) { + Log.e(TAG, "publish: called post GC on WifiNanManager"); + return; + } + if (mTerminated) { + Log.e(TAG, "publish: called after termination"); + return; + } + mgr.subscribe(mClientId, mLooper, subscribeConfig, callback); + } + + /** + * Create a {@link NetworkRequest.Builder#setNetworkSpecifier(String)} for a + * WiFi NAN connection to the specified peer. The + * {@link NetworkRequest.Builder#addTransportType(int)} should be set to + * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_NAN}. + * <p> + * This API is targeted for applications which can obtain the peer MAC address using OOB + * (out-of-band) discovery. NAN discovery does not provide the MAC address of the peer - + * when using NAN discovery use the alternative network specifier method - + * {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, int, byte[])}. + * + * @param role The role of this device: + * {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_INITIATOR} or + * {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_RESPONDER} + * @param peer The MAC address of the peer's NAN discovery interface. On a RESPONDER this + * value is used to gate the acceptance of a connection request from only that + * peer. A RESPONDER may specified a null - indicating that it will accept + * connection requests from any device. + * @param token An arbitrary token (message) to be used to match connection initiation request + * to a responder setup. A RESPONDER is set up with a {@code token} which must + * be matched by the token provided by the INITIATOR. A null token is permitted + * on the RESPONDER and matches any peer token. An empty ({@code ""}) token is + * not the same as a null token and requires the peer token to be empty as well. + * + * @return A string to be used to construct + * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to + * {@link android.net.ConnectivityManager#requestNetwork(NetworkRequest, android.net.ConnectivityManager.NetworkCallback)} + * [or other varieties of that API]. + */ + public String createNetworkSpecifier(@WifiNanManager.DataPathRole int role, @Nullable byte[] peer, + @Nullable byte[] token) { + WifiNanManager mgr = mMgr.get(); + if (mgr == null) { + Log.e(TAG, "createNetworkSpecifier: called post GC on WifiNanManager"); + return ""; + } + if (mTerminated) { + Log.e(TAG, "createNetworkSpecifier: called after termination"); + return ""; + } + return mgr.createNetworkSpecifier(mClientId, role, peer, token); + } +} diff --git a/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java b/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java index 58c52d5faf72..b8d77aa1f8e4 100644 --- a/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java +++ b/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java @@ -36,8 +36,8 @@ public class WifiNanSubscribeDiscoverySession extends WifiNanDiscoveryBaseSessio /** * {@hide} */ - public WifiNanSubscribeDiscoverySession(WifiNanManager manager, int sessionId) { - super(manager, sessionId); + public WifiNanSubscribeDiscoverySession(WifiNanManager manager, int clientId, int sessionId) { + super(manager, clientId, sessionId); } /** @@ -67,7 +67,7 @@ public class WifiNanSubscribeDiscoverySession extends WifiNanDiscoveryBaseSessio return; } - mgr.updateSubscribe(mSessionId, subscribeConfig); + mgr.updateSubscribe(mClientId, mSessionId, subscribeConfig); } } } |