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#include "context_hub.h" 18 19#define LOG_NDEBUG 0 20#define LOG_TAG "ContextHubService" 21 22#include <inttypes.h> 23#include <jni.h> 24#include <queue> 25#include <unordered_map> 26#include <string.h> 27#include <stdint.h> 28#include <stdio.h> 29#include <stdlib.h> 30 31#include <cutils/log.h> 32 33#include "JNIHelp.h" 34#include "core_jni_helpers.h" 35 36static constexpr int OS_APP_ID=-1; 37 38static constexpr int MIN_APP_ID=1; 39static constexpr int MAX_APP_ID=128; 40 41static constexpr size_t MSG_HEADER_SIZE=4; 42static constexpr int HEADER_FIELD_MSG_TYPE=0; 43//static constexpr int HEADER_FIELD_MSG_VERSION=1; 44static constexpr int HEADER_FIELD_HUB_HANDLE=2; 45static constexpr int HEADER_FIELD_APP_INSTANCE=3; 46 47namespace android { 48 49namespace { 50 51/* 52 * Finds the length of a statically-sized array using template trickery that 53 * also prevents it from being applied to the wrong type. 54 */ 55template <typename T, size_t N> 56constexpr size_t array_length(T (&)[N]) { return N; } 57 58struct jniInfo_s { 59 JavaVM *vm; 60 jclass contextHubInfoClass; 61 jclass contextHubServiceClass; 62 jclass memoryRegionsClass; 63 64 jobject jContextHubService; 65 66 jmethodID msgReceiptCallBack; 67 68 jmethodID contextHubInfoCtor; 69 jmethodID contextHubInfoSetId; 70 jmethodID contextHubInfoSetName; 71 jmethodID contextHubInfoSetVendor; 72 jmethodID contextHubInfoSetToolchain; 73 jmethodID contextHubInfoSetPlatformVersion; 74 jmethodID contextHubInfoSetStaticSwVersion; 75 jmethodID contextHubInfoSetToolchainVersion; 76 jmethodID contextHubInfoSetPeakMips; 77 jmethodID contextHubInfoSetStoppedPowerDrawMw; 78 jmethodID contextHubInfoSetSleepPowerDrawMw; 79 jmethodID contextHubInfoSetPeakPowerDrawMw; 80 jmethodID contextHubInfoSetSupportedSensors; 81 jmethodID contextHubInfoSetMemoryRegions; 82 jmethodID contextHubInfoSetMaxPacketLenBytes; 83 84 jmethodID contextHubServiceMsgReceiptCallback; 85 jmethodID contextHubServiceAddAppInstance; 86}; 87 88struct context_hub_info_s { 89 uint32_t *cookies; 90 int numHubs; 91 const struct context_hub_t *hubs; 92 struct context_hub_module_t *contextHubModule; 93}; 94 95struct app_instance_info_s { 96 uint32_t hubHandle; // Id of the hub this app is on 97 int instanceId; // systemwide unique instance id - assigned 98 struct hub_app_info appInfo; // returned from the HAL 99 uint64_t truncName; // Possibly truncated name - logging 100}; 101 102struct contextHubServiceDb_s { 103 int initialized; 104 context_hub_info_s hubInfo; 105 jniInfo_s jniInfo; 106 std::queue<int> freeIds; 107 std::unordered_map<int, app_instance_info_s> appInstances; 108}; 109 110} // unnamed namespace 111 112static contextHubServiceDb_s db; 113 114int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg, 115 void *cookie); 116 117const context_hub_t *get_hub_info(int hubHandle) { 118 if (hubHandle >= 0 && hubHandle < db.hubInfo.numHubs) { 119 return &db.hubInfo.hubs[hubHandle]; 120 } 121 return nullptr; 122} 123 124static int send_msg_to_hub(const hub_message_t *msg, int hubHandle) { 125 const context_hub_t *info = get_hub_info(hubHandle); 126 127 if (info) { 128 return db.hubInfo.contextHubModule->send_message(info->hub_id, msg); 129 } else { 130 ALOGD("%s: Hub information is null for hubHandle %d", __FUNCTION__, hubHandle); 131 return -1; 132 } 133} 134 135static int set_os_app_as_destination(hub_message_t *msg, int hubHandle) { 136 const context_hub_t *info = get_hub_info(hubHandle); 137 138 if (info) { 139 msg->app_name = info->os_app_name; 140 return 0; 141 } else { 142 ALOGD("%s: Hub information is null for hubHandle %d", __FUNCTION__, hubHandle); 143 return -1; 144 } 145} 146 147static int get_hub_id_for_hub_handle(int hubHandle) { 148 if (hubHandle < 0 || hubHandle >= db.hubInfo.numHubs) { 149 return -1; 150 } else { 151 return db.hubInfo.hubs[hubHandle].hub_id; 152 } 153} 154 155static int get_hub_id_for_app_instance(int id) { 156 if (!db.appInstances.count(id)) { 157 ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id); 158 return -1; 159 } 160 161 int hubHandle = db.appInstances[id].hubHandle; 162 163 return db.hubInfo.hubs[hubHandle].hub_id; 164} 165 166static int get_app_instance_for_app_id(uint64_t app_id) { 167 auto end = db.appInstances.end(); 168 for (auto current = db.appInstances.begin(); current != end; ++current) { 169 if (current->second.appInfo.app_name.id == app_id) { 170 return current->first; 171 } 172 } 173 ALOGD("Cannot find app for app instance %" PRIu64 ".", app_id); 174 return -1; 175} 176 177static int set_dest_app(hub_message_t *msg, int id) { 178 if (!db.appInstances.count(id)) { 179 ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id); 180 return -1; 181 } 182 183 msg->app_name = db.appInstances[id].appInfo.app_name; 184 return 0; 185} 186 187static void send_query_for_apps() { 188 hub_message_t msg; 189 190 msg.message_type = CONTEXT_HUB_QUERY_APPS; 191 msg.message_len = 0; 192 193 for (int i = 0; i < db.hubInfo.numHubs; i++ ) { 194 ALOGD("Sending query for apps to hub %d", i); 195 set_os_app_as_destination(&msg, i); 196 if (send_msg_to_hub(&msg, i) != 0) { 197 ALOGW("Could not query hub %i for apps", i); 198 } 199 } 200} 201 202static int return_id(int id) { 203 // Note : This method is not thread safe. 204 // id returned is guarenteed to be in use 205 db.freeIds.push(id); 206 return 0; 207} 208 209static int generate_id(void) { 210 // Note : This method is not thread safe. 211 int retVal = -1; 212 213 if (!db.freeIds.empty()) { 214 retVal = db.freeIds.front(); 215 db.freeIds.pop(); 216 } 217 218 return retVal; 219} 220 221int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *env) { 222 // Not checking if the apps are indeed distinct 223 app_instance_info_s entry; 224 int appInstanceHandle = generate_id(); 225 226 assert(appInfo); 227 228 if (appInstanceHandle < 0) { 229 ALOGE("Cannot find resources to add app instance %d", 230 appInstanceHandle); 231 return -1; 232 } 233 234 entry.appInfo = *appInfo; 235 entry.instanceId = appInstanceHandle; 236 entry.truncName = appInfo->app_name.id; 237 entry.hubHandle = hubHandle; 238 db.appInstances[appInstanceHandle] = entry; 239 240 // Finally - let the service know of this app instance 241 env->CallIntMethod(db.jniInfo.jContextHubService, 242 db.jniInfo.contextHubServiceAddAppInstance, 243 hubHandle, entry.instanceId, entry.truncName, 244 entry.appInfo.version); 245 246 ALOGW("Added App 0x%" PRIx64 " on hub Handle %" PRId32 247 " as appInstance %d", entry.truncName, 248 entry.hubHandle, appInstanceHandle); 249 250 return appInstanceHandle; 251} 252 253int delete_app_instance(int id) { 254 if (!db.appInstances.count(id)) { 255 return -1; 256 } 257 258 return_id(id); 259 db.appInstances.erase(id); 260 261 return 0; 262} 263 264 265static void initContextHubService() { 266 int err = 0; 267 db.hubInfo.hubs = nullptr; 268 db.hubInfo.numHubs = 0; 269 int i; 270 271 err = hw_get_module(CONTEXT_HUB_MODULE_ID, 272 (hw_module_t const**)(&db.hubInfo.contextHubModule)); 273 274 if (err) { 275 ALOGE("** Could not load %s module : err %s", CONTEXT_HUB_MODULE_ID, 276 strerror(-err)); 277 } 278 279 // Prep for storing app info 280 for(i = MIN_APP_ID; i <= MAX_APP_ID; i++) { 281 db.freeIds.push(i); 282 } 283 284 if (db.hubInfo.contextHubModule) { 285 int retNumHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule, 286 &db.hubInfo.hubs); 287 ALOGD("ContextHubModule returned %d hubs ", retNumHubs); 288 db.hubInfo.numHubs = retNumHubs; 289 290 if (db.hubInfo.numHubs > 0) { 291 db.hubInfo.numHubs = retNumHubs; 292 db.hubInfo.cookies = (uint32_t *)malloc(sizeof(uint32_t) * db.hubInfo.numHubs); 293 294 if (!db.hubInfo.cookies) { 295 ALOGW("Ran out of memory allocating cookies, bailing"); 296 return; 297 } 298 299 for (i = 0; i < db.hubInfo.numHubs; i++) { 300 db.hubInfo.cookies[i] = db.hubInfo.hubs[i].hub_id; 301 if (db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id, 302 context_hub_callback, 303 &db.hubInfo.cookies[i]) == 0) { 304 } 305 } 306 } 307 308 send_query_for_apps(); 309 } else { 310 ALOGW("No Context Hub Module present"); 311 } 312} 313 314static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_t msgLen) { 315 JNIEnv *env; 316 317 if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) { 318 return -1; 319 } 320 321 jbyteArray jmsg = env->NewByteArray(msgLen); 322 if (jmsg == nullptr) { 323 ALOGW("Can't allocate %zu byte array", msgLen); 324 return -1; 325 } 326 jintArray jheader = env->NewIntArray(headerLen); 327 if (jheader == nullptr) { 328 env->DeleteLocalRef(jmsg); 329 ALOGW("Can't allocate %zu int array", headerLen); 330 return -1; 331 } 332 333 env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg); 334 env->SetIntArrayRegion(jheader, 0, headerLen, (jint *)header); 335 336 int ret = (env->CallIntMethod(db.jniInfo.jContextHubService, 337 db.jniInfo.contextHubServiceMsgReceiptCallback, 338 jheader, jmsg) != 0); 339 env->DeleteLocalRef(jmsg); 340 env->DeleteLocalRef(jheader); 341 342 return ret; 343} 344 345int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) { 346 JNIEnv *env; 347 if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) { 348 return -1; 349 } 350 351 int numApps = msgLen/sizeof(hub_app_info); 352 hub_app_info info; 353 hub_app_info *unalignedInfoAddr = (hub_app_info*)msg; 354 355 for (int i = 0; i < numApps; i++, unalignedInfoAddr++) { 356 memcpy(&info, unalignedInfoAddr, sizeof(info)); 357 add_app_instance(&info, hubHandle, env); 358 } 359 360 return 0; 361} 362 363 364int handle_os_message(uint32_t msgType, uint32_t hubHandle, 365 char *msg, int msgLen) { 366 int retVal; 367 368 //ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d", 369 // hubHandle, msgType, msgLen); 370 371 switch(msgType) { 372 case CONTEXT_HUB_APPS_ENABLE: 373 retVal = 0; 374 break; 375 376 case CONTEXT_HUB_APPS_DISABLE: 377 retVal = 0; 378 break; 379 380 case CONTEXT_HUB_LOAD_APP: 381 retVal = 0; 382 break; 383 384 case CONTEXT_HUB_UNLOAD_APP: 385 retVal = 0; 386 break; 387 388 case CONTEXT_HUB_QUERY_APPS: 389 retVal = handle_query_apps_response(msg, msgLen, hubHandle); 390 break; 391 392 case CONTEXT_HUB_QUERY_MEMORY: 393 retVal = 0; 394 break; 395 396 default: 397 retVal = -1; 398 break; 399 400 } 401 402 return retVal; 403} 404 405static bool sanity_check_cookie(void *cookie, uint32_t hub_id) { 406 int *ptr = (int *)cookie; 407 408 if (!ptr || *ptr >= db.hubInfo.numHubs) { 409 return false; 410 } 411 412 if (db.hubInfo.hubs[*ptr].hub_id != hub_id) { 413 return false; 414 } else { 415 return true; 416 } 417} 418 419int context_hub_callback(uint32_t hubId, 420 const struct hub_message_t *msg, 421 void *cookie) { 422 if (!msg) { 423 return -1; 424 } 425 if (!sanity_check_cookie(cookie, hubId)) { 426 ALOGW("Incorrect cookie %" PRId32 " for cookie %p! Bailing", 427 hubId, cookie); 428 429 return -1; 430 } 431 432 uint32_t messageType = msg->message_type; 433 uint32_t hubHandle = *(uint32_t*) cookie; 434 435 if (messageType < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) { 436 handle_os_message(messageType, hubHandle, (char*) msg->message, msg->message_len); 437 } else { 438 int appHandle = get_app_instance_for_app_id(msg->app_name.id); 439 if (appHandle < 0) { 440 ALOGE("Filtering out message due to invalid App Instance."); 441 } else { 442 uint32_t msgHeader[MSG_HEADER_SIZE] = {}; 443 msgHeader[HEADER_FIELD_MSG_TYPE] = messageType; 444 msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle; 445 msgHeader[HEADER_FIELD_APP_INSTANCE] = appHandle; 446 onMessageReceipt(msgHeader, MSG_HEADER_SIZE, (char*) msg->message, msg->message_len); 447 } 448 } 449 450 return 0; 451} 452 453static int init_jni(JNIEnv *env, jobject instance) { 454 455 if (env->GetJavaVM(&db.jniInfo.vm) != JNI_OK) { 456 return -1; 457 } 458 459 db.jniInfo.jContextHubService = env->NewGlobalRef(instance); 460 461 db.jniInfo.contextHubInfoClass = 462 env->FindClass("android/hardware/location/ContextHubInfo"); 463 464 db.jniInfo.contextHubServiceClass = 465 env->FindClass("android/hardware/location/ContextHubService"); 466 467 db.jniInfo.memoryRegionsClass = 468 env->FindClass("android/hardware/location/MemoryRegion"); 469 470 db.jniInfo.contextHubInfoCtor = 471 env->GetMethodID(db.jniInfo.contextHubInfoClass, "<init>", "()V"); 472 db.jniInfo.contextHubInfoSetId = 473 env->GetMethodID(db.jniInfo.contextHubInfoClass, "setId", "(I)V"); 474 db.jniInfo.contextHubInfoSetName = 475 env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName", 476 "(Ljava/lang/String;)V"); 477 478 db.jniInfo.contextHubInfoSetVendor = 479 env->GetMethodID(db.jniInfo.contextHubInfoClass, 480 "setVendor", "(Ljava/lang/String;)V"); 481 db.jniInfo.contextHubInfoSetToolchain = 482 env->GetMethodID(db.jniInfo.contextHubInfoClass, 483 "setToolchain", "(Ljava/lang/String;)V"); 484 db.jniInfo.contextHubInfoSetPlatformVersion = 485 env->GetMethodID(db.jniInfo.contextHubInfoClass, 486 "setPlatformVersion", "(I)V"); 487 db.jniInfo.contextHubInfoSetStaticSwVersion = 488 env->GetMethodID(db.jniInfo.contextHubInfoClass, 489 "setStaticSwVersion", "(I)V"); 490 db.jniInfo.contextHubInfoSetToolchainVersion = 491 env->GetMethodID(db.jniInfo.contextHubInfoClass, 492 "setToolchainVersion", "(I)V"); 493 db.jniInfo.contextHubInfoSetPeakMips = 494 env->GetMethodID(db.jniInfo.contextHubInfoClass, 495 "setPeakMips", "(F)V"); 496 db.jniInfo.contextHubInfoSetStoppedPowerDrawMw = 497 env->GetMethodID(db.jniInfo.contextHubInfoClass, 498 "setStoppedPowerDrawMw", "(F)V"); 499 db.jniInfo.contextHubInfoSetSleepPowerDrawMw = 500 env->GetMethodID(db.jniInfo.contextHubInfoClass, 501 "setSleepPowerDrawMw", "(F)V"); 502 db.jniInfo.contextHubInfoSetPeakPowerDrawMw = 503 env->GetMethodID(db.jniInfo.contextHubInfoClass, 504 "setPeakPowerDrawMw", "(F)V"); 505 db.jniInfo.contextHubInfoSetSupportedSensors = 506 env->GetMethodID(db.jniInfo.contextHubInfoClass, 507 "setSupportedSensors", "([I)V"); 508 db.jniInfo.contextHubInfoSetMemoryRegions = 509 env->GetMethodID(db.jniInfo.contextHubInfoClass, 510 "setMemoryRegions", "([Landroid/hardware/location/MemoryRegion;)V"); 511 db.jniInfo.contextHubInfoSetMaxPacketLenBytes = 512 env->GetMethodID(db.jniInfo.contextHubInfoClass, 513 "setMaxPacketLenBytes", "(I)V"); 514 515 516 db.jniInfo.contextHubServiceMsgReceiptCallback = 517 env->GetMethodID(db.jniInfo.contextHubServiceClass, "onMessageReceipt", 518 "([I[B)I"); 519 db.jniInfo.contextHubInfoSetName = 520 env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName", 521 "(Ljava/lang/String;)V"); 522 523 db.jniInfo.contextHubServiceAddAppInstance = 524 env->GetMethodID(db.jniInfo.contextHubServiceClass, 525 "addAppInstance", "(IIJI)I"); 526 527 528 529 return 0; 530} 531 532static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t *hub) { 533 jstring jstrBuf; 534 jintArray jintBuf; 535 jobjectArray jmemBuf; 536 537 int dummyConnectedSensors[] = {1, 2, 3, 4, 5}; 538 539 jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass, 540 db.jniInfo.contextHubInfoCtor); 541 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub->hub_id); 542 543 jstrBuf = env->NewStringUTF(hub->name); 544 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetName, jstrBuf); 545 env->DeleteLocalRef(jstrBuf); 546 547 jstrBuf = env->NewStringUTF(hub->vendor); 548 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetVendor, jstrBuf); 549 env->DeleteLocalRef(jstrBuf); 550 551 jstrBuf = env->NewStringUTF(hub->toolchain); 552 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchain, jstrBuf); 553 env->DeleteLocalRef(jstrBuf); 554 555 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPlatformVersion, hub->platform_version); 556 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchainVersion, hub->toolchain_version); 557 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakMips, hub->peak_mips); 558 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetStoppedPowerDrawMw, 559 hub->stopped_power_draw_mw); 560 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSleepPowerDrawMw, 561 hub->sleep_power_draw_mw); 562 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakPowerDrawMw, 563 hub->peak_power_draw_mw); 564 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMaxPacketLenBytes, 565 hub->max_supported_msg_len); 566 567 568 // TODO : jintBuf = env->NewIntArray(hub->num_connected_sensors); 569 // TODO : env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, 570 // hub->connected_sensors); 571 jintBuf = env->NewIntArray(array_length(dummyConnectedSensors)); 572 env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, dummyConnectedSensors); 573 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf); 574 env->DeleteLocalRef(jintBuf); 575 576 // We are not getting the memory regions from the CH Hal - change this when it is available 577 jmemBuf = env->NewObjectArray(0, db.jniInfo.memoryRegionsClass, nullptr); 578 // Note the zero size above. We do not need to set any elements 579 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMemoryRegions, jmemBuf); 580 env->DeleteLocalRef(jmemBuf); 581 582 583 return jHub; 584} 585 586static jobjectArray nativeInitialize(JNIEnv *env, jobject instance) 587{ 588 jobject hub; 589 jobjectArray retArray; 590 591 if (init_jni(env, instance) < 0) { 592 return nullptr; 593 } 594 595 initContextHubService(); 596 597 if (db.hubInfo.numHubs > 1) { 598 ALOGW("Clamping the number of hubs to 1"); 599 db.hubInfo.numHubs = 1; 600 } 601 602 retArray = env->NewObjectArray(db.hubInfo.numHubs, db.jniInfo.contextHubInfoClass, nullptr); 603 604 for(int i = 0; i < db.hubInfo.numHubs; i++) { 605 hub = constructJContextHubInfo(env, &db.hubInfo.hubs[i]); 606 env->SetObjectArrayElement(retArray, i, hub); 607 } 608 609 return retArray; 610} 611 612static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_, 613 jbyteArray data_) { 614 jint retVal = -1; // Default to failure 615 616 jint *header = env->GetIntArrayElements(header_, 0); 617 unsigned int numHeaderElements = env->GetArrayLength(header_); 618 jbyte *data = env->GetByteArrayElements(data_, 0); 619 int dataBufferLength = env->GetArrayLength(data_); 620 621 622 if (numHeaderElements >= MSG_HEADER_SIZE) { 623 bool setAddressSuccess; 624 int hubId; 625 hub_message_t msg; 626 627 if (header[HEADER_FIELD_APP_INSTANCE] == OS_APP_ID) { 628 setAddressSuccess = (set_os_app_as_destination(&msg, header[HEADER_FIELD_HUB_HANDLE]) == 0); 629 hubId = get_hub_id_for_hub_handle(header[HEADER_FIELD_HUB_HANDLE]); 630 } else { 631 setAddressSuccess = (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0); 632 hubId = get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]); 633 } 634 635 if (setAddressSuccess && hubId >= 0) { 636 msg.message_type = header[HEADER_FIELD_MSG_TYPE]; 637 msg.message_len = dataBufferLength; 638 msg.message = data; 639 retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg); 640 } else { 641 ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d", 642 header[HEADER_FIELD_APP_INSTANCE], 643 header[HEADER_FIELD_HUB_HANDLE], 644 (int)setAddressSuccess); 645 } 646 } else { 647 ALOGD("Malformed header len"); 648 } 649 650 env->ReleaseIntArrayElements(header_, header, 0); 651 env->ReleaseByteArrayElements(data_, data, 0); 652 653 return retVal; 654} 655 656//-------------------------------------------------------------------------------------------------- 657// 658static const JNINativeMethod gContextHubServiceMethods[] = { 659 {"nativeInitialize", 660 "()[Landroid/hardware/location/ContextHubInfo;", 661 (void*)nativeInitialize }, 662 {"nativeSendMessage", 663 "([I[B)I", 664 (void*)nativeSendMessage } 665}; 666 667}//namespace android 668 669using namespace android; 670 671int register_android_hardware_location_ContextHubService(JNIEnv *env) 672{ 673 RegisterMethodsOrDie(env, "android/hardware/location/ContextHubService", 674 gContextHubServiceMethods, NELEM(gContextHubServiceMethods)); 675 676 return 0; 677} 678