Loading automotive/vehicle/2.0/default/Android.bp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -15,10 +15,12 @@ cc_defaults { cc_defaults { name: "vhal_v2_0_defaults", name: "vhal_v2_0_defaults", shared_libs: [ shared_libs: [ "libbinder_ndk", "libhidlbase", "libhidlbase", "liblog", "liblog", "libutils", "libutils", "android.hardware.automotive.vehicle@2.0", "android.hardware.automotive.vehicle@2.0", "carwatchdog_aidl_interface-ndk_platform", ], ], cflags: [ cflags: [ "-Wall", "-Wall", Loading Loading @@ -46,6 +48,7 @@ cc_library { "common/src/VehiclePropertyStore.cpp", "common/src/VehiclePropertyStore.cpp", "common/src/VehicleUtils.cpp", "common/src/VehicleUtils.cpp", "common/src/VmsUtils.cpp", "common/src/VmsUtils.cpp", "common/src/WatchdogClient.cpp", ], ], shared_libs: [ shared_libs: [ "libbase", "libbase", Loading automotive/vehicle/2.0/default/VehicleService.cpp +19 −2 Original line number Original line Diff line number Diff line Loading @@ -20,9 +20,12 @@ #include <iostream> #include <iostream> #include <android/binder_process.h> #include <utils/Looper.h> #include <vhal_v2_0/EmulatedVehicleConnector.h> #include <vhal_v2_0/EmulatedVehicleConnector.h> #include <vhal_v2_0/EmulatedVehicleHal.h> #include <vhal_v2_0/EmulatedVehicleHal.h> #include <vhal_v2_0/VehicleHalManager.h> #include <vhal_v2_0/VehicleHalManager.h> #include <vhal_v2_0/WatchdogClient.h> using namespace android; using namespace android; using namespace android::hardware; using namespace android::hardware; Loading @@ -36,7 +39,7 @@ int main(int /* argc */, char* /* argv */ []) { auto service = std::make_unique<VehicleHalManager>(hal.get()); auto service = std::make_unique<VehicleHalManager>(hal.get()); connector->setValuePool(hal->getValuePool()); connector->setValuePool(hal->getValuePool()); configureRpcThreadpool(4, true /* callerWillJoin */); configureRpcThreadpool(4, false /* callerWillJoin */); ALOGI("Registering as service..."); ALOGI("Registering as service..."); status_t status = service->registerAsService(); status_t status = service->registerAsService(); Loading @@ -46,8 +49,22 @@ int main(int /* argc */, char* /* argv */ []) { return 1; return 1; } } // Setup a binder thread pool to be a car watchdog client. ABinderProcess_setThreadPoolMaxThreadCount(1); ABinderProcess_startThreadPool(); sp<Looper> looper(Looper::prepare(0 /* opts */)); std::shared_ptr<WatchdogClient> watchdogClient = ndk::SharedRefBase::make<WatchdogClient>(looper, service.get()); // The current health check is done in the main thread, so it falls short of capturing the real // situation. Checking through HAL binder thread should be considered. if (!watchdogClient->initialize()) { ALOGE("Failed to initialize car watchdog client"); return 1; } ALOGI("Ready"); ALOGI("Ready"); joinRpcThreadpool(); while (true) { looper->pollAll(-1 /* timeoutMillis */); } return 1; return 1; } } automotive/vehicle/2.0/default/common/include/vhal_v2_0/WatchdogClient.h 0 → 100644 +74 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_ #define android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_ #include "VehicleHalManager.h" #include <aidl/android/automotive/watchdog/BnCarWatchdog.h> #include <aidl/android/automotive/watchdog/BnCarWatchdogClient.h> #include <utils/Looper.h> #include <utils/Mutex.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { class WatchdogClient : public aidl::android::automotive::watchdog::BnCarWatchdogClient { public: explicit WatchdogClient(const ::android::sp<::android::Looper>& handlerLooper, VehicleHalManager* vhalManager); ndk::ScopedAStatus checkIfAlive( int32_t sessionId, aidl::android::automotive::watchdog::TimeoutLength timeout) override; ndk::ScopedAStatus prepareProcessTermination() override; bool initialize(); private: class MessageHandlerImpl : public ::android::MessageHandler { public: explicit MessageHandlerImpl(WatchdogClient* client); void handleMessage(const ::android::Message& message) override; private: WatchdogClient* mClient; }; private: void respondToWatchdog(); bool isClientHealthy() const; private: ::android::sp<::android::Looper> mHandlerLooper; ::android::sp<MessageHandlerImpl> mMessageHandler; std::shared_ptr<aidl::android::automotive::watchdog::ICarWatchdog> mWatchdogServer; std::shared_ptr<aidl::android::automotive::watchdog::ICarWatchdogClient> mTestClient; VehicleHalManager* mVhalManager; ::android::Mutex mMutex; int mCurrentSessionId GUARDED_BY(mMutex); }; } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_ automotive/vehicle/2.0/default/common/src/WatchdogClient.cpp 0 → 100644 +140 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "automotive.vehicle@2.0-watchdog" #include <common/include/vhal_v2_0/WatchdogClient.h> #include <android/binder_manager.h> #include <android/hardware/automotive/vehicle/2.0/types.h> using aidl::android::automotive::watchdog::ICarWatchdog; using aidl::android::automotive::watchdog::TimeoutLength; namespace { enum { WHAT_CHECK_ALIVE = 1 }; } // namespace namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { WatchdogClient::WatchdogClient(const sp<Looper>& handlerLooper, VehicleHalManager* vhalManager) : mHandlerLooper(handlerLooper), mVhalManager(vhalManager), mCurrentSessionId(-1) { mMessageHandler = new MessageHandlerImpl(this); } ndk::ScopedAStatus WatchdogClient::checkIfAlive(int32_t sessionId, TimeoutLength /*timeout*/) { mHandlerLooper->removeMessages(mMessageHandler, WHAT_CHECK_ALIVE); { Mutex::Autolock lock(mMutex); mCurrentSessionId = sessionId; } mHandlerLooper->sendMessage(mMessageHandler, Message(WHAT_CHECK_ALIVE)); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus WatchdogClient::prepareProcessTermination() { return ndk::ScopedAStatus::ok(); } bool WatchdogClient::initialize() { ndk::SpAIBinder binder( AServiceManager_getService("android.automotive.watchdog.ICarWatchdog/default")); if (binder.get() == nullptr) { ALOGE("Failed to get carwatchdog daemon"); return false; } std::shared_ptr<ICarWatchdog> server = ICarWatchdog::fromBinder(binder); if (server == nullptr) { ALOGE("Failed to connect to carwatchdog daemon"); return false; } mWatchdogServer = server; binder = this->asBinder(); if (binder.get() == nullptr) { ALOGE("Failed to get car watchdog client binder object"); return false; } std::shared_ptr<ICarWatchdogClient> client = ICarWatchdogClient::fromBinder(binder); if (client == nullptr) { ALOGE("Failed to get ICarWatchdogClient from binder"); return false; } mTestClient = client; mWatchdogServer->registerClient(client, TimeoutLength::TIMEOUT_NORMAL); ALOGI("Successfully registered the client to car watchdog server"); return true; } void WatchdogClient::respondToWatchdog() { if (mWatchdogServer == nullptr) { ALOGW("Cannot respond to car watchdog daemon: car watchdog daemon is not connected"); return; } int sessionId; { Mutex::Autolock lock(mMutex); sessionId = mCurrentSessionId; } if (isClientHealthy()) { ndk::ScopedAStatus status = mWatchdogServer->tellClientAlive(mTestClient, sessionId); if (!status.isOk()) { ALOGE("Failed to call tellClientAlive(session id = %d): %d", sessionId, status.getStatus()); return; } } } bool WatchdogClient::isClientHealthy() const { // We consider that default vehicle HAL is healthy if we can get PERF_VEHICLE_SPEED value. StatusCode status = StatusCode::TRY_AGAIN; VehiclePropValue propValue = {.prop = (int32_t)VehicleProperty::PERF_VEHICLE_SPEED}; while (status == StatusCode::TRY_AGAIN) { mVhalManager->get(propValue, [&propValue, &status](StatusCode s, const VehiclePropValue& v) { status = s; if (s == StatusCode::OK) { propValue = v; } }); } return status == StatusCode::OK; } WatchdogClient::MessageHandlerImpl::MessageHandlerImpl(WatchdogClient* client) : mClient(client) {} void WatchdogClient::MessageHandlerImpl::handleMessage(const Message& message) { switch (message.what) { case WHAT_CHECK_ALIVE: mClient->respondToWatchdog(); break; default: ALOGW("Unknown message: %d", message.what); } } } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android Loading
automotive/vehicle/2.0/default/Android.bp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -15,10 +15,12 @@ cc_defaults { cc_defaults { name: "vhal_v2_0_defaults", name: "vhal_v2_0_defaults", shared_libs: [ shared_libs: [ "libbinder_ndk", "libhidlbase", "libhidlbase", "liblog", "liblog", "libutils", "libutils", "android.hardware.automotive.vehicle@2.0", "android.hardware.automotive.vehicle@2.0", "carwatchdog_aidl_interface-ndk_platform", ], ], cflags: [ cflags: [ "-Wall", "-Wall", Loading Loading @@ -46,6 +48,7 @@ cc_library { "common/src/VehiclePropertyStore.cpp", "common/src/VehiclePropertyStore.cpp", "common/src/VehicleUtils.cpp", "common/src/VehicleUtils.cpp", "common/src/VmsUtils.cpp", "common/src/VmsUtils.cpp", "common/src/WatchdogClient.cpp", ], ], shared_libs: [ shared_libs: [ "libbase", "libbase", Loading
automotive/vehicle/2.0/default/VehicleService.cpp +19 −2 Original line number Original line Diff line number Diff line Loading @@ -20,9 +20,12 @@ #include <iostream> #include <iostream> #include <android/binder_process.h> #include <utils/Looper.h> #include <vhal_v2_0/EmulatedVehicleConnector.h> #include <vhal_v2_0/EmulatedVehicleConnector.h> #include <vhal_v2_0/EmulatedVehicleHal.h> #include <vhal_v2_0/EmulatedVehicleHal.h> #include <vhal_v2_0/VehicleHalManager.h> #include <vhal_v2_0/VehicleHalManager.h> #include <vhal_v2_0/WatchdogClient.h> using namespace android; using namespace android; using namespace android::hardware; using namespace android::hardware; Loading @@ -36,7 +39,7 @@ int main(int /* argc */, char* /* argv */ []) { auto service = std::make_unique<VehicleHalManager>(hal.get()); auto service = std::make_unique<VehicleHalManager>(hal.get()); connector->setValuePool(hal->getValuePool()); connector->setValuePool(hal->getValuePool()); configureRpcThreadpool(4, true /* callerWillJoin */); configureRpcThreadpool(4, false /* callerWillJoin */); ALOGI("Registering as service..."); ALOGI("Registering as service..."); status_t status = service->registerAsService(); status_t status = service->registerAsService(); Loading @@ -46,8 +49,22 @@ int main(int /* argc */, char* /* argv */ []) { return 1; return 1; } } // Setup a binder thread pool to be a car watchdog client. ABinderProcess_setThreadPoolMaxThreadCount(1); ABinderProcess_startThreadPool(); sp<Looper> looper(Looper::prepare(0 /* opts */)); std::shared_ptr<WatchdogClient> watchdogClient = ndk::SharedRefBase::make<WatchdogClient>(looper, service.get()); // The current health check is done in the main thread, so it falls short of capturing the real // situation. Checking through HAL binder thread should be considered. if (!watchdogClient->initialize()) { ALOGE("Failed to initialize car watchdog client"); return 1; } ALOGI("Ready"); ALOGI("Ready"); joinRpcThreadpool(); while (true) { looper->pollAll(-1 /* timeoutMillis */); } return 1; return 1; } }
automotive/vehicle/2.0/default/common/include/vhal_v2_0/WatchdogClient.h 0 → 100644 +74 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_ #define android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_ #include "VehicleHalManager.h" #include <aidl/android/automotive/watchdog/BnCarWatchdog.h> #include <aidl/android/automotive/watchdog/BnCarWatchdogClient.h> #include <utils/Looper.h> #include <utils/Mutex.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { class WatchdogClient : public aidl::android::automotive::watchdog::BnCarWatchdogClient { public: explicit WatchdogClient(const ::android::sp<::android::Looper>& handlerLooper, VehicleHalManager* vhalManager); ndk::ScopedAStatus checkIfAlive( int32_t sessionId, aidl::android::automotive::watchdog::TimeoutLength timeout) override; ndk::ScopedAStatus prepareProcessTermination() override; bool initialize(); private: class MessageHandlerImpl : public ::android::MessageHandler { public: explicit MessageHandlerImpl(WatchdogClient* client); void handleMessage(const ::android::Message& message) override; private: WatchdogClient* mClient; }; private: void respondToWatchdog(); bool isClientHealthy() const; private: ::android::sp<::android::Looper> mHandlerLooper; ::android::sp<MessageHandlerImpl> mMessageHandler; std::shared_ptr<aidl::android::automotive::watchdog::ICarWatchdog> mWatchdogServer; std::shared_ptr<aidl::android::automotive::watchdog::ICarWatchdogClient> mTestClient; VehicleHalManager* mVhalManager; ::android::Mutex mMutex; int mCurrentSessionId GUARDED_BY(mMutex); }; } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_
automotive/vehicle/2.0/default/common/src/WatchdogClient.cpp 0 → 100644 +140 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "automotive.vehicle@2.0-watchdog" #include <common/include/vhal_v2_0/WatchdogClient.h> #include <android/binder_manager.h> #include <android/hardware/automotive/vehicle/2.0/types.h> using aidl::android::automotive::watchdog::ICarWatchdog; using aidl::android::automotive::watchdog::TimeoutLength; namespace { enum { WHAT_CHECK_ALIVE = 1 }; } // namespace namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { WatchdogClient::WatchdogClient(const sp<Looper>& handlerLooper, VehicleHalManager* vhalManager) : mHandlerLooper(handlerLooper), mVhalManager(vhalManager), mCurrentSessionId(-1) { mMessageHandler = new MessageHandlerImpl(this); } ndk::ScopedAStatus WatchdogClient::checkIfAlive(int32_t sessionId, TimeoutLength /*timeout*/) { mHandlerLooper->removeMessages(mMessageHandler, WHAT_CHECK_ALIVE); { Mutex::Autolock lock(mMutex); mCurrentSessionId = sessionId; } mHandlerLooper->sendMessage(mMessageHandler, Message(WHAT_CHECK_ALIVE)); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus WatchdogClient::prepareProcessTermination() { return ndk::ScopedAStatus::ok(); } bool WatchdogClient::initialize() { ndk::SpAIBinder binder( AServiceManager_getService("android.automotive.watchdog.ICarWatchdog/default")); if (binder.get() == nullptr) { ALOGE("Failed to get carwatchdog daemon"); return false; } std::shared_ptr<ICarWatchdog> server = ICarWatchdog::fromBinder(binder); if (server == nullptr) { ALOGE("Failed to connect to carwatchdog daemon"); return false; } mWatchdogServer = server; binder = this->asBinder(); if (binder.get() == nullptr) { ALOGE("Failed to get car watchdog client binder object"); return false; } std::shared_ptr<ICarWatchdogClient> client = ICarWatchdogClient::fromBinder(binder); if (client == nullptr) { ALOGE("Failed to get ICarWatchdogClient from binder"); return false; } mTestClient = client; mWatchdogServer->registerClient(client, TimeoutLength::TIMEOUT_NORMAL); ALOGI("Successfully registered the client to car watchdog server"); return true; } void WatchdogClient::respondToWatchdog() { if (mWatchdogServer == nullptr) { ALOGW("Cannot respond to car watchdog daemon: car watchdog daemon is not connected"); return; } int sessionId; { Mutex::Autolock lock(mMutex); sessionId = mCurrentSessionId; } if (isClientHealthy()) { ndk::ScopedAStatus status = mWatchdogServer->tellClientAlive(mTestClient, sessionId); if (!status.isOk()) { ALOGE("Failed to call tellClientAlive(session id = %d): %d", sessionId, status.getStatus()); return; } } } bool WatchdogClient::isClientHealthy() const { // We consider that default vehicle HAL is healthy if we can get PERF_VEHICLE_SPEED value. StatusCode status = StatusCode::TRY_AGAIN; VehiclePropValue propValue = {.prop = (int32_t)VehicleProperty::PERF_VEHICLE_SPEED}; while (status == StatusCode::TRY_AGAIN) { mVhalManager->get(propValue, [&propValue, &status](StatusCode s, const VehiclePropValue& v) { status = s; if (s == StatusCode::OK) { propValue = v; } }); } return status == StatusCode::OK; } WatchdogClient::MessageHandlerImpl::MessageHandlerImpl(WatchdogClient* client) : mClient(client) {} void WatchdogClient::MessageHandlerImpl::handleMessage(const Message& message) { switch (message.what) { case WHAT_CHECK_ALIVE: mClient->respondToWatchdog(); break; default: ALOGW("Unknown message: %d", message.what); } } } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android