/**
* Defines a request object to configure a Wi-Fi NAN network. Built using
* {@link ConfigRequest.Builder}. Configuration is requested using
- * {@link WifiNanManager#requestConfig(ConfigRequest)}. Note that the actual
- * achieved configuration may be different from the requested configuration -
- * since multiple applications may request different configurations.
+ * {@link WifiNanManager#connect(android.os.Looper, WifiNanEventCallback, ConfigRequest)}
+ * . Note that the actual achieved configuration may be different from the
+ * requested configuration - since multiple applications may request different
+ * configurations.
*
* @hide PROPOSED_NAN_API
*/
&& mEnableIdentityChangeCallback == lhs.mEnableIdentityChangeCallback;
}
+ /**
+ * Checks for equality of two configuration - but only considering their
+ * on-the-air NAN configuration impact.
+ *
+ * @param o Object to compare to.
+ * @return true if configuration objects have the same on-the-air
+ * configuration, false otherwise.
+ * @hide
+ */
+ public boolean equalsOnTheAir(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof ConfigRequest)) {
+ return false;
+ }
+
+ ConfigRequest lhs = (ConfigRequest) o;
+
+ return mSupport5gBand == lhs.mSupport5gBand && mMasterPreference == lhs.mMasterPreference
+ && mClusterLow == lhs.mClusterLow && mClusterHigh == lhs.mClusterHigh;
+ }
+
@Override
public int hashCode() {
int result = 17;
}
/**
+ * Validates that the contents of the ConfigRequest are valid. Otherwise
+ * throws an IllegalArgumentException.
+ *
+ * @hide
+ */
+ public void validate() throws IllegalArgumentException {
+ if (mMasterPreference < 0) {
+ throw new IllegalArgumentException(
+ "Master Preference specification must be non-negative");
+ }
+ if (mMasterPreference == 1 || mMasterPreference == 255 || mMasterPreference > 255) {
+ throw new IllegalArgumentException("Master Preference specification must not "
+ + "exceed 255 or use 1 or 255 (reserved values)");
+ }
+ if (mClusterLow < CLUSTER_ID_MIN) {
+ throw new IllegalArgumentException("Cluster specification must be non-negative");
+ }
+ if (mClusterLow > CLUSTER_ID_MAX) {
+ throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF");
+ }
+ if (mClusterHigh < CLUSTER_ID_MIN) {
+ throw new IllegalArgumentException("Cluster specification must be non-negative");
+ }
+ if (mClusterHigh > CLUSTER_ID_MAX) {
+ throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF");
+ }
+ if (mClusterLow > mClusterHigh) {
+ throw new IllegalArgumentException(
+ "Invalid argument combination - must have Cluster Low <= Cluster High");
+ }
+ }
+
+ /**
* Builder used to build {@link ConfigRequest} objects.
*/
public static final class Builder {
* @param support5gBand Support for 5G band is required.
* @return The builder to facilitate chaining
* {@code builder.setXXX(..).setXXX(..)}.
+ * @hide PROPOSED_NAN_SYSTEM_API
*/
public Builder setSupport5gBand(boolean support5gBand) {
mSupport5gBand = support5gBand;
* @param masterPreference The requested master preference
* @return The builder to facilitate chaining
* {@code builder.setXXX(..).setXXX(..)}.
+ * @hide PROPOSED_NAN_SYSTEM_API
*/
public Builder setMasterPreference(int masterPreference) {
if (masterPreference < 0) {
* @param clusterLow The lower range of the generated cluster ID.
* @return The builder to facilitate chaining
* {@code builder.setClusterLow(..).setClusterHigh(..)}.
+ * @hide PROPOSED_NAN_SYSTEM_API
*/
public Builder setClusterLow(int clusterLow) {
if (clusterLow < CLUSTER_ID_MIN) {
* @param clusterHigh The upper range of the generated cluster ID.
* @return The builder to facilitate chaining
* {@code builder.setClusterLow(..).setClusterHigh(..)}.
+ * @hide PROPOSED_NAN_SYSTEM_API
*/
public Builder setClusterHigh(int clusterHigh) {
if (clusterHigh < CLUSTER_ID_MIN) {
*/
oneway interface IWifiNanEventCallback
{
- void onConfigCompleted(in ConfigRequest completedConfig);
- void onConfigFailed(in ConfigRequest failedConfig, int reason);
+ void onConnectSuccess();
+ void onConnectFail(int reason);
void onNanDown(int reason);
void onIdentityChanged();
}
interface IWifiNanManager
{
// client API
- int connect(in IBinder binder, in IWifiNanEventCallback callback);
+ int connect(in IBinder binder, in IWifiNanEventCallback callback,
+ in ConfigRequest configRequest);
void disconnect(int clientId, in IBinder binder);
- void requestConfig(int clientId, in ConfigRequest configRequest);
void publish(int clientId, in PublishConfig publishConfig, in IWifiNanSessionCallback callback);
void subscribe(int clientId, in SubscribeConfig subscribeConfig,
oneway interface IWifiNanSessionCallback
{
void onSessionStarted(int sessionId);
+ void onSessionConfigSuccess();
void onSessionConfigFail(int reason);
void onSessionTerminated(int reason);
/**
* Defines the configuration of a NAN publish session. Built using
* {@link PublishConfig.Builder}. Publish is done using
- * {@link WifiNanManager#publish(PublishConfig, WifiNanSessionCallback, int)} or
- * {@link WifiNanPublishSession#publish(PublishConfig)}.
+ * {@link WifiNanManager#publish(PublishConfig, WifiNanSessionCallback)} or
+ * {@link WifiNanPublishSession#updatePublish(PublishConfig)}.
*
* @hide PROPOSED_NAN_API
*/
}
/**
+ * Validates that the contents of the PublishConfig are valid. Otherwise
+ * throws an IllegalArgumentException.
+ *
+ * @hide
+ */
+ public void validate() throws IllegalArgumentException {
+ if (mServiceSpecificInfoLength != 0 && (mServiceSpecificInfo == null
+ || mServiceSpecificInfo.length < mServiceSpecificInfoLength)) {
+ throw new IllegalArgumentException("Non-matching combination of "
+ + "serviceSpecificInfo and serviceSpecificInfoLength");
+ }
+ if (mTxFilterLength != 0 && (mTxFilter == null || mTxFilter.length < mTxFilterLength)) {
+ throw new IllegalArgumentException(
+ "Non-matching combination of txFilter and txFilterLength");
+ }
+ if (mRxFilterLength != 0 && (mRxFilter == null || mRxFilter.length < mRxFilterLength)) {
+ throw new IllegalArgumentException(
+ "Non-matching combination of rxFilter and rxFilterLength");
+ }
+ if (mPublishType < PUBLISH_TYPE_UNSOLICITED || mPublishType > PUBLISH_TYPE_SOLICITED) {
+ throw new IllegalArgumentException("Invalid publishType - " + mPublishType);
+ }
+ if (mPublishCount < 0) {
+ throw new IllegalArgumentException("Invalid publishCount - must be non-negative");
+ }
+ if (mTtlSec < 0) {
+ throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
+ }
+ if (mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED && mRxFilterLength != 0) {
+ throw new IllegalArgumentException("Invalid publish config: UNSOLICITED "
+ + "publishes (active) can't have an Rx filter");
+ }
+ if (mPublishType == PublishConfig.PUBLISH_TYPE_SOLICITED && mTxFilterLength != 0) {
+ throw new IllegalArgumentException("Invalid publish config: SOLICITED "
+ + "publishes (passive) can't have a Tx filter");
+ }
+ }
+
+ /**
* Builder used to build {@link PublishConfig} objects.
*/
public static final class Builder {
* Sets the number of times a solicited (
* {@link PublishConfig.Builder#setPublishType(int)}) publish session
* will transmit a packet. When the count is reached an event will be
- * generated for {@link WifiNanSessionCallback#onPublishTerminated(int)}
+ * generated for {@link WifiNanSessionCallback#onSessionTerminated(int)}
* with reason={@link WifiNanSessionCallback#TERMINATE_REASON_DONE}.
*
* @param publishCount Number of publish packets to transmit.
* {@link PublishConfig.Builder#setPublishCount(int)}) publish session
* will be alive - i.e. transmitting a packet. When the TTL is reached
* an event will be generated for
- * {@link WifiNanSessionCallback#onPublishTerminated(int)} with reason=
+ * {@link WifiNanSessionCallback#onSessionTerminated(int)} with reason=
* {@link WifiNanSessionCallback#TERMINATE_REASON_DONE}.
*
* @param ttlSec Lifetime of a publish session in seconds.
/**
* Configure whether a publish terminate notification
- * {@link WifiNanSessionCallback#onPublishTerminated(int)} is reported
+ * {@link WifiNanSessionCallback#onSessionTerminated(int)} is reported
* back to the callback.
*
* @param enable If true the terminate callback will be called when the
* Defines the configuration of a NAN subscribe session. Built using
* {@link SubscribeConfig.Builder}. Subscribe is done using
* {@link WifiNanManager#subscribe(SubscribeConfig, WifiNanSessionCallback)} or
- * {@link WifiNanSubscribeSession#subscribe(SubscribeConfig)}.
+ * {@link WifiNanSubscribeSession#updateSubscribe(SubscribeConfig)}.
*
* @hide PROPOSED_NAN_API
*/
}
/**
+ * Validates that the contents of the SubscribeConfig are valid. Otherwise
+ * throws an IllegalArgumentException.
+ *
+ * @hide
+ */
+ public void validate() throws IllegalArgumentException {
+ if (mServiceSpecificInfoLength != 0 && (mServiceSpecificInfo == null
+ || mServiceSpecificInfo.length < mServiceSpecificInfoLength)) {
+ throw new IllegalArgumentException("Non-matching combination of "
+ + "serviceSpecificInfo and serviceSpecificInfoLength");
+ }
+ if (mTxFilterLength != 0 && (mTxFilter == null || mTxFilter.length < mTxFilterLength)) {
+ throw new IllegalArgumentException(
+ "Non-matching combination of txFilter and txFilterLength");
+ }
+ if (mRxFilterLength != 0 && (mRxFilter == null || mRxFilter.length < mRxFilterLength)) {
+ throw new IllegalArgumentException(
+ "Non-matching combination of rxFilter and rxFilterLength");
+ }
+ if (mSubscribeType < SUBSCRIBE_TYPE_PASSIVE || mSubscribeType > SUBSCRIBE_TYPE_ACTIVE) {
+ throw new IllegalArgumentException("Invalid subscribeType - " + mSubscribeType);
+ }
+ if (mSubscribeCount < 0) {
+ throw new IllegalArgumentException("Invalid subscribeCount - must be non-negative");
+ }
+ if (mTtlSec < 0) {
+ throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
+ }
+ if (mMatchStyle != MATCH_STYLE_FIRST_ONLY && mMatchStyle != MATCH_STYLE_ALL) {
+ throw new IllegalArgumentException(
+ "Invalid matchType - must be MATCH_FIRST_ONLY or MATCH_ALL");
+ }
+ if (mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE && mRxFilterLength != 0) {
+ throw new IllegalArgumentException(
+ "Invalid subscribe config: ACTIVE subscribes can't have an Rx filter");
+ }
+ if (mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE && mTxFilterLength != 0) {
+ throw new IllegalArgumentException(
+ "Invalid subscribe config: PASSIVE subscribes can't have a Tx filter");
+ }
+ }
+
+ /**
* Builder used to build {@link SubscribeConfig} objects.
*/
public static final class Builder {
*/
public Builder setServiceSpecificInfo(byte[] serviceSpecificInfo,
int serviceSpecificInfoLength) {
+ if (serviceSpecificInfoLength != 0 && (serviceSpecificInfo == null
+ || serviceSpecificInfo.length < serviceSpecificInfoLength)) {
+ throw new IllegalArgumentException("Non-matching combination of "
+ + "serviceSpecificInfo and serviceSpecificInfoLength");
+ }
mServiceSpecificInfoLength = serviceSpecificInfoLength;
mServiceSpecificInfo = serviceSpecificInfo;
return this;
* {@code builder.setXXX(..).setXXX(..)}.
*/
public Builder setTxFilter(byte[] txFilter, int txFilterLength) {
+ if (txFilterLength != 0 && (txFilter == null || txFilter.length < txFilterLength)) {
+ throw new IllegalArgumentException(
+ "Non-matching combination of txFilter and txFilterLength");
+ }
mTxFilter = txFilter;
mTxFilterLength = txFilterLength;
return this;
* {@code builder.setXXX(..).setXXX(..)}.
*/
public Builder setRxFilter(byte[] rxFilter, int rxFilterLength) {
+ if (rxFilterLength != 0 && (rxFilter == null || rxFilter.length < rxFilterLength)) {
+ throw new IllegalArgumentException(
+ "Non-matching combination of rxFilter and rxFilterLength");
+ }
mRxFilter = rxFilter;
mRxFilterLength = rxFilterLength;
return this;
* {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe
* session will transmit a packet. When the count is reached an event
* will be generated for
- * {@link WifiNanSessionCallback#onSubscribeTerminated(int)} with
- * reason= {@link WifiNanSessionCallback#TERMINATE_REASON_DONE}.
+ * {@link WifiNanSessionCallback#onSessionTerminated(int)} with reason=
+ * {@link WifiNanSessionCallback#TERMINATE_REASON_DONE}.
*
* @param subscribeCount Number of subscribe packets to transmit.
* @return The builder to facilitate chaining
* {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe
* session will be alive - i.e. transmitting a packet. When the TTL is
* reached an event will be generated for
- * {@link WifiNanSessionCallback#onSubscribeTerminated(int)} with
- * reason= {@link WifiNanSessionCallback#TERMINATE_REASON_DONE}.
+ * {@link WifiNanSessionCallback#onSessionTerminated(int)} with reason=
+ * {@link WifiNanSessionCallback#TERMINATE_REASON_DONE}.
*
* @param ttlSec Lifetime of a subscribe session in seconds.
* @return The builder to facilitate chaining
/**
* Configure whether a subscribe terminate notification
- * {@link WifiNanSessionCallback#onSubscribeTerminated(int)} is reported
+ * {@link WifiNanSessionCallback#onSessionTerminated(int)} is reported
* back to the callback.
*
* @param enable If true the terminate callback will be called when the
package android.net.wifi.nan;
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Base class for NAN events callbacks. Should be extended by applications
* wanting notifications. These are callbacks applying to the NAN connection as
* @hide PROPOSED_NAN_API
*/
public class WifiNanEventCallback {
+ @IntDef({
+ REASON_INVALID_ARGS, REASON_ALREADY_CONNECTED_INCOMPAT_CONFIG, REASON_REQUESTED,
+ REASON_OTHER })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EventReasonCodes {
+ }
+
/**
- * Called when NAN configuration is completed.
- *
- * @param completedConfig The actual configuration request which was
- * completed. Note that it may be different from that requested
- * by the application. The service combines configuration
- * requests from all applications.
+ * Failure reason flag for {@link WifiNanEventCallback} callbacks. Indicates
+ * invalid argument in the requested operation.
+ */
+ public static final int REASON_INVALID_ARGS = 1000;
+
+ /**
+ * Failure reason flag for {@link WifiNanEventCallback} callbacks. Indicates
+ * that a {@link ConfigRequest} passed in
+ * {@link WifiNanManager#connect(android.os.Looper, WifiNanEventCallback, ConfigRequest)}
+ * couldn't be applied since other connections already exist with an
+ * incompatible configurations.
+ */
+ public static final int REASON_ALREADY_CONNECTED_INCOMPAT_CONFIG = 1001;
+
+ /**
+ * Reason flag for {@link WifiNanEventCallback#onNanDown(int)} callback.
+ * Indicates NAN is shut-down per user request.
+ */
+ public static final int REASON_REQUESTED = 1002;
+
+ /**
+ * Failure reason flag for {@link WifiNanEventCallback} callbacks. Indicates
+ * an unspecified error occurred during the operation.
+ */
+ public static final int REASON_OTHER = 1003;
+
+ /**
+ * Called when NAN connect operation
+ * {@link WifiNanManager#connect(android.os.Looper, WifiNanEventCallback)}
+ * is completed. Doesn't necessarily mean that have joined or started a NAN
+ * cluster. An indication is provided by {@link #onIdentityChanged()}.
*/
- public void onConfigCompleted(ConfigRequest completedConfig) {
+ public void onConnectSuccess() {
/* empty */
}
/**
- * Called when NAN configuration failed.
+ * Called when NAN connect operation
+ * {@code WifiNanManager#connect(android.os.Looper, WifiNanEventCallback)}
+ * failed.
*
* @param reason Failure reason code, see
- * {@code WifiNanSessionCallback.FAIL_*}.
+ * {@code WifiNanEventCallback.REASON_*}.
*/
- public void onConfigFailed(@SuppressWarnings("unused") ConfigRequest failedConfig, int reason) {
+ public void onConnectFail(@EventReasonCodes int reason) {
/* empty */
}
* Called when NAN cluster is down
*
* @param reason Reason code for event, see
- * {@code WifiNanSessionCallback.FAIL_*}.
+ * {@code WifiNanEventCallback.REASON_*}.
*/
- public void onNanDown(int reason) {
+ public void onNanDown(@EventReasonCodes int reason) {
/* empty */
}
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.ref.WeakReference;
+
/**
* This class provides the primary API for managing Wi-Fi NAN operation:
* including discovery and data-links. Get an instance of this class by calling
private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
+ private final IWifiNanManager mService;
+
+ /*
+ * State transitions:
+ * UNCONNECTED -- (connect()) --> CONNECTING -- (onConnectSuccess()) --> CONNECTED
+ * UNCONNECTED -- (connect()) --> CONNECTING -- (onConnectFail()) --> UNCONNECTED
+ * CONNECTED||CONNECTING -- (disconnect()) --> UNCONNECTED
+ * CONNECTED||CONNECTING -- onNanDown() --> UNCONNECTED
+ */
+ private static final int STATE_UNCONNECTED = 0;
+ private static final int STATE_CONNECTING = 1;
+ private static final int STATE_CONNECTED = 2;
+
+ private Object mLock = new Object(); // lock access to the following vars
+
+ @GuardedBy("mLock")
+ private int mState = STATE_UNCONNECTED;
+
+ @GuardedBy("mLock")
private IBinder mBinder;
- private int mClientId = -1;
- private IWifiNanManager mService;
+
+ @GuardedBy("mLock")
+ private int mClientId;
+
+ @GuardedBy("mLock")
private Looper mLooper;
/**
}
/**
- * Re-connect to the Wi-Fi NAN service - enabling the application to execute
+ * Connect to the Wi-Fi NAN service - enabling the application to execute
* {@link WifiNanManager} APIs.
*
* @param looper The Looper on which to execute all callbacks related to the
* @param callback A callback extended from {@link WifiNanEventCallback}.
*/
public void connect(Looper looper, WifiNanEventCallback callback) {
- if (VDBG) Log.v(TAG, "connect()");
-
- if (callback == null) {
- throw new IllegalArgumentException("Invalid callback - must not be null");
- }
+ connect(looper, callback, null);
+ }
- if (mClientId != -1) {
- Log.e(TAG, "connect(): mClientId=" + mClientId
- + ": seems to calling connect() without disconnecting() first!");
- throw new IllegalStateException("Calling connect() without disconnecting() first!");
+ /**
+ * Connect to the Wi-Fi NAN service - enabling the application to execute
+ * {@link WifiNanManager} APIs. Allows requesting a specific configuration
+ * using {@link ConfigRequest} structure. Limited to privileged access.
+ *
+ * @param looper The Looper on which to execute all callbacks related to the
+ * connection - including all sessions opened as part of this
+ * connection.
+ * @param callback A callback extended from {@link WifiNanEventCallback}.
+ * @param configRequest The requested NAN configuration.
+ */
+ public void connect(Looper looper, WifiNanEventCallback callback, ConfigRequest configRequest) {
+ if (VDBG) {
+ Log.v(TAG, "connect(): looper=" + looper + ", callback=" + callback + ", configRequest="
+ + configRequest);
}
- mLooper = looper;
- mBinder = new Binder();
+ synchronized (mLock) {
+ if (mState != STATE_UNCONNECTED) {
+ Log.e(TAG, "connect(): Calling connect() when state != UNCONNECTED!");
+ return;
+ }
- try {
- mClientId = mService.connect(mBinder, new WifiNanEventCallbackProxy(mLooper, callback));
- } catch (RemoteException e) {
- Log.w(TAG, "connect RemoteException (FYI - ignoring): " + e);
+ mLooper = looper;
+ mBinder = new Binder();
+ mState = STATE_CONNECTING;
+
+ try {
+ mClientId = mService.connect(mBinder,
+ new WifiNanEventCallbackProxy(this, looper, callback), configRequest);
+ } catch (RemoteException e) {
+ mLooper = null;
+ mBinder = null;
+ mState = STATE_UNCONNECTED;
+ e.rethrowAsRuntimeException();
+ }
}
}
* {@link WifiNanManager#connect(Looper, WifiNanEventCallback)} .
*/
public void disconnect() {
- if (mClientId == -1) {
- /*
- * Warning only since could be called multiple times as cleaning-up
- * (and no damage done).
- */
- Log.w(TAG, "disconnect(): called without calling connect() first - or called "
- + "multiple times.");
- return;
+ if (VDBG) Log.v(TAG, "disconnect()");
+
+ IBinder binder;
+ int clientId;
+ synchronized (mLock) {
+ if (mState == STATE_UNCONNECTED) {
+ Log.e(TAG, "disconnect(): called while UNCONNECTED - ignored");
+ return;
+ }
+
+ binder = mBinder;
+ clientId = mClientId;
+
+ mState = STATE_UNCONNECTED;
+ mBinder = null;
+ mLooper = null;
+ mClientId = 0;
}
+
try {
- if (VDBG) Log.v(TAG, "disconnect()");
- mService.disconnect(mClientId, mBinder);
- mBinder = null;
- mClientId = -1;
+ mService.disconnect(clientId, binder);
} catch (RemoteException e) {
- Log.w(TAG, "disconnect RemoteException (FYI - ignoring): " + e);
+ e.rethrowAsRuntimeException();
}
}
@Override
protected void finalize() throws Throwable {
- if (mBinder != null) {
- if (DBG) Log.d(TAG, "finalize: disconnect() not called - executing now");
+ if (mState != STATE_UNCONNECTED) {
disconnect();
}
}
/**
- * Requests a NAN configuration, specified by {@link ConfigRequest}. Note
- * that NAN is a shared resource and the device can only be a member of a
- * single cluster. Thus the service may merge configuration requests from
- * multiple applications and configure NAN differently from individual
- * requests.
- * <p>
- * The {@link WifiNanEventCallback#onConfigCompleted(ConfigRequest)} will be
- * called when configuration is completed (if a callback is registered for
- * this specific event).
- *
- * @param configRequest The requested NAN configuration.
- */
- public void requestConfig(ConfigRequest configRequest) {
- if (VDBG) Log.v(TAG, "requestConfig(): configRequest=" + configRequest);
-
- if (mClientId == -1) {
- Log.e(TAG, "requestConfig(): called without an initial connect()!");
- throw new IllegalStateException("Calling requestConfig() without a connect() first!");
- }
-
- try {
- mService.requestConfig(mClientId, configRequest);
- } catch (RemoteException e) {
- Log.w(TAG, "requestConfig RemoteException (FYI - ignoring): " + e);
- }
- }
-
- /**
* Request a NAN publish session. The actual publish session is provided by
* the
* {@link WifiNanSessionCallback#onPublishStarted(WifiNanPublishSession)}
public void publish(PublishConfig publishConfig, WifiNanSessionCallback callback) {
if (VDBG) Log.v(TAG, "publish(): config=" + publishConfig);
- if (publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED
- && publishConfig.mRxFilterLength != 0) {
- throw new IllegalArgumentException("Invalid publish config: UNSOLICITED "
- + "publishes (active) can't have an Rx filter");
- }
- if (publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_SOLICITED
- && publishConfig.mTxFilterLength != 0) {
- throw new IllegalArgumentException("Invalid publish config: SOLICITED "
- + "publishes (passive) can't have a Tx filter");
- }
- if (callback == null) {
- throw new IllegalArgumentException("Invalid callback - must not be null");
- }
+ int clientId;
+ Looper looper;
+ synchronized (mLock) {
+ if (mState != STATE_CONNECTED) {
+ Log.e(TAG, "publish(): called when not CONNECTED!");
+ return;
+ }
- if (mClientId == -1) {
- Log.e(TAG, "publish(): called without an initial connect()!");
- throw new IllegalStateException("Calling publish() without a connect() first!");
+ clientId = mClientId;
+ looper = mLooper;
}
-
try {
- mService.publish(mClientId, publishConfig,
- new WifiNanSessionCallbackProxy(mLooper, true, callback));
+ mService.publish(clientId, publishConfig,
+ new WifiNanSessionCallbackProxy(this, looper, true, callback));
} catch (RemoteException e) {
- Log.w(TAG, "publish RemoteException: " + e);
+ e.rethrowAsRuntimeException();
}
}
public void updatePublish(int sessionId, PublishConfig publishConfig) {
if (VDBG) Log.v(TAG, "updatePublish(): config=" + publishConfig);
- if (publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED
- && publishConfig.mRxFilterLength != 0) {
- throw new IllegalArgumentException("Invalid publish config: UNSOLICITED "
- + "publishes (active) can't have an Rx filter");
- }
- if (publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_SOLICITED
- && publishConfig.mTxFilterLength != 0) {
- throw new IllegalArgumentException("Invalid publish config: SOLICITED "
- + "publishes (passive) can't have a Tx filter");
- }
+ int clientId;
+ synchronized (mLock) {
+ if (mState != STATE_CONNECTED) {
+ Log.e(TAG, "updatePublish(): called when not CONNECTED)!");
+ return;
+ }
+ clientId = mClientId;
+ }
try {
- mService.updatePublish(mClientId, sessionId, publishConfig);
+ mService.updatePublish(clientId, sessionId, publishConfig);
} catch (RemoteException e) {
- Log.w(TAG, "updatePublish RemoteException: " + e);
+ e.rethrowAsRuntimeException();
}
}
Log.v(TAG, "subscribe(): config=" + subscribeConfig);
}
- if (subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE
- && subscribeConfig.mRxFilterLength != 0) {
- throw new IllegalArgumentException(
- "Invalid subscribe config: ACTIVE subscribes can't have an Rx filter");
- }
- if (subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE
- && subscribeConfig.mTxFilterLength != 0) {
- throw new IllegalArgumentException(
- "Invalid subscribe config: PASSIVE subscribes can't have a Tx filter");
- }
+ int clientId;
+ Looper looper;
+ synchronized (mLock) {
+ if (mState != STATE_CONNECTED) {
+ Log.e(TAG, "subscribe(): called when not CONNECTED!");
+ return;
+ }
- if (mClientId == -1) {
- Log.e(TAG, "subscribe(): called without an initial connect()!");
- throw new IllegalStateException("Calling subscribe() without a connect() first!");
+ clientId = mClientId;
+ looper = mLooper;
}
try {
- mService.subscribe(mClientId, subscribeConfig,
- new WifiNanSessionCallbackProxy(mLooper, false, callback));
+ mService.subscribe(clientId, subscribeConfig,
+ new WifiNanSessionCallbackProxy(this, looper, false, callback));
} catch (RemoteException e) {
- Log.w(TAG, "subscribe RemoteException: " + e);
+ e.rethrowAsRuntimeException();
}
}
Log.v(TAG, "subscribe(): config=" + subscribeConfig);
}
- if (subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE
- && subscribeConfig.mRxFilterLength != 0) {
- throw new IllegalArgumentException(
- "Invalid subscribe config: ACTIVE subscribes can't have an Rx filter");
- }
- if (subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE
- && subscribeConfig.mTxFilterLength != 0) {
- throw new IllegalArgumentException(
- "Invalid subscribe config: PASSIVE subscribes can't have a Tx filter");
+ int clientId;
+ synchronized (mLock) {
+ if (mState != STATE_CONNECTED) {
+ Log.e(TAG, "updateSubscribe(): called when not CONNECTED!");
+ return;
+ }
+
+ clientId = mClientId;
}
try {
- mService.updateSubscribe(mClientId, sessionId, subscribeConfig);
+ mService.updateSubscribe(clientId, sessionId, subscribeConfig);
} catch (RemoteException e) {
- Log.w(TAG, "updateSubscribe RemoteException: " + e);
+ e.rethrowAsRuntimeException();
}
}
public void terminateSession(int sessionId) {
if (DBG) Log.d(TAG, "Terminate NAN session #" + sessionId);
+ int clientId;
+ synchronized (mLock) {
+ if (mState != STATE_CONNECTED) {
+ Log.e(TAG, "terminateSession(): called when not CONNECTED!");
+ return;
+ }
+
+ clientId = mClientId;
+ }
+
try {
- mService.terminateSession(mClientId, sessionId);
+ mService.terminateSession(clientId, sessionId);
} catch (RemoteException e) {
- Log.w(TAG, "terminateSession RemoteException (FYI - ignoring): " + e);
+ e.rethrowAsRuntimeException();
}
}
*/
public void sendMessage(int sessionId, int peerId, byte[] message, int messageLength,
int messageId) {
- try {
- if (VDBG) {
- Log.v(TAG, "sendMessage(): sessionId=" + sessionId + ", peerId=" + peerId
- + ", messageLength=" + messageLength + ", messageId=" + messageId);
+ if (VDBG) {
+ Log.v(TAG, "sendMessage(): sessionId=" + sessionId + ", peerId=" + peerId
+ + ", messageLength=" + messageLength + ", messageId=" + messageId);
+ }
+
+ int clientId;
+ synchronized (mLock) {
+ if (mState != STATE_CONNECTED) {
+ Log.e(TAG, "sendMessage(): called when not CONNECTED!");
+ return;
}
- mService.sendMessage(mClientId, sessionId, peerId, message, messageLength, messageId);
+
+ clientId = mClientId;
+ }
+
+ try {
+ mService.sendMessage(clientId, sessionId, peerId, message, messageLength, messageId);
} catch (RemoteException e) {
- Log.w(TAG, "subscribe RemoteException (FYI - ignoring): " + e);
+ e.rethrowAsRuntimeException();
}
}
private static class WifiNanEventCallbackProxy extends IWifiNanEventCallback.Stub {
- private static final int CALLBACK_CONFIG_COMPLETED = 0;
- private static final int CALLBACK_CONFIG_FAILED = 1;
+ private static final int CALLBACK_CONNECT_SUCCESS = 0;
+ private static final int CALLBACK_CONNECT_FAIL = 1;
private static final int CALLBACK_NAN_DOWN = 2;
private static final int CALLBACK_IDENTITY_CHANGED = 3;
- private final WifiNanEventCallback mOriginalCallback;
private final Handler mHandler;
/**
*
* @param looper The looper on which to execute the callbacks.
*/
- WifiNanEventCallbackProxy(Looper looper, WifiNanEventCallback originalCallback) {
- mOriginalCallback = originalCallback;
+ WifiNanEventCallbackProxy(WifiNanManager mgr, Looper looper,
+ final WifiNanEventCallback originalCallback) {
+ final WeakReference<WifiNanManager> nanManager = new WeakReference<WifiNanManager>(mgr);
if (VDBG) Log.v(TAG, "WifiNanEventCallbackProxy ctor: looper=" + looper);
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
- if (DBG) Log.d(TAG, "What=" + msg.what + ", msg=" + msg);
+ if (DBG) {
+ Log.d(TAG, "WifiNanEventCallbackProxy: What=" + msg.what + ", msg=" + msg);
+ }
+
+ WifiNanManager mgr = nanManager.get();
+ if (mgr == null) {
+ Log.w(TAG, "WifiNanEventCallbackProxy: handleMessage post GC");
+ return;
+ }
+
switch (msg.what) {
- case CALLBACK_CONFIG_COMPLETED:
- mOriginalCallback.onConfigCompleted((ConfigRequest) msg.obj);
+ case CALLBACK_CONNECT_SUCCESS:
+ synchronized (mgr.mLock) {
+ if (mgr.mState != STATE_CONNECTING) {
+ Log.w(TAG, "onConnectSuccess indication received but not in "
+ + "CONNECTING state. Ignoring.");
+ return;
+ }
+ mgr.mState = STATE_CONNECTED;
+ }
+ originalCallback.onConnectSuccess();
break;
- case CALLBACK_CONFIG_FAILED:
- mOriginalCallback.onConfigFailed((ConfigRequest) msg.obj, msg.arg1);
+ case CALLBACK_CONNECT_FAIL:
+ synchronized (mgr.mLock) {
+ if (mgr.mState != STATE_CONNECTING) {
+ Log.w(TAG, "onConnectFail indication received but not in "
+ + "CONNECTING state. Ignoring.");
+ return;
+ }
+
+ mgr.mState = STATE_UNCONNECTED;
+ mgr.mBinder = null;
+ mgr.mLooper = null;
+ mgr.mClientId = 0;
+ }
+ nanManager.clear();
+ originalCallback.onConnectFail(msg.arg1);
break;
case CALLBACK_NAN_DOWN:
- mOriginalCallback.onNanDown(msg.arg1);
+ synchronized (mgr.mLock) {
+ mgr.mState = STATE_UNCONNECTED;
+ mgr.mBinder = null;
+ mgr.mLooper = null;
+ mgr.mClientId = 0;
+ }
+ nanManager.clear();
+ originalCallback.onNanDown(msg.arg1);
break;
case CALLBACK_IDENTITY_CHANGED:
- mOriginalCallback.onIdentityChanged();
+ originalCallback.onIdentityChanged();
break;
}
}
}
@Override
- public void onConfigCompleted(ConfigRequest completedConfig) {
- if (VDBG) Log.v(TAG, "onConfigCompleted: configRequest=" + completedConfig);
+ public void onConnectSuccess() {
+ if (VDBG) Log.v(TAG, "onConnectSuccess");
- Message msg = mHandler.obtainMessage(CALLBACK_CONFIG_COMPLETED);
- msg.obj = completedConfig;
+ Message msg = mHandler.obtainMessage(CALLBACK_CONNECT_SUCCESS);
mHandler.sendMessage(msg);
}
@Override
- public void onConfigFailed(ConfigRequest failedConfig, int reason) {
- if (VDBG) {
- Log.v(TAG,
- "onConfigFailed: failedConfig=" + failedConfig + ", reason=" + reason);
- }
+ public void onConnectFail(int reason) {
+ if (VDBG) Log.v(TAG, "onConfigFailed: reason=" + reason);
- Message msg = mHandler.obtainMessage(CALLBACK_CONFIG_FAILED);
+ Message msg = mHandler.obtainMessage(CALLBACK_CONNECT_FAIL);
msg.arg1 = reason;
- msg.obj = failedConfig;
mHandler.sendMessage(msg);
}
}
}
- private class WifiNanSessionCallbackProxy extends IWifiNanSessionCallback.Stub {
+ private static class WifiNanSessionCallbackProxy extends IWifiNanSessionCallback.Stub {
private static final int CALLBACK_SESSION_STARTED = 0;
- private static final int CALLBACK_SESSION_CONFIG_FAIL = 1;
- private static final int CALLBACK_SESSION_TERMINATED = 2;
- private static final int CALLBACK_MATCH = 3;
- private static final int CALLBACK_MESSAGE_SEND_SUCCESS = 4;
- private static final int CALLBACK_MESSAGE_SEND_FAIL = 5;
- private static final int CALLBACK_MESSAGE_RECEIVED = 6;
+ private static final int CALLBACK_SESSION_CONFIG_SUCCESS = 1;
+ private static final int CALLBACK_SESSION_CONFIG_FAIL = 2;
+ private static final int CALLBACK_SESSION_TERMINATED = 3;
+ private static final int CALLBACK_MATCH = 4;
+ private static final int CALLBACK_MESSAGE_SEND_SUCCESS = 5;
+ private static final int CALLBACK_MESSAGE_SEND_FAIL = 6;
+ private static final int CALLBACK_MESSAGE_RECEIVED = 7;
private static final String MESSAGE_BUNDLE_KEY_PEER_ID = "peer_id";
private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2";
+ private final WeakReference<WifiNanManager> mNanManager;
private final boolean mIsPublish;
private final WifiNanSessionCallback mOriginalCallback;
private final Handler mHandler;
private WifiNanSession mSession;
- WifiNanSessionCallbackProxy(Looper looper, boolean isPublish,
+ WifiNanSessionCallbackProxy(WifiNanManager mgr, Looper looper, boolean isPublish,
WifiNanSessionCallback originalCallback) {
+ mNanManager = new WeakReference<>(mgr);
mIsPublish = isPublish;
mOriginalCallback = originalCallback;
@Override
public void handleMessage(Message msg) {
if (DBG) Log.d(TAG, "What=" + msg.what + ", msg=" + msg);
+
+ if (mNanManager.get() == null) {
+ Log.w(TAG, "WifiNanSessionCallbackProxy: handleMessage post GC");
+ return;
+ }
+
switch (msg.what) {
case CALLBACK_SESSION_STARTED:
onProxySessionStarted(msg.arg1);
break;
+ case CALLBACK_SESSION_CONFIG_SUCCESS:
+ mOriginalCallback.onSessionConfigSuccess();
+ break;
case CALLBACK_SESSION_CONFIG_FAIL:
- onProxySessionConfigFail(msg.arg1);
+ mOriginalCallback.onSessionConfigFail(msg.arg1);
+ if (mSession == null) {
+ /*
+ * creation failed (as opposed to update
+ * failing)
+ */
+ mNanManager.clear();
+ }
break;
case CALLBACK_SESSION_TERMINATED:
onProxySessionTerminated(msg.arg1);
}
@Override
+ public void onSessionConfigSuccess() {
+ if (VDBG) Log.v(TAG, "onSessionConfigSuccess");
+
+ Message msg = mHandler.obtainMessage(CALLBACK_SESSION_CONFIG_SUCCESS);
+ mHandler.sendMessage(msg);
+ }
+
+ @Override
public void onSessionConfigFail(int reason) {
if (VDBG) Log.v(TAG, "onSessionConfigFail: reason=" + reason);
throw new IllegalStateException(
"onSessionStarted: sessionId=" + sessionId + ": session already created!?");
}
+
+ WifiNanManager mgr = mNanManager.get();
+ if (mgr == null) {
+ Log.w(TAG, "onProxySessionStarted: mgr GC'd");
+ return;
+ }
+
if (mIsPublish) {
- WifiNanPublishSession session = new WifiNanPublishSession(WifiNanManager.this,
- sessionId, mOriginalCallback);
+ WifiNanPublishSession session = new WifiNanPublishSession(mgr, sessionId);
mSession = session;
mOriginalCallback.onPublishStarted(session);
} else {
- WifiNanSubscribeSession session = new WifiNanSubscribeSession(WifiNanManager.this,
- sessionId, mOriginalCallback);
+ WifiNanSubscribeSession session = new WifiNanSubscribeSession(mgr, sessionId);
mSession = session;
mOriginalCallback.onSubscribeStarted(session);
}
}
- public void onProxySessionConfigFail(int reason) {
- if (VDBG) Log.v(TAG, "Proxy: onSessionConfigFail: reason=" + reason);
- mOriginalCallback.onSessionConfigFail(reason);
- }
-
public void onProxySessionTerminated(int reason) {
if (VDBG) Log.v(TAG, "Proxy: onSessionTerminated: reason=" + reason);
- mOriginalCallback.onSessionTerminated(reason);
if (mSession != null) {
- mSession.terminate();
+ mSession.setTerminated();
+ mSession = null;
} else {
Log.w(TAG, "Proxy: onSessionTerminated called but mSession is null!?");
}
+ mNanManager.clear();
+ mOriginalCallback.onSessionTerminated(reason);
}
}
}
package android.net.wifi.nan;
+import android.util.Log;
+
/**
* A representation of a NAN publish session. Created when
* {@link WifiNanManager#publish(PublishConfig, WifiNanSessionCallback)} is
* @hide PROPOSED_NAN_API
*/
public class WifiNanPublishSession extends WifiNanSession {
+ private static final String TAG = "WifiNanPublishSession";
+
/**
* {@hide}
*/
- public WifiNanPublishSession(WifiNanManager manager, int sessionId,
- WifiNanSessionCallback callback) {
- super(manager, sessionId, callback);
+ public WifiNanPublishSession(WifiNanManager manager, int sessionId) {
+ super(manager, sessionId);
}
/**
*/
public void updatePublish(PublishConfig publishConfig) {
if (mTerminated) {
- mCallback.onSessionConfigFail(WifiNanSessionCallback.FAIL_REASON_SESSION_TERMINATED);
+ Log.w(TAG, "updatePublish: called on terminated session");
return;
} else {
- mManager.updatePublish(mSessionId, publishConfig);
+ WifiNanManager mgr = mMgr.get();
+ if (mgr == null) {
+ Log.w(TAG, "updatePublish: called post GC on WifiNanManager");
+ return;
+ }
+
+ mgr.updatePublish(mSessionId, publishConfig);
}
}
}
import android.util.Log;
+import java.lang.ref.WeakReference;
+
/**
* A representation of a single publish or subscribe NAN session. This object
* will not be created directly - only its child classes are available:
private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
- protected WifiNanManager mManager;
+ /**
+ * @hide
+ */
+ protected WeakReference<WifiNanManager> mMgr;
+
+ /**
+ * @hide
+ */
protected final int mSessionId;
- protected final WifiNanSessionCallback mCallback;
+ /**
+ * @hide
+ */
protected boolean mTerminated = false;
/**
* {@hide}
*/
- public WifiNanSession(WifiNanManager manager, int sessionId,
- WifiNanSessionCallback callback) {
+ public WifiNanSession(WifiNanManager manager, int sessionId) {
if (VDBG) Log.v(TAG, "New client created: manager=" + manager + ", sessionId=" + sessionId);
- mManager = manager;
+ mMgr = new WeakReference<>(manager);
mSessionId = sessionId;
- mCallback = callback;
}
/**
* additional operations are termination.
*/
public void terminate() {
- mManager.terminateSession(mSessionId);
+ WifiNanManager mgr = mMgr.get();
+ if (mgr == null) {
+ Log.w(TAG, "terminate: called post GC on WifiNanManager");
+ return;
+ }
+ mgr.terminateSession(mSessionId);
mTerminated = true;
- mManager = null;
+ mMgr.clear();
+ }
+
+ /**
+ * Sets the status of the session to terminated - i.e. an indication that
+ * already terminated rather than executing a termination.
+ *
+ * @hide
+ */
+ public void setTerminated() {
+ if (mTerminated) {
+ Log.w(TAG, "terminate: already terminated.");
+ return;
+ }
+ mTerminated = true;
+ mMgr.clear();
}
@Override
Log.w(TAG, "WifiNanSession mSessionId=" + mSessionId
+ " was not explicitly terminated. The session may use resources until "
+ "terminated so step should be done explicitly");
+ terminate();
}
- terminate();
}
/**
*/
public void sendMessage(int peerId, byte[] message, int messageLength, int messageId) {
if (mTerminated) {
- mCallback.onMessageSendFail(messageId,
- WifiNanSessionCallback.FAIL_REASON_SESSION_TERMINATED);
+ Log.w(TAG, "sendMessage: called on terminated session");
return;
- }
+ } else {
+ WifiNanManager mgr = mMgr.get();
+ if (mgr == null) {
+ Log.w(TAG, "sendMessage: called post GC on WifiNanManager");
+ return;
+ }
- mManager.sendMessage(mSessionId, peerId, message, messageLength, messageId);
+ mgr.sendMessage(mSessionId, peerId, message, messageLength, messageId);
+ }
}
}
package android.net.wifi.nan;
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Base class for NAN session events callbacks. Should be extended by
* applications wanting notifications. The callbacks are registered when a
* publish or subscribe session is created using
* {@link WifiNanManager#publish(PublishConfig, WifiNanSessionCallback)} or
* {@link WifiNanManager#subscribe(SubscribeConfig, WifiNanSessionCallback)} .
- * These are callbacks applying to a specific NAN session. Events corresponding
- * to the NAN link are delivered using {@link WifiNanEventCallback}.
+ * These are callbacks applying to a specific NAN session.
* <p>
* A single callback is registered at session creation - it cannot be replaced.
*
* @hide PROPOSED_NAN_API
*/
public class WifiNanSessionCallback {
+ @IntDef({
+ REASON_NO_RESOURCES, REASON_INVALID_ARGS, REASON_NO_MATCH_SESSION,
+ REASON_TX_FAIL, REASON_OTHER })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SessionReasonCodes {
+ }
+
+ @IntDef({
+ TERMINATE_REASON_DONE, TERMINATE_REASON_FAIL })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SessionTerminateCodes {
+ }
+
/**
- * Failure reason flag for {@link WifiNanEventCallback} and
- * {@link WifiNanSessionCallback} callbacks. Indicates no resources to
- * execute the requested operation.
+ * Failure reason flag for {@link WifiNanSessionCallback} callbacks.
+ * Indicates no resources to execute the requested operation.
*/
- public static final int FAIL_REASON_NO_RESOURCES = 0;
+ public static final int REASON_NO_RESOURCES = 0;
/**
- * Failure reason flag for {@link WifiNanEventCallback} and
- * {@link WifiNanSessionCallback} callbacks. Indicates invalid argument in
- * the requested operation.
+ * Failure reason flag for {@link WifiNanSessionCallback} callbacks.
+ * Indicates invalid argument in the requested operation.
*/
- public static final int FAIL_REASON_INVALID_ARGS = 1;
+ public static final int REASON_INVALID_ARGS = 1;
/**
- * Failure reason flag for {@link WifiNanEventCallback} and
- * {@link WifiNanSessionCallback} callbacks. Indicates a message is
- * transmitted without a match (i.e. a discovery) occurring first.
+ * Failure reason flag for {@link WifiNanSessionCallback} callbacks.
+ * Indicates a message is transmitted without a match (i.e. a discovery)
+ * occurring first.
*/
- public static final int FAIL_REASON_NO_MATCH_SESSION = 2;
+ public static final int REASON_NO_MATCH_SESSION = 2;
/**
- * Failure reason flag for {@link WifiNanSessionCallback} callbacks.
- * Indicates that a command has been issued to a session which is
- * terminated. Session termination may have been caused explicitly by the
- * user using the {@code WifiNanSession#terminate()} or implicitly as a
- * result of the original session reaching its lifetime or being terminated
- * due to an error.
+ * Failure reason flag for
+ * {@link WifiNanSessionCallback#onMessageSendFail(int, int)} callback.
+ * Indicates transmission failure: this may be due to local transmission
+ * failure or to no ACK received - i.e. remote device didn't receive the
+ * sent message.
*/
- public static final int FAIL_REASON_SESSION_TERMINATED = 3;
+ public static final int REASON_TX_FAIL = 3;
/**
- * Failure reason flag for {@link WifiNanEventCallback} and
- * {@link WifiNanSessionCallback} callbacks. Indicates an unspecified error
- * occurred during the operation.
+ * Failure reason flag for {@link WifiNanSessionCallback} callbacks.
+ * Indicates an unspecified error occurred during the operation.
*/
- public static final int FAIL_REASON_OTHER = 4;
+ public static final int REASON_OTHER = 4;
/**
* Failure reason flag for
* requested operations (per {@link PublishConfig} or
* {@link SubscribeConfig}) have been executed.
*/
- public static final int TERMINATE_REASON_DONE = 0;
+ public static final int TERMINATE_REASON_DONE = 100;
/**
* Failure reason flag for
* Indicates that publish or subscribe session is terminated due to a
* failure.
*/
- public static final int TERMINATE_REASON_FAIL = 1;
+ public static final int TERMINATE_REASON_FAIL = 101;
/**
* Called when a publish operation is started successfully.
/* empty */
}
+ /**
+ * Called when a session update configuration (publish or subscribe update)
+ * succeeds.
+ */
+ public void onSessionConfigSuccess() {
+ /* empty */
+ }
/**
* Called when a session configuration (publish or subscribe setup or
* update) fails.
*
* @param reason The failure reason using
- * {@code WifiNanSessionCallback.FAIL_*} codes.
+ * {@code WifiNanSessionCallback.REASON_*} codes.
*/
- public void onSessionConfigFail(int reason) {
+ public void onSessionConfigFail(@SessionReasonCodes int reason) {
/* empty */
}
* @param reason The termination reason using
* {@code WifiNanSessionCallback.TERMINATE_*} codes.
*/
- public void onSessionTerminated(int reason) {
+ public void onSessionTerminated(@SessionTerminateCodes int reason) {
/* empty */
}
* - never both
*
* @param reason The failure reason using
- * {@code WifiNanSessionCallback.FAIL_*} codes.
+ * {@code WifiNanSessionCallback.REASON_*} codes.
*/
- public void onMessageSendFail(@SuppressWarnings("unused") int messageId, int reason) {
+ public void onMessageSendFail(@SuppressWarnings("unused") int messageId,
+ @SessionReasonCodes int reason) {
/* empty */
}
package android.net.wifi.nan;
+import android.util.Log;
+
/**
* A representation of a NAN subscribe session. Created when
* {@link WifiNanManager#subscribe(SubscribeConfig, WifiNanSessionCallback)} is
* @hide PROPOSED_NAN_API
*/
public class WifiNanSubscribeSession extends WifiNanSession {
+ private static final String TAG = "WifiNanSubscribeSession";
+
/**
* {@hide}
*/
- public WifiNanSubscribeSession(WifiNanManager manager, int sessionId,
- WifiNanSessionCallback callback) {
- super(manager, sessionId, callback);
+ public WifiNanSubscribeSession(WifiNanManager manager, int sessionId) {
+ super(manager, sessionId);
}
/**
*/
public void updateSubscribe(SubscribeConfig subscribeConfig) {
if (mTerminated) {
- mCallback.onSessionConfigFail(WifiNanSessionCallback.FAIL_REASON_SESSION_TERMINATED);
+ Log.w(TAG, "updateSubscribe: called on terminated session");
return;
} else {
- mManager.updateSubscribe(mSessionId, subscribeConfig);
+ WifiNanManager mgr = mMgr.get();
+ if (mgr == null) {
+ Log.w(TAG, "updateSubscribe: called post GC on WifiNanManager");
+ return;
+ }
+
+ mgr.updateSubscribe(mSessionId, subscribeConfig);
}
}
}