/* * Copyright 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. */ #include #include "SurroundViewService.h" using namespace android_auto::surround_view; namespace android { namespace hardware { namespace automotive { namespace sv { namespace V1_0 { namespace implementation { std::mutex SurroundViewService::sLock; sp SurroundViewService::sService; sp SurroundViewService::sSurroundView2dSession; sp SurroundViewService::sSurroundView3dSession; const std::string kCameraIds[] = {"0", "1", "2", "3"}; static const int kVhalUpdateRate = 10; SurroundViewService::SurroundViewService() : mVhalHandler(nullptr), mAnimationModule(nullptr), mIOModule(nullptr) { mVhalHandler = new VhalHandler(); mIOModule = new IOModule("/vendor/etc/automotive/sv/sv_sample_config.xml"); } SurroundViewService::~SurroundViewService() { if (mVhalHandler != nullptr) { delete mVhalHandler; } if (mIOModule != nullptr) { delete mIOModule; } if (mAnimationModule != nullptr) { delete mAnimationModule; } } sp SurroundViewService::getInstance() { std::scoped_lock lock(sLock); if (sService == nullptr) { sService = new SurroundViewService(); if (!sService->initialize()) { LOG(ERROR) << "Cannot initialize the service properly"; sService = nullptr; return nullptr; } } return sService; } std::vector getAnimationPropertiesToRead(const AnimationConfig& animationConfig) { std::set propertiesSet; for(const auto& animation: animationConfig.animations) { for(const auto& opPair : animation.gammaOpsMap) { propertiesSet.insert(opPair.first); } for(const auto& opPair : animation.textureOpsMap) { propertiesSet.insert(opPair.first); } for(const auto& opPair : animation.rotationOpsMap) { propertiesSet.insert(opPair.first); } for(const auto& opPair : animation.translationOpsMap) { propertiesSet.insert(opPair.first); } } std::vector propertiesToRead; propertiesToRead.assign(propertiesSet.begin(), propertiesSet.end()); return propertiesToRead; } bool SurroundViewService::initialize() { // Get the EVS manager service LOG(INFO) << "Acquiring EVS Enumerator"; mEvs = IEvsEnumerator::getService("default"); if (mEvs == nullptr) { LOG(ERROR) << "getService returned NULL. Exiting."; return false; } IOStatus status = mIOModule->initialize(); if (status != IOStatus::OK) { LOG(ERROR) << "IO Module cannot be initialized properly"; return false; } if (!mIOModule->getConfig(&mConfig)) { LOG(ERROR) << "Cannot parse Car Config file properly"; return false; } // Since we only keep one instance of the SurroundViewService and initialize // method is always called after the constructor, it is safe to put the // allocation here and the de-allocation in service's constructor. mAnimationModule = new AnimationModule( mConfig.carModelConfig.carModel.partsMap, mConfig.carModelConfig.carModel.texturesMap, mConfig.carModelConfig.animationConfig.animations); // Initialize the VHal Handler with update method and rate. // TODO(b/157498592): The update rate should align with the EVS camera // update rate. if (mVhalHandler->initialize(VhalHandler::GET, kVhalUpdateRate)) { // Initialize the vhal handler properties to read. std::vector propertiesToRead; // Add animation properties to read if 3d and animations are enabled. if (mConfig.sv3dConfig.sv3dEnabled && mConfig.sv3dConfig.sv3dAnimationsEnabled) { const std::vector animationPropertiesToRead = getAnimationPropertiesToRead(mConfig.carModelConfig.animationConfig); propertiesToRead.insert(propertiesToRead.end(), animationPropertiesToRead.begin(), animationPropertiesToRead.end()); } // Call vhal handler setPropertiesToRead with all properties. if (!mVhalHandler->setPropertiesToRead(propertiesToRead)) { LOG(WARNING) << "VhalHandler setPropertiesToRead failed."; } } else { LOG(WARNING) << "VhalHandler cannot be initialized properly"; } return true; } Return SurroundViewService::getCameraIds(getCameraIds_cb _hidl_cb) { hidl_vec cameraIds = {kCameraIds[0], kCameraIds[1], kCameraIds[2], kCameraIds[3]}; _hidl_cb(cameraIds); return {}; } Return SurroundViewService::start2dSession(start2dSession_cb _hidl_cb) { LOG(DEBUG) << __FUNCTION__; std::scoped_lock lock(sLock); if (sSurroundView2dSession != nullptr) { LOG(WARNING) << "Only one 2d session is supported at the same time"; _hidl_cb(nullptr, SvResult::INTERNAL_ERROR); } else { sSurroundView2dSession = new SurroundView2dSession(mEvs, &mConfig); if (sSurroundView2dSession->initialize()) { _hidl_cb(sSurroundView2dSession, SvResult::OK); } else { _hidl_cb(nullptr, SvResult::INTERNAL_ERROR); } } return {}; } Return SurroundViewService::stop2dSession( const sp& sv2dSession) { LOG(DEBUG) << __FUNCTION__; std::scoped_lock lock(sLock); if (sv2dSession != nullptr && sv2dSession == sSurroundView2dSession) { sSurroundView2dSession = nullptr; return SvResult::OK; } else { LOG(ERROR) << __FUNCTION__ << ": Invalid argument"; return SvResult::INVALID_ARG; } } Return SurroundViewService::start3dSession(start3dSession_cb _hidl_cb) { LOG(DEBUG) << __FUNCTION__; std::scoped_lock lock(sLock); if (sSurroundView3dSession != nullptr) { LOG(WARNING) << "Only one 3d session is supported at the same time"; _hidl_cb(nullptr, SvResult::INTERNAL_ERROR); } else { sSurroundView3dSession = new SurroundView3dSession(mEvs, mVhalHandler, mAnimationModule, &mConfig); if (sSurroundView3dSession->initialize()) { _hidl_cb(sSurroundView3dSession, SvResult::OK); } else { _hidl_cb(nullptr, SvResult::INTERNAL_ERROR); } } return {}; } Return SurroundViewService::stop3dSession( const sp& sv3dSession) { LOG(DEBUG) << __FUNCTION__; std::scoped_lock lock(sLock); if (sv3dSession != nullptr && sv3dSession == sSurroundView3dSession) { sSurroundView3dSession = nullptr; return SvResult::OK; } else { LOG(ERROR) << __FUNCTION__ << ": Invalid argument"; return SvResult::INVALID_ARG; } } } // namespace implementation } // namespace V1_0 } // namespace sv } // namespace automotive } // namespace hardware } // namespace android