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