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
17package com.android.server.wifi.nan;
18
19import android.net.wifi.nan.ConfigRequest;
20import android.net.wifi.nan.PublishData;
21import android.net.wifi.nan.PublishSettings;
22import android.net.wifi.nan.SubscribeData;
23import android.net.wifi.nan.SubscribeSettings;
24import android.net.wifi.nan.WifiNanSessionListener;
25import android.util.Log;
26
27import com.android.server.wifi.WifiNative;
28
29import libcore.util.HexEncoding;
30
31/**
32 * Native calls to access the Wi-Fi NAN HAL.
33 *
34 * Relies on WifiNative to perform the actual HAL registration.
35 *
36 * {@hide}
37 */
38public class WifiNanNative {
39    private static final String TAG = "WifiNanNative";
40    private static final boolean DBG = false;
41    private static final boolean VDBG = false; // STOPSHIP if true
42
43    private static final int WIFI_SUCCESS = 0;
44
45    private static boolean sNanNativeInit = false;
46
47    private static WifiNanNative sWifiNanNativeSingleton;
48
49    private static native int registerNanNatives();
50
51    public static WifiNanNative getInstance() {
52        // dummy reference - used to make sure that WifiNative is loaded before
53        // us since it is the one to load the shared library and starts its
54        // initialization.
55        WifiNative dummy = WifiNative.getWlanNativeInterface();
56        if (dummy == null) {
57            Log.w(TAG, "can't get access to WifiNative");
58            return null;
59        }
60
61        if (sWifiNanNativeSingleton == null) {
62            sWifiNanNativeSingleton = new WifiNanNative();
63            registerNanNatives();
64        }
65
66        return sWifiNanNativeSingleton;
67    }
68
69    public static class Capabilities {
70        public int maxConcurrentNanClusters;
71        public int maxPublishes;
72        public int maxSubscribes;
73        public int maxServiceNameLen;
74        public int maxMatchFilterLen;
75        public int maxTotalMatchFilterLen;
76        public int maxServiceSpecificInfoLen;
77        public int maxVsaDataLen;
78        public int maxMeshDataLen;
79        public int maxNdiInterfaces;
80        public int maxNdpSessions;
81        public int maxAppInfoLen;
82
83        @Override
84        public String toString() {
85            return "Capabilities [maxConcurrentNanClusters=" + maxConcurrentNanClusters
86                    + ", maxPublishes=" + maxPublishes + ", maxSubscribes=" + maxSubscribes
87                    + ", maxServiceNameLen=" + maxServiceNameLen + ", maxMatchFilterLen="
88                    + maxMatchFilterLen + ", maxTotalMatchFilterLen=" + maxTotalMatchFilterLen
89                    + ", maxServiceSpecificInfoLen=" + maxServiceSpecificInfoLen
90                    + ", maxVsaDataLen=" + maxVsaDataLen + ", maxMeshDataLen=" + maxMeshDataLen
91                    + ", maxNdiInterfaces=" + maxNdiInterfaces + ", maxNdpSessions="
92                    + maxNdpSessions + ", maxAppInfoLen=" + maxAppInfoLen + "]";
93        }
94    }
95
96    /* package */ static native int initNanHandlersNative(Object cls, int iface);
97
98    private static native int getCapabilitiesNative(short transactionId, Object cls, int iface);
99
100    private boolean isNanInit(boolean tryToInit) {
101        if (!tryToInit || sNanNativeInit) {
102            return sNanNativeInit;
103        }
104
105        if (DBG) Log.d(TAG, "isNanInit: trying to init");
106        synchronized (WifiNative.sLock) {
107            boolean halStarted = WifiNative.getWlanNativeInterface().isHalStarted();
108            if (!halStarted) {
109                halStarted = WifiNative.getWlanNativeInterface().startHal();
110            }
111            if (halStarted) {
112                int ret = initNanHandlersNative(WifiNative.class, WifiNative.sWlan0Index);
113                if (DBG) Log.d(TAG, "initNanHandlersNative: res=" + ret);
114                sNanNativeInit = ret == WIFI_SUCCESS;
115
116                if (sNanNativeInit) {
117                    ret = getCapabilitiesNative(
118                            WifiNanStateManager.getInstance().createNextTransactionId(),
119                            WifiNative.class,
120                            WifiNative.sWlan0Index);
121                    if (DBG) Log.d(TAG, "getCapabilitiesNative: res=" + ret);
122                }
123
124                return sNanNativeInit;
125            } else {
126                Log.w(TAG, "isNanInit: HAL not initialized");
127                return false;
128            }
129        }
130    }
131
132    private WifiNanNative() {
133        // do nothing
134    }
135
136    private static native int enableAndConfigureNative(short transactionId, Object cls, int iface,
137            ConfigRequest configRequest);
138
139    public void enableAndConfigure(short transactionId, ConfigRequest configRequest) {
140        boolean success;
141
142        if (VDBG) Log.d(TAG, "enableAndConfigure: configRequest=" + configRequest);
143        if (isNanInit(true)) {
144            int ret;
145            synchronized (WifiNative.sLock) {
146                ret = enableAndConfigureNative(transactionId, WifiNative.class,
147                        WifiNative.sWlan0Index, configRequest);
148            }
149            if (DBG) Log.d(TAG, "enableAndConfigureNative: ret=" + ret);
150            success = ret == WIFI_SUCCESS;
151        } else {
152            Log.w(TAG, "enableAndConfigure: NanInit fails");
153            success = false;
154        }
155
156
157        // TODO: do something on !success - send failure message back
158    }
159
160    private static native int disableNative(short transactionId, Object cls, int iface);
161
162    public void disable(short transactionId) {
163        boolean success;
164
165        if (VDBG) Log.d(TAG, "disableNan");
166        if (isNanInit(true)) {
167            int ret;
168            synchronized (WifiNative.sLock) {
169                ret = disableNative(transactionId, WifiNative.class, WifiNative.sWlan0Index);
170            }
171            if (DBG) Log.d(TAG, "disableNative: ret=" + ret);
172            success = ret == WIFI_SUCCESS;
173        } else {
174            Log.w(TAG, "disable: cannot initialize NAN");
175            success = false;
176        }
177
178        // TODO: do something on !success - send failure message back
179    }
180
181    private static native int publishNative(short transactionId, int publishId, Object cls,
182            int iface,
183            PublishData publishData, PublishSettings publishSettings);
184
185    public void publish(short transactionId, int publishId, PublishData publishData,
186            PublishSettings publishSettings) {
187        boolean success;
188
189        if (VDBG) {
190            Log.d(TAG, "publish: transactionId=" + transactionId + ",data='" + publishData
191                    + "', settings=" + publishSettings);
192        }
193
194        if (isNanInit(true)) {
195            int ret;
196            synchronized (WifiNative.sLock) {
197                ret = publishNative(transactionId, publishId, WifiNative.class,
198                        WifiNative.sWlan0Index, publishData, publishSettings);
199            }
200            if (DBG) Log.d(TAG, "publishNative: ret=" + ret);
201            success = ret == WIFI_SUCCESS;
202        } else {
203            Log.w(TAG, "publish: cannot initialize NAN");
204            success = false;
205        }
206
207        // TODO: do something on !success - send failure message back
208    }
209
210    private static native int subscribeNative(short transactionId, int subscribeId, Object cls,
211            int iface, SubscribeData subscribeData, SubscribeSettings subscribeSettings);
212
213    public void subscribe(short transactionId, int subscribeId, SubscribeData subscribeData,
214            SubscribeSettings subscribeSettings) {
215        boolean success;
216
217        if (VDBG) {
218            Log.d(TAG, "subscribe: transactionId=" + transactionId + ", data='" + subscribeData
219                    + "', settings=" + subscribeSettings);
220        }
221
222        if (isNanInit(true)) {
223            int ret;
224            synchronized (WifiNative.sLock) {
225                ret = subscribeNative(transactionId, subscribeId, WifiNative.class,
226                        WifiNative.sWlan0Index, subscribeData, subscribeSettings);
227            }
228            if (DBG) Log.d(TAG, "subscribeNative: ret=" + ret);
229            success = ret == WIFI_SUCCESS;
230        } else {
231            Log.w(TAG, "subscribe: cannot initialize NAN");
232            success = false;
233        }
234
235        // TODO: do something on !success - send failure message back
236    }
237
238    private static native int sendMessageNative(short transactionId, Object cls, int iface,
239            int pubSubId, int requestorInstanceId, byte[] dest, byte[] message, int messageLength);
240
241    public void sendMessage(short transactionId, int pubSubId, int requestorInstanceId, byte[] dest,
242            byte[] message, int messageLength) {
243        boolean success;
244
245        if (VDBG) {
246            Log.d(TAG,
247                    "sendMessage: transactionId=" + transactionId + ", pubSubId=" + pubSubId
248                            + ", requestorInstanceId=" + requestorInstanceId + ", dest="
249                            + String.valueOf(HexEncoding.encode(dest)) + ", messageLength="
250                            + messageLength);
251        }
252
253        if (isNanInit(true)) {
254            int ret;
255            synchronized (WifiNative.sLock) {
256                ret = sendMessageNative(transactionId, WifiNative.class, WifiNative.sWlan0Index,
257                        pubSubId, requestorInstanceId, dest, message, messageLength);
258            }
259            if (DBG) Log.d(TAG, "sendMessageNative: ret=" + ret);
260            success = ret == WIFI_SUCCESS;
261        } else {
262            Log.w(TAG, "sendMessage: cannot initialize NAN");
263            success = false;
264        }
265
266        // TODO: do something on !success - send failure message back
267    }
268
269    private static native int stopPublishNative(short transactionId, Object cls, int iface,
270            int pubSubId);
271
272    public void stopPublish(short transactionId, int pubSubId) {
273        boolean success;
274
275        if (VDBG) {
276            Log.d(TAG, "stopPublish: transactionId=" + transactionId + ", pubSubId=" + pubSubId);
277        }
278
279        if (isNanInit(true)) {
280            int ret;
281            synchronized (WifiNative.sLock) {
282                ret = stopPublishNative(transactionId, WifiNative.class, WifiNative.sWlan0Index,
283                        pubSubId);
284            }
285            if (DBG) Log.d(TAG, "stopPublishNative: ret=" + ret);
286            success = ret == WIFI_SUCCESS;
287        } else {
288            Log.w(TAG, "stopPublish: cannot initialize NAN");
289            success = false;
290        }
291
292        // TODO: do something on !success - send failure message back
293    }
294
295    private static native int stopSubscribeNative(short transactionId, Object cls, int iface,
296            int pubSubId);
297
298    public void stopSubscribe(short transactionId, int pubSubId) {
299        boolean success;
300
301        if (VDBG) {
302            Log.d(TAG, "stopSubscribe: transactionId=" + transactionId + ", pubSubId=" + pubSubId);
303        }
304
305        if (isNanInit(true)) {
306            int ret;
307            synchronized (WifiNative.sLock) {
308                ret = stopSubscribeNative(transactionId, WifiNative.class, WifiNative.sWlan0Index,
309                        pubSubId);
310            }
311            if (DBG) Log.d(TAG, "stopSubscribeNative: ret=" + ret);
312            success = ret == WIFI_SUCCESS;
313        } else {
314            Log.w(TAG, "stopSubscribe: cannot initialize NAN");
315            success = false;
316        }
317
318        // TODO: do something on !success - send failure message back
319    }
320
321    // EVENTS
322
323    // NanResponseType for API responses: will add values as needed
324    public static final int NAN_RESPONSE_ENABLED = 0;
325    public static final int NAN_RESPONSE_PUBLISH = 2;
326    public static final int NAN_RESPONSE_PUBLISH_CANCEL = 3;
327    public static final int NAN_RESPONSE_TRANSMIT_FOLLOWUP = 4;
328    public static final int NAN_RESPONSE_SUBSCRIBE = 5;
329    public static final int NAN_RESPONSE_SUBSCRIBE_CANCEL = 6;
330    public static final int NAN_RESPONSE_GET_CAPABILITIES = 12;
331
332    // direct copy from wifi_nan.h: need to keep in sync
333    public static final int NAN_STATUS_SUCCESS = 0;
334    public static final int NAN_STATUS_TIMEOUT = 1;
335    public static final int NAN_STATUS_DE_FAILURE = 2;
336    public static final int NAN_STATUS_INVALID_MSG_VERSION = 3;
337    public static final int NAN_STATUS_INVALID_MSG_LEN = 4;
338    public static final int NAN_STATUS_INVALID_MSG_ID = 5;
339    public static final int NAN_STATUS_INVALID_HANDLE = 6;
340    public static final int NAN_STATUS_NO_SPACE_AVAILABLE = 7;
341    public static final int NAN_STATUS_INVALID_PUBLISH_TYPE = 8;
342    public static final int NAN_STATUS_INVALID_TX_TYPE = 9;
343    public static final int NAN_STATUS_INVALID_MATCH_ALGORITHM = 10;
344    public static final int NAN_STATUS_DISABLE_IN_PROGRESS = 11;
345    public static final int NAN_STATUS_INVALID_TLV_LEN = 12;
346    public static final int NAN_STATUS_INVALID_TLV_TYPE = 13;
347    public static final int NAN_STATUS_MISSING_TLV_TYPE = 14;
348    public static final int NAN_STATUS_INVALID_TOTAL_TLVS_LEN = 15;
349    public static final int NAN_STATUS_INVALID_MATCH_HANDLE = 16;
350    public static final int NAN_STATUS_INVALID_TLV_VALUE = 17;
351    public static final int NAN_STATUS_INVALID_TX_PRIORITY = 18;
352    public static final int NAN_STATUS_INVALID_CONNECTION_MAP = 19;
353
354    // NAN Configuration Response codes
355    public static final int NAN_STATUS_INVALID_RSSI_CLOSE_VALUE = 4096;
356    public static final int NAN_STATUS_INVALID_RSSI_MIDDLE_VALUE = 4097;
357    public static final int NAN_STATUS_INVALID_HOP_COUNT_LIMIT = 4098;
358    public static final int NAN_STATUS_INVALID_MASTER_PREFERENCE_VALUE = 4099;
359    public static final int NAN_STATUS_INVALID_LOW_CLUSTER_ID_VALUE = 4100;
360    public static final int NAN_STATUS_INVALID_HIGH_CLUSTER_ID_VALUE = 4101;
361    public static final int NAN_STATUS_INVALID_BACKGROUND_SCAN_PERIOD = 4102;
362    public static final int NAN_STATUS_INVALID_RSSI_PROXIMITY_VALUE = 4103;
363    public static final int NAN_STATUS_INVALID_SCAN_CHANNEL = 4104;
364    public static final int NAN_STATUS_INVALID_POST_NAN_CONNECTIVITY_CAPABILITIES_BITMAP = 4105;
365    public static final int NAN_STATUS_INVALID_FA_MAP_NUMCHAN_VALUE = 4106;
366    public static final int NAN_STATUS_INVALID_FA_MAP_DURATION_VALUE = 4107;
367    public static final int NAN_STATUS_INVALID_FA_MAP_CLASS_VALUE = 4108;
368    public static final int NAN_STATUS_INVALID_FA_MAP_CHANNEL_VALUE = 4109;
369    public static final int NAN_STATUS_INVALID_FA_MAP_AVAILABILITY_INTERVAL_BITMAP_VALUE = 4110;
370    public static final int NAN_STATUS_INVALID_FA_MAP_MAP_ID = 4111;
371    public static final int NAN_STATUS_INVALID_POST_NAN_DISCOVERY_CONN_TYPE_VALUE = 4112;
372    public static final int NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DEVICE_ROLE_VALUE = 4113;
373    public static final int NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DURATION_VALUE = 4114;
374    public static final int NAN_STATUS_INVALID_POST_NAN_DISCOVERY_BITMAP_VALUE = 4115;
375    public static final int NAN_STATUS_MISSING_FUTHER_AVAILABILITY_MAP = 4116;
376    public static final int NAN_STATUS_INVALID_BAND_CONFIG_FLAGS = 4117;
377
378    // publish/subscribe termination reasons
379    public static final int NAN_TERMINATED_REASON_INVALID = 8192;
380    public static final int NAN_TERMINATED_REASON_TIMEOUT = 8193;
381    public static final int NAN_TERMINATED_REASON_USER_REQUEST = 8194;
382    public static final int NAN_TERMINATED_REASON_FAILURE = 8195;
383    public static final int NAN_TERMINATED_REASON_COUNT_REACHED = 8196;
384    public static final int NAN_TERMINATED_REASON_DE_SHUTDOWN = 8197;
385    public static final int NAN_TERMINATED_REASON_DISABLE_IN_PROGRESS = 8198;
386    public static final int NAN_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED = 8199;
387    public static final int NAN_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED = 8200;
388    public static final int NAN_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY = 8201;
389
390    private static int translateHalStatusToPublicStatus(int halStatus) {
391        switch (halStatus) {
392            case NAN_STATUS_NO_SPACE_AVAILABLE:
393                return WifiNanSessionListener.FAIL_REASON_NO_RESOURCES;
394
395            case NAN_STATUS_TIMEOUT:
396            case NAN_STATUS_DE_FAILURE:
397            case NAN_STATUS_DISABLE_IN_PROGRESS:
398                return WifiNanSessionListener.FAIL_REASON_OTHER;
399
400            case NAN_STATUS_INVALID_MSG_VERSION:
401            case NAN_STATUS_INVALID_MSG_LEN:
402            case NAN_STATUS_INVALID_MSG_ID:
403            case NAN_STATUS_INVALID_HANDLE:
404            case NAN_STATUS_INVALID_PUBLISH_TYPE:
405            case NAN_STATUS_INVALID_TX_TYPE:
406            case NAN_STATUS_INVALID_MATCH_ALGORITHM:
407            case NAN_STATUS_INVALID_TLV_LEN:
408            case NAN_STATUS_INVALID_TLV_TYPE:
409            case NAN_STATUS_MISSING_TLV_TYPE:
410            case NAN_STATUS_INVALID_TOTAL_TLVS_LEN:
411            case NAN_STATUS_INVALID_MATCH_HANDLE:
412            case NAN_STATUS_INVALID_TLV_VALUE:
413            case NAN_STATUS_INVALID_TX_PRIORITY:
414            case NAN_STATUS_INVALID_CONNECTION_MAP:
415            case NAN_STATUS_INVALID_RSSI_CLOSE_VALUE:
416            case NAN_STATUS_INVALID_RSSI_MIDDLE_VALUE:
417            case NAN_STATUS_INVALID_HOP_COUNT_LIMIT:
418            case NAN_STATUS_INVALID_MASTER_PREFERENCE_VALUE:
419            case NAN_STATUS_INVALID_LOW_CLUSTER_ID_VALUE:
420            case NAN_STATUS_INVALID_HIGH_CLUSTER_ID_VALUE:
421            case NAN_STATUS_INVALID_BACKGROUND_SCAN_PERIOD:
422            case NAN_STATUS_INVALID_RSSI_PROXIMITY_VALUE:
423            case NAN_STATUS_INVALID_SCAN_CHANNEL:
424            case NAN_STATUS_INVALID_POST_NAN_CONNECTIVITY_CAPABILITIES_BITMAP:
425            case NAN_STATUS_INVALID_FA_MAP_NUMCHAN_VALUE:
426            case NAN_STATUS_INVALID_FA_MAP_DURATION_VALUE:
427            case NAN_STATUS_INVALID_FA_MAP_CLASS_VALUE:
428            case NAN_STATUS_INVALID_FA_MAP_CHANNEL_VALUE:
429            case NAN_STATUS_INVALID_FA_MAP_AVAILABILITY_INTERVAL_BITMAP_VALUE:
430            case NAN_STATUS_INVALID_FA_MAP_MAP_ID:
431            case NAN_STATUS_INVALID_POST_NAN_DISCOVERY_CONN_TYPE_VALUE:
432            case NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DEVICE_ROLE_VALUE:
433            case NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DURATION_VALUE:
434            case NAN_STATUS_INVALID_POST_NAN_DISCOVERY_BITMAP_VALUE:
435            case NAN_STATUS_MISSING_FUTHER_AVAILABILITY_MAP:
436            case NAN_STATUS_INVALID_BAND_CONFIG_FLAGS:
437                return WifiNanSessionListener.FAIL_REASON_INVALID_ARGS;
438
439                // publish/subscribe termination reasons
440            case NAN_TERMINATED_REASON_TIMEOUT:
441            case NAN_TERMINATED_REASON_USER_REQUEST:
442            case NAN_TERMINATED_REASON_COUNT_REACHED:
443                return WifiNanSessionListener.TERMINATE_REASON_DONE;
444
445            case NAN_TERMINATED_REASON_INVALID:
446            case NAN_TERMINATED_REASON_FAILURE:
447            case NAN_TERMINATED_REASON_DE_SHUTDOWN:
448            case NAN_TERMINATED_REASON_DISABLE_IN_PROGRESS:
449            case NAN_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED:
450            case NAN_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED:
451            case NAN_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY:
452                return WifiNanSessionListener.TERMINATE_REASON_FAIL;
453        }
454
455        return WifiNanSessionListener.FAIL_REASON_OTHER;
456    }
457
458    // callback from native
459    private static void onNanNotifyResponse(short transactionId, int responseType, int status,
460            int value) {
461        if (VDBG) {
462            Log.v(TAG,
463                    "onNanNotifyResponse: transactionId=" + transactionId + ", responseType="
464                    + responseType + ", status=" + status + ", value=" + value);
465        }
466
467        switch (responseType) {
468            case NAN_RESPONSE_ENABLED:
469                if (status == NAN_STATUS_SUCCESS) {
470                    WifiNanStateManager.getInstance().onConfigCompleted(transactionId);
471                } else {
472                    WifiNanStateManager.getInstance().onConfigFailed(transactionId,
473                            translateHalStatusToPublicStatus(status));
474                }
475                break;
476            case NAN_RESPONSE_PUBLISH_CANCEL:
477                if (status != NAN_STATUS_SUCCESS) {
478                    Log.e(TAG, "onNanNotifyResponse: NAN_RESPONSE_PUBLISH_CANCEL error - status="
479                            + status + ", value=" + value);
480                }
481                break;
482            case NAN_RESPONSE_TRANSMIT_FOLLOWUP:
483                if (status == NAN_STATUS_SUCCESS) {
484                    WifiNanStateManager.getInstance().onMessageSendSuccess(transactionId);
485                } else {
486                    WifiNanStateManager.getInstance().onMessageSendFail(transactionId,
487                            translateHalStatusToPublicStatus(status));
488                }
489                break;
490            case NAN_RESPONSE_SUBSCRIBE_CANCEL:
491                if (status != NAN_STATUS_SUCCESS) {
492                    Log.e(TAG, "onNanNotifyResponse: NAN_RESPONSE_PUBLISH_CANCEL error - status="
493                            + status + ", value=" + value);
494                }
495                break;
496            default:
497                WifiNanStateManager.getInstance().onUnknownTransaction(responseType, transactionId,
498                        translateHalStatusToPublicStatus(status));
499                break;
500        }
501    }
502
503    private static void onNanNotifyResponsePublishSubscribe(short transactionId, int responseType,
504            int status, int value, int pubSubId) {
505        if (VDBG) {
506            Log.v(TAG,
507                    "onNanNotifyResponsePublishSubscribe: transactionId=" + transactionId
508                            + ", responseType=" + responseType + ", status=" + status + ", value="
509                            + value + ", pubSubId=" + pubSubId);
510        }
511
512        switch (responseType) {
513            case NAN_RESPONSE_PUBLISH:
514                if (status == NAN_STATUS_SUCCESS) {
515                    WifiNanStateManager.getInstance().onPublishSuccess(transactionId, pubSubId);
516                } else {
517                    WifiNanStateManager.getInstance().onPublishFail(transactionId,
518                            translateHalStatusToPublicStatus(status));
519                }
520                break;
521            case NAN_RESPONSE_SUBSCRIBE:
522                if (status == NAN_STATUS_SUCCESS) {
523                    WifiNanStateManager.getInstance().onSubscribeSuccess(transactionId, pubSubId);
524                } else {
525                    WifiNanStateManager.getInstance().onSubscribeFail(transactionId,
526                            translateHalStatusToPublicStatus(status));
527                }
528                break;
529            default:
530                WifiNanStateManager.getInstance().onUnknownTransaction(responseType, transactionId,
531                        translateHalStatusToPublicStatus(status));
532                break;
533        }
534    }
535
536    private static void onNanNotifyResponseCapabilities(short transactionId, int status, int value,
537            Capabilities capabilities) {
538        if (VDBG) {
539            Log.v(TAG, "onNanNotifyResponsePublishSubscribe: transactionId=" + transactionId
540                    + ", status=" + status + ", value=" + value + ", capabilities=" + capabilities);
541        }
542
543        if (status == NAN_STATUS_SUCCESS) {
544            WifiNanStateManager.getInstance().onCapabilitiesUpdate(transactionId, capabilities);
545        } else {
546            Log.e(TAG,
547                    "onNanNotifyResponseCapabilities: error status=" + status + ", value=" + value);
548        }
549    }
550
551    public static final int NAN_EVENT_ID_DISC_MAC_ADDR = 0;
552    public static final int NAN_EVENT_ID_STARTED_CLUSTER = 1;
553    public static final int NAN_EVENT_ID_JOINED_CLUSTER = 2;
554
555    // callback from native
556    private static void onDiscoveryEngineEvent(int eventType, byte[] mac) {
557        if (VDBG) {
558            Log.v(TAG, "onDiscoveryEngineEvent: eventType=" + eventType + ", mac="
559                    + String.valueOf(HexEncoding.encode(mac)));
560        }
561
562        if (eventType == NAN_EVENT_ID_DISC_MAC_ADDR) {
563            WifiNanStateManager.getInstance().onInterfaceAddressChange(mac);
564        } else if (eventType == NAN_EVENT_ID_STARTED_CLUSTER) {
565            WifiNanStateManager.getInstance()
566                    .onClusterChange(WifiNanClientState.CLUSTER_CHANGE_EVENT_STARTED, mac);
567        } else if (eventType == NAN_EVENT_ID_JOINED_CLUSTER) {
568            WifiNanStateManager.getInstance()
569                    .onClusterChange(WifiNanClientState.CLUSTER_CHANGE_EVENT_JOINED, mac);
570        } else {
571            Log.w(TAG, "onDiscoveryEngineEvent: invalid eventType=" + eventType);
572        }
573    }
574
575    // callback from native
576    private static void onMatchEvent(int pubSubId, int requestorInstanceId, byte[] mac,
577            byte[] serviceSpecificInfo, int serviceSpecificInfoLength, byte[] matchFilter,
578            int matchFilterLength) {
579        if (VDBG) {
580            Log.v(TAG, "onMatchEvent: pubSubId=" + pubSubId + ", requestorInstanceId="
581                    + requestorInstanceId + ", mac=" + String.valueOf(HexEncoding.encode(mac))
582                    + ", serviceSpecificInfo=" + serviceSpecificInfo + ", matchFilterLength="
583                    + matchFilterLength + ", matchFilter=" + matchFilter);
584        }
585
586        WifiNanStateManager.getInstance().onMatch(pubSubId, requestorInstanceId, mac,
587                serviceSpecificInfo, serviceSpecificInfoLength, matchFilter, matchFilterLength);
588    }
589
590    // callback from native
591    private static void onPublishTerminated(int publishId, int status) {
592        if (VDBG) Log.v(TAG, "onPublishTerminated: publishId=" + publishId + ", status=" + status);
593
594        WifiNanStateManager.getInstance().onPublishTerminated(publishId,
595                translateHalStatusToPublicStatus(status));
596    }
597
598    // callback from native
599    private static void onSubscribeTerminated(int subscribeId, int status) {
600        if (VDBG) {
601            Log.v(TAG, "onSubscribeTerminated: subscribeId=" + subscribeId + ", status=" + status);
602        }
603
604        WifiNanStateManager.getInstance().onSubscribeTerminated(subscribeId,
605                translateHalStatusToPublicStatus(status));
606    }
607
608    // callback from native
609    private static void onFollowupEvent(int pubSubId, int requestorInstanceId, byte[] mac,
610            byte[] message, int messageLength) {
611        if (VDBG) {
612            Log.v(TAG, "onFollowupEvent: pubSubId=" + pubSubId + ", requestorInstanceId="
613                    + requestorInstanceId + ", mac=" + String.valueOf(HexEncoding.encode(mac))
614                    + ", messageLength=" + messageLength);
615        }
616
617        WifiNanStateManager.getInstance().onMessageReceived(pubSubId, requestorInstanceId, mac,
618                message, messageLength);
619    }
620
621    // callback from native
622    private static void onDisabledEvent(int status) {
623        if (VDBG) Log.v(TAG, "onDisabledEvent: status=" + status);
624
625        WifiNanStateManager.getInstance().onNanDown(translateHalStatusToPublicStatus(status));
626    }
627}
628