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