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 #include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
19 #include <android/hardware/automotive/sv/1.0/ISurroundViewService.h>
20 #include <android/hardware/automotive/sv/1.0/ISurroundView2dSession.h>
21 #include <android/hardware/automotive/sv/1.0/ISurroundView3dSession.h>
22 #include <hidl/HidlTransportSupport.h>
23 #include <stdio.h>
24 #include <utils/StrongPointer.h>
25 #include <utils/Log.h>
26 #include <thread>
27
28 #include "SurroundViewServiceCallback.h"
29
30 // libhidl:
31 using android::hardware::configureRpcThreadpool;
32 using android::hardware::joinRpcThreadpool;
33
34 using android::sp;
35 using android::hardware::Return;
36 using android::hardware::automotive::evs::V1_0::EvsResult;
37
38 using BufferDesc_1_0 = android::hardware::automotive::evs::V1_0::BufferDesc;
39 using DisplayState = android::hardware::automotive::evs::V1_0::DisplayState;
40
41 using namespace android::hardware::automotive::sv::V1_0;
42 using namespace android::hardware::automotive::evs::V1_1;
43
44 const int kLowResolutionWidth = 120;
45 const int kLowResolutionHeight = 90;
46
47 enum DemoMode {
48 UNKNOWN,
49 DEMO_2D,
50 DEMO_3D,
51 };
52
run2dSurroundView(sp<ISurroundViewService> pSurroundViewService,sp<IEvsDisplay> pDisplay)53 bool run2dSurroundView(sp<ISurroundViewService> pSurroundViewService,
54 sp<IEvsDisplay> pDisplay) {
55 LOG(INFO) << "Run 2d Surround View demo";
56
57 // Call HIDL API "start2dSession"
58 sp<ISurroundView2dSession> surroundView2dSession;
59
60 SvResult svResult;
61 pSurroundViewService->start2dSession(
62 [&surroundView2dSession, &svResult](
63 const sp<ISurroundView2dSession>& session, SvResult result) {
64 surroundView2dSession = session;
65 svResult = result;
66 });
67
68 if (surroundView2dSession == nullptr || svResult != SvResult::OK) {
69 LOG(ERROR) << "Failed to start2dSession";
70 return false;
71 } else {
72 LOG(INFO) << "start2dSession succeeded";
73 }
74
75 sp<SurroundViewServiceCallback> sv2dCallback
76 = new SurroundViewServiceCallback(pDisplay, surroundView2dSession);
77
78 // Start 2d stream with callback
79 if (surroundView2dSession->startStream(sv2dCallback) != SvResult::OK) {
80 LOG(ERROR) << "Failed to start 2d stream";
81 return false;
82 }
83
84 // Let the SV algorithm run for 10 seconds for HIGH_QUALITY
85 std::this_thread::sleep_for(std::chrono::seconds(10));
86
87 // Switch to low quality and lower resolution
88 Sv2dConfig config;
89 config.width = kLowResolutionWidth;
90 config.blending = SvQuality::LOW;
91 if (surroundView2dSession->set2dConfig(config) != SvResult::OK) {
92 LOG(ERROR) << "Failed to set2dConfig";
93 return false;
94 }
95
96 // Let the SV algorithm run for 10 seconds for LOW_QUALITY
97 std::this_thread::sleep_for(std::chrono::seconds(10));
98
99 // TODO(b/150412555): wait for the last frame
100 // Stop the 2d stream and session
101 surroundView2dSession->stopStream();
102
103 pSurroundViewService->stop2dSession(surroundView2dSession);
104 surroundView2dSession = nullptr;
105
106 LOG(INFO) << "SV 2D session finished.";
107
108 return true;
109 };
110
run3dSurroundView(sp<ISurroundViewService> pSurroundViewService,sp<IEvsDisplay> pDisplay)111 bool run3dSurroundView(sp<ISurroundViewService> pSurroundViewService,
112 sp<IEvsDisplay> pDisplay) {
113 LOG(INFO) << "Run 3d Surround View demo";
114
115 // Call HIDL API "start3dSession"
116 sp<ISurroundView3dSession> surroundView3dSession;
117
118 SvResult svResult;
119 pSurroundViewService->start3dSession(
120 [&surroundView3dSession, &svResult](
121 const sp<ISurroundView3dSession>& session, SvResult result) {
122 surroundView3dSession = session;
123 svResult = result;
124 });
125
126 if (surroundView3dSession == nullptr || svResult != SvResult::OK) {
127 LOG(ERROR) << "Failed to start3dSession";
128 return false;
129 } else {
130 LOG(INFO) << "start3dSession succeeded";
131 }
132
133 // TODO(b/150412555): now we have the dummy view here since the views are
134 // set in service. This should be fixed.
135 std::vector<View3d> singleView(1);
136 surroundView3dSession->setViews(singleView);
137
138 if (surroundView3dSession->setViews(singleView) != SvResult::OK) {
139 LOG(ERROR) << "Failed to setViews";
140 return false;
141 }
142
143 sp<SurroundViewServiceCallback> sv3dCallback
144 = new SurroundViewServiceCallback(pDisplay, surroundView3dSession);
145
146 // Start 3d stream with callback
147 if (surroundView3dSession->startStream(sv3dCallback) != SvResult::OK) {
148 LOG(ERROR) << "Failed to start 3d stream";
149 return false;
150 }
151
152 // Let the SV algorithm run for 10 seconds for HIGH_QUALITY
153 std::this_thread::sleep_for(std::chrono::seconds(10));
154
155 // Switch to low quality and lower resolution
156 Sv3dConfig config;
157 config.width = kLowResolutionWidth;
158 config.height = kLowResolutionHeight;
159 config.carDetails = SvQuality::LOW;
160 if (surroundView3dSession->set3dConfig(config) != SvResult::OK) {
161 LOG(ERROR) << "Failed to set3dConfig";
162 return false;
163 }
164
165 // Let the SV algorithm run for 10 seconds for LOW_QUALITY
166 std::this_thread::sleep_for(std::chrono::seconds(10));
167
168 // TODO(b/150412555): wait for the last frame
169 // Stop the 3d stream and session
170 surroundView3dSession->stopStream();
171
172 pSurroundViewService->stop3dSession(surroundView3dSession);
173 surroundView3dSession = nullptr;
174
175 LOG(DEBUG) << "SV 3D session finished.";
176
177 return true;
178 };
179
180 // Main entry point
main(int argc,char ** argv)181 int main(int argc, char** argv) {
182 // Start up
183 LOG(INFO) << "SV app starting";
184
185 DemoMode mode = UNKNOWN;
186 for (int i=1; i< argc; i++) {
187 if (strcmp(argv[i], "--use2d") == 0) {
188 mode = DEMO_2D;
189 } else if (strcmp(argv[i], "--use3d") == 0) {
190 mode = DEMO_3D;
191 } else {
192 LOG(WARNING) << "Ignoring unrecognized command line arg: "
193 << argv[i];
194 }
195 }
196
197 if (mode == UNKNOWN) {
198 LOG(ERROR) << "No demo mode is specified. Exiting";
199 return EXIT_FAILURE;
200 }
201
202 // Set thread pool size to one to avoid concurrent events from the HAL.
203 // This pool will handle the SurroundViewStream callbacks.
204 configureRpcThreadpool(1, false /* callerWillJoin */);
205
206 // Try to connect to EVS service
207 LOG(INFO) << "Acquiring EVS Enumerator";
208 sp<IEvsEnumerator> evs = IEvsEnumerator::getService();
209 if (evs == nullptr) {
210 LOG(ERROR) << "getService(default) returned NULL. Exiting.";
211 return EXIT_FAILURE;
212 }
213
214 // Try to connect to SV service
215 LOG(INFO) << "Acquiring SV Service";
216 android::sp<ISurroundViewService> surroundViewService
217 = ISurroundViewService::getService("default");
218
219 if (surroundViewService == nullptr) {
220 LOG(ERROR) << "getService(default) returned NULL.";
221 return EXIT_FAILURE;
222 } else {
223 LOG(INFO) << "Get ISurroundViewService default";
224 }
225
226 // Connect to evs display
227 int displayId;
228 evs->getDisplayIdList([&displayId](auto idList) {
229 displayId = idList[0];
230 });
231
232 LOG(INFO) << "Acquiring EVS Display with ID: "
233 << displayId;
234 sp<IEvsDisplay> display = evs->openDisplay_1_1(displayId);
235 if (display == nullptr) {
236 LOG(ERROR) << "EVS Display unavailable. Exiting.";
237 return EXIT_FAILURE;
238 }
239
240 if (mode == DEMO_2D) {
241 if (!run2dSurroundView(surroundViewService, display)) {
242 LOG(ERROR) << "Something went wrong in 2d surround view demo. "
243 << "Exiting.";
244 return EXIT_FAILURE;
245 }
246 } else if (mode == DEMO_3D) {
247 if (!run3dSurroundView(surroundViewService, display)) {
248 LOG(ERROR) << "Something went wrong in 3d surround view demo. "
249 << "Exiting.";
250 return EXIT_FAILURE;
251 }
252 }
253
254 evs->closeDisplay(display);
255
256 LOG(DEBUG) << "SV sample app finished running successfully";
257 return EXIT_SUCCESS;
258 }
259