blob: 667c4b1de6d06f94da485eb4ef802bca8ea64afb [file] [log] [blame]
Etan Cohen20d329b2015-09-29 13:49:02 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net.wifi.nan;
18
19import android.os.Binder;
20import android.os.IBinder;
21import android.os.RemoteException;
22import android.util.Log;
23
24/**
25 * This class provides the primary API for managing Wi-Fi NAN operation:
26 * including discovery and data-links. Get an instance of this class by calling
27 * {@link android.content.Context#getSystemService(String)
28 * Context.getSystemService(Context.WIFI_NAN_SERVICE)}.
29 * <p>
30 * The class provides access to:
31 * <ul>
32 * <li>Configure a NAN connection and register for events.
33 * <li>Create publish and subscribe sessions.
34 * <li>Create NAN network specifier to be used to create a NAN network.
35 * </ul>
36 *
37 * @hide PROPOSED_NAN_API
38 */
39public class WifiNanManager {
40 private static final String TAG = "WifiNanManager";
Etan Cohen7d6c3892016-02-11 14:57:00 -080041 private static final boolean DBG = false;
Etan Cohen20d329b2015-09-29 13:49:02 -070042 private static final boolean VDBG = false; // STOPSHIP if true
43
44 private IBinder mBinder;
45
46 private IWifiNanManager mService;
47
48 /**
49 * {@hide}
50 */
51 public WifiNanManager(IWifiNanManager service) {
52 mService = service;
53 }
54
55 /**
56 * Re-connect to the Wi-Fi NAN service - enabling the application to execute
57 * {@link WifiNanManager} APIs. Application don't normally need to call this
58 * API since it is executed in the constructor. However, applications which
59 * have explicitly {@link WifiNanManager#disconnect()} need to call this
60 * function to re-connect.
61 *
62 * @param listener A listener extended from {@link WifiNanEventListener}.
63 * @param events The set of events to be delivered to the {@code listener}.
64 * OR'd event flags from {@link WifiNanEventListener
65 * NanEventListener.LISTEN*}.
66 */
67 public void connect(WifiNanEventListener listener, int events) {
68 try {
69 if (VDBG) Log.v(TAG, "connect()");
70 if (listener == null) {
71 throw new IllegalArgumentException("Invalid listener - must not be null");
72 }
73 if (mBinder == null) {
74 mBinder = new Binder();
75 }
76 mService.connect(mBinder, listener.callback, events);
77 } catch (RemoteException e) {
78 Log.w(TAG, "connect RemoteException (FYI - ignoring): " + e);
79 }
80 }
81
82 /**
83 * Disconnect from the Wi-Fi NAN service and destroy all outstanding
84 * operations - i.e. all publish and subscribes are terminated, any
85 * outstanding data-link is shut-down, and all requested NAN configurations
86 * are cancelled.
87 * <p>
88 * An application may then re-connect using
89 * {@link WifiNanManager#connect(WifiNanEventListener, int)} .
90 */
91 public void disconnect() {
92 try {
93 if (VDBG) Log.v(TAG, "disconnect()");
94 mService.disconnect(mBinder);
95 mBinder = null;
96 } catch (RemoteException e) {
97 Log.w(TAG, "disconnect RemoteException (FYI - ignoring): " + e);
98 }
99 }
100
101 /**
102 * Requests a NAN configuration, specified by {@link ConfigRequest}. Note
103 * that NAN is a shared resource and the device can only be a member of a
104 * single cluster. Thus the service may merge configuration requests from
105 * multiple applications and configure NAN differently from individual
106 * requests.
107 * <p>
108 * The {@link WifiNanEventListener#onConfigCompleted(ConfigRequest)} will be
109 * called when configuration is completed (if a listener is registered for
110 * this specific event).
111 *
112 * @param configRequest The requested NAN configuration.
113 */
114 public void requestConfig(ConfigRequest configRequest) {
115 if (VDBG) Log.v(TAG, "requestConfig(): configRequest=" + configRequest);
116 try {
117 mService.requestConfig(configRequest);
118 } catch (RemoteException e) {
119 Log.w(TAG, "requestConfig RemoteException (FYI - ignoring): " + e);
120 }
121 }
122
123 /**
124 * Request a NAN publish session. The results of the publish session
125 * operation will result in callbacks to the indicated listener:
126 * {@link WifiNanSessionListener NanSessionListener.on*}.
127 *
128 * @param publishData The {@link PublishData} specifying the contents of the
129 * publish session.
130 * @param publishSettings The {@link PublishSettings} specifying the
131 * settings for the publish session.
132 * @param listener The {@link WifiNanSessionListener} derived objects to be used
133 * for the event callbacks specified by {@code events}.
134 * @param events The list of events to be delivered to the {@code listener}
135 * object. An OR'd value of {@link WifiNanSessionListener
136 * NanSessionListener.LISTEN_*}.
137 * @return The {@link WifiNanPublishSession} which can be used to further
138 * control the publish session.
139 */
140 public WifiNanPublishSession publish(PublishData publishData, PublishSettings publishSettings,
141 WifiNanSessionListener listener, int events) {
142 return publishRaw(publishData, publishSettings, listener,
143 events | WifiNanSessionListener.LISTEN_HIDDEN_FLAGS);
144 }
145
146 /**
147 * Same as publish(*) but does not modify the event flag
148 *
149 * @hide
150 */
151 public WifiNanPublishSession publishRaw(PublishData publishData,
152 PublishSettings publishSettings, WifiNanSessionListener listener, int events) {
153 if (VDBG) Log.v(TAG, "publish(): data='" + publishData + "', settings=" + publishSettings);
154
155 if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_UNSOLICITED
156 && publishData.mRxFilterLength != 0) {
157 throw new IllegalArgumentException("Invalid publish data & settings: UNSOLICITED "
158 + "publishes (active) can't have an Rx filter");
159 }
160 if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_SOLICITED
161 && publishData.mTxFilterLength != 0) {
162 throw new IllegalArgumentException("Invalid publish data & settings: SOLICITED "
163 + "publishes (passive) can't have a Tx filter");
164 }
165 if (listener == null) {
166 throw new IllegalArgumentException("Invalid listener - must not be null");
167 }
168
169 int sessionId;
170
171 try {
172 sessionId = mService.createSession(listener.callback, events);
173 if (DBG) Log.d(TAG, "publish: session created - sessionId=" + sessionId);
174 mService.publish(sessionId, publishData, publishSettings);
175 } catch (RemoteException e) {
176 Log.w(TAG, "createSession/publish RemoteException: " + e);
177 return null;
178 }
179
180 return new WifiNanPublishSession(this, sessionId);
181 }
182
183 /**
184 * {@hide}
185 */
186 public void publish(int sessionId, PublishData publishData, PublishSettings publishSettings) {
187 if (VDBG) Log.v(TAG, "publish(): data='" + publishData + "', settings=" + publishSettings);
188
189 if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_UNSOLICITED
190 && publishData.mRxFilterLength != 0) {
191 throw new IllegalArgumentException("Invalid publish data & settings: UNSOLICITED "
192 + "publishes (active) can't have an Rx filter");
193 }
194 if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_SOLICITED
195 && publishData.mTxFilterLength != 0) {
196 throw new IllegalArgumentException("Invalid publish data & settings: SOLICITED "
197 + "publishes (passive) can't have a Tx filter");
198 }
199
200 try {
201 mService.publish(sessionId, publishData, publishSettings);
202 } catch (RemoteException e) {
203 Log.w(TAG, "publish RemoteException: " + e);
204 }
205 }
206 /**
207 * Request a NAN subscribe session. The results of the subscribe session
208 * operation will result in callbacks to the indicated listener:
209 * {@link WifiNanSessionListener NanSessionListener.on*}.
210 *
211 * @param subscribeData The {@link SubscribeData} specifying the contents of
212 * the subscribe session.
213 * @param subscribeSettings The {@link SubscribeSettings} specifying the
214 * settings for the subscribe session.
215 * @param listener The {@link WifiNanSessionListener} derived objects to be used
216 * for the event callbacks specified by {@code events}.
217 * @param events The list of events to be delivered to the {@code listener}
218 * object. An OR'd value of {@link WifiNanSessionListener
219 * NanSessionListener.LISTEN_*}.
220 * @return The {@link WifiNanSubscribeSession} which can be used to further
221 * control the subscribe session.
222 */
223 public WifiNanSubscribeSession subscribe(SubscribeData subscribeData,
224 SubscribeSettings subscribeSettings,
225 WifiNanSessionListener listener, int events) {
226 return subscribeRaw(subscribeData, subscribeSettings, listener,
227 events | WifiNanSessionListener.LISTEN_HIDDEN_FLAGS);
228 }
229
230 /**
231 * Same as subscribe(*) but does not modify the event flag
232 *
233 * @hide
234 */
235 public WifiNanSubscribeSession subscribeRaw(SubscribeData subscribeData,
236 SubscribeSettings subscribeSettings, WifiNanSessionListener listener, int events) {
237 if (VDBG) {
238 Log.v(TAG, "subscribe(): data='" + subscribeData + "', settings=" + subscribeSettings);
239 }
240
241 if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_ACTIVE
242 && subscribeData.mRxFilterLength != 0) {
243 throw new IllegalArgumentException(
244 "Invalid subscribe data & settings: ACTIVE subscribes can't have an Rx filter");
245 }
246 if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE
247 && subscribeData.mTxFilterLength != 0) {
248 throw new IllegalArgumentException(
249 "Invalid subscribe data & settings: PASSIVE subscribes can't have a Tx filter");
250 }
251
252 int sessionId;
253
254 try {
255 sessionId = mService.createSession(listener.callback, events);
256 if (DBG) Log.d(TAG, "subscribe: session created - sessionId=" + sessionId);
257 mService.subscribe(sessionId, subscribeData, subscribeSettings);
258 } catch (RemoteException e) {
259 Log.w(TAG, "createSession/subscribe RemoteException: " + e);
260 return null;
261 }
262
263 return new WifiNanSubscribeSession(this, sessionId);
264 }
265
266 /**
267 * {@hide}
268 */
269 public void subscribe(int sessionId, SubscribeData subscribeData,
270 SubscribeSettings subscribeSettings) {
271 if (VDBG) {
272 Log.v(TAG, "subscribe(): data='" + subscribeData + "', settings=" + subscribeSettings);
273 }
274
275 if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_ACTIVE
276 && subscribeData.mRxFilterLength != 0) {
277 throw new IllegalArgumentException(
278 "Invalid subscribe data & settings: ACTIVE subscribes can't have an Rx filter");
279 }
280 if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE
281 && subscribeData.mTxFilterLength != 0) {
282 throw new IllegalArgumentException(
283 "Invalid subscribe data & settings: PASSIVE subscribes can't have a Tx filter");
284 }
285
286 try {
287 mService.subscribe(sessionId, subscribeData, subscribeSettings);
288 } catch (RemoteException e) {
289 Log.w(TAG, "subscribe RemoteException: " + e);
290 }
291 }
292
293 /**
294 * {@hide}
295 */
296 public void stopSession(int sessionId) {
297 if (DBG) Log.d(TAG, "Stop NAN session #" + sessionId);
298
299 try {
300 mService.stopSession(sessionId);
301 } catch (RemoteException e) {
302 Log.w(TAG, "stopSession RemoteException (FYI - ignoring): " + e);
303 }
304 }
305
306 /**
307 * {@hide}
308 */
309 public void destroySession(int sessionId) {
310 if (DBG) Log.d(TAG, "Destroy NAN session #" + sessionId);
311
312 try {
313 mService.destroySession(sessionId);
314 } catch (RemoteException e) {
315 Log.w(TAG, "destroySession RemoteException (FYI - ignoring): " + e);
316 }
317 }
318
319 /**
320 * {@hide}
321 */
Etan Cohenb0fde5d2016-01-26 08:51:02 -0800322 public void sendMessage(int sessionId, int peerId, byte[] message, int messageLength,
323 int messageId) {
Etan Cohen20d329b2015-09-29 13:49:02 -0700324 try {
325 if (VDBG) {
326 Log.v(TAG, "sendMessage(): sessionId=" + sessionId + ", peerId=" + peerId
Etan Cohenb0fde5d2016-01-26 08:51:02 -0800327 + ", messageLength=" + messageLength + ", messageId=" + messageId);
Etan Cohen20d329b2015-09-29 13:49:02 -0700328 }
Etan Cohenb0fde5d2016-01-26 08:51:02 -0800329 mService.sendMessage(sessionId, peerId, message, messageLength, messageId);
Etan Cohen20d329b2015-09-29 13:49:02 -0700330 } catch (RemoteException e) {
331 Log.w(TAG, "subscribe RemoteException (FYI - ignoring): " + e);
332 }
333 }
334}