1 /*
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 
17 package android.net.wifi.nan;
18 
19 import android.os.Bundle;
20 import android.os.Handler;
21 import android.os.Looper;
22 import android.os.Message;
23 import android.util.Log;
24 
25 /**
26  * Base class for NAN session events callbacks. Should be extended by
27  * applications wanting notifications. The callbacks are registered when a
28  * publish or subscribe session is created using
29  * {@link WifiNanManager#publish(PublishData, PublishSettings, WifiNanSessionListener, int)}
30  * or
31  * {@link WifiNanManager#subscribe(SubscribeData, SubscribeSettings, WifiNanSessionListener, int)}
32  * . These are callbacks applying to a specific NAN session. Events
33  * corresponding to the NAN link are delivered using {@link WifiNanEventListener}.
34  * <p>
35  * A single listener is registered at session creation - it cannot be replaced.
36  * <p>
37  * During registration specify which specific events are desired using a set of
38  * {@code NanSessionListener.LISTEN_*} flags OR'd together. Only those events
39  * will be delivered to the registered listener. Override those callbacks
40  * {@code NanSessionListener.on*} for the registered events.
41  *
42  * @hide PROPOSED_NAN_API
43  */
44 public class WifiNanSessionListener {
45     private static final String TAG = "WifiNanSessionListener";
46     private static final boolean DBG = false;
47     private static final boolean VDBG = false; // STOPSHIP if true
48 
49     /**
50      * Publish fail callback event registration flag. Corresponding callback is
51      * {@link WifiNanSessionListener#onPublishFail(int)}.
52      *
53      * @hide
54      */
55     public static final int LISTEN_PUBLISH_FAIL = 0x1 << 0;
56 
57     /**
58      * Publish terminated callback event registration flag. Corresponding
59      * callback is {@link WifiNanSessionListener#onPublishTerminated(int)}.
60      */
61     public static final int LISTEN_PUBLISH_TERMINATED = 0x1 << 1;
62 
63     /**
64      * Subscribe fail callback event registration flag. Corresponding callback
65      * is {@link WifiNanSessionListener#onSubscribeFail(int)}.
66      *
67      * @hide
68      */
69     public static final int LISTEN_SUBSCRIBE_FAIL = 0x1 << 2;
70 
71     /**
72      * Subscribe terminated callback event registration flag. Corresponding
73      * callback is {@link WifiNanSessionListener#onSubscribeTerminated(int)}.
74      */
75     public static final int LISTEN_SUBSCRIBE_TERMINATED = 0x1 << 3;
76 
77     /**
78      * Match (discovery: publish or subscribe) callback event registration flag.
79      * Corresponding callback is
80      * {@link WifiNanSessionListener#onMatch(int, byte[], int, byte[], int)}.
81      *
82      * @hide
83      */
84     public static final int LISTEN_MATCH = 0x1 << 4;
85 
86     /**
87      * Message sent successfully callback event registration flag. Corresponding
88      * callback is {@link WifiNanSessionListener#onMessageSendSuccess()}.
89      *
90      * @hide
91      */
92     public static final int LISTEN_MESSAGE_SEND_SUCCESS = 0x1 << 5;
93 
94     /**
95      * Message sending failure callback event registration flag. Corresponding
96      * callback is {@link WifiNanSessionListener#onMessageSendFail(int)}.
97      *
98      * @hide
99      */
100     public static final int LISTEN_MESSAGE_SEND_FAIL = 0x1 << 6;
101 
102     /**
103      * Message received callback event registration flag. Corresponding callback
104      * is {@link WifiNanSessionListener#onMessageReceived(int, byte[], int)}.
105      *
106      * @hide
107      */
108     public static final int LISTEN_MESSAGE_RECEIVED = 0x1 << 7;
109 
110     /**
111      * List of hidden events: which are mandatory - i.e. they will be added to
112      * every request.
113      *
114      * @hide
115      */
116     public static final int LISTEN_HIDDEN_FLAGS = LISTEN_PUBLISH_FAIL | LISTEN_SUBSCRIBE_FAIL
117             | LISTEN_MATCH | LISTEN_MESSAGE_SEND_SUCCESS | LISTEN_MESSAGE_SEND_FAIL
118             | LISTEN_MESSAGE_RECEIVED;
119 
120     /**
121      * Failure reason flag for {@link WifiNanEventListener} and
122      * {@link WifiNanSessionListener} callbacks. Indicates no resources to execute
123      * the requested operation.
124      */
125     public static final int FAIL_REASON_NO_RESOURCES = 0;
126 
127     /**
128      * Failure reason flag for {@link WifiNanEventListener} and
129      * {@link WifiNanSessionListener} callbacks. Indicates invalid argument in the
130      * requested operation.
131      */
132     public static final int FAIL_REASON_INVALID_ARGS = 1;
133 
134     /**
135      * Failure reason flag for {@link WifiNanEventListener} and
136      * {@link WifiNanSessionListener} callbacks. Indicates a message is transmitted
137      * without a match (i.e. a discovery) occurring first.
138      */
139     public static final int FAIL_REASON_NO_MATCH_SESSION = 2;
140 
141     /**
142      * Failure reason flag for {@link WifiNanEventListener} and
143      * {@link WifiNanSessionListener} callbacks. Indicates an unspecified error
144      * occurred during the operation.
145      */
146     public static final int FAIL_REASON_OTHER = 3;
147 
148     /**
149      * Failure reason flag for
150      * {@link WifiNanSessionListener#onPublishTerminated(int)} and
151      * {@link WifiNanSessionListener#onSubscribeTerminated(int)} callbacks.
152      * Indicates that publish or subscribe session is done - i.e. all the
153      * requested operations (per {@link PublishSettings} or
154      * {@link SubscribeSettings}) have been executed.
155      */
156     public static final int TERMINATE_REASON_DONE = 0;
157 
158     /**
159      * Failure reason flag for
160      * {@link WifiNanSessionListener#onPublishTerminated(int)} and
161      * {@link WifiNanSessionListener#onSubscribeTerminated(int)} callbacks.
162      * Indicates that publish or subscribe session is terminated due to a
163      * failure.
164      */
165     public static final int TERMINATE_REASON_FAIL = 1;
166 
167     private static final String MESSAGE_BUNDLE_KEY_PEER_ID = "peer_id";
168     private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
169     private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2";
170 
171     private final Handler mHandler;
172 
173     /**
174      * Constructs a {@link WifiNanSessionListener} using the looper of the current
175      * thread. I.e. all callbacks will be delivered on the current thread.
176      */
WifiNanSessionListener()177     public WifiNanSessionListener() {
178         this(Looper.myLooper());
179     }
180 
181     /**
182      * Constructs a {@link WifiNanSessionListener} using the specified looper. I.e.
183      * all callbacks will delivered on the thread of the specified looper.
184      *
185      * @param looper The looper on which to execute the callbacks.
186      */
WifiNanSessionListener(Looper looper)187     public WifiNanSessionListener(Looper looper) {
188         if (VDBG) Log.v(TAG, "ctor: looper=" + looper);
189         mHandler = new Handler(looper) {
190             @Override
191             public void handleMessage(Message msg) {
192                 if (DBG) Log.d(TAG, "What=" + msg.what + ", msg=" + msg);
193                 switch (msg.what) {
194                     case LISTEN_PUBLISH_FAIL:
195                         WifiNanSessionListener.this.onPublishFail(msg.arg1);
196                         break;
197                     case LISTEN_PUBLISH_TERMINATED:
198                         WifiNanSessionListener.this.onPublishTerminated(msg.arg1);
199                         break;
200                     case LISTEN_SUBSCRIBE_FAIL:
201                         WifiNanSessionListener.this.onSubscribeFail(msg.arg1);
202                         break;
203                     case LISTEN_SUBSCRIBE_TERMINATED:
204                         WifiNanSessionListener.this.onSubscribeTerminated(msg.arg1);
205                         break;
206                     case LISTEN_MATCH:
207                         WifiNanSessionListener.this.onMatch(
208                                 msg.getData().getInt(MESSAGE_BUNDLE_KEY_PEER_ID),
209                                 msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE), msg.arg1,
210                                 msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2), msg.arg2);
211                         break;
212                     case LISTEN_MESSAGE_SEND_SUCCESS:
213                         WifiNanSessionListener.this.onMessageSendSuccess(msg.arg1);
214                         break;
215                     case LISTEN_MESSAGE_SEND_FAIL:
216                         WifiNanSessionListener.this.onMessageSendFail(msg.arg1, msg.arg2);
217                         break;
218                     case LISTEN_MESSAGE_RECEIVED:
219                         WifiNanSessionListener.this.onMessageReceived(msg.arg2,
220                                 msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE), msg.arg1);
221                         break;
222                 }
223             }
224         };
225     }
226 
227     /**
228      * Called when a publish operation fails. It is dummy method (empty
229      * implementation printing out a log message). Override to implement your
230      * custom response.
231      *
232      * @param reason The failure reason using {@code NanSessionListener.FAIL_*}
233      *            codes.
234      */
onPublishFail(int reason)235     public void onPublishFail(int reason) {
236         if (VDBG) Log.v(TAG, "onPublishFail: called in stub - override if interested");
237     }
238 
239     /**
240      * Called when a publish operation terminates. Event will only be delivered
241      * if registered using {@link WifiNanSessionListener#LISTEN_PUBLISH_TERMINATED}.
242      * A dummy (empty implementation printing out a warning). Make sure to
243      * override if registered.
244      *
245      * @param reason The termination reason using
246      *            {@code NanSessionListener.TERMINATE_*} codes.
247      */
onPublishTerminated(int reason)248     public void onPublishTerminated(int reason) {
249         Log.w(TAG, "onPublishTerminated: called in stub - override if interested or disable");
250     }
251 
252     /**
253      * Called when a subscribe operation fails. It is dummy method (empty
254      * implementation printing out a log message). Override to implement your
255      * custom response.
256      *
257      * @param reason The failure reason using {@code NanSessionListener.FAIL_*}
258      *            codes.
259      */
onSubscribeFail(int reason)260     public void onSubscribeFail(int reason) {
261         if (VDBG) Log.v(TAG, "onSubscribeFail: called in stub - override if interested");
262     }
263 
264     /**
265      * Called when a subscribe operation terminates. Event will only be
266      * delivered if registered using
267      * {@link WifiNanSessionListener#LISTEN_SUBSCRIBE_TERMINATED}. A dummy (empty
268      * implementation printing out a warning). Make sure to override if
269      * registered.
270      *
271      * @param reason The termination reason using
272      *            {@code NanSessionListener.TERMINATE_*} codes.
273      */
onSubscribeTerminated(int reason)274     public void onSubscribeTerminated(int reason) {
275         Log.w(TAG, "onSubscribeTerminated: called in stub - override if interested or disable");
276     }
277 
278     /**
279      * Called when a discovery (publish or subscribe) operation results in a
280      * match - i.e. when a peer is discovered. It is dummy method (empty
281      * implementation printing out a log message). Override to implement your
282      * custom response.
283      *
284      * @param peerId The ID of the peer matching our discovery operation.
285      * @param serviceSpecificInfo The service specific information (arbitrary
286      *            byte array) provided by the peer as part of its discovery
287      *            packet.
288      * @param serviceSpecificInfoLength The length of the service specific
289      *            information array.
290      * @param matchFilter The filter (Tx on advertiser and Rx on listener) which
291      *            resulted in this match.
292      * @param matchFilterLength The length of the match filter array.
293      */
onMatch(int peerId, byte[] serviceSpecificInfo, int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength)294     public void onMatch(int peerId, byte[] serviceSpecificInfo,
295             int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength) {
296         if (VDBG) Log.v(TAG, "onMatch: called in stub - override if interested");
297     }
298 
299     /**
300      * Called when a message is transmitted successfully - i.e. when we know
301      * that it was received successfully (corresponding to an ACK being
302      * received). It is dummy method (empty implementation printing out a log
303      * message). Override to implement your custom response.
304      * <p>
305      * Note that either this callback or
306      * {@link WifiNanSessionListener#onMessageSendFail(int, int)} will be
307      * received - never both.
308      */
onMessageSendSuccess(int messageId)309     public void onMessageSendSuccess(int messageId) {
310         if (VDBG) Log.v(TAG, "onMessageSendSuccess: called in stub - override if interested");
311     }
312 
313     /**
314      * Called when a message transmission fails - i.e. when no ACK is received.
315      * The hardware will usually attempt to re-transmit several times - this
316      * event is received after all retries are exhausted. There is a possibility
317      * that message was received by the destination successfully but the ACK was
318      * lost. It is dummy method (empty implementation printing out a log
319      * message). Override to implement your custom response.
320      * <p>
321      * Note that either this callback or
322      * {@link WifiNanSessionListener#onMessageSendSuccess(int)} will be received
323      * - never both
324      *
325      * @param reason The failure reason using {@code NanSessionListener.FAIL_*}
326      *            codes.
327      */
onMessageSendFail(int messageId, int reason)328     public void onMessageSendFail(int messageId, int reason) {
329         if (VDBG) Log.v(TAG, "onMessageSendFail: called in stub - override if interested");
330     }
331 
332     /**
333      * Called when a message is received from a discovery session peer. It is
334      * dummy method (empty implementation printing out a log message). Override
335      * to implement your custom response.
336      *
337      * @param peerId The ID of the peer sending the message.
338      * @param message A byte array containing the message.
339      * @param messageLength The length of the byte array containing the relevant
340      *            message bytes.
341      */
onMessageReceived(int peerId, byte[] message, int messageLength)342     public void onMessageReceived(int peerId, byte[] message, int messageLength) {
343         if (VDBG) Log.v(TAG, "onMessageReceived: called in stub - override if interested");
344     }
345 
346     /**
347      * {@hide}
348      */
349     public IWifiNanSessionListener callback = new IWifiNanSessionListener.Stub() {
350         @Override
351         public void onPublishFail(int reason) {
352             if (VDBG) Log.v(TAG, "onPublishFail: reason=" + reason);
353 
354             Message msg = mHandler.obtainMessage(LISTEN_PUBLISH_FAIL);
355             msg.arg1 = reason;
356             mHandler.sendMessage(msg);
357         }
358 
359         @Override
360         public void onPublishTerminated(int reason) {
361             if (VDBG) Log.v(TAG, "onPublishResponse: reason=" + reason);
362 
363             Message msg = mHandler.obtainMessage(LISTEN_PUBLISH_TERMINATED);
364             msg.arg1 = reason;
365             mHandler.sendMessage(msg);
366         }
367 
368         @Override
369         public void onSubscribeFail(int reason) {
370             if (VDBG) Log.v(TAG, "onSubscribeFail: reason=" + reason);
371 
372             Message msg = mHandler.obtainMessage(LISTEN_SUBSCRIBE_FAIL);
373             msg.arg1 = reason;
374             mHandler.sendMessage(msg);
375         }
376 
377         @Override
378         public void onSubscribeTerminated(int reason) {
379             if (VDBG) Log.v(TAG, "onSubscribeTerminated: reason=" + reason);
380 
381             Message msg = mHandler.obtainMessage(LISTEN_SUBSCRIBE_TERMINATED);
382             msg.arg1 = reason;
383             mHandler.sendMessage(msg);
384         }
385 
386         @Override
387         public void onMatch(int peerId, byte[] serviceSpecificInfo,
388                 int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength) {
389             if (VDBG) Log.v(TAG, "onMatch: peerId=" + peerId);
390 
391             Bundle data = new Bundle();
392             data.putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId);
393             data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, serviceSpecificInfo);
394             data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2, matchFilter);
395 
396             Message msg = mHandler.obtainMessage(LISTEN_MATCH);
397             msg.arg1 = serviceSpecificInfoLength;
398             msg.arg2 = matchFilterLength;
399             msg.setData(data);
400             mHandler.sendMessage(msg);
401         }
402 
403         @Override
404         public void onMessageSendSuccess(int messageId) {
405             if (VDBG) Log.v(TAG, "onMessageSendSuccess");
406 
407             Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_SEND_SUCCESS);
408             msg.arg1 = messageId;
409             mHandler.sendMessage(msg);
410         }
411 
412         @Override
413         public void onMessageSendFail(int messageId, int reason) {
414             if (VDBG) Log.v(TAG, "onMessageSendFail: reason=" + reason);
415 
416             Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_SEND_FAIL);
417             msg.arg1 = messageId;
418             msg.arg2 = reason;
419             mHandler.sendMessage(msg);
420         }
421 
422         @Override
423         public void onMessageReceived(int peerId, byte[] message, int messageLength) {
424             if (VDBG) {
425                 Log.v(TAG, "onMessageReceived: peerId='" + peerId + "', messageLength="
426                         + messageLength);
427             }
428 
429             Bundle data = new Bundle();
430             data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, message);
431 
432             Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_RECEIVED);
433             msg.arg1 = messageLength;
434             msg.arg2 = peerId;
435             msg.setData(data);
436             mHandler.sendMessage(msg);
437         }
438     };
439 }
440