1 /*
2  * Copyright 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 #define LOG_TAG "wifinan"
18 
19 #include "jni.h"
20 #include "JniConstants.h"
21 #include <ScopedUtfChars.h>
22 #include <ScopedBytes.h>
23 #include <utils/misc.h>
24 #include <utils/Log.h>
25 #include <utils/String16.h>
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <sys/socket.h>
29 #include <linux/if.h>
30 #include "wifi.h"
31 #include "wifi_hal.h"
32 #include "jni_helper.h"
33 
34 namespace android {
35 
36 static jclass mCls;                             /* saved WifiNanNative object */
37 static JavaVM *mVM = NULL;                      /* saved JVM pointer */
38 
39 wifi_handle getWifiHandle(JNIHelper &helper, jclass cls);
40 wifi_interface_handle getIfaceHandle(JNIHelper &helper, jclass cls, jint index);
41 
42 extern wifi_hal_fn hal_fn;
43 
44 // Start NAN functions
45 
OnNanNotifyResponse(transaction_id id,NanResponseMsg * msg)46 static void OnNanNotifyResponse(transaction_id id, NanResponseMsg* msg) {
47   ALOGD(
48       "OnNanNotifyResponse: transaction_id=%d, status=%d, value=%d, response_type=%d",
49       id, msg->status, msg->value, msg->response_type);
50 
51   JNIHelper helper(mVM);
52   switch (msg->response_type) {
53     case NAN_RESPONSE_PUBLISH:
54       helper.reportEvent(mCls, "onNanNotifyResponsePublishSubscribe",
55                          "(SIIII)V", (short) id, (int) msg->response_type,
56                          (int) msg->status, (int) msg->value,
57                          msg->body.publish_response.publish_id);
58       break;
59     case NAN_RESPONSE_SUBSCRIBE:
60       helper.reportEvent(mCls, "onNanNotifyResponsePublishSubscribe",
61                          "(SIIII)V", (short) id, (int) msg->response_type,
62                          (int) msg->status, (int) msg->value,
63                          msg->body.subscribe_response.subscribe_id);
64       break;
65     case NAN_GET_CAPABILITIES: {
66       JNIObject<jobject> data = helper.createObject(
67           "com/android/server/wifi/nan/WifiNanNative$Capabilities");
68       if (data == NULL) {
69         ALOGE(
70             "Error in allocating WifiNanNative.Capabilities OnNanNotifyResponse");
71         return;
72       }
73 
74       helper.setIntField(
75           data, "maxConcurrentNanClusters",
76           (int) msg->body.nan_capabilities.max_concurrent_nan_clusters);
77       helper.setIntField(data, "maxPublishes",
78                          (int) msg->body.nan_capabilities.max_publishes);
79       helper.setIntField(data, "maxSubscribes",
80                          (int) msg->body.nan_capabilities.max_subscribes);
81       helper.setIntField(data, "maxServiceNameLen",
82                          (int) msg->body.nan_capabilities.max_service_name_len);
83       helper.setIntField(data, "maxMatchFilterLen",
84                          (int) msg->body.nan_capabilities.max_match_filter_len);
85       helper.setIntField(
86           data, "maxTotalMatchFilterLen",
87           (int) msg->body.nan_capabilities.max_total_match_filter_len);
88       helper.setIntField(
89           data, "maxServiceSpecificInfoLen",
90           (int) msg->body.nan_capabilities.max_service_specific_info_len);
91       helper.setIntField(data, "maxVsaDataLen",
92                          (int) msg->body.nan_capabilities.max_vsa_data_len);
93       helper.setIntField(data, "maxMeshDataLen",
94                          (int) msg->body.nan_capabilities.max_mesh_data_len);
95       helper.setIntField(data, "maxNdiInterfaces",
96                          (int) msg->body.nan_capabilities.max_ndi_interfaces);
97       helper.setIntField(data, "maxNdpSessions",
98                          (int) msg->body.nan_capabilities.max_ndp_sessions);
99       helper.setIntField(data, "maxAppInfoLen",
100                          (int) msg->body.nan_capabilities.max_app_info_len);
101 
102       helper.reportEvent(
103           mCls, "onNanNotifyResponseCapabilities",
104           "(SIILcom/android/server/wifi/nan/WifiNanNative$Capabilities;)V",
105           (short) id, (int) msg->status, (int) msg->value, data.get());
106       break;
107     }
108     default:
109       helper.reportEvent(mCls, "onNanNotifyResponse", "(SIII)V", (short) id,
110                          (int) msg->response_type, (int) msg->status,
111                          (int) msg->value);
112       break;
113   }
114 }
115 
OnNanEventPublishTerminated(NanPublishTerminatedInd * event)116 static void OnNanEventPublishTerminated(NanPublishTerminatedInd* event) {
117     ALOGD("OnNanEventPublishTerminated");
118 
119     JNIHelper helper(mVM);
120     helper.reportEvent(mCls, "onPublishTerminated", "(II)V",
121                        event->publish_id, event->reason);
122 }
123 
OnNanEventMatch(NanMatchInd * event)124 static void OnNanEventMatch(NanMatchInd* event) {
125     ALOGD("OnNanEventMatch");
126 
127     JNIHelper helper(mVM);
128 
129     JNIObject<jbyteArray> macBytes = helper.newByteArray(6);
130     helper.setByteArrayRegion(macBytes, 0, 6, (jbyte *) event->addr);
131 
132     JNIObject<jbyteArray> ssiBytes = helper.newByteArray(event->service_specific_info_len);
133     helper.setByteArrayRegion(ssiBytes, 0, event->service_specific_info_len,
134                               (jbyte *) event->service_specific_info);
135 
136     JNIObject<jbyteArray> mfBytes = helper.newByteArray(event->sdf_match_filter_len);
137     helper.setByteArrayRegion(mfBytes, 0, event->sdf_match_filter_len,
138                               (jbyte *) event->sdf_match_filter);
139 
140     helper.reportEvent(mCls, "onMatchEvent", "(II[B[BI[BI)V",
141                        (int) event->publish_subscribe_id,
142                        (int) event->requestor_instance_id,
143                        macBytes.get(),
144                        ssiBytes.get(), event->service_specific_info_len,
145                        mfBytes.get(), event->sdf_match_filter_len);
146 }
147 
OnNanEventMatchExpired(NanMatchExpiredInd * event)148 static void OnNanEventMatchExpired(NanMatchExpiredInd* event) {
149     ALOGD("OnNanEventMatchExpired");
150 }
151 
OnNanEventSubscribeTerminated(NanSubscribeTerminatedInd * event)152 static void OnNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) {
153     ALOGD("OnNanEventSubscribeTerminated");
154 
155     JNIHelper helper(mVM);
156     helper.reportEvent(mCls, "onSubscribeTerminated", "(II)V",
157                        event->subscribe_id, event->reason);
158 }
159 
OnNanEventFollowup(NanFollowupInd * event)160 static void OnNanEventFollowup(NanFollowupInd* event) {
161     ALOGD("OnNanEventFollowup");
162 
163     JNIHelper helper(mVM);
164 
165     JNIObject<jbyteArray> macBytes = helper.newByteArray(6);
166     helper.setByteArrayRegion(macBytes, 0, 6, (jbyte *) event->addr);
167 
168     JNIObject<jbyteArray> msgBytes = helper.newByteArray(event->service_specific_info_len);
169     helper.setByteArrayRegion(msgBytes, 0, event->service_specific_info_len, (jbyte *) event->service_specific_info);
170 
171     helper.reportEvent(mCls, "onFollowupEvent", "(II[B[BI)V",
172                        (int) event->publish_subscribe_id,
173                        (int) event->requestor_instance_id,
174                        macBytes.get(),
175                        msgBytes.get(),
176                        (int) event->service_specific_info_len);
177 }
178 
OnNanEventDiscEngEvent(NanDiscEngEventInd * event)179 static void OnNanEventDiscEngEvent(NanDiscEngEventInd* event) {
180     ALOGD("OnNanEventDiscEngEvent called: event_type=%d", event->event_type);
181 
182     JNIHelper helper(mVM);
183 
184     JNIObject<jbyteArray> macBytes = helper.newByteArray(6);
185     if (event->event_type == NAN_EVENT_ID_DISC_MAC_ADDR) {
186         helper.setByteArrayRegion(macBytes, 0, 6, (jbyte *) event->data.mac_addr.addr);
187     } else {
188         helper.setByteArrayRegion(macBytes, 0, 6, (jbyte *) event->data.cluster.addr);
189     }
190 
191     helper.reportEvent(mCls, "onDiscoveryEngineEvent", "(I[B)V",
192                        (int) event->event_type, macBytes.get());
193 }
194 
OnNanEventDisabled(NanDisabledInd * event)195 static void OnNanEventDisabled(NanDisabledInd* event) {
196     ALOGD("OnNanEventDisabled called: reason=%d", event->reason);
197 
198     JNIHelper helper(mVM);
199 
200     helper.reportEvent(mCls, "onDisabledEvent", "(I)V", (int) event->reason);
201 }
202 
OnNanEventTca(NanTCAInd * event)203 static void OnNanEventTca(NanTCAInd* event) {
204     ALOGD("OnNanEventTca");
205 }
206 
OnNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd * event)207 static void OnNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) {
208     ALOGD("OnNanEventSdfPayload");
209 }
210 
android_net_wifi_nan_register_handler(JNIEnv * env,jclass cls,jclass wifi_native_cls,jint iface)211 static jint android_net_wifi_nan_register_handler(JNIEnv *env, jclass cls,
212                                                   jclass wifi_native_cls,
213                                                   jint iface) {
214     JNIHelper helper(env);
215     wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);
216 
217     ALOGD("android_net_wifi_nan_register_handler handle=%p", handle);
218 
219     NanCallbackHandler handlers;
220     handlers.NotifyResponse = OnNanNotifyResponse;
221     handlers.EventPublishTerminated = OnNanEventPublishTerminated;
222     handlers.EventMatch = OnNanEventMatch;
223     handlers.EventMatchExpired = OnNanEventMatchExpired;
224     handlers.EventSubscribeTerminated = OnNanEventSubscribeTerminated;
225     handlers.EventFollowup = OnNanEventFollowup;
226     handlers.EventDiscEngEvent = OnNanEventDiscEngEvent;
227     handlers.EventDisabled = OnNanEventDisabled;
228     handlers.EventTca = OnNanEventTca;
229     handlers.EventBeaconSdfPayload = OnNanEventBeaconSdfPayload;
230 
231     if (mVM == NULL) {
232         env->GetJavaVM(&mVM);
233         mCls = (jclass) env->NewGlobalRef(cls);
234     }
235 
236     return hal_fn.wifi_nan_register_handler(handle, handlers);
237 }
238 
android_net_wifi_nan_enable_request(JNIEnv * env,jclass cls,jshort transaction_id,jclass wifi_native_cls,jint iface,jobject config_request)239 static jint android_net_wifi_nan_enable_request(JNIEnv *env, jclass cls,
240                                                 jshort transaction_id,
241                                                 jclass wifi_native_cls,
242                                                 jint iface,
243                                                 jobject config_request) {
244     JNIHelper helper(env);
245     wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);
246 
247     ALOGD("android_net_wifi_nan_enable_request handle=%p, id=%d",
248           handle, transaction_id);
249 
250     NanEnableRequest msg;
251     memset(&msg, 0, sizeof(NanEnableRequest));
252 
253     /* configurable settings */
254     msg.config_support_5g = 1;
255     msg.support_5g_val = helper.getBoolField(config_request, "mSupport5gBand");
256     msg.master_pref = helper.getIntField(config_request, "mMasterPreference");
257     msg.cluster_low = helper.getIntField(config_request, "mClusterLow");
258     msg.cluster_high = helper.getIntField(config_request, "mClusterHigh");
259 
260     return hal_fn.wifi_nan_enable_request(transaction_id, handle, &msg);
261 }
262 
android_net_wifi_nan_get_capabilities(JNIEnv * env,jclass cls,jshort transaction_id,jclass wifi_native_cls,jint iface)263 static jint android_net_wifi_nan_get_capabilities(JNIEnv *env, jclass cls,
264                                                   jshort transaction_id,
265                                                   jclass wifi_native_cls,
266                                                   jint iface) {
267   JNIHelper helper(env);
268   wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);
269 
270   ALOGD("android_net_wifi_nan_get_capabilities handle=%p, id=%d", handle,
271         transaction_id);
272 
273   return hal_fn.wifi_nan_get_capabilities(transaction_id, handle);
274 }
275 
android_net_wifi_nan_disable_request(JNIEnv * env,jclass cls,jshort transaction_id,jclass wifi_native_cls,jint iface)276 static jint android_net_wifi_nan_disable_request(JNIEnv *env, jclass cls,
277                                                  jshort transaction_id,
278                                                  jclass wifi_native_cls,
279                                                  jint iface) {
280     JNIHelper helper(env);
281     wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);
282 
283     ALOGD("android_net_wifi_nan_disable_request handle=%p, id=%d",
284           handle, transaction_id);
285 
286     return hal_fn.wifi_nan_disable_request(transaction_id, handle);
287 }
288 
android_net_wifi_nan_publish(JNIEnv * env,jclass cls,jshort transaction_id,jint publish_id,jclass wifi_native_cls,jint iface,jobject publish_data,jobject publish_settings)289 static jint android_net_wifi_nan_publish(JNIEnv *env, jclass cls,
290                                          jshort transaction_id,
291                                          jint publish_id,
292                                          jclass wifi_native_cls,
293                                          jint iface,
294                                          jobject publish_data,
295                                          jobject publish_settings) {
296     JNIHelper helper(env);
297     wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);
298 
299     ALOGD("android_net_wifi_nan_publish handle=%p, id=%d", handle, transaction_id);
300 
301     NanPublishRequest msg;
302     memset(&msg, 0, sizeof(NanPublishRequest));
303 
304     /* hard-coded settings - TBD: move to configurable */
305     msg.period = 500;
306     msg.publish_match_indicator = NAN_MATCH_ALG_MATCH_ONCE;
307     msg.rssi_threshold_flag = 0;
308     msg.connmap = 0;
309 
310     /* configurable settings */
311     msg.publish_id = publish_id;
312 
313     JNIObject<jstring> objStr1 = helper.getStringField(publish_data, "mServiceName");
314     if (objStr1 == NULL) {
315         ALOGE("Error accessing mServiceName field");
316         return 0;
317     }
318     ScopedUtfChars chars1(env, objStr1);
319     const char *serviceName = chars1.c_str();
320     if (serviceName == NULL) {
321         ALOGE("Error getting mServiceName");
322         return 0;
323     }
324     msg.service_name_len = strlen(serviceName);
325     strcpy((char*)msg.service_name, serviceName);
326 
327     msg.service_specific_info_len = helper.getIntField(publish_data, "mServiceSpecificInfoLength");
328     if (msg.service_specific_info_len != 0) {
329         helper.getByteArrayField(publish_data, "mServiceSpecificInfo",
330                              msg.service_specific_info, msg.service_specific_info_len);
331     }
332 
333 
334     msg.tx_match_filter_len = helper.getIntField(publish_data, "mTxFilterLength");
335     if (msg.tx_match_filter_len != 0) {
336         helper.getByteArrayField(publish_data, "mTxFilter",
337                              msg.tx_match_filter, msg.tx_match_filter_len);
338     }
339 
340     msg.rx_match_filter_len = helper.getIntField(publish_data, "mRxFilterLength");
341     if (msg.rx_match_filter_len != 0) {
342         helper.getByteArrayField(publish_data, "mRxFilter",
343                              msg.rx_match_filter, msg.rx_match_filter_len);
344     }
345 
346     msg.publish_type = (NanPublishType)helper.getIntField(publish_settings, "mPublishType");
347     msg.publish_count = helper.getIntField(publish_settings, "mPublishCount");
348     msg.ttl = helper.getIntField(publish_settings, "mTtlSec");
349 
350     msg.tx_type = NAN_TX_TYPE_BROADCAST;
351     if (msg.publish_type != NAN_PUBLISH_TYPE_UNSOLICITED)
352       msg.tx_type = NAN_TX_TYPE_UNICAST;
353 
354     return hal_fn.wifi_nan_publish_request(transaction_id, handle, &msg);
355 }
356 
android_net_wifi_nan_subscribe(JNIEnv * env,jclass cls,jshort transaction_id,jint subscribe_id,jclass wifi_native_cls,jint iface,jobject subscribe_data,jobject subscribe_settings)357 static jint android_net_wifi_nan_subscribe(JNIEnv *env, jclass cls,
358                                            jshort transaction_id,
359                                            jint subscribe_id,
360                                            jclass wifi_native_cls,
361                                            jint iface,
362                                            jobject subscribe_data,
363                                            jobject subscribe_settings) {
364     JNIHelper helper(env);
365     wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);
366 
367     ALOGD("android_net_wifi_nan_subscribe handle=%p, id=%d", handle, transaction_id);
368 
369     NanSubscribeRequest msg;
370     memset(&msg, 0, sizeof(NanSubscribeRequest));
371 
372     /* hard-coded settings - TBD: move to configurable */
373     msg.period = 500;
374     msg.serviceResponseFilter = NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
375     msg.serviceResponseInclude = NAN_SRF_INCLUDE_RESPOND;
376     msg.useServiceResponseFilter = NAN_DO_NOT_USE_SRF;
377     msg.ssiRequiredForMatchIndication = NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
378     msg.subscribe_match_indicator = NAN_MATCH_ALG_MATCH_ONCE;
379     msg.rssi_threshold_flag = 0;
380     msg.connmap = 0;
381     msg.num_intf_addr_present = 0;
382 
383     /* configurable settings */
384     msg.subscribe_id = subscribe_id;
385 
386     JNIObject<jstring> objStr1 = helper.getStringField(subscribe_data, "mServiceName");
387     if (objStr1 == NULL) {
388         ALOGE("Error accessing mServiceName field");
389         return 0;
390     }
391     ScopedUtfChars chars1(env, objStr1);
392     const char *serviceName = chars1.c_str();
393     if (serviceName == NULL) {
394         ALOGE("Error getting mServiceName");
395         return 0;
396     }
397     msg.service_name_len = strlen(serviceName);
398     strcpy((char*)msg.service_name, serviceName);
399 
400     msg.service_specific_info_len = helper.getIntField(subscribe_data, "mServiceSpecificInfoLength");
401     if (msg.service_specific_info_len != 0) {
402         helper.getByteArrayField(subscribe_data, "mServiceSpecificInfo",
403                              msg.service_specific_info, msg.service_specific_info_len);
404     }
405 
406     msg.tx_match_filter_len = helper.getIntField(subscribe_data, "mTxFilterLength");
407     if (msg.tx_match_filter_len != 0) {
408         helper.getByteArrayField(subscribe_data, "mTxFilter",
409                              msg.tx_match_filter, msg.tx_match_filter_len);
410     }
411 
412     msg.rx_match_filter_len = helper.getIntField(subscribe_data, "mRxFilterLength");
413     if (msg.rx_match_filter_len != 0) {
414         helper.getByteArrayField(subscribe_data, "mRxFilter",
415                              msg.rx_match_filter, msg.rx_match_filter_len);
416     }
417 
418     msg.subscribe_type = (NanSubscribeType)helper.getIntField(subscribe_settings, "mSubscribeType");
419     msg.subscribe_count = helper.getIntField(subscribe_settings, "mSubscribeCount");
420     msg.ttl = helper.getIntField(subscribe_settings, "mTtlSec");
421 
422     return hal_fn.wifi_nan_subscribe_request(transaction_id, handle, &msg);
423 }
424 
android_net_wifi_nan_send_message(JNIEnv * env,jclass cls,jshort transaction_id,jclass wifi_native_cls,jint iface,jint pub_sub_id,jint req_instance_id,jbyteArray dest,jbyteArray message,jint message_length)425 static jint android_net_wifi_nan_send_message(JNIEnv *env, jclass cls,
426                                               jshort transaction_id,
427                                               jclass wifi_native_cls,
428                                               jint iface,
429                                               jint pub_sub_id,
430                                               jint req_instance_id,
431                                               jbyteArray dest,
432                                               jbyteArray message,
433                                               jint message_length) {
434     JNIHelper helper(env);
435     wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);
436 
437     ALOGD("android_net_wifi_nan_send_message handle=%p, id=%d", handle, transaction_id);
438 
439     NanTransmitFollowupRequest msg;
440     memset(&msg, 0, sizeof(NanTransmitFollowupRequest));
441 
442     /* hard-coded settings - TBD: move to configurable */
443     msg.publish_subscribe_id = pub_sub_id;
444     msg.requestor_instance_id = req_instance_id;
445     msg.priority = NAN_TX_PRIORITY_NORMAL;
446     msg.dw_or_faw = NAN_TRANSMIT_IN_DW;
447 
448     /* configurable settings */
449     msg.service_specific_info_len = message_length;
450 
451     ScopedBytesRO messageBytes(env, message);
452     memcpy(msg.service_specific_info, (byte*) messageBytes.get(), message_length);
453 
454     ScopedBytesRO destBytes(env, dest);
455     memcpy(msg.addr, (byte*) destBytes.get(), 6);
456 
457     return hal_fn.wifi_nan_transmit_followup_request(transaction_id, handle, &msg);
458 }
459 
android_net_wifi_nan_stop_publish(JNIEnv * env,jclass cls,jshort transaction_id,jclass wifi_native_cls,jint iface,jint pub_sub_id)460 static jint android_net_wifi_nan_stop_publish(JNIEnv *env, jclass cls,
461                                               jshort transaction_id,
462                                               jclass wifi_native_cls,
463                                               jint iface,
464                                               jint pub_sub_id) {
465     JNIHelper helper(env);
466     wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);
467 
468     ALOGD("android_net_wifi_nan_stop_publish handle=%p, id=%d", handle, transaction_id);
469 
470     NanPublishCancelRequest msg;
471     memset(&msg, 0, sizeof(NanPublishCancelRequest));
472 
473     msg.publish_id = pub_sub_id;
474 
475     return hal_fn.wifi_nan_publish_cancel_request(transaction_id, handle, &msg);
476 }
477 
android_net_wifi_nan_stop_subscribe(JNIEnv * env,jclass cls,jshort transaction_id,jclass wifi_native_cls,jint iface,jint pub_sub_id)478 static jint android_net_wifi_nan_stop_subscribe(JNIEnv *env, jclass cls,
479                                               jshort transaction_id,
480                                               jclass wifi_native_cls,
481                                               jint iface,
482                                               jint pub_sub_id) {
483     JNIHelper helper(env);
484     wifi_interface_handle handle = getIfaceHandle(helper, wifi_native_cls, iface);
485 
486     ALOGD("android_net_wifi_nan_stop_subscribe handle=%p, id=%d", handle, transaction_id);
487 
488     NanSubscribeCancelRequest msg;
489     memset(&msg, 0, sizeof(NanSubscribeCancelRequest));
490 
491     msg.subscribe_id = pub_sub_id;
492 
493     return hal_fn.wifi_nan_subscribe_cancel_request(transaction_id, handle, &msg);
494 }
495 
496 // ----------------------------------------------------------------------------
497 
498 /*
499  * JNI registration.
500  */
501 
502 static JNINativeMethod gWifiNanMethods[] = {
503     /* name, signature, funcPtr */
504 
505     {"initNanHandlersNative", "(Ljava/lang/Object;I)I", (void*)android_net_wifi_nan_register_handler },
506     {"getCapabilitiesNative", "(SLjava/lang/Object;I)I", (void*)android_net_wifi_nan_get_capabilities },
507     {"enableAndConfigureNative", "(SLjava/lang/Object;ILandroid/net/wifi/nan/ConfigRequest;)I", (void*)android_net_wifi_nan_enable_request },
508     {"disableNative", "(SLjava/lang/Object;I)I", (void*)android_net_wifi_nan_disable_request },
509     {"publishNative", "(SILjava/lang/Object;ILandroid/net/wifi/nan/PublishData;Landroid/net/wifi/nan/PublishSettings;)I", (void*)android_net_wifi_nan_publish },
510     {"subscribeNative", "(SILjava/lang/Object;ILandroid/net/wifi/nan/SubscribeData;Landroid/net/wifi/nan/SubscribeSettings;)I", (void*)android_net_wifi_nan_subscribe },
511     {"sendMessageNative", "(SLjava/lang/Object;III[B[BI)I", (void*)android_net_wifi_nan_send_message },
512     {"stopPublishNative", "(SLjava/lang/Object;II)I", (void*)android_net_wifi_nan_stop_publish },
513     {"stopSubscribeNative", "(SLjava/lang/Object;II)I", (void*)android_net_wifi_nan_stop_subscribe },
514 };
515 
516 /* User to register native functions */
517 extern "C"
Java_com_android_server_wifi_nan_WifiNanNative_registerNanNatives(JNIEnv * env,jclass clazz)518 jint Java_com_android_server_wifi_nan_WifiNanNative_registerNanNatives(JNIEnv* env, jclass clazz) {
519     return jniRegisterNativeMethods(env,
520             "com/android/server/wifi/nan/WifiNanNative", gWifiNanMethods, NELEM(gWifiNanMethods));
521 }
522 
523 }; // namespace android
524