1 /*
2  * Copyright 2020 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 
17 #include <android-base/logging.h>
18 
19 #include "CoreLibSetupHelper.h"
20 #include "SurroundViewService.h"
21 
22 using namespace android_auto::surround_view;
23 
24 namespace android {
25 namespace hardware {
26 namespace automotive {
27 namespace sv {
28 namespace V1_0 {
29 namespace implementation {
30 
31 std::mutex SurroundViewService::sLock;
32 sp<SurroundViewService> SurroundViewService::sService;
33 sp<SurroundView2dSession> SurroundViewService::sSurroundView2dSession;
34 sp<SurroundView3dSession> SurroundViewService::sSurroundView3dSession;
35 
36 const std::string kCameraIds[] = {"0", "1", "2", "3"};
37 static const int kVhalUpdateRate = 10;
38 
SurroundViewService()39 SurroundViewService::SurroundViewService() {
40     mVhalHandler = new VhalHandler();
41     mIOModule = new IOModule("/vendor/etc/automotive/sv/sv_sample_config.xml");
42 }
43 
~SurroundViewService()44 SurroundViewService::~SurroundViewService() {
45     delete mVhalHandler;
46     delete mAnimationModule;
47 }
48 
getInstance()49 sp<SurroundViewService> SurroundViewService::getInstance() {
50     std::scoped_lock<std::mutex> lock(sLock);
51     if (sService == nullptr) {
52         sService = new SurroundViewService();
53         if (!sService->initialize()) {
54             LOG(ERROR) << "Cannot initialize the service properly";
55             sService = nullptr;
56             return nullptr;
57         }
58     }
59     return sService;
60 }
61 
getAnimationPropertiesToRead(const AnimationConfig & animationConfig)62 std::vector<uint64_t> getAnimationPropertiesToRead(const AnimationConfig& animationConfig) {
63     std::set<uint64_t> propertiesSet;
64     for(const auto& animation: animationConfig.animations) {
65         for(const auto& opPair : animation.gammaOpsMap) {
66             propertiesSet.insert(opPair.first);
67         }
68 
69         for(const auto& opPair : animation.textureOpsMap) {
70             propertiesSet.insert(opPair.first);
71         }
72 
73         for(const auto& opPair : animation.rotationOpsMap) {
74             propertiesSet.insert(opPair.first);
75         }
76 
77         for(const auto& opPair : animation.translationOpsMap) {
78             propertiesSet.insert(opPair.first);
79         }
80     }
81     std::vector<uint64_t> propertiesToRead;
82     propertiesToRead.assign(propertiesSet.begin(), propertiesSet.end());
83     return propertiesToRead;
84 }
85 
initialize()86 bool SurroundViewService::initialize() {
87     // Get the EVS manager service
88     LOG(INFO) << "Acquiring EVS Enumerator";
89     mEvs = IEvsEnumerator::getService("default");
90     if (mEvs == nullptr) {
91         LOG(ERROR) << "getService returned NULL.  Exiting.";
92         return false;
93     }
94 
95     IOStatus status = mIOModule->initialize();
96     if (status != IOStatus::OK) {
97         LOG(ERROR) << "IO Module cannot be initialized properly";
98         return false;
99     }
100 
101     if (!mIOModule->getConfig(&mConfig)) {
102         LOG(ERROR) << "Cannot parse Car Config file properly";
103         return false;
104     }
105 
106     // Since we only keep one instance of the SurroundViewService and initialize
107     // method is always called after the constructor, it is safe to put the
108     // allocation here and the de-allocation in service's constructor.
109     mAnimationModule = new AnimationModule(
110             mConfig.carModelConfig.carModel.partsMap,
111             mConfig.carModelConfig.carModel.texturesMap,
112             mConfig.carModelConfig.animationConfig.animations);
113 
114     // Initialize the VHal Handler with update method and rate.
115     // TODO(b/157498592): The update rate should align with the EVS camera
116     // update rate.
117     if (mVhalHandler->initialize(VhalHandler::GET, kVhalUpdateRate)) {
118         // Initialize the vhal handler properties to read.
119         std::vector<uint64_t> propertiesToRead;
120 
121         // Add animation properties to read if 3d and animations are enabled.
122         if (mConfig.sv3dConfig.sv3dEnabled && mConfig.sv3dConfig.sv3dAnimationsEnabled) {
123             const std::vector<uint64_t> animationPropertiesToRead =
124                     getAnimationPropertiesToRead(mConfig.carModelConfig.animationConfig);
125             propertiesToRead.insert(propertiesToRead.end(), animationPropertiesToRead.begin(),
126                     animationPropertiesToRead.end());
127         }
128 
129         // Call vhal handler setPropertiesToRead with all properties.
130         if (!mVhalHandler->setPropertiesToRead(propertiesToRead)) {
131             LOG(WARNING) << "VhalHandler setPropertiesToRead failed.";
132         }
133     } else {
134         LOG(WARNING) << "VhalHandler cannot be initialized properly";
135     }
136 
137     return true;
138 }
139 
getCameraIds(getCameraIds_cb _hidl_cb)140 Return<void> SurroundViewService::getCameraIds(getCameraIds_cb _hidl_cb) {
141     hidl_vec<hidl_string> cameraIds = {kCameraIds[0], kCameraIds[1],
142         kCameraIds[2], kCameraIds[3]};
143     _hidl_cb(cameraIds);
144     return {};
145 }
146 
start2dSession(start2dSession_cb _hidl_cb)147 Return<void> SurroundViewService::start2dSession(start2dSession_cb _hidl_cb) {
148     LOG(DEBUG) << __FUNCTION__;
149     std::scoped_lock<std::mutex> lock(sLock);
150 
151     if (sSurroundView2dSession != nullptr) {
152         LOG(WARNING) << "Only one 2d session is supported at the same time";
153         _hidl_cb(nullptr, SvResult::INTERNAL_ERROR);
154     } else {
155         sSurroundView2dSession = new SurroundView2dSession(mEvs, &mConfig);
156         if (sSurroundView2dSession->initialize()) {
157             _hidl_cb(sSurroundView2dSession, SvResult::OK);
158         } else {
159             _hidl_cb(nullptr, SvResult::INTERNAL_ERROR);
160         }
161     }
162     return {};
163 }
164 
stop2dSession(const sp<ISurroundView2dSession> & sv2dSession)165 Return<SvResult> SurroundViewService::stop2dSession(
166     const sp<ISurroundView2dSession>& sv2dSession) {
167     LOG(DEBUG) << __FUNCTION__;
168     std::scoped_lock<std::mutex> lock(sLock);
169 
170     if (sv2dSession != nullptr && sv2dSession == sSurroundView2dSession) {
171         sSurroundView2dSession = nullptr;
172         return SvResult::OK;
173     } else {
174         LOG(ERROR) << __FUNCTION__ << ": Invalid argument";
175         return SvResult::INVALID_ARG;
176     }
177 }
178 
start3dSession(start3dSession_cb _hidl_cb)179 Return<void> SurroundViewService::start3dSession(start3dSession_cb _hidl_cb) {
180     LOG(DEBUG) << __FUNCTION__;
181     std::scoped_lock<std::mutex> lock(sLock);
182 
183     if (sSurroundView3dSession != nullptr) {
184         LOG(WARNING) << "Only one 3d session is supported at the same time";
185         _hidl_cb(nullptr, SvResult::INTERNAL_ERROR);
186     } else {
187         sSurroundView3dSession = new SurroundView3dSession(mEvs,
188                                                            mVhalHandler,
189                                                            mAnimationModule,
190                                                            &mConfig);
191         if (sSurroundView3dSession->initialize()) {
192             _hidl_cb(sSurroundView3dSession, SvResult::OK);
193         } else {
194             _hidl_cb(nullptr, SvResult::INTERNAL_ERROR);
195         }
196     }
197     return {};
198 }
199 
stop3dSession(const sp<ISurroundView3dSession> & sv3dSession)200 Return<SvResult> SurroundViewService::stop3dSession(
201     const sp<ISurroundView3dSession>& sv3dSession) {
202     LOG(DEBUG) << __FUNCTION__;
203     std::scoped_lock<std::mutex> lock(sLock);
204 
205     if (sv3dSession != nullptr && sv3dSession == sSurroundView3dSession) {
206         sSurroundView3dSession = nullptr;
207         return SvResult::OK;
208     } else {
209         LOG(ERROR) << __FUNCTION__ << ": Invalid argument";
210         return SvResult::INVALID_ARG;
211     }
212 }
213 
214 }  // namespace implementation
215 }  // namespace V1_0
216 }  // namespace sv
217 }  // namespace automotive
218 }  // namespace hardware
219 }  // namespace android
220