| /* |
| * 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 int mClientId = -1; |
| 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 (mClientId != -1) { |
| Log.w(TAG, "connect(): mClientId=" + mClientId |
| + ": seems to calling connect() without disconnecting() first!"); |
| } |
| if (mBinder == null) { |
| mBinder = new Binder(); |
| } |
| mClientId = 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(mClientId, mBinder); |
| mBinder = null; |
| mClientId = -1; |
| } 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(mClientId, 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 publishConfig The {@link PublishConfig} specifying the |
| * configuration of 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(PublishConfig publishConfig, |
| WifiNanSessionListener listener, int events) { |
| return publishRaw(publishConfig, listener, |
| events | WifiNanSessionListener.LISTEN_HIDDEN_FLAGS); |
| } |
| |
| /** |
| * Same as publish(*) but does not modify the event flag |
| * |
| * @hide |
| */ |
| public WifiNanPublishSession publishRaw(PublishConfig publishConfig, |
| WifiNanSessionListener listener, int events) { |
| 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 (listener == null) { |
| throw new IllegalArgumentException("Invalid listener - must not be null"); |
| } |
| |
| int sessionId; |
| |
| try { |
| sessionId = mService.createSession(mClientId, listener.callback, events); |
| if (DBG) Log.d(TAG, "publish: session created - sessionId=" + sessionId); |
| mService.publish(mClientId, sessionId, publishConfig); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| |
| return new WifiNanPublishSession(this, sessionId); |
| } |
| |
| /** |
| * {@hide} |
| */ |
| public void publish(int sessionId, PublishConfig publishConfig) { |
| 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"); |
| } |
| |
| try { |
| mService.publish(mClientId, sessionId, publishConfig); |
| } 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 subscribeConfig The {@link SubscribeConfig} specifying the |
| * configuration of 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(SubscribeConfig subscribeConfig, |
| WifiNanSessionListener listener, int events) { |
| return subscribeRaw(subscribeConfig, listener, |
| events | WifiNanSessionListener.LISTEN_HIDDEN_FLAGS); |
| } |
| |
| /** |
| * Same as subscribe(*) but does not modify the event flag |
| * |
| * @hide |
| */ |
| public WifiNanSubscribeSession subscribeRaw(SubscribeConfig subscribeConfig, |
| WifiNanSessionListener listener, int events) { |
| if (VDBG) { |
| 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 sessionId; |
| |
| try { |
| sessionId = mService.createSession(mClientId, listener.callback, events); |
| if (DBG) Log.d(TAG, "subscribe: session created - sessionId=" + sessionId); |
| mService.subscribe(mClientId, sessionId, subscribeConfig); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| |
| return new WifiNanSubscribeSession(this, sessionId); |
| } |
| |
| /** |
| * {@hide} |
| */ |
| public void subscribe(int sessionId, SubscribeConfig subscribeConfig) { |
| if (VDBG) { |
| 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"); |
| } |
| |
| try { |
| mService.subscribe(mClientId, sessionId, subscribeConfig); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * {@hide} |
| */ |
| public void stopSession(int sessionId) { |
| if (DBG) Log.d(TAG, "Stop NAN session #" + sessionId); |
| |
| try { |
| mService.stopSession(mClientId, 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(mClientId, 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(mClientId, sessionId, peerId, message, messageLength, messageId); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| } |