Home | History | Annotate | Download | only in vehicle_network_service
      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