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