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 #define LOG_TAG "VehicleNetwork" 17 18 #include <binder/PermissionCache.h> 19 #include <utils/Errors.h> 20 #include <utils/SystemClock.h> 21 22 #include <private/android_filesystem_config.h> 23 24 #include <vehicle-internal.h> 25 26 #include "VehicleHalPropertyUtil.h" 27 #include "VehicleNetworkService.h" 28 29 //#define DBG_EVENT 30 //#define DBG_VERBOSE 31 #ifdef DBG_EVENT 32 #define EVENT_LOG(x...) ALOGD(x) 33 #else 34 #define EVENT_LOG(x...) 35 #endif 36 #ifdef DBG_VERBOSE 37 #define LOG_VERBOSE(x...) ALOGD(x) 38 #else 39 #define LOG_VERBOSE(x...) 40 #endif 41 42 namespace android { 43 44 VehicleHalMessageHandler::VehicleHalMessageHandler(const sp<Looper>& looper, 45 VehicleNetworkService& service) 46 : mLooper(looper), 47 mService(service), 48 mFreeListIndex(0), 49 mLastDispatchTime(0) { 50 } 51 52 VehicleHalMessageHandler::~VehicleHalMessageHandler() { 53 Mutex::Autolock autoLock(mLock); 54 for (int i = 0; i < NUM_PROPERTY_EVENT_LISTS; i++) { 55 for (auto& e : mHalPropertyList[i]) { 56 VehiclePropValueUtil::deleteMembers(e); 57 delete e; 58 } 59 } 60 for (VehicleHalError* e : mHalErrors) { 61 delete e; 62 } 63 } 64 65 static const int MS_TO_NS = 1000000; 66 67 void VehicleHalMessageHandler::handleHalEvent(vehicle_prop_value_t *eventData) { 68 EVENT_LOG("handleHalEvent 0x%x", eventData->prop); 69 Mutex::Autolock autoLock(mLock); 70 List<vehicle_prop_value_t*>& propList = mHalPropertyList[mFreeListIndex]; 71 propList.push_back(eventData); 72 int64_t deltaFromLast = elapsedRealtime() - mLastDispatchTime; 73 if (deltaFromLast > DISPATCH_INTERVAL_MS) { 74 mLooper->sendMessage(this, Message(HAL_EVENT)); 75 } else { 76 mLooper->sendMessageDelayed((DISPATCH_INTERVAL_MS - deltaFromLast) * MS_TO_NS, 77 this, Message(HAL_EVENT)); 78 } 79 } 80 81 void VehicleHalMessageHandler::handleHalError(VehicleHalError* error) { 82 Mutex::Autolock autoLock(mLock); 83 mHalErrors.push_back(error); 84 mLooper->sendMessage(this, Message(HAL_ERROR)); 85 } 86 87 void VehicleHalMessageHandler::handleMockStart() { 88 Mutex::Autolock autoLock(mLock); 89 mHalPropertyList[0].clear(); 90 mHalPropertyList[1].clear(); 91 sp<MessageHandler> self(this); 92 mLooper->removeMessages(self); 93 } 94 95 void VehicleHalMessageHandler::doHandleHalEvent() { 96 // event dispatching can take time, so do it outside lock and that requires double buffering. 97 // inside lock, free buffer is swapped with non-free buffer. 98 List<vehicle_prop_value_t*>* events = NULL; 99 do { 100 Mutex::Autolock autoLock(mLock); 101 mLastDispatchTime = elapsedRealtime(); 102 int nonFreeListIndex = mFreeListIndex ^ 0x1; 103 List<vehicle_prop_value_t*>* nonFreeList = &(mHalPropertyList[nonFreeListIndex]); 104 List<vehicle_prop_value_t*>* freeList = &(mHalPropertyList[mFreeListIndex]); 105 if (nonFreeList->size() > 0) { 106 for (auto& e : *freeList) { 107 nonFreeList->push_back(e); 108 } 109 freeList->clear(); 110 events = nonFreeList; 111 } else if (freeList->size() > 0) { 112 events = freeList; 113 mFreeListIndex = nonFreeListIndex; 114 } 115 } while (false); 116 if (events != NULL) { 117 EVENT_LOG("doHandleHalEvent, num events:%d", events->size()); 118 mService.dispatchHalEvents(*events); 119 //TODO implement return to memory pool 120 for (auto& e : *events) { 121 VehiclePropValueUtil::deleteMembers(e); 122 delete e; 123 } 124 events->clear(); 125 } 126 } 127 128 void VehicleHalMessageHandler::doHandleHalError() { 129 VehicleHalError* error = NULL; 130 do { 131 Mutex::Autolock autoLock(mLock); 132 if (mHalErrors.size() > 0) { 133 auto itr = mHalErrors.begin(); 134 error = *itr; 135 mHalErrors.erase(itr); 136 } 137 } while (false); 138 if (error != NULL) { 139 mService.dispatchHalError(error); 140 } 141 } 142 143 void VehicleHalMessageHandler::handleMessage(const Message& message) { 144 switch (message.what) { 145 case HAL_EVENT: 146 doHandleHalEvent(); 147 break; 148 case HAL_ERROR: 149 doHandleHalError(); 150 break; 151 } 152 } 153 154 // ---------------------------------------------------------------------------- 155 156 void MockDeathHandler::binderDied(const wp<IBinder>& who) { 157 mService.handleHalMockDeath(who); 158 } 159 160 // ---------------------------------------------------------------------------- 161 162 PropertyValueCache::PropertyValueCache() { 163 164 } 165 166 PropertyValueCache::~PropertyValueCache() { 167 for (size_t i = 0; i < mCache.size(); i++) { 168 vehicle_prop_value_t* v = mCache.editValueAt(i); 169 VehiclePropValueUtil::deleteMembers(v); 170 delete v; 171 } 172 mCache.clear(); 173 } 174 175 void PropertyValueCache::writeToCache(const vehicle_prop_value_t& value) { 176 vehicle_prop_value_t* v; 177 ssize_t index = mCache.indexOfKey(value.prop); 178 if (index < 0) { 179 v = VehiclePropValueUtil::allocVehicleProp(value); 180 ASSERT_OR_HANDLE_NO_MEMORY(v, return); 181 mCache.add(value.prop, v); 182 } else { 183 v = mCache.editValueAt(index); 184 VehiclePropValueUtil::copyVehicleProp(v, value, true /* deleteOldData */); 185 } 186 } 187 188 bool PropertyValueCache::readFromCache(vehicle_prop_value_t* value) { 189 ssize_t index = mCache.indexOfKey(value->prop); 190 if (index < 0) { 191 ALOGE("readFromCache 0x%x, not found", value->prop); 192 return false; 193 } 194 const vehicle_prop_value_t* cached = mCache.valueAt(index); 195 //TODO this can be improved by just passing pointer and not deleting members. 196 status_t r = VehiclePropValueUtil::copyVehicleProp(value, *cached); 197 if (r != NO_ERROR) { 198 ALOGD("readFromCache 0x%x, copy failed %d", value->prop, r); 199 return false; 200 } 201 return true; 202 } 203 204 // ---------------------------------------------------------------------------- 205 206 207 VehicleNetworkService* VehicleNetworkService::sInstance = NULL; 208 209 status_t VehicleNetworkService::dump(int fd, const Vector<String16>& /*args*/) { 210 static const String16 sDump("android.permission.DUMP"); 211 String8 msg; 212 if (!PermissionCache::checkCallingPermission(sDump)) { 213 msg.appendFormat("Permission Denial: " 214 "can't dump VNS from pid=%d, uid=%d\n", 215 IPCThreadState::self()->getCallingPid(), 216 IPCThreadState::self()->getCallingUid()); 217 write(fd, msg.string(), msg.size()); 218 return NO_ERROR; 219 } 220 msg.append("MockingEnabled=%d\n", mMockingEnabled ? 1 : 0); 221 msg.append("*Properties\n"); 222 for (auto& prop : mProperties->getList()) { 223 VechilePropertyUtil::dumpProperty(msg, *prop); 224 } 225 if (mMockingEnabled) { 226 msg.append("*Mocked Properties\n"); 227 for (auto& prop : mPropertiesForMocking->getList()) { 228 //TODO dump more info 229 msg.appendFormat("property 0x%x\n", prop->prop); 230 } 231 } 232 msg.append("*Active clients*\n"); 233 for (size_t i = 0; i < mBinderToClientMap.size(); i++) { 234 msg.appendFormat("pid %d uid %d\n", mBinderToClientMap.valueAt(i)->getPid(), 235 mBinderToClientMap.valueAt(i)->getUid()); 236 } 237 msg.append("*Active clients per property*\n"); 238 for (size_t i = 0; i < mPropertyToClientsMap.size(); i++) { 239 msg.appendFormat("prop 0x%x, pids:", mPropertyToClientsMap.keyAt(i)); 240 sp<HalClientSpVector> clients = mPropertyToClientsMap.valueAt(i); 241 for (size_t j = 0; j < clients->size(); j++) { 242 msg.appendFormat("%d,", clients->itemAt(j)->getPid()); 243 } 244 msg.append("\n"); 245 } 246 msg.append("*Subscription info per property*\n"); 247 for (size_t i = 0; i < mSubscriptionInfos.size(); i++) { 248 const SubscriptionInfo& info = mSubscriptionInfos.valueAt(i); 249 msg.appendFormat("prop 0x%x, sample rate %f Hz, zones 0x%x\n", mSubscriptionInfos.keyAt(i), 250 info.sampleRate, info.zones); 251 } 252 msg.append("*Event counts per property*\n"); 253 for (size_t i = 0; i < mEventsCount.size(); i++) { 254 msg.appendFormat("prop 0x%x: %d\n", mEventsCount.keyAt(i), 255 mEventsCount.valueAt(i)); 256 } 257 msg.append("*Vehicle Network Service Permissions*\n"); 258 mVehiclePropertyAccessControl.dump(msg); 259 260 write(fd, msg.string(), msg.size()); 261 return NO_ERROR; 262 } 263 264 bool VehicleNetworkService::isOperationAllowed(int32_t property, bool isWrite) { 265 const uid_t uid = IPCThreadState::self()->getCallingUid(); 266 267 bool allowed = mVehiclePropertyAccessControl.testAccess(property, uid, isWrite); 268 if (!allowed) { 269 ALOGW("Property 0x%x: access not allowed for uid %d, isWrite %d", property, uid, isWrite); 270 } 271 return allowed; 272 } 273 274 VehicleNetworkService::VehicleNetworkService() 275 : mModule(NULL), 276 mMockingEnabled(false) { 277 sInstance = this; 278 279 // Load vehicle network services policy file 280 if(!mVehiclePropertyAccessControl.init()) { 281 LOG_ALWAYS_FATAL("Vehicle property access policy could not be initialized."); 282 } 283 } 284 285 VehicleNetworkService::~VehicleNetworkService() { 286 sInstance = NULL; 287 for (size_t i = 0; i < mPropertyToClientsMap.size(); i++) { 288 sp<HalClientSpVector> clients = mPropertyToClientsMap.editValueAt(i); 289 clients->clear(); 290 } 291 mBinderToClientMap.clear(); 292 mPropertyToClientsMap.clear(); 293 mSubscriptionInfos.clear(); 294 } 295 296 void VehicleNetworkService::binderDied(const wp<IBinder>& who) { 297 List<int32_t> propertiesToUnsubscribe; 298 do { 299 Mutex::Autolock autoLock(mLock); 300 sp<IBinder> ibinder = who.promote(); 301 ibinder->unlinkToDeath(this); 302 ssize_t index = mBinderToClientMap.indexOfKey(ibinder); 303 if (index < 0) { 304 // already removed. ignore 305 return; 306 } 307 sp<HalClient> currentClient = mBinderToClientMap.editValueAt(index); 308 ALOGW("client binder death, pid: %d, uid:%d", currentClient->getPid(), 309 currentClient->getUid()); 310 mBinderToClientMap.removeItemsAt(index); 311 312 for (size_t i = 0; i < mPropertyToClientsMap.size(); i++) { 313 sp<HalClientSpVector>& clients = mPropertyToClientsMap.editValueAt(i); 314 clients->remove(currentClient); 315 // TODO update frame rate 316 if (clients->size() == 0) { 317 int32_t property = mPropertyToClientsMap.keyAt(i); 318 propertiesToUnsubscribe.push_back(property); 319 mSubscriptionInfos.removeItem(property); 320 } 321 } 322 for (int32_t property : propertiesToUnsubscribe) { 323 mPropertyToClientsMap.removeItem(property); 324 } 325 } while (false); 326 for (int32_t property : propertiesToUnsubscribe) { 327 mDevice->unsubscribe(mDevice, property); 328 } 329 } 330 331 void VehicleNetworkService::handleHalMockDeath(const wp<IBinder>& who) { 332 ALOGE("Hal mock binder died"); 333 sp<IBinder> ibinder = who.promote(); 334 stopMocking(IVehicleNetworkHalMock::asInterface(ibinder)); 335 } 336 337 int VehicleNetworkService::eventCallback(const vehicle_prop_value_t *eventData) { 338 EVENT_LOG("eventCallback 0x%x"); 339 sInstance->onHalEvent(eventData); 340 return NO_ERROR; 341 } 342 343 int VehicleNetworkService::errorCallback(int32_t errorCode, int32_t property, int32_t operation) { 344 status_t r = sInstance->onHalError(errorCode, property, operation); 345 if (r != NO_ERROR) { 346 ALOGE("VehicleNetworkService::errorCallback onHalError failed with %d", r); 347 } 348 return NO_ERROR; 349 } 350 351 extern "C" { 352 vehicle_prop_config_t const * getInternalProperties(); 353 int getNumInternalProperties(); 354 }; 355 356 void VehicleNetworkService::onFirstRef() { 357 Mutex::Autolock autoLock(mLock); 358 status_t r = loadHal(); 359 if (r!= NO_ERROR) { 360 ALOGE("cannot load HAL, error:%d", r); 361 return; 362 } 363 mHandlerThread = new HandlerThread(); 364 r = mHandlerThread->start("HAL.NATIVE_LOOP"); 365 if (r != NO_ERROR) { 366 ALOGE("cannot start handler thread, error:%d", r); 367 return; 368 } 369 sp<VehicleHalMessageHandler> handler(new VehicleHalMessageHandler(mHandlerThread->getLooper(), 370 *this)); 371 ASSERT_ALWAYS_ON_NO_MEMORY(handler.get()); 372 mHandler = handler; 373 r = mDevice->init(mDevice, eventCallback, errorCallback); 374 if (r != NO_ERROR) { 375 ALOGE("HAL init failed:%d", r); 376 return; 377 } 378 int numConfigs = 0; 379 vehicle_prop_config_t const* configs = mDevice->list_properties(mDevice, &numConfigs); 380 mProperties = new VehiclePropertiesHolder(false /* deleteConfigsInDestructor */); 381 ASSERT_ALWAYS_ON_NO_MEMORY(mProperties); 382 for (int i = 0; i < numConfigs; i++) { 383 mProperties->getList().push_back(&configs[i]); 384 } 385 configs = getInternalProperties(); 386 for (int i = 0; i < getNumInternalProperties(); i++) { 387 mProperties->getList().push_back(&configs[i]); 388 } 389 } 390 391 void VehicleNetworkService::release() { 392 do { 393 Mutex::Autolock autoLock(mLock); 394 mHandlerThread->quit(); 395 } while (false); 396 mDevice->release(mDevice); 397 } 398 399 vehicle_prop_config_t const * VehicleNetworkService::findConfigLocked(int32_t property) { 400 for (auto& config : (mMockingEnabled ? 401 mPropertiesForMocking->getList() : mProperties->getList())) { 402 if (config->prop == property) { 403 return config; 404 } 405 } 406 ALOGW("property not found 0x%x", property); 407 return NULL; 408 } 409 410 bool VehicleNetworkService::isGettableLocked(int32_t property) { 411 vehicle_prop_config_t const * config = findConfigLocked(property); 412 if (config == NULL) { 413 return false; 414 } 415 if ((config->access & VEHICLE_PROP_ACCESS_READ) == 0) { 416 ALOGI("cannot get, property 0x%x is write only", property); 417 return false; 418 } 419 return true; 420 } 421 422 bool VehicleNetworkService::isSettableLocked(int32_t property, int32_t valueType) { 423 vehicle_prop_config_t const * config = findConfigLocked(property); 424 if (config == NULL) { 425 return false; 426 } 427 if ((config->access & VEHICLE_PROP_ACCESS_WRITE) == 0) { 428 ALOGI("cannot set, property 0x%x is read only", property); 429 return false; 430 } 431 if (config->value_type != valueType) { 432 ALOGW("cannot set, property 0x%x expects type 0x%x while got 0x%x", property, 433 config->value_type, valueType); 434 return false; 435 } 436 return true; 437 } 438 439 bool VehicleNetworkService::isSubscribableLocked(int32_t property) { 440 vehicle_prop_config_t const * config = findConfigLocked(property); 441 if (config == NULL) { 442 return false; 443 } 444 if ((config->access & VEHICLE_PROP_ACCESS_READ) == 0) { 445 ALOGI("cannot subscribe, property 0x%x is write only", property); 446 return false; 447 } 448 if (config->change_mode == VEHICLE_PROP_CHANGE_MODE_STATIC) { 449 ALOGI("cannot subscribe, property 0x%x is static", property); 450 return false; 451 } 452 return true; 453 } 454 455 bool VehicleNetworkService::isZonedProperty(vehicle_prop_config_t const * config) { 456 if (config == NULL) { 457 return false; 458 } 459 switch (config->value_type) { 460 case VEHICLE_VALUE_TYPE_ZONED_INT32: 461 case VEHICLE_VALUE_TYPE_ZONED_FLOAT: 462 case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN: 463 case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2: 464 case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3: 465 case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2: 466 case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3: 467 return true; 468 } 469 return false; 470 } 471 472 sp<VehiclePropertiesHolder> VehicleNetworkService::listProperties(int32_t property) { 473 Mutex::Autolock autoLock(mLock); 474 if (property == 0) { 475 if (!mMockingEnabled) { 476 return mProperties; 477 } else { 478 return mPropertiesForMocking; 479 } 480 } else { 481 sp<VehiclePropertiesHolder> p; 482 const vehicle_prop_config_t* config = findConfigLocked(property); 483 if (config != NULL) { 484 p = new VehiclePropertiesHolder(false /* deleteConfigsInDestructor */); 485 p->getList().push_back(config); 486 ASSERT_OR_HANDLE_NO_MEMORY(p.get(), return p); 487 } 488 return p; 489 } 490 } 491 492 status_t VehicleNetworkService::getProperty(vehicle_prop_value_t *data) { 493 bool inMocking = false; 494 do { // for lock scoping 495 Mutex::Autolock autoLock(mLock); 496 if (!isGettableLocked(data->prop)) { 497 ALOGW("getProperty, cannot get 0x%x", data->prop); 498 return BAD_VALUE; 499 } 500 if ((data->prop >= (int32_t)VEHICLE_PROPERTY_INTERNAL_START) && 501 (data->prop <= (int32_t)VEHICLE_PROPERTY_INTERNAL_END)) { 502 if (!mCache.readFromCache(data)) { 503 return BAD_VALUE; 504 } 505 return NO_ERROR; 506 } 507 //TODO caching for static, on-change type? 508 if (mMockingEnabled) { 509 inMocking = true; 510 } 511 } while (false); 512 // set done outside lock to allow concurrent access 513 if (inMocking) { 514 status_t r = mHalMock->onPropertyGet(data); 515 if (r != NO_ERROR) { 516 ALOGW("getProperty 0x%x failed, mock returned %d", data->prop, r); 517 } 518 return r; 519 } 520 /* 521 * get call can return -EAGAIN error when hal has not fetched all data. In that case, 522 * keep retrying for certain time with some sleep. This will happen only at initial stage. 523 */ 524 status_t r = -EAGAIN; 525 int retryCount = 0; 526 while (true) { 527 r = mDevice->get(mDevice, data); 528 if (r == NO_ERROR) { 529 break; 530 } 531 if (r != -EAGAIN) { 532 break; 533 } 534 retryCount++; 535 if (retryCount > MAX_GET_RETRY_FOR_NOT_READY) { 536 ALOGE("Vehicle hal keep retrying not ready after multiple retries"); 537 break; 538 } 539 usleep(GET_WAIT_US); 540 } 541 if (r != NO_ERROR) { 542 ALOGW("getProperty 0x%x failed, HAL returned %d", data->prop, r); 543 } 544 return r; 545 } 546 547 void VehicleNetworkService::releaseMemoryFromGet(vehicle_prop_value_t* value) { 548 switch (value->prop) { 549 case VEHICLE_VALUE_TYPE_STRING: 550 case VEHICLE_VALUE_TYPE_BYTES: { 551 Mutex::Autolock autoLock(mLock); 552 mDevice->release_memory_from_get(mDevice, value); 553 } break; 554 } 555 } 556 557 status_t VehicleNetworkService::setProperty(const vehicle_prop_value_t& data) { 558 bool isInternalProperty = false; 559 bool inMocking = false; 560 do { // for lock scoping 561 Mutex::Autolock autoLock(mLock); 562 if (!isSettableLocked(data.prop, data.value_type)) { 563 ALOGW("setProperty, cannot set 0x%x", data.prop); 564 return BAD_VALUE; 565 } 566 if ((data.prop >= (int32_t)VEHICLE_PROPERTY_INTERNAL_START) && 567 (data.prop <= (int32_t)VEHICLE_PROPERTY_INTERNAL_END)) { 568 isInternalProperty = true; 569 mCache.writeToCache(data); 570 } 571 if (mMockingEnabled) { 572 inMocking = true; 573 } 574 } while (false); 575 if (inMocking) { 576 status_t r = mHalMock->onPropertySet(data); 577 if (r != NO_ERROR) { 578 ALOGW("setProperty 0x%x failed, mock returned %d", data.prop, r); 579 return r; 580 } 581 } 582 if (isInternalProperty) { 583 // for internal property, just publish it. 584 onHalEvent(&data, inMocking); 585 return NO_ERROR; 586 } 587 if (inMocking) { 588 return NO_ERROR; 589 } 590 //TODO add value check requires auto generated code to return value range for enum types 591 // set done outside lock to allow concurrent access 592 status_t r = mDevice->set(mDevice, &data); 593 if (r != NO_ERROR) { 594 ALOGW("setProperty 0x%x failed, HAL returned %d", data.prop, r); 595 } 596 return r; 597 } 598 599 status_t VehicleNetworkService::subscribe(const sp<IVehicleNetworkListener> &listener, int32_t prop, 600 float sampleRate, int32_t zones) { 601 bool shouldSubscribe = false; 602 bool inMock = false; 603 int32_t newZones = zones; 604 do { 605 Mutex::Autolock autoLock(mLock); 606 if (!isSubscribableLocked(prop)) { 607 return BAD_VALUE; 608 } 609 vehicle_prop_config_t const * config = findConfigLocked(prop); 610 if (config->change_mode == VEHICLE_PROP_CHANGE_MODE_ON_CHANGE) { 611 if (sampleRate != 0) { 612 ALOGW("Sample rate set to non-zeo for on change type. Ignore it"); 613 sampleRate = 0; 614 } 615 } else { 616 if (sampleRate > config->max_sample_rate) { 617 ALOGW("sample rate %f higher than max %f. limit to max", sampleRate, 618 config->max_sample_rate); 619 sampleRate = config->max_sample_rate; 620 } 621 if (sampleRate < config->min_sample_rate) { 622 ALOGW("sample rate %f lower than min %f. limit to min", sampleRate, 623 config->min_sample_rate); 624 sampleRate = config->min_sample_rate; 625 } 626 } 627 if (isZonedProperty(config)) { 628 if ((zones != 0) && ((zones & config->vehicle_zone_flags) != zones)) { 629 ALOGE("subscribe requested zones 0x%x out of range, supported:0x%x", zones, 630 config->vehicle_zone_flags); 631 return BAD_VALUE; 632 } 633 } else { // ignore zone 634 zones = 0; 635 } 636 sp<IBinder> ibinder = IInterface::asBinder(listener); 637 LOG_VERBOSE("subscribe, binder 0x%x prop 0x%x", ibinder.get(), prop); 638 sp<HalClient> client = findOrCreateClientLocked(ibinder, listener); 639 if (client.get() == NULL) { 640 ALOGE("subscribe, no memory, cannot create HalClient"); 641 return NO_MEMORY; 642 } 643 sp<HalClientSpVector> clientsForProperty = findOrCreateClientsVectorForPropertyLocked(prop); 644 if (clientsForProperty.get() == NULL) { 645 ALOGE("subscribe, no memory, cannot create HalClientSpVector"); 646 return NO_MEMORY; 647 } 648 clientsForProperty->add(client); 649 ssize_t index = mSubscriptionInfos.indexOfKey(prop); 650 if (index < 0) { 651 // first time subscription for this property 652 shouldSubscribe = true; 653 } else { 654 const SubscriptionInfo& info = mSubscriptionInfos.valueAt(index); 655 if (info.sampleRate < sampleRate) { 656 shouldSubscribe = true; 657 } 658 newZones = (info.zones == 0) ? 0 : ((zones == 0) ? 0 : (info.zones | zones)); 659 if (info.zones != newZones) { 660 shouldSubscribe = true; 661 } 662 } 663 client->setSubscriptionInfo(prop, sampleRate, zones); 664 if (shouldSubscribe) { 665 inMock = mMockingEnabled; 666 SubscriptionInfo info(sampleRate, newZones); 667 mSubscriptionInfos.add(prop, info); 668 if ((prop >= (int32_t)VEHICLE_PROPERTY_INTERNAL_START) && 669 (prop <= (int32_t)VEHICLE_PROPERTY_INTERNAL_END)) { 670 LOG_VERBOSE("subscribe to internal property, prop 0x%x", prop); 671 return NO_ERROR; 672 } 673 } 674 } while (false); 675 if (shouldSubscribe) { 676 status_t r; 677 if (inMock) { 678 r = mHalMock->onPropertySubscribe(prop, sampleRate, newZones); 679 if (r != NO_ERROR) { 680 ALOGW("subscribe 0x%x failed, mock returned %d", prop, r); 681 } 682 } else { 683 LOG_VERBOSE("subscribe to HAL, prop 0x%x sample rate:%f zones:0x%x", prop, sampleRate, 684 newZones); 685 r = mDevice->subscribe(mDevice, prop, sampleRate, newZones); 686 if (r != NO_ERROR) { 687 ALOGW("subscribe 0x%x failed, HAL returned %d", prop, r); 688 } 689 } 690 return r; 691 } 692 return NO_ERROR; 693 } 694 695 void VehicleNetworkService::unsubscribe(const sp<IVehicleNetworkListener> &listener, int32_t prop) { 696 bool shouldUnsubscribe = false; 697 bool inMocking = false; 698 do { 699 Mutex::Autolock autoLock(mLock); 700 if (!isSubscribableLocked(prop)) { 701 return; 702 } 703 sp<IBinder> ibinder = IInterface::asBinder(listener); 704 LOG_VERBOSE("unsubscribe, binder 0x%x, prop 0x%x", ibinder.get(), prop); 705 sp<HalClient> client = findClientLocked(ibinder); 706 if (client.get() == NULL) { 707 ALOGD("unsubscribe client not found in binder map"); 708 return; 709 } 710 shouldUnsubscribe = removePropertyFromClientLocked(ibinder, client, prop); 711 if ((prop >= (int32_t)VEHICLE_PROPERTY_INTERNAL_START) && 712 (prop <= (int32_t)VEHICLE_PROPERTY_INTERNAL_END)) { 713 LOG_VERBOSE("unsubscribe to internal property, prop 0x%x", prop); 714 return; 715 } 716 if (mMockingEnabled) { 717 inMocking = true; 718 } 719 } while (false); 720 if (shouldUnsubscribe) { 721 if (inMocking) { 722 mHalMock->onPropertyUnsubscribe(prop); 723 } else { 724 mDevice->unsubscribe(mDevice, prop); 725 } 726 } 727 } 728 729 sp<HalClient> VehicleNetworkService::findClientLocked(sp<IBinder>& ibinder) { 730 sp<HalClient> client; 731 ssize_t index = mBinderToClientMap.indexOfKey(ibinder); 732 if (index < 0) { 733 return client; 734 } 735 return mBinderToClientMap.editValueAt(index); 736 } 737 738 sp<HalClient> VehicleNetworkService::findOrCreateClientLocked(sp<IBinder>& ibinder, 739 const sp<IVehicleNetworkListener> &listener) { 740 sp<HalClient> client; 741 ssize_t index = mBinderToClientMap.indexOfKey(ibinder); 742 if (index < 0) { 743 IPCThreadState* self = IPCThreadState::self(); 744 pid_t pid = self->getCallingPid(); 745 uid_t uid = self->getCallingUid(); 746 client = new HalClient(listener, pid, uid); 747 ASSERT_OR_HANDLE_NO_MEMORY(client.get(), return client); 748 ibinder->linkToDeath(this); 749 LOG_VERBOSE("add binder 0x%x to map", ibinder.get()); 750 mBinderToClientMap.add(ibinder, client); 751 } else { 752 client = mBinderToClientMap.editValueAt(index); 753 } 754 return client; 755 } 756 757 sp<HalClientSpVector> VehicleNetworkService::findClientsVectorForPropertyLocked(int32_t property) { 758 sp<HalClientSpVector> clientsForProperty; 759 ssize_t index = mPropertyToClientsMap.indexOfKey(property); 760 if (index >= 0) { 761 clientsForProperty = mPropertyToClientsMap.editValueAt(index); 762 } 763 return clientsForProperty; 764 } 765 766 sp<HalClientSpVector> VehicleNetworkService::findOrCreateClientsVectorForPropertyLocked( 767 int32_t property) { 768 sp<HalClientSpVector> clientsForProperty; 769 ssize_t index = mPropertyToClientsMap.indexOfKey(property); 770 if (index >= 0) { 771 clientsForProperty = mPropertyToClientsMap.editValueAt(index); 772 } else { 773 clientsForProperty = new HalClientSpVector(); 774 ASSERT_OR_HANDLE_NO_MEMORY(clientsForProperty.get(), return clientsForProperty); 775 mPropertyToClientsMap.add(property, clientsForProperty); 776 } 777 return clientsForProperty; 778 } 779 780 /** 781 * remove given property from client and remove HalCLient if necessary. 782 * @return true if the property should be unsubscribed from HAL (=no more clients). 783 */ 784 bool VehicleNetworkService::removePropertyFromClientLocked(sp<IBinder>& ibinder, 785 sp<HalClient>& client, int32_t property) { 786 if(!client->removePropertyAndCheckIfActive(property)) { 787 // client is no longer necessary 788 mBinderToClientMap.removeItem(ibinder); 789 ibinder->unlinkToDeath(this); 790 } 791 sp<HalClientSpVector> clientsForProperty = findClientsVectorForPropertyLocked(property); 792 if (clientsForProperty.get() == NULL) { 793 // no subscription 794 return false; 795 } 796 clientsForProperty->remove(client); 797 //TODO reset sample rate. do not care for now. 798 if (clientsForProperty->size() == 0) { 799 mPropertyToClientsMap.removeItem(property); 800 mSubscriptionInfos.removeItem(property); 801 return true; 802 } 803 return false; 804 } 805 806 status_t VehicleNetworkService::injectEvent(const vehicle_prop_value_t& value) { 807 ALOGI("injectEvent property:0x%x", value.prop); 808 return onHalEvent(&value, true); 809 } 810 811 status_t VehicleNetworkService::startMocking(const sp<IVehicleNetworkHalMock>& mock) { 812 sp<VehicleHalMessageHandler> handler; 813 List<sp<HalClient> > clientsToDispatch; 814 do { 815 Mutex::Autolock autoLock(mLock); 816 if (mMockingEnabled) { 817 ALOGW("startMocking while already enabled"); 818 // allow it as test can fail without clearing 819 if (mHalMock != NULL) { 820 IInterface::asBinder(mHalMock)->unlinkToDeath(mHalMockDeathHandler.get()); 821 } 822 } 823 ALOGW("starting vehicle HAL mocking"); 824 sp<IBinder> ibinder = IInterface::asBinder(mock); 825 if (mHalMockDeathHandler.get() == NULL) { 826 mHalMockDeathHandler = new MockDeathHandler(*this); 827 } 828 ibinder->linkToDeath(mHalMockDeathHandler); 829 mHalMock = mock; 830 mMockingEnabled = true; 831 // Mock implementation should make sure that its startMocking call is not blocking its 832 // onlistProperties call. Otherwise, this will lead into dead-lock. 833 mPropertiesForMocking = mock->onListProperties(); 834 handleHalRestartAndGetClientsToDispatchLocked(clientsToDispatch); 835 //TODO handle binder death 836 handler = mHandler; 837 } while (false); 838 handler->handleMockStart(); 839 for (auto& client : clientsToDispatch) { 840 client->dispatchHalRestart(true); 841 } 842 clientsToDispatch.clear(); 843 return NO_ERROR; 844 } 845 846 void VehicleNetworkService::stopMocking(const sp<IVehicleNetworkHalMock>& mock) { 847 List<sp<HalClient> > clientsToDispatch; 848 do { 849 Mutex::Autolock autoLock(mLock); 850 if (mHalMock.get() == NULL) { 851 return; 852 } 853 sp<IBinder> ibinder = IInterface::asBinder(mock); 854 if (ibinder != IInterface::asBinder(mHalMock)) { 855 ALOGE("stopMocking, not the one started"); 856 return; 857 } 858 ALOGW("stopping vehicle HAL mocking"); 859 ibinder->unlinkToDeath(mHalMockDeathHandler.get()); 860 mHalMock = NULL; 861 mMockingEnabled = false; 862 handleHalRestartAndGetClientsToDispatchLocked(clientsToDispatch); 863 } while (false); 864 for (auto& client : clientsToDispatch) { 865 client->dispatchHalRestart(false); 866 } 867 clientsToDispatch.clear(); 868 } 869 870 void VehicleNetworkService::handleHalRestartAndGetClientsToDispatchLocked( 871 List<sp<HalClient> >& clientsToDispatch) { 872 // all subscriptions are invalid 873 mPropertyToClientsMap.clear(); 874 mSubscriptionInfos.clear(); 875 mEventsCount.clear(); 876 List<sp<HalClient> > clientsToRemove; 877 for (size_t i = 0; i < mBinderToClientMap.size(); i++) { 878 sp<HalClient> client = mBinderToClientMap.valueAt(i); 879 client->removeAllProperties(); 880 if (client->isMonitoringHalRestart()) { 881 clientsToDispatch.push_back(client); 882 } 883 if (!client->isActive()) { 884 clientsToRemove.push_back(client); 885 } 886 } 887 for (auto& client : clientsToRemove) { 888 // client is no longer necessary 889 sp<IBinder> ibinder = IInterface::asBinder(client->getListener()); 890 mBinderToClientMap.removeItem(ibinder); 891 ibinder->unlinkToDeath(this); 892 } 893 clientsToRemove.clear(); 894 } 895 896 status_t VehicleNetworkService::injectHalError(int32_t errorCode, int32_t property, 897 int32_t operation) { 898 return onHalError(errorCode, property, operation, true /*isInjection*/); 899 } 900 901 status_t VehicleNetworkService::startErrorListening(const sp<IVehicleNetworkListener> &listener) { 902 sp<IBinder> ibinder = IInterface::asBinder(listener); 903 sp<HalClient> client; 904 do { 905 Mutex::Autolock autoLock(mLock); 906 client = findOrCreateClientLocked(ibinder, listener); 907 } while (false); 908 if (client.get() == NULL) { 909 ALOGW("startErrorListening failed, no memory"); 910 return NO_MEMORY; 911 } 912 client->setHalErrorMonitoringState(true); 913 return NO_ERROR; 914 } 915 916 void VehicleNetworkService::stopErrorListening(const sp<IVehicleNetworkListener> &listener) { 917 sp<IBinder> ibinder = IInterface::asBinder(listener); 918 sp<HalClient> client; 919 do { 920 Mutex::Autolock autoLock(mLock); 921 client = findClientLocked(ibinder); 922 } while (false); 923 if (client.get() != NULL) { 924 client->setHalErrorMonitoringState(false); 925 } 926 } 927 928 status_t VehicleNetworkService::startHalRestartMonitoring( 929 const sp<IVehicleNetworkListener> &listener) { 930 sp<IBinder> ibinder = IInterface::asBinder(listener); 931 sp<HalClient> client; 932 do { 933 Mutex::Autolock autoLock(mLock); 934 client = findOrCreateClientLocked(ibinder, listener); 935 } while (false); 936 if (client.get() == NULL) { 937 ALOGW("startHalRestartMonitoring failed, no memory"); 938 return NO_MEMORY; 939 } 940 client->setHalRestartMonitoringState(true); 941 return NO_ERROR; 942 } 943 944 void VehicleNetworkService::stopHalRestartMonitoring(const sp<IVehicleNetworkListener> &listener) { 945 sp<IBinder> ibinder = IInterface::asBinder(listener); 946 sp<HalClient> client; 947 do { 948 Mutex::Autolock autoLock(mLock); 949 client = findClientLocked(ibinder); 950 } while (false); 951 if (client.get() != NULL) { 952 client->setHalRestartMonitoringState(false); 953 } 954 } 955 956 status_t VehicleNetworkService::onHalEvent(const vehicle_prop_value_t* eventData, bool isInjection) 957 { 958 sp<VehicleHalMessageHandler> handler; 959 do { 960 Mutex::Autolock autoLock(mLock); 961 if (!isInjection) { 962 if (mMockingEnabled) { 963 // drop real HAL event if mocking is enabled 964 return NO_ERROR; 965 } 966 } 967 ssize_t index = mEventsCount.indexOfKey(eventData->prop); 968 if (index < 0) { 969 mEventsCount.add(eventData->prop, 1); 970 } else { 971 int count = mEventsCount.valueAt(index); 972 count++; 973 mEventsCount.add(eventData->prop, count); 974 } 975 handler = mHandler; 976 } while (false); 977 //TODO add memory pool 978 vehicle_prop_value_t* copy = VehiclePropValueUtil::allocVehicleProp(*eventData); 979 ASSERT_OR_HANDLE_NO_MEMORY(copy, return NO_MEMORY); 980 handler->handleHalEvent(copy); 981 return NO_ERROR; 982 } 983 984 status_t VehicleNetworkService::onHalError(int32_t errorCode, int32_t property, int32_t operation, 985 bool isInjection) { 986 sp<VehicleHalMessageHandler> handler; 987 VehicleHalError* error = NULL; 988 do { 989 Mutex::Autolock autoLock(mLock); 990 if (!isInjection) { 991 if (mMockingEnabled) { 992 // drop real HAL error if mocking is enabled 993 return NO_ERROR; 994 } 995 } 996 997 error = new VehicleHalError(errorCode, property, operation); 998 if (error == NULL) { 999 return NO_MEMORY; 1000 } 1001 handler = mHandler; 1002 } while (false); 1003 ALOGI("HAL error, error code:%d, property:0x%x, operation:%d, isInjection:%d", 1004 errorCode, property, operation, isInjection? 1 : 0); 1005 handler->handleHalError(error); 1006 return NO_ERROR; 1007 } 1008 1009 void VehicleNetworkService::dispatchHalEvents(List<vehicle_prop_value_t*>& events) { 1010 HalClientSpVector activeClients; 1011 do { // for lock scoping 1012 Mutex::Autolock autoLock(mLock); 1013 for (vehicle_prop_value_t* e : events) { 1014 ssize_t index = mPropertyToClientsMap.indexOfKey(e->prop); 1015 if (index < 0) { 1016 EVENT_LOG("HAL event for not subscribed property 0x%x", e->prop); 1017 continue; 1018 } 1019 sp<HalClientSpVector>& clients = mPropertyToClientsMap.editValueAt(index); 1020 EVENT_LOG("dispatchHalEvents, prop 0x%x, active clients %d", e->prop, clients->size()); 1021 for (size_t i = 0; i < clients->size(); i++) { 1022 sp<HalClient>& client = clients->editItemAt(i); 1023 activeClients.add(client); 1024 client->addEvent(e); 1025 } 1026 } 1027 } while (false); 1028 EVENT_LOG("dispatchHalEvents num events %d, active clients:%d", events.size(), 1029 activeClients.size()); 1030 for (size_t i = 0; i < activeClients.size(); i++) { 1031 sp<HalClient> client = activeClients.editItemAt(i); 1032 client->dispatchEvents(); 1033 } 1034 activeClients.clear(); 1035 } 1036 1037 void VehicleNetworkService::dispatchHalError(VehicleHalError* error) { 1038 List<sp<HalClient> > clientsToDispatch; 1039 do { 1040 Mutex::Autolock autoLock(mLock); 1041 if (error->property != 0) { 1042 sp<HalClientSpVector> clientsForProperty = findClientsVectorForPropertyLocked( 1043 error->property); 1044 if (clientsForProperty.get() != NULL) { 1045 for (size_t i = 0; i < clientsForProperty->size(); i++) { 1046 sp<HalClient> client = clientsForProperty->itemAt(i); 1047 clientsToDispatch.push_back(client); 1048 } 1049 } 1050 } 1051 // Send to global error handler if property is 0 or if no client subscribing. 1052 if (error->property == 0 || clientsToDispatch.size() == 0) { 1053 for (size_t i = 0; i < mBinderToClientMap.size(); i++) { 1054 sp<HalClient> client = mBinderToClientMap.valueAt(i); 1055 if (client->isMonitoringHalError()) { 1056 clientsToDispatch.push_back(client); 1057 } 1058 } 1059 } 1060 } while (false); 1061 ALOGI("dispatchHalError error:%d, property:0x%x, operation:%d, num clients to dispatch:%d", 1062 error->errorCode, error->property, error->operation, clientsToDispatch.size()); 1063 for (auto& client : clientsToDispatch) { 1064 client->dispatchHalError(error->errorCode, error->property, error->operation); 1065 } 1066 clientsToDispatch.clear(); 1067 } 1068 1069 status_t VehicleNetworkService::loadHal() { 1070 int r = hw_get_module(VEHICLE_HARDWARE_MODULE_ID, (hw_module_t const**)&mModule); 1071 if (r != NO_ERROR) { 1072 ALOGE("cannot load HAL module, error:%d", r); 1073 return r; 1074 } 1075 r = mModule->common.methods->open(&mModule->common, VEHICLE_HARDWARE_DEVICE, 1076 (hw_device_t**)&mDevice); 1077 return r; 1078 } 1079 1080 void VehicleNetworkService::closeHal() { 1081 mDevice->common.close(&mDevice->common); 1082 } 1083 }; 1084