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
VehicleHalMessageHandler(const sp<Looper> & looper,VehicleNetworkService & service)44 VehicleHalMessageHandler::VehicleHalMessageHandler(const sp<Looper>& looper,
45 VehicleNetworkService& service)
46 : mLooper(looper),
47 mService(service),
48 mFreeListIndex(0),
49 mLastDispatchTime(0) {
50 }
51
~VehicleHalMessageHandler()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
handleHalEvent(vehicle_prop_value_t * eventData)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
handleHalError(VehicleHalError * error)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
handleMockStart()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
doHandleHalEvent()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
doHandleHalError()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
handleMessage(const Message & message)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
binderDied(const wp<IBinder> & who)156 void MockDeathHandler::binderDied(const wp<IBinder>& who) {
157 mService.handleHalMockDeath(who);
158 }
159
160 // ----------------------------------------------------------------------------
161
PropertyValueCache()162 PropertyValueCache::PropertyValueCache() {
163
164 }
165
~PropertyValueCache()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
writeToCache(const vehicle_prop_value_t & value)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
readFromCache(vehicle_prop_value_t * value)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
dump(int fd,const Vector<String16> &)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
isOperationAllowed(int32_t property,bool isWrite)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
VehicleNetworkService()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
~VehicleNetworkService()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
binderDied(const wp<IBinder> & who)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
handleHalMockDeath(const wp<IBinder> & who)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
eventCallback(const vehicle_prop_value_t * eventData)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
errorCallback(int32_t errorCode,int32_t property,int32_t operation)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
onFirstRef()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
release()391 void VehicleNetworkService::release() {
392 do {
393 Mutex::Autolock autoLock(mLock);
394 mHandlerThread->quit();
395 } while (false);
396 mDevice->release(mDevice);
397 }
398
findConfigLocked(int32_t property)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
isGettableLocked(int32_t property)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
isSettableLocked(int32_t property,int32_t valueType)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
isSubscribableLocked(int32_t property)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
isZonedProperty(vehicle_prop_config_t const * config)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
listProperties(int32_t property)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
getProperty(vehicle_prop_value_t * data)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
releaseMemoryFromGet(vehicle_prop_value_t * value)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
setProperty(const vehicle_prop_value_t & data)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
subscribe(const sp<IVehicleNetworkListener> & listener,int32_t prop,float sampleRate,int32_t zones)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
unsubscribe(const sp<IVehicleNetworkListener> & listener,int32_t prop)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
findClientLocked(sp<IBinder> & ibinder)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
findOrCreateClientLocked(sp<IBinder> & ibinder,const sp<IVehicleNetworkListener> & listener)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
findClientsVectorForPropertyLocked(int32_t property)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
findOrCreateClientsVectorForPropertyLocked(int32_t property)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 */
removePropertyFromClientLocked(sp<IBinder> & ibinder,sp<HalClient> & client,int32_t property)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
injectEvent(const vehicle_prop_value_t & value)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
startMocking(const sp<IVehicleNetworkHalMock> & mock)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
stopMocking(const sp<IVehicleNetworkHalMock> & mock)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
handleHalRestartAndGetClientsToDispatchLocked(List<sp<HalClient>> & clientsToDispatch)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
injectHalError(int32_t errorCode,int32_t property,int32_t operation)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
startErrorListening(const sp<IVehicleNetworkListener> & listener)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
stopErrorListening(const sp<IVehicleNetworkListener> & listener)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
startHalRestartMonitoring(const sp<IVehicleNetworkListener> & listener)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
stopHalRestartMonitoring(const sp<IVehicleNetworkListener> & listener)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
onHalEvent(const vehicle_prop_value_t * eventData,bool isInjection)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
onHalError(int32_t errorCode,int32_t property,int32_t operation,bool isInjection)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
dispatchHalEvents(List<vehicle_prop_value_t * > & events)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
dispatchHalError(VehicleHalError * error)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
loadHal()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
closeHal()1080 void VehicleNetworkService::closeHal() {
1081 mDevice->common.close(&mDevice->common);
1082 }
1083 };
1084