blob: 1b78bebfbba7532c5bf985e6f83dcd69b742ba3c [file] [log] [blame]
/*
* 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.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
/**
* 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
* {@link android.content.Context#getSystemService(String)
* Context.getSystemService(Context.WIFI_NAN_SERVICE)}.
* <p>
* The class provides access to:
* <ul>
* <li>Configure a NAN connection and register for events.
* <li>Create publish and subscribe sessions.
* <li>Create NAN network specifier to be used to create a NAN network.
* </ul>
*
* @hide PROPOSED_NAN_API
*/
public class WifiNanManager {
private static final String TAG = "WifiNanManager";
private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
private IBinder mBinder;
private IWifiNanManager mService;
/**
* {@hide}
*/
public WifiNanManager(IWifiNanManager service) {
mService = service;
}
/**
* Re-connect to the Wi-Fi NAN service - enabling the application to execute
* {@link WifiNanManager} APIs. Application don't normally need to call this
* API since it is executed in the constructor. However, applications which
* have explicitly {@link WifiNanManager#disconnect()} need to call this
* function to re-connect.
*
* @param listener A listener extended from {@link WifiNanEventListener}.
* @param events The set of events to be delivered to the {@code listener}.
* OR'd event flags from {@link WifiNanEventListener
* NanEventListener.LISTEN*}.
*/
public void connect(WifiNanEventListener listener, int events) {
try {
if (VDBG) Log.v(TAG, "connect()");
if (listener == null) {
throw new IllegalArgumentException("Invalid listener - must not be null");
}
if (mBinder == null) {
mBinder = new Binder();
}
mService.connect(mBinder, listener.callback, events);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Disconnect from the Wi-Fi NAN service and destroy all outstanding
* operations - i.e. all publish and subscribes are terminated, any
* outstanding data-link is shut-down, and all requested NAN configurations
* are cancelled.
* <p>
* An application may then re-connect using
* {@link WifiNanManager#connect(WifiNanEventListener, int)} .
*/
public void disconnect() {
try {
if (VDBG) Log.v(TAG, "disconnect()");
mService.disconnect(mBinder);
mBinder = null;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* 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 WifiNanEventListener#onConfigCompleted(ConfigRequest)} will be
* called when configuration is completed (if a listener 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);
try {
mService.requestConfig(configRequest);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Request a NAN publish session. The results of the publish session
* operation will result in callbacks to the indicated listener:
* {@link WifiNanSessionListener NanSessionListener.on*}.
*
* @param publishData The {@link PublishData} specifying the contents of the
* publish session.
* @param publishSettings The {@link PublishSettings} specifying the
* settings for the publish session.
* @param listener The {@link WifiNanSessionListener} derived objects to be used
* for the event callbacks specified by {@code events}.
* @param events The list of events to be delivered to the {@code listener}
* object. An OR'd value of {@link WifiNanSessionListener
* NanSessionListener.LISTEN_*}.
* @return The {@link WifiNanPublishSession} which can be used to further
* control the publish session.
*/
public WifiNanPublishSession publish(PublishData publishData, PublishSettings publishSettings,
WifiNanSessionListener listener, int events) {
return publishRaw(publishData, publishSettings, listener,
events | WifiNanSessionListener.LISTEN_HIDDEN_FLAGS);
}
/**
* Same as publish(*) but does not modify the event flag
*
* @hide
*/
public WifiNanPublishSession publishRaw(PublishData publishData,
PublishSettings publishSettings, WifiNanSessionListener listener, int events) {
if (VDBG) Log.v(TAG, "publish(): data='" + publishData + "', settings=" + publishSettings);
if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_UNSOLICITED
&& publishData.mRxFilterLength != 0) {
throw new IllegalArgumentException("Invalid publish data & settings: UNSOLICITED "
+ "publishes (active) can't have an Rx filter");
}
if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_SOLICITED
&& publishData.mTxFilterLength != 0) {
throw new IllegalArgumentException("Invalid publish data & settings: SOLICITED "
+ "publishes (passive) can't have a Tx filter");
}
if (listener == null) {
throw new IllegalArgumentException("Invalid listener - must not be null");
}
int sessionId;
try {
sessionId = mService.createSession(listener.callback, events);
if (DBG) Log.d(TAG, "publish: session created - sessionId=" + sessionId);
mService.publish(sessionId, publishData, publishSettings);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return new WifiNanPublishSession(this, sessionId);
}
/**
* {@hide}
*/
public void publish(int sessionId, PublishData publishData, PublishSettings publishSettings) {
if (VDBG) Log.v(TAG, "publish(): data='" + publishData + "', settings=" + publishSettings);
if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_UNSOLICITED
&& publishData.mRxFilterLength != 0) {
throw new IllegalArgumentException("Invalid publish data & settings: UNSOLICITED "
+ "publishes (active) can't have an Rx filter");
}
if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_SOLICITED
&& publishData.mTxFilterLength != 0) {
throw new IllegalArgumentException("Invalid publish data & settings: SOLICITED "
+ "publishes (passive) can't have a Tx filter");
}
try {
mService.publish(sessionId, publishData, publishSettings);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Request a NAN subscribe session. The results of the subscribe session
* operation will result in callbacks to the indicated listener:
* {@link WifiNanSessionListener NanSessionListener.on*}.
*
* @param subscribeData The {@link SubscribeData} specifying the contents of
* the subscribe session.
* @param subscribeSettings The {@link SubscribeSettings} specifying the
* settings for the subscribe session.
* @param listener The {@link WifiNanSessionListener} derived objects to be used
* for the event callbacks specified by {@code events}.
* @param events The list of events to be delivered to the {@code listener}
* object. An OR'd value of {@link WifiNanSessionListener
* NanSessionListener.LISTEN_*}.
* @return The {@link WifiNanSubscribeSession} which can be used to further
* control the subscribe session.
*/
public WifiNanSubscribeSession subscribe(SubscribeData subscribeData,
SubscribeSettings subscribeSettings,
WifiNanSessionListener listener, int events) {
return subscribeRaw(subscribeData, subscribeSettings, listener,
events | WifiNanSessionListener.LISTEN_HIDDEN_FLAGS);
}
/**
* Same as subscribe(*) but does not modify the event flag
*
* @hide
*/
public WifiNanSubscribeSession subscribeRaw(SubscribeData subscribeData,
SubscribeSettings subscribeSettings, WifiNanSessionListener listener, int events) {
if (VDBG) {
Log.v(TAG, "subscribe(): data='" + subscribeData + "', settings=" + subscribeSettings);
}
if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_ACTIVE
&& subscribeData.mRxFilterLength != 0) {
throw new IllegalArgumentException(
"Invalid subscribe data & settings: ACTIVE subscribes can't have an Rx filter");
}
if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE
&& subscribeData.mTxFilterLength != 0) {
throw new IllegalArgumentException(
"Invalid subscribe data & settings: PASSIVE subscribes can't have a Tx filter");
}
int sessionId;
try {
sessionId = mService.createSession(listener.callback, events);
if (DBG) Log.d(TAG, "subscribe: session created - sessionId=" + sessionId);
mService.subscribe(sessionId, subscribeData, subscribeSettings);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return new WifiNanSubscribeSession(this, sessionId);
}
/**
* {@hide}
*/
public void subscribe(int sessionId, SubscribeData subscribeData,
SubscribeSettings subscribeSettings) {
if (VDBG) {
Log.v(TAG, "subscribe(): data='" + subscribeData + "', settings=" + subscribeSettings);
}
if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_ACTIVE
&& subscribeData.mRxFilterLength != 0) {
throw new IllegalArgumentException(
"Invalid subscribe data & settings: ACTIVE subscribes can't have an Rx filter");
}
if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE
&& subscribeData.mTxFilterLength != 0) {
throw new IllegalArgumentException(
"Invalid subscribe data & settings: PASSIVE subscribes can't have a Tx filter");
}
try {
mService.subscribe(sessionId, subscribeData, subscribeSettings);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* {@hide}
*/
public void stopSession(int sessionId) {
if (DBG) Log.d(TAG, "Stop NAN session #" + sessionId);
try {
mService.stopSession(sessionId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* {@hide}
*/
public void destroySession(int sessionId) {
if (DBG) Log.d(TAG, "Destroy NAN session #" + sessionId);
try {
mService.destroySession(sessionId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* {@hide}
*/
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);
}
mService.sendMessage(sessionId, peerId, message, messageLength, messageId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}