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