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 com.android.server.wifi.nan;
18 
19 import android.net.wifi.nan.ConfigRequest;
20 import android.net.wifi.nan.IWifiNanEventListener;
21 import android.net.wifi.nan.IWifiNanSessionListener;
22 import android.net.wifi.nan.PublishData;
23 import android.net.wifi.nan.PublishSettings;
24 import android.net.wifi.nan.SubscribeData;
25 import android.net.wifi.nan.SubscribeSettings;
26 import android.os.Bundle;
27 import android.os.Handler;
28 import android.os.Looper;
29 import android.os.Message;
30 import android.util.Log;
31 import android.util.SparseArray;
32 
33 import libcore.util.HexEncoding;
34 
35 import java.io.FileDescriptor;
36 import java.io.PrintWriter;
37 import java.util.ArrayList;
38 import java.util.List;
39 
40 public class WifiNanStateManager {
41     private static final String TAG = "WifiNanStateManager";
42     private static final boolean DBG = false;
43     private static final boolean VDBG = false; // STOPSHIP if true
44 
45     private static WifiNanStateManager sNanStateManagerSingleton;
46 
47     private static final int MESSAGE_CONNECT = 0;
48     private static final int MESSAGE_DISCONNECT = 1;
49     private static final int MESSAGE_REQUEST_CONFIG = 4;
50     private static final int MESSAGE_CREATE_SESSION = 5;
51     private static final int MESSAGE_DESTROY_SESSION = 6;
52     private static final int MESSAGE_PUBLISH = 7;
53     private static final int MESSAGE_SUBSCRIBE = 8;
54     private static final int MESSAGE_SEND_MESSAGE = 9;
55     private static final int MESSAGE_STOP_SESSION = 10;
56     private static final int MESSAGE_ON_CONFIG_COMPLETED = 11;
57     private static final int MESSAGE_ON_CONFIG_FAILED = 12;
58     private static final int MESSAGE_ON_NAN_DOWN = 13;
59     private static final int MESSAGE_ON_INTERFACE_CHANGE = 14;
60     private static final int MESSAGE_ON_CLUSTER_CHANGE = 15;
61     private static final int MESSAGE_ON_PUBLISH_SUCCESS = 16;
62     private static final int MESSAGE_ON_PUBLISH_FAIL = 17;
63     private static final int MESSAGE_ON_PUBLISH_TERMINATED = 18;
64     private static final int MESSAGE_ON_SUBSCRIBE_SUCCESS = 19;
65     private static final int MESSAGE_ON_SUBSCRIBE_FAIL = 20;
66     private static final int MESSAGE_ON_SUBSCRIBE_TERMINATED = 21;
67     private static final int MESSAGE_ON_MESSAGE_SEND_SUCCESS = 22;
68     private static final int MESSAGE_ON_MESSAGE_SEND_FAIL = 23;
69     private static final int MESSAGE_ON_UNKNOWN_TRANSACTION = 24;
70     private static final int MESSAGE_ON_MATCH = 25;
71     private static final int MESSAGE_ON_MESSAGE_RECEIVED = 26;
72     private static final int MESSAGE_ON_CAPABILITIES_UPDATED = 27;
73 
74     private static final String MESSAGE_BUNDLE_KEY_SESSION_ID = "session_id";
75     private static final String MESSAGE_BUNDLE_KEY_EVENTS = "events";
76     private static final String MESSAGE_BUNDLE_KEY_PUBLISH_DATA = "publish_data";
77     private static final String MESSAGE_BUNDLE_KEY_PUBLISH_SETTINGS = "publish_settings";
78     private static final String MESSAGE_BUNDLE_KEY_SUBSCRIBE_DATA = "subscribe_data";
79     private static final String MESSAGE_BUNDLE_KEY_SUBSCRIBE_SETTINGS = "subscribe_settings";
80     private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
81     private static final String MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID = "message_peer_id";
82     private static final String MESSAGE_BUNDLE_KEY_MESSAGE_ID = "message_id";
83     private static final String MESSAGE_BUNDLE_KEY_RESPONSE_TYPE = "response_type";
84     private static final String MESSAGE_BUNDLE_KEY_SSI_LENGTH = "ssi_length";
85     private static final String MESSAGE_BUNDLE_KEY_SSI_DATA = "ssi_data";
86     private static final String MESSAGE_BUNDLE_KEY_FILTER_LENGTH = "filter_length";
87     private static final String MESSAGE_BUNDLE_KEY_FILTER_DATA = "filter_data";
88     private static final String MESSAGE_BUNDLE_KEY_MAC_ADDRESS = "mac_address";
89     private static final String MESSAGE_BUNDLE_KEY_MESSAGE_DATA = "message_data";
90     private static final String MESSAGE_BUNDLE_KEY_MESSAGE_LENGTH = "message_length";
91 
92     private WifiNanNative.Capabilities mCapabilities;
93 
94     private WifiNanStateHandler mHandler;
95 
96     // no synchronization necessary: only access through Handler
97     private final SparseArray<WifiNanClientState> mClients = new SparseArray<>();
98     private final SparseArray<TransactionInfoBase> mPendingResponses = new SparseArray<>();
99     private short mNextTransactionId = 1;
100 
WifiNanStateManager()101     private WifiNanStateManager() {
102         // EMPTY: singleton pattern
103     }
104 
getInstance()105     public static WifiNanStateManager getInstance() {
106         if (sNanStateManagerSingleton == null) {
107             sNanStateManagerSingleton = new WifiNanStateManager();
108         }
109 
110         return sNanStateManagerSingleton;
111     }
112 
start(Looper looper)113     public void start(Looper looper) {
114         Log.i(TAG, "start()");
115 
116         mHandler = new WifiNanStateHandler(looper);
117     }
118 
connect(int uid, IWifiNanEventListener listener, int events)119     public void connect(int uid, IWifiNanEventListener listener, int events) {
120         Message msg = mHandler.obtainMessage(MESSAGE_CONNECT);
121         msg.arg1 = uid;
122         msg.arg2 = events;
123         msg.obj = listener;
124         mHandler.sendMessage(msg);
125     }
126 
disconnect(int uid)127     public void disconnect(int uid) {
128         Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT);
129         msg.arg1 = uid;
130         mHandler.sendMessage(msg);
131     }
132 
requestConfig(int uid, ConfigRequest configRequest)133     public void requestConfig(int uid, ConfigRequest configRequest) {
134         Message msg = mHandler.obtainMessage(MESSAGE_REQUEST_CONFIG);
135         msg.arg1 = uid;
136         msg.obj = configRequest;
137         mHandler.sendMessage(msg);
138     }
139 
stopSession(int uid, int sessionId)140     public void stopSession(int uid, int sessionId) {
141         Message msg = mHandler.obtainMessage(MESSAGE_STOP_SESSION);
142         msg.arg1 = uid;
143         msg.arg2 = sessionId;
144         mHandler.sendMessage(msg);
145     }
146 
destroySession(int uid, int sessionId)147     public void destroySession(int uid, int sessionId) {
148         Message msg = mHandler.obtainMessage(MESSAGE_DESTROY_SESSION);
149         msg.arg1 = uid;
150         msg.arg2 = sessionId;
151         mHandler.sendMessage(msg);
152     }
153 
createSession(int uid, int sessionId, IWifiNanSessionListener listener, int events)154     public void createSession(int uid, int sessionId, IWifiNanSessionListener listener,
155             int events) {
156         Bundle data = new Bundle();
157         data.putInt(MESSAGE_BUNDLE_KEY_EVENTS, events);
158 
159         Message msg = mHandler.obtainMessage(MESSAGE_CREATE_SESSION);
160         msg.setData(data);
161         msg.arg1 = uid;
162         msg.arg2 = sessionId;
163         msg.obj = listener;
164         mHandler.sendMessage(msg);
165     }
166 
publish(int uid, int sessionId, PublishData publishData, PublishSettings publishSettings)167     public void publish(int uid, int sessionId, PublishData publishData,
168             PublishSettings publishSettings) {
169         Bundle data = new Bundle();
170         data.putParcelable(MESSAGE_BUNDLE_KEY_PUBLISH_DATA, publishData);
171         data.putParcelable(MESSAGE_BUNDLE_KEY_PUBLISH_SETTINGS, publishSettings);
172 
173         Message msg = mHandler.obtainMessage(MESSAGE_PUBLISH);
174         msg.setData(data);
175         msg.arg1 = uid;
176         msg.arg2 = sessionId;
177         mHandler.sendMessage(msg);
178     }
179 
subscribe(int uid, int sessionId, SubscribeData subscribeData, SubscribeSettings subscribeSettings)180     public void subscribe(int uid, int sessionId, SubscribeData subscribeData,
181             SubscribeSettings subscribeSettings) {
182         Bundle data = new Bundle();
183         data.putParcelable(MESSAGE_BUNDLE_KEY_SUBSCRIBE_DATA, subscribeData);
184         data.putParcelable(MESSAGE_BUNDLE_KEY_SUBSCRIBE_SETTINGS, subscribeSettings);
185 
186         Message msg = mHandler.obtainMessage(MESSAGE_SUBSCRIBE);
187         msg.setData(data);
188         msg.arg1 = uid;
189         msg.arg2 = sessionId;
190         mHandler.sendMessage(msg);
191     }
192 
sendMessage(int uid, int sessionId, int peerId, byte[] message, int messageLength, int messageId)193     public void sendMessage(int uid, int sessionId, int peerId, byte[] message, int messageLength,
194             int messageId) {
195         Bundle data = new Bundle();
196         data.putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
197         data.putInt(MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID, peerId);
198         data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, message);
199         data.putInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID, messageId);
200 
201         Message msg = mHandler.obtainMessage(MESSAGE_SEND_MESSAGE);
202         msg.arg1 = uid;
203         msg.arg2 = messageLength;
204         msg.setData(data);
205         mHandler.sendMessage(msg);
206     }
207 
onCapabilitiesUpdate(short transactionId, WifiNanNative.Capabilities capabilities)208     public void onCapabilitiesUpdate(short transactionId, WifiNanNative.Capabilities capabilities) {
209         Message msg = mHandler.obtainMessage(MESSAGE_ON_CAPABILITIES_UPDATED);
210         msg.arg1 = transactionId;
211         msg.obj = capabilities;
212         mHandler.sendMessage(msg);
213     }
214 
onConfigCompleted(short transactionId)215     public void onConfigCompleted(short transactionId) {
216         Message msg = mHandler.obtainMessage(MESSAGE_ON_CONFIG_COMPLETED);
217         msg.arg1 = transactionId;
218         mHandler.sendMessage(msg);
219     }
220 
onConfigFailed(short transactionId, int reason)221     public void onConfigFailed(short transactionId, int reason) {
222         Message msg = mHandler.obtainMessage(MESSAGE_ON_CONFIG_FAILED);
223         msg.arg1 = transactionId;
224         msg.arg2 = reason;
225         mHandler.sendMessage(msg);
226     }
227 
onPublishSuccess(short transactionId, int publishId)228     public void onPublishSuccess(short transactionId, int publishId) {
229         Message msg = mHandler.obtainMessage(MESSAGE_ON_PUBLISH_SUCCESS);
230         msg.arg1 = transactionId;
231         msg.arg2 = publishId;
232         mHandler.sendMessage(msg);
233     }
234 
onPublishFail(short transactionId, int status)235     public void onPublishFail(short transactionId, int status) {
236         Message msg = mHandler.obtainMessage(MESSAGE_ON_PUBLISH_FAIL);
237         msg.arg1 = transactionId;
238         msg.arg2 = status;
239         mHandler.sendMessage(msg);
240     }
241 
onMessageSendSuccess(short transactionId)242     public void onMessageSendSuccess(short transactionId) {
243         Message msg = mHandler.obtainMessage(MESSAGE_ON_MESSAGE_SEND_SUCCESS);
244         msg.arg1 = transactionId;
245         mHandler.sendMessage(msg);
246     }
247 
onMessageSendFail(short transactionId, int status)248     public void onMessageSendFail(short transactionId, int status) {
249         Message msg = mHandler.obtainMessage(MESSAGE_ON_MESSAGE_SEND_FAIL);
250         msg.arg1 = transactionId;
251         msg.arg2 = status;
252         mHandler.sendMessage(msg);
253     }
254 
onSubscribeSuccess(short transactionId, int subscribeId)255     public void onSubscribeSuccess(short transactionId, int subscribeId) {
256         Message msg = mHandler.obtainMessage(MESSAGE_ON_SUBSCRIBE_SUCCESS);
257         msg.arg1 = transactionId;
258         msg.arg2 = subscribeId;
259         mHandler.sendMessage(msg);
260     }
261 
onSubscribeFail(short transactionId, int status)262     public void onSubscribeFail(short transactionId, int status) {
263         Message msg = mHandler.obtainMessage(MESSAGE_ON_SUBSCRIBE_FAIL);
264         msg.arg1 = transactionId;
265         msg.arg2 = status;
266         mHandler.sendMessage(msg);
267     }
268 
onUnknownTransaction(int responseType, short transactionId, int status)269     public void onUnknownTransaction(int responseType, short transactionId, int status) {
270         Message msg = mHandler.obtainMessage(MESSAGE_ON_UNKNOWN_TRANSACTION);
271         Bundle data = new Bundle();
272         data.putInt(MESSAGE_BUNDLE_KEY_RESPONSE_TYPE, responseType);
273         msg.setData(data);
274         msg.arg1 = transactionId;
275         msg.arg2 = status;
276         mHandler.sendMessage(msg);
277     }
278 
onInterfaceAddressChange(byte[] mac)279     public void onInterfaceAddressChange(byte[] mac) {
280         Message msg = mHandler.obtainMessage(MESSAGE_ON_INTERFACE_CHANGE);
281         msg.obj = mac;
282         mHandler.sendMessage(msg);
283     }
284 
onClusterChange(int flag, byte[] clusterId)285     public void onClusterChange(int flag, byte[] clusterId) {
286         Message msg = mHandler.obtainMessage(MESSAGE_ON_CLUSTER_CHANGE);
287         msg.arg1 = flag;
288         msg.obj = clusterId;
289         mHandler.sendMessage(msg);
290     }
291 
onMatch(int pubSubId, int requestorInstanceId, byte[] peerMac, byte[] serviceSpecificInfo, int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength)292     public void onMatch(int pubSubId, int requestorInstanceId, byte[] peerMac,
293             byte[] serviceSpecificInfo, int serviceSpecificInfoLength, byte[] matchFilter,
294             int matchFilterLength) {
295         Message msg = mHandler.obtainMessage(MESSAGE_ON_MATCH);
296         msg.arg1 = pubSubId;
297         msg.arg2 = requestorInstanceId;
298         Bundle data = new Bundle();
299         data.putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac);
300         data.putByteArray(MESSAGE_BUNDLE_KEY_SSI_DATA, serviceSpecificInfo);
301         data.putInt(MESSAGE_BUNDLE_KEY_SSI_LENGTH, serviceSpecificInfoLength);
302         data.putByteArray(MESSAGE_BUNDLE_KEY_FILTER_DATA, matchFilter);
303         data.putInt(MESSAGE_BUNDLE_KEY_FILTER_LENGTH, matchFilterLength);
304         msg.setData(data);
305         mHandler.sendMessage(msg);
306     }
307 
onPublishTerminated(int publishId, int status)308     public void onPublishTerminated(int publishId, int status) {
309         Message msg = mHandler.obtainMessage(MESSAGE_ON_PUBLISH_TERMINATED);
310         msg.arg1 = publishId;
311         msg.arg2 = status;
312         mHandler.sendMessage(msg);
313     }
314 
onSubscribeTerminated(int subscribeId, int status)315     public void onSubscribeTerminated(int subscribeId, int status) {
316         Message msg = mHandler.obtainMessage(MESSAGE_ON_SUBSCRIBE_TERMINATED);
317         msg.arg1 = subscribeId;
318         msg.arg2 = status;
319         mHandler.sendMessage(msg);
320     }
321 
onMessageReceived(int pubSubId, int requestorInstanceId, byte[] peerMac, byte[] message, int messageLength)322     public void onMessageReceived(int pubSubId, int requestorInstanceId, byte[] peerMac,
323             byte[] message, int messageLength) {
324         Message msg = mHandler.obtainMessage(MESSAGE_ON_MESSAGE_RECEIVED);
325         msg.arg1 = pubSubId;
326         msg.arg2 = requestorInstanceId;
327         Bundle data = new Bundle();
328         data.putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac);
329         data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA, message);
330         data.putInt(MESSAGE_BUNDLE_KEY_MESSAGE_LENGTH, messageLength);
331         msg.setData(data);
332         mHandler.sendMessage(msg);
333     }
334 
onNanDown(int reason)335     public void onNanDown(int reason) {
336         Message msg = mHandler.obtainMessage(MESSAGE_ON_NAN_DOWN);
337         msg.arg1 = reason;
338         mHandler.sendMessage(msg);
339     }
340 
341     private class WifiNanStateHandler extends Handler {
WifiNanStateHandler(android.os.Looper looper)342         WifiNanStateHandler(android.os.Looper looper) {
343             super(looper);
344         }
345 
346         @Override
handleMessage(Message msg)347         public void handleMessage(Message msg) {
348             if (DBG) {
349                 Log.d(TAG, "Message: " + msg.what);
350             }
351             switch (msg.what) {
352                 case MESSAGE_CONNECT: {
353                     if (VDBG) {
354                         Log.d(TAG, "NAN connection request received");
355                     }
356                     connectLocal(msg.arg1, (IWifiNanEventListener) msg.obj, msg.arg2);
357                     break;
358                 }
359                 case MESSAGE_DISCONNECT: {
360                     if (VDBG) {
361                         Log.d(TAG, "NAN disconnection request received");
362                     }
363                     disconnectLocal(msg.arg1);
364                     break;
365                 }
366                 case MESSAGE_REQUEST_CONFIG: {
367                     if (VDBG) {
368                         Log.d(TAG, "NAN configuration request received");
369                     }
370                     requestConfigLocal(msg.arg1, (ConfigRequest) msg.obj);
371                     break;
372                 }
373                 case MESSAGE_CREATE_SESSION: {
374                     if (VDBG) {
375                         Log.d(TAG, "Create session");
376                     }
377                     int events = msg.getData().getInt(MESSAGE_BUNDLE_KEY_EVENTS);
378                     createSessionLocal(msg.arg1, msg.arg2, (IWifiNanSessionListener) msg.obj,
379                             events);
380                     break;
381                 }
382                 case MESSAGE_DESTROY_SESSION: {
383                     if (VDBG) {
384                         Log.d(TAG, "Destroy session");
385                     }
386                     destroySessionLocal(msg.arg1, msg.arg2);
387                     break;
388                 }
389                 case MESSAGE_PUBLISH: {
390                     Bundle data = msg.getData();
391                     PublishData publishData = (PublishData) data
392                             .getParcelable(MESSAGE_BUNDLE_KEY_PUBLISH_DATA);
393                     PublishSettings publishSettings = (PublishSettings) data
394                             .getParcelable(MESSAGE_BUNDLE_KEY_PUBLISH_SETTINGS);
395                     if (VDBG) {
396                         Log.d(TAG,
397                                 "Publish: data='" + publishData + "', settings=" + publishSettings);
398                     }
399 
400                     publishLocal(msg.arg1, msg.arg2, publishData, publishSettings);
401                     break;
402                 }
403                 case MESSAGE_SUBSCRIBE: {
404                     Bundle data = msg.getData();
405                     SubscribeData subscribeData = (SubscribeData) data
406                             .getParcelable(MESSAGE_BUNDLE_KEY_SUBSCRIBE_DATA);
407                     SubscribeSettings subscribeSettings = (SubscribeSettings) data
408                             .getParcelable(MESSAGE_BUNDLE_KEY_SUBSCRIBE_SETTINGS);
409                     if (VDBG) {
410                         Log.d(TAG, "Subscribe: data='" + subscribeData + "', settings="
411                                 + subscribeSettings);
412                     }
413 
414                     subscribeLocal(msg.arg1, msg.arg2, subscribeData, subscribeSettings);
415                     break;
416                 }
417                 case MESSAGE_SEND_MESSAGE: {
418                     Bundle data = msg.getData();
419                     int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
420                     int peerId = data.getInt(MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID);
421                     byte[] message = data.getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE);
422                     int messageId = data.getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID);
423 
424                     if (VDBG) {
425                         Log.d(TAG, "Send Message: message='" + message + "' (ID=" + messageId
426                                 + ") to peerId=" + peerId);
427                     }
428 
429                     sendFollowonMessageLocal(msg.arg1, sessionId, peerId, message, msg.arg2,
430                             messageId);
431                     break;
432                 }
433                 case MESSAGE_STOP_SESSION: {
434                     if (VDBG) {
435                         Log.d(TAG, "Stop session");
436                     }
437                     stopSessionLocal(msg.arg1, msg.arg2);
438                     break;
439                 }
440                 case MESSAGE_ON_CAPABILITIES_UPDATED:
441                     onCapabilitiesUpdatedLocal((short) msg.arg1,
442                             (WifiNanNative.Capabilities) msg.obj);
443                     break;
444                 case MESSAGE_ON_CONFIG_COMPLETED:
445                     onConfigCompletedLocal((short) msg.arg1);
446                     break;
447                 case MESSAGE_ON_CONFIG_FAILED:
448                     onConfigFailedLocal((short) msg.arg1, msg.arg2);
449                     break;
450                 case MESSAGE_ON_NAN_DOWN:
451                     onNanDownLocal(msg.arg1);
452                     break;
453                 case MESSAGE_ON_INTERFACE_CHANGE:
454                     onInterfaceAddressChangeLocal((byte[]) msg.obj);
455                     break;
456                 case MESSAGE_ON_CLUSTER_CHANGE:
457                     onClusterChangeLocal(msg.arg1, (byte[]) msg.obj);
458                     break;
459                 case MESSAGE_ON_PUBLISH_SUCCESS:
460                     onPublishSuccessLocal((short) msg.arg1, msg.arg2);
461                     break;
462                 case MESSAGE_ON_PUBLISH_FAIL:
463                     onPublishFailLocal((short) msg.arg1, msg.arg2);
464                     break;
465                 case MESSAGE_ON_PUBLISH_TERMINATED:
466                     onPublishTerminatedLocal(msg.arg1, msg.arg2);
467                     break;
468                 case MESSAGE_ON_SUBSCRIBE_SUCCESS:
469                     onSubscribeSuccessLocal((short) msg.arg1, msg.arg2);
470                     break;
471                 case MESSAGE_ON_SUBSCRIBE_FAIL:
472                     onSubscribeFailLocal((short) msg.arg1, msg.arg2);
473                     break;
474                 case MESSAGE_ON_SUBSCRIBE_TERMINATED:
475                     onSubscribeTerminatedLocal(msg.arg1, msg.arg2);
476                     break;
477                 case MESSAGE_ON_MESSAGE_SEND_SUCCESS:
478                     onMessageSendSuccessLocal((short) msg.arg1);
479                     break;
480                 case MESSAGE_ON_MESSAGE_SEND_FAIL:
481                     onMessageSendFailLocal((short) msg.arg1, msg.arg2);
482                     break;
483                 case MESSAGE_ON_UNKNOWN_TRANSACTION:
484                     onUnknownTransactionLocal(
485                             msg.getData().getInt(MESSAGE_BUNDLE_KEY_RESPONSE_TYPE),
486                             (short) msg.arg1, msg.arg2);
487                     break;
488                 case MESSAGE_ON_MATCH: {
489                     int pubSubId = msg.arg1;
490                     int requestorInstanceId = msg.arg2;
491                     byte[] peerMac = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS);
492                     byte[] serviceSpecificInfo = msg.getData()
493                             .getByteArray(MESSAGE_BUNDLE_KEY_SSI_DATA);
494                     int serviceSpecificInfoLength = msg.getData()
495                             .getInt(MESSAGE_BUNDLE_KEY_SSI_LENGTH);
496                     byte[] matchFilter = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_FILTER_DATA);
497                     int matchFilterLength = msg.getData().getInt(MESSAGE_BUNDLE_KEY_FILTER_LENGTH);
498                     onMatchLocal(pubSubId, requestorInstanceId, peerMac, serviceSpecificInfo,
499                             serviceSpecificInfoLength, matchFilter, matchFilterLength);
500                     break;
501                 }
502                 case MESSAGE_ON_MESSAGE_RECEIVED: {
503                     int pubSubId = msg.arg1;
504                     int requestorInstanceId = msg.arg2;
505                     byte[] peerMac = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS);
506                     byte[] message = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA);
507                     int messageLength = msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_LENGTH);
508                     onMessageReceivedLocal(pubSubId, requestorInstanceId, peerMac, message,
509                             messageLength);
510                     break;
511                 }
512                 default:
513                     Log.e(TAG, "Unknown message code: " + msg.what);
514             }
515         }
516     }
517 
518     /*
519      * Transaction management classes & operations
520      */
521 
522     // non-synchronized (should be ok as long as only used from NanStateManager,
523     // NanClientState, and NanSessionState)
createNextTransactionId()524     /* package */ short createNextTransactionId() {
525         return mNextTransactionId++;
526     }
527 
528     private static class TransactionInfoBase {
529         short mTransactionId;
530     }
531 
532     private static class TransactionInfoSession extends TransactionInfoBase {
533         public WifiNanClientState mClient;
534         public WifiNanSessionState mSession;
535     }
536 
537     private static class TransactionInfoMessage extends TransactionInfoSession {
538         public int mMessageId;
539     }
540 
541     private static class TransactionInfoConfig extends TransactionInfoBase {
542         public ConfigRequest mConfig;
543     }
544 
allocateAndRegisterTransactionId(TransactionInfoBase info)545     private void allocateAndRegisterTransactionId(TransactionInfoBase info) {
546         info.mTransactionId = createNextTransactionId();
547 
548         mPendingResponses.put(info.mTransactionId, info);
549     }
550 
fillInTransactionInfoSession(TransactionInfoSession info, int uid, int sessionId)551     private void fillInTransactionInfoSession(TransactionInfoSession info, int uid,
552             int sessionId) {
553         WifiNanClientState client = mClients.get(uid);
554         if (client == null) {
555             throw new IllegalStateException(
556                     "getAndRegisterTransactionId: no client exists for uid=" + uid);
557         }
558         info.mClient = client;
559 
560         WifiNanSessionState session = info.mClient.getSession(sessionId);
561         if (session == null) {
562             throw new IllegalStateException(
563                     "getAndRegisterSessionTransactionId: no session exists for uid=" + uid
564                             + ", sessionId=" + sessionId);
565         }
566         info.mSession = session;
567     }
568 
createTransactionInfo()569     private TransactionInfoBase createTransactionInfo() {
570         TransactionInfoBase info = new TransactionInfoBase();
571         allocateAndRegisterTransactionId(info);
572         return info;
573     }
574 
createTransactionInfoSession(int uid, int sessionId)575     private TransactionInfoSession createTransactionInfoSession(int uid, int sessionId) {
576         TransactionInfoSession info = new TransactionInfoSession();
577         fillInTransactionInfoSession(info, uid, sessionId);
578         allocateAndRegisterTransactionId(info);
579         return info;
580     }
581 
createTransactionInfoMessage(int uid, int sessionId, int messageId)582     private TransactionInfoMessage createTransactionInfoMessage(int uid, int sessionId,
583             int messageId) {
584         TransactionInfoMessage info = new TransactionInfoMessage();
585         fillInTransactionInfoSession(info, uid, sessionId);
586         info.mMessageId = messageId;
587         allocateAndRegisterTransactionId(info);
588         return info;
589     }
590 
createTransactionInfoConfig(ConfigRequest configRequest)591     private TransactionInfoConfig createTransactionInfoConfig(ConfigRequest configRequest) {
592         TransactionInfoConfig info = new TransactionInfoConfig();
593         info.mConfig = configRequest;
594         allocateAndRegisterTransactionId(info);
595         return info;
596     }
597 
getAndRemovePendingResponseTransactionInfo(short transactionId)598     private TransactionInfoBase getAndRemovePendingResponseTransactionInfo(short transactionId) {
599         TransactionInfoBase transInfo = mPendingResponses.get(transactionId);
600         if (transInfo != null) {
601             mPendingResponses.remove(transactionId);
602         }
603 
604         return transInfo;
605     }
606 
getNanSessionStateForPubSubId(int pubSubId)607     private WifiNanSessionState getNanSessionStateForPubSubId(int pubSubId) {
608         for (int i = 0; i < mClients.size(); ++i) {
609             WifiNanSessionState session = mClients.valueAt(i)
610                     .getNanSessionStateForPubSubId(pubSubId);
611             if (session != null) {
612                 return session;
613             }
614         }
615 
616         return null;
617     }
618 
619     /*
620      * Actions (calls from API to service)
621      */
connectLocal(int uid, IWifiNanEventListener listener, int events)622     private void connectLocal(int uid, IWifiNanEventListener listener, int events) {
623         if (VDBG) {
624             Log.v(TAG, "connect(): uid=" + uid + ", listener=" + listener + ", events=" + events);
625         }
626 
627         if (mClients.get(uid) != null) {
628             Log.e(TAG, "connect: entry already exists for uid=" + uid);
629             return;
630         }
631 
632         WifiNanClientState client = new WifiNanClientState(uid, listener, events);
633         mClients.put(uid, client);
634     }
635 
disconnectLocal(int uid)636     private void disconnectLocal(int uid) {
637         if (VDBG) {
638             Log.v(TAG, "disconnect(): uid=" + uid);
639         }
640 
641         WifiNanClientState client = mClients.get(uid);
642         mClients.delete(uid);
643 
644         if (client == null) {
645             Log.e(TAG, "disconnect: no entry for uid=" + uid);
646             return;
647         }
648 
649         List<Integer> toRemove = new ArrayList<>();
650         for (int i = 0; i < mPendingResponses.size(); ++i) {
651             TransactionInfoBase info = mPendingResponses.valueAt(i);
652             if (!(info instanceof TransactionInfoSession)) {
653                 continue;
654             }
655             if (((TransactionInfoSession) info).mClient.getUid() == uid) {
656                 toRemove.add(i);
657             }
658         }
659         for (Integer id : toRemove) {
660             mPendingResponses.removeAt(id);
661         }
662 
663         client.destroy();
664 
665         if (mClients.size() == 0) {
666             WifiNanNative.getInstance().disable(createTransactionInfo().mTransactionId);
667             return;
668         }
669 
670         ConfigRequest merged = mergeConfigRequests();
671 
672         WifiNanNative.getInstance()
673                 .enableAndConfigure(createTransactionInfoConfig(merged).mTransactionId, merged);
674     }
675 
requestConfigLocal(int uid, ConfigRequest configRequest)676     private void requestConfigLocal(int uid, ConfigRequest configRequest) {
677         if (VDBG) {
678             Log.v(TAG, "requestConfig(): uid=" + uid + ", configRequest=" + configRequest);
679         }
680 
681         WifiNanClientState client = mClients.get(uid);
682         if (client == null) {
683             Log.e(TAG, "requestConfig: no client exists for uid=" + uid);
684             return;
685         }
686 
687         client.setConfigRequest(configRequest);
688 
689         ConfigRequest merged = mergeConfigRequests();
690 
691         WifiNanNative.getInstance()
692                 .enableAndConfigure(createTransactionInfoConfig(merged).mTransactionId, merged);
693     }
694 
createSessionLocal(int uid, int sessionId, IWifiNanSessionListener listener, int events)695     private void createSessionLocal(int uid, int sessionId, IWifiNanSessionListener listener,
696             int events) {
697         if (VDBG) {
698             Log.v(TAG, "createSession(): uid=" + uid + ", sessionId=" + sessionId + ", listener="
699                     + listener + ", events=" + events);
700         }
701 
702         WifiNanClientState client = mClients.get(uid);
703         if (client == null) {
704             Log.e(TAG, "createSession: no client exists for uid=" + uid);
705             return;
706         }
707 
708         client.createSession(sessionId, listener, events);
709     }
710 
destroySessionLocal(int uid, int sessionId)711     private void destroySessionLocal(int uid, int sessionId) {
712         if (VDBG) {
713             Log.v(TAG, "destroySession(): uid=" + uid + ", sessionId=" + sessionId);
714         }
715 
716         WifiNanClientState client = mClients.get(uid);
717         if (client == null) {
718             Log.e(TAG, "destroySession: no client exists for uid=" + uid);
719             return;
720         }
721 
722         List<Integer> toRemove = new ArrayList<>();
723         for (int i = 0; i < mPendingResponses.size(); ++i) {
724             TransactionInfoBase info = mPendingResponses.valueAt(i);
725             if (!(info instanceof TransactionInfoSession)) {
726                 continue;
727             }
728             TransactionInfoSession infoSession = (TransactionInfoSession) info;
729             if (infoSession.mClient.getUid() == uid
730                     && infoSession.mSession.getSessionId() == sessionId) {
731                 toRemove.add(i);
732             }
733         }
734         for (Integer id : toRemove) {
735             mPendingResponses.removeAt(id);
736         }
737 
738         client.destroySession(sessionId);
739     }
740 
publishLocal(int uid, int sessionId, PublishData publishData, PublishSettings publishSettings)741     private void publishLocal(int uid, int sessionId, PublishData publishData,
742             PublishSettings publishSettings) {
743         if (VDBG) {
744             Log.v(TAG, "publish(): uid=" + uid + ", sessionId=" + sessionId + ", data="
745                     + publishData + ", settings=" + publishSettings);
746         }
747 
748         TransactionInfoSession info = createTransactionInfoSession(uid, sessionId);
749 
750         info.mSession.publish(info.mTransactionId, publishData, publishSettings);
751     }
752 
subscribeLocal(int uid, int sessionId, SubscribeData subscribeData, SubscribeSettings subscribeSettings)753     private void subscribeLocal(int uid, int sessionId, SubscribeData subscribeData,
754             SubscribeSettings subscribeSettings) {
755         if (VDBG) {
756             Log.v(TAG, "subscribe(): uid=" + uid + ", sessionId=" + sessionId + ", data="
757                     + subscribeData + ", settings=" + subscribeSettings);
758         }
759 
760         TransactionInfoSession info = createTransactionInfoSession(uid, sessionId);
761 
762         info.mSession.subscribe(info.mTransactionId, subscribeData, subscribeSettings);
763     }
764 
sendFollowonMessageLocal(int uid, int sessionId, int peerId, byte[] message, int messageLength, int messageId)765     private void sendFollowonMessageLocal(int uid, int sessionId, int peerId, byte[] message,
766             int messageLength, int messageId) {
767         if (VDBG) {
768             Log.v(TAG, "sendMessage(): uid=" + uid + ", sessionId=" + sessionId + ", peerId="
769                     + peerId + ", messageLength=" + messageLength + ", messageId=" + messageId);
770         }
771 
772         TransactionInfoMessage info = createTransactionInfoMessage(uid, sessionId, messageId);
773 
774         info.mSession.sendMessage(info.mTransactionId, peerId, message, messageLength, messageId);
775     }
776 
stopSessionLocal(int uid, int sessionId)777     private void stopSessionLocal(int uid, int sessionId) {
778         if (VDBG) {
779             Log.v(TAG, "stopSession(): uid=" + uid + ", sessionId=" + sessionId);
780         }
781 
782         TransactionInfoSession info = createTransactionInfoSession(uid, sessionId);
783 
784         info.mSession.stop(info.mTransactionId);
785     }
786 
787     /*
788      * Callbacks (calls from HAL/Native to service)
789      */
790 
onCapabilitiesUpdatedLocal(short transactionId, WifiNanNative.Capabilities capabilities)791     private void onCapabilitiesUpdatedLocal(short transactionId,
792             WifiNanNative.Capabilities capabilities) {
793         if (VDBG) {
794             Log.v(TAG, "onCapabilitiesUpdatedLocal: transactionId=" + transactionId
795                     + ", capabilites=" + capabilities);
796         }
797 
798         mCapabilities = capabilities;
799     }
800 
onConfigCompletedLocal(short transactionId)801     private void onConfigCompletedLocal(short transactionId) {
802         if (VDBG) {
803             Log.v(TAG, "onConfigCompleted: transactionId=" + transactionId);
804         }
805 
806         TransactionInfoBase info = getAndRemovePendingResponseTransactionInfo(transactionId);
807         if (info == null) {
808             Log.e(TAG, "onConfigCompleted: no transaction info for transactionId=" + transactionId);
809             return;
810         }
811         if (!(info instanceof TransactionInfoConfig)) {
812             Log.e(TAG, "onConfigCompleted: invalid info structure stored for transactionId="
813                     + transactionId);
814             return;
815         }
816         TransactionInfoConfig infoConfig = (TransactionInfoConfig) info;
817 
818         if (DBG) {
819             Log.d(TAG, "onConfigCompleted: request=" + infoConfig.mConfig);
820         }
821 
822         for (int i = 0; i < mClients.size(); ++i) {
823             WifiNanClientState client = mClients.valueAt(i);
824             client.onConfigCompleted(infoConfig.mConfig);
825         }
826     }
827 
onConfigFailedLocal(short transactionId, int reason)828     private void onConfigFailedLocal(short transactionId, int reason) {
829         if (VDBG) {
830             Log.v(TAG, "onEnableFailed: transactionId=" + transactionId + ", reason=" + reason);
831         }
832 
833         TransactionInfoBase info = getAndRemovePendingResponseTransactionInfo(transactionId);
834         if (info == null) {
835             Log.e(TAG, "onConfigFailed: no transaction info for transactionId=" + transactionId);
836             return;
837         }
838         if (!(info instanceof TransactionInfoConfig)) {
839             Log.e(TAG, "onConfigCompleted: invalid info structure stored for transactionId="
840                     + transactionId);
841             return;
842         }
843         TransactionInfoConfig infoConfig = (TransactionInfoConfig) info;
844 
845         if (DBG) {
846             Log.d(TAG, "onConfigFailed: request=" + infoConfig.mConfig);
847         }
848 
849         for (int i = 0; i < mClients.size(); ++i) {
850             WifiNanClientState client = mClients.valueAt(i);
851             client.onConfigFailed(infoConfig.mConfig, reason);
852         }
853     }
854 
onNanDownLocal(int reason)855     private void onNanDownLocal(int reason) {
856         if (VDBG) {
857             Log.v(TAG, "onNanDown: reason=" + reason);
858         }
859 
860         int interested = 0;
861         for (int i = 0; i < mClients.size(); ++i) {
862             WifiNanClientState client = mClients.valueAt(i);
863             interested += client.onNanDown(reason);
864         }
865 
866         if (interested == 0) {
867             Log.e(TAG, "onNanDown: event received but no listeners registered for this event "
868                     + "- should be disabled from fw!");
869         }
870     }
871 
onInterfaceAddressChangeLocal(byte[] mac)872     private void onInterfaceAddressChangeLocal(byte[] mac) {
873         if (VDBG) {
874             Log.v(TAG, "onInterfaceAddressChange: mac=" + String.valueOf(HexEncoding.encode(mac)));
875         }
876 
877         int interested = 0;
878         for (int i = 0; i < mClients.size(); ++i) {
879             WifiNanClientState client = mClients.valueAt(i);
880             interested += client.onInterfaceAddressChange(mac);
881         }
882 
883         if (interested == 0) {
884             Log.e(TAG, "onInterfaceAddressChange: event received but no listeners registered "
885                     + "for this event - should be disabled from fw!");
886         }
887     }
888 
onClusterChangeLocal(int flag, byte[] clusterId)889     private void onClusterChangeLocal(int flag, byte[] clusterId) {
890         if (VDBG) {
891             Log.v(TAG, "onClusterChange: flag=" + flag + ", clusterId="
892                     + String.valueOf(HexEncoding.encode(clusterId)));
893         }
894 
895         int interested = 0;
896         for (int i = 0; i < mClients.size(); ++i) {
897             WifiNanClientState client = mClients.valueAt(i);
898             interested += client.onClusterChange(flag, clusterId);
899         }
900 
901         if (interested == 0) {
902             Log.e(TAG, "onClusterChange: event received but no listeners registered for this "
903                     + "event - should be disabled from fw!");
904         }
905     }
906 
onPublishSuccessLocal(short transactionId, int publishId)907     private void onPublishSuccessLocal(short transactionId, int publishId) {
908         if (VDBG) {
909             Log.v(TAG, "onPublishSuccess: transactionId=" + transactionId + ", publishId="
910                     + publishId);
911         }
912 
913         TransactionInfoBase info = getAndRemovePendingResponseTransactionInfo(transactionId);
914         if (info == null) {
915             Log.e(TAG, "onPublishSuccess(): no info registered for transactionId=" + transactionId);
916             return;
917         }
918         if (!(info instanceof TransactionInfoSession)) {
919             Log.e(TAG, "onPublishSuccess: invalid info structure stored for transactionId="
920                     + transactionId);
921             return;
922         }
923         TransactionInfoSession infoSession = (TransactionInfoSession) info;
924 
925         infoSession.mSession.onPublishSuccess(publishId);
926     }
927 
onPublishFailLocal(short transactionId, int status)928     private void onPublishFailLocal(short transactionId, int status) {
929         if (VDBG) {
930             Log.v(TAG, "onPublishFail: transactionId=" + transactionId + ", status=" + status);
931         }
932 
933         TransactionInfoBase info = getAndRemovePendingResponseTransactionInfo(transactionId);
934         if (info == null) {
935             Log.e(TAG, "onPublishFail(): no info registered for transactionId=" + transactionId);
936             return;
937         }
938         if (!(info instanceof TransactionInfoSession)) {
939             Log.e(TAG, "onPublishFail: invalid info structure stored for transactionId="
940                     + transactionId);
941             return;
942         }
943         TransactionInfoSession infoSession = (TransactionInfoSession) info;
944 
945         infoSession.mSession.onPublishFail(status);
946     }
947 
onPublishTerminatedLocal(int publishId, int status)948     private void onPublishTerminatedLocal(int publishId, int status) {
949         if (VDBG) {
950             Log.v(TAG, "onPublishTerminated: publishId=" + publishId + ", status=" + status);
951         }
952 
953         WifiNanSessionState session = getNanSessionStateForPubSubId(publishId);
954         if (session == null) {
955             Log.e(TAG, "onPublishTerminated: no session found for publishId=" + publishId);
956             return;
957         }
958 
959         session.onPublishTerminated(status);
960     }
961 
onSubscribeSuccessLocal(short transactionId, int subscribeId)962     private void onSubscribeSuccessLocal(short transactionId, int subscribeId) {
963         if (VDBG) {
964             Log.v(TAG, "onSubscribeSuccess: transactionId=" + transactionId + ", subscribeId="
965                     + subscribeId);
966         }
967 
968         TransactionInfoBase info = getAndRemovePendingResponseTransactionInfo(transactionId);
969         if (info == null) {
970             Log.e(TAG,
971                     "onSubscribeSuccess(): no info registered for transactionId=" + transactionId);
972             return;
973         }
974         if (!(info instanceof TransactionInfoSession)) {
975             Log.e(TAG, "onSubscribeSuccess: invalid info structure stored for transactionId="
976                     + transactionId);
977             return;
978         }
979         TransactionInfoSession infoSession = (TransactionInfoSession) info;
980 
981         infoSession.mSession.onSubscribeSuccess(subscribeId);
982     }
983 
onSubscribeFailLocal(short transactionId, int status)984     private void onSubscribeFailLocal(short transactionId, int status) {
985         if (VDBG) {
986             Log.v(TAG, "onSubscribeFail: transactionId=" + transactionId + ", status=" + status);
987         }
988 
989         TransactionInfoBase info = getAndRemovePendingResponseTransactionInfo(transactionId);
990         if (info == null) {
991             Log.e(TAG, "onSubscribeFail(): no info registered for transactionId=" + transactionId);
992             return;
993         }
994         if (!(info instanceof TransactionInfoSession)) {
995             Log.e(TAG, "onSubscribeFail: invalid info structure stored for transactionId="
996                     + transactionId);
997             return;
998         }
999         TransactionInfoSession infoSession = (TransactionInfoSession) info;
1000 
1001         infoSession.mSession.onSubscribeFail(status);
1002     }
1003 
onSubscribeTerminatedLocal(int subscribeId, int status)1004     private void onSubscribeTerminatedLocal(int subscribeId, int status) {
1005         if (VDBG) {
1006             Log.v(TAG, "onPublishTerminated: subscribeId=" + subscribeId + ", status=" + status);
1007         }
1008 
1009         WifiNanSessionState session = getNanSessionStateForPubSubId(subscribeId);
1010         if (session == null) {
1011             Log.e(TAG, "onSubscribeTerminated: no session found for subscribeId=" + subscribeId);
1012             return;
1013         }
1014 
1015         session.onSubscribeTerminated(status);
1016     }
1017 
onMessageSendSuccessLocal(short transactionId)1018     private void onMessageSendSuccessLocal(short transactionId) {
1019         if (VDBG) {
1020             Log.v(TAG, "onMessageSendSuccess: transactionId=" + transactionId);
1021         }
1022 
1023         TransactionInfoBase info = getAndRemovePendingResponseTransactionInfo(transactionId);
1024         if (info == null) {
1025             Log.e(TAG, "onMessageSendSuccess(): no info registered for transactionId="
1026                     + transactionId);
1027             return;
1028         }
1029         if (!(info instanceof TransactionInfoMessage)) {
1030             Log.e(TAG, "onMessageSendSuccess: invalid info structure stored for transactionId="
1031                     + transactionId);
1032             return;
1033         }
1034         TransactionInfoMessage infoMessage = (TransactionInfoMessage) info;
1035 
1036         infoMessage.mSession.onMessageSendSuccess(infoMessage.mMessageId);
1037     }
1038 
onMessageSendFailLocal(short transactionId, int status)1039     private void onMessageSendFailLocal(short transactionId, int status) {
1040         if (VDBG) {
1041             Log.v(TAG, "onMessageSendFail: transactionId=" + transactionId + ", status=" + status);
1042         }
1043 
1044         TransactionInfoBase info = getAndRemovePendingResponseTransactionInfo(transactionId);
1045         if (info == null) {
1046             Log.e(TAG,
1047                     "onMessageSendFail(): no info registered for transactionId=" + transactionId);
1048             return;
1049         }
1050         if (!(info instanceof TransactionInfoMessage)) {
1051             Log.e(TAG, "onMessageSendFail: invalid info structure stored for transactionId="
1052                     + transactionId);
1053             return;
1054         }
1055         TransactionInfoMessage infoMessage = (TransactionInfoMessage) info;
1056 
1057         infoMessage.mSession.onMessageSendFail(infoMessage.mMessageId, status);
1058     }
1059 
onUnknownTransactionLocal(int responseType, short transactionId, int status)1060     private void onUnknownTransactionLocal(int responseType, short transactionId, int status) {
1061         Log.e(TAG, "onUnknownTransaction: responseType=" + responseType + ", transactionId="
1062                 + transactionId + ", status=" + status);
1063 
1064         TransactionInfoBase info = getAndRemovePendingResponseTransactionInfo(transactionId);
1065         if (info == null) {
1066             Log.e(TAG, "onUnknownTransaction(): no info registered for transactionId="
1067                     + transactionId);
1068         }
1069     }
1070 
onMatchLocal(int pubSubId, int requestorInstanceId, byte[] peerMac, byte[] serviceSpecificInfo, int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength)1071     private void onMatchLocal(int pubSubId, int requestorInstanceId, byte[] peerMac,
1072             byte[] serviceSpecificInfo, int serviceSpecificInfoLength, byte[] matchFilter,
1073             int matchFilterLength) {
1074         if (VDBG) {
1075             Log.v(TAG, "onMatch: pubSubId=" + pubSubId + ", requestorInstanceId="
1076                     + requestorInstanceId + ", peerMac="
1077                     + String.valueOf(HexEncoding.encode(peerMac)) + ", serviceSpecificInfoLength="
1078                     + serviceSpecificInfoLength + ", serviceSpecificInfo=" + serviceSpecificInfo
1079                     + ", matchFilterLength=" + matchFilterLength + ", matchFilter=" + matchFilter);
1080         }
1081 
1082         WifiNanSessionState session = getNanSessionStateForPubSubId(pubSubId);
1083         if (session == null) {
1084             Log.e(TAG, "onMatch: no session found for pubSubId=" + pubSubId);
1085             return;
1086         }
1087 
1088         session.onMatch(requestorInstanceId, peerMac, serviceSpecificInfo,
1089                 serviceSpecificInfoLength, matchFilter, matchFilterLength);
1090     }
1091 
onMessageReceivedLocal(int pubSubId, int requestorInstanceId, byte[] peerMac, byte[] message, int messageLength)1092     private void onMessageReceivedLocal(int pubSubId, int requestorInstanceId, byte[] peerMac,
1093             byte[] message, int messageLength) {
1094         if (VDBG) {
1095             Log.v(TAG,
1096                     "onMessageReceived: pubSubId=" + pubSubId + ", requestorInstanceId="
1097                             + requestorInstanceId + ", peerMac="
1098                             + String.valueOf(HexEncoding.encode(peerMac)) + ", messageLength="
1099                             + messageLength);
1100         }
1101 
1102         WifiNanSessionState session = getNanSessionStateForPubSubId(pubSubId);
1103         if (session == null) {
1104             Log.e(TAG, "onMessageReceived: no session found for pubSubId=" + pubSubId);
1105             return;
1106         }
1107 
1108         session.onMessageReceived(requestorInstanceId, peerMac, message, messageLength);
1109     }
1110 
mergeConfigRequests()1111     private ConfigRequest mergeConfigRequests() {
1112         if (VDBG) {
1113             Log.v(TAG, "mergeConfigRequests(): mClients=[" + mClients + "]");
1114         }
1115 
1116         if (mClients.size() == 0) {
1117             Log.e(TAG, "mergeConfigRequests: invalid state - called with 0 clients registered!");
1118             return null;
1119         }
1120 
1121         if (mClients.size() == 1) {
1122             return mClients.valueAt(0).getConfigRequest();
1123         }
1124 
1125         // TODO: continue working on merge algorithm:
1126         // - if any request 5g: enable
1127         // - maximal master preference
1128         // - cluster range covering all requests: assume that [0,max] is a
1129         // non-request
1130         boolean support5gBand = false;
1131         int masterPreference = 0;
1132         boolean clusterIdValid = false;
1133         int clusterLow = 0;
1134         int clusterHigh = ConfigRequest.CLUSTER_ID_MAX;
1135         for (int i = 0; i < mClients.size(); ++i) {
1136             ConfigRequest cr = mClients.valueAt(i).getConfigRequest();
1137 
1138             if (cr.mSupport5gBand) {
1139                 support5gBand = true;
1140             }
1141 
1142             masterPreference = Math.max(masterPreference, cr.mMasterPreference);
1143 
1144             if (cr.mClusterLow != 0 || cr.mClusterHigh != ConfigRequest.CLUSTER_ID_MAX) {
1145                 if (!clusterIdValid) {
1146                     clusterLow = cr.mClusterLow;
1147                     clusterHigh = cr.mClusterHigh;
1148                 } else {
1149                     clusterLow = Math.min(clusterLow, cr.mClusterLow);
1150                     clusterHigh = Math.max(clusterHigh, cr.mClusterHigh);
1151                 }
1152                 clusterIdValid = true;
1153             }
1154         }
1155         ConfigRequest.Builder builder = new ConfigRequest.Builder();
1156         builder.setSupport5gBand(support5gBand).setMasterPreference(masterPreference)
1157                 .setClusterLow(clusterLow).setClusterHigh(clusterHigh);
1158 
1159         return builder.build();
1160     }
1161 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1162     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1163         pw.println("NanStateManager:");
1164         pw.println("  mClients: [" + mClients + "]");
1165         pw.println("  mPendingResponses: [" + mPendingResponses + "]");
1166         pw.println("  mCapabilities: [" + mCapabilities + "]");
1167         pw.println("  mNextTransactionId: " + mNextTransactionId);
1168         for (int i = 0; i < mClients.size(); ++i) {
1169             mClients.valueAt(i).dump(fd, pw, args);
1170         }
1171     }
1172 }
1173