1 /*
2  * Copyright 2022 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 "MockHidlEvsHal.h"
18 
19 #include "Constants.h"
20 
21 #include <android-base/logging.h>
22 #include <camera/CameraMetadata.h>
23 #include <hardware/gralloc.h>
24 #include <ui/DisplayMode.h>
25 #include <utils/SystemClock.h>
26 
27 #include <functional>
28 #include <future>
29 
30 #include <system/graphics-base.h>
31 
32 namespace {
33 
34 using ::android::hardware::automotive::evs::V1_0::DisplayDesc;
35 using ::android::hardware::automotive::evs::V1_0::DisplayState;
36 using ::android::hardware::automotive::evs::V1_0::EvsResult;
37 using ::android::hardware::automotive::evs::V1_1::BufferDesc;
38 using ::android::hardware::automotive::evs::V1_1::CameraDesc;
39 using ::android::hardware::automotive::evs::V1_1::CameraParam;
40 using ::android::hardware::automotive::evs::V1_1::EvsEventDesc;
41 using ::android::hardware::automotive::evs::V1_1::EvsEventType;
42 using ::android::hardware::automotive::evs::V1_1::IEvsCamera;
43 using ::android::hardware::automotive::evs::V1_1::IEvsCameraStream;
44 using ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
45 using ::android::hardware::automotive::evs::V1_1::IEvsEnumerator;
46 using ::android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArray;
47 using ::android::hardware::camera::device::V3_2::Stream;
48 using ::std::chrono_literals::operator""ms;
49 using ::std::chrono_literals::operator""s;
50 
51 inline constexpr char kMockCameraDeviceNamePrefix[] = "/dev/mockcamera";
52 inline constexpr int32_t kCameraParamDefaultMinValue = -255;
53 inline constexpr int32_t kCameraParamDefaultMaxValue = 255;
54 inline constexpr int32_t kCameraParamDefaultStepValue = 3;
55 inline constexpr size_t kMinimumNumBuffers = 2;
56 inline constexpr size_t kMaximumNumBuffers = 10;
57 
58 }  // namespace
59 
60 namespace aidl::android::automotive::evs::implementation {
61 
~MockHidlEvsHal()62 MockHidlEvsHal::~MockHidlEvsHal() {
63     std::lock_guard lock(mLock);
64     for (auto& [id, state] : mStreamState) {
65         auto it = mCameraFrameThread.find(id);
66         if (it == mCameraFrameThread.end() || !it->second.joinable()) {
67             continue;
68         }
69 
70         state = StreamState::kStopping;
71         it->second.join();
72     }
73 
74     deinitializeBufferPoolLocked();
75     mCameraClient.clear();
76 }
77 
getEnumerator()78 ::android::sp<IEvsEnumerator> MockHidlEvsHal::getEnumerator() {
79     if (!mMockHidlEvsEnumerator) {
80         LOG(ERROR) << "MockHidlEvsHal has not initialized yet.";
81         return nullptr;
82     }
83 
84     return mMockHidlEvsEnumerator;
85 }
86 
initialize()87 void MockHidlEvsHal::initialize() {
88     initializeBufferPool(kMaximumNumBuffers);
89     configureCameras(mNumCameras);
90     configureDisplays(mNumDisplays);
91     configureEnumerator();
92 }
93 
buildCameraMetadata(int32_t width,int32_t height,int32_t format,::android::hardware::hidl_vec<uint8_t> * out)94 bool MockHidlEvsHal::buildCameraMetadata(int32_t width, int32_t height, int32_t format,
95                                          ::android::hardware::hidl_vec<uint8_t>* out) {
96     ::android::CameraMetadata metadata;
97 
98     const std::vector<int32_t> availableStreamConfigurations =
99             {format, width, height, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT};
100 
101     metadata.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
102                     availableStreamConfigurations.data(), availableStreamConfigurations.size());
103 
104     camera_metadata_t* p = metadata.release();
105     if (validate_camera_metadata_structure(p, /* expected_size= */ nullptr) != ::android::OK) {
106         LOG(ERROR) << "Failed to build a camera metadata.";
107         return false;
108     }
109 
110     size_t n = get_camera_metadata_size(p);
111     out->resize(n);
112     memcpy(out->data(), p, n);
113 
114     return true;
115 }
116 
forwardFrames(size_t numberOfFramesToForward,const std::string & deviceId)117 void MockHidlEvsHal::forwardFrames(size_t numberOfFramesToForward, const std::string& deviceId) {
118     std::unique_lock l(mLock);
119     ::android::base::ScopedLockAssertion lock_assertion(mLock);
120     auto it = mStreamState.find(deviceId);
121     if (it != mStreamState.end() && it->second != StreamState::kStopped) {
122         LOG(WARNING) << "A mock video stream is already active.";
123         return;
124     }
125     mStreamState.insert_or_assign(deviceId, StreamState::kRunning);
126 
127     for (size_t count = 0;
128          mStreamState[deviceId] == StreamState::kRunning && count < numberOfFramesToForward;
129          ++count) {
130         if (mBufferPool.empty()) {
131             if (!mBufferAvailableSignal.wait_for(l, /* rel_time= */ 10s, [this]() REQUIRES(mLock) {
132                     // Waiting for a buffer to use.
133                     return !mBufferPool.empty();
134                 })) {
135                 LOG(ERROR) << "Buffer timeout; " << count << "/" << numberOfFramesToForward
136                            << " are sent.";
137                 break;
138             }
139         }
140 
141         auto it = mCameraClient.find(deviceId);
142         if (it == mCameraClient.end() || it->second == nullptr) {
143             LOG(ERROR) << "Failed to forward a frame as no active recipient exists; " << count
144                        << "/" << numberOfFramesToForward << " are sent.";
145             break;
146         }
147 
148         BufferDesc bufferToForward = mBufferPool.back();
149         mBufferPool.pop_back();
150 
151         bufferToForward.timestamp = static_cast<int64_t>(::android::elapsedRealtimeNano() * 1e+3);
152         bufferToForward.deviceId = deviceId;
153 
154         // Mark a buffer in-use.
155         mBuffersInUse.push_back(bufferToForward);
156         l.unlock();
157 
158         // Forward a duplicated buffer.  This must be done without a lock
159         // because a shared data will be modified in doneWithFrame().
160         ::android::hardware::hidl_vec<BufferDesc> packet;
161         packet.resize(1);
162         packet[0] = bufferToForward;
163         it->second->deliverFrame_1_1(packet);
164 
165         LOG(DEBUG) << deviceId << ": " << (count + 1) << "/" << numberOfFramesToForward
166                    << " frames are sent";
167         std::this_thread::sleep_for(33ms);  // 30 frames per seconds
168         l.lock();
169     }
170 
171     if (mStreamState.find(deviceId) != mStreamState.end()) {
172         mStreamState[deviceId] = StreamState::kStopped;
173     }
174 }
175 
initializeBufferPool(size_t requested)176 size_t MockHidlEvsHal::initializeBufferPool(size_t requested) {
177     std::lock_guard lock(mLock);
178     for (auto count = 0; count < requested; ++count) {
179         AHardwareBuffer_Desc desc = {
180                 .width = 64,
181                 .height = 32,
182                 .layers = 1,
183                 .format = HAL_PIXEL_FORMAT_RGBA_8888,
184                 .usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
185         };
186         AHardwareBuffer* ahwb;
187         if (AHardwareBuffer_allocate(&desc, &ahwb) != ::android::NO_ERROR) {
188             LOG(ERROR) << "Failed to allocate AHardwareBuffer";
189             return count;
190         }
191         buffer_handle_t memHandle = AHardwareBuffer_getNativeHandle(ahwb);
192         BufferDesc aBuffer = {
193                 .buffer =
194                         {
195                                 .nativeHandle = memHandle,
196                         },
197                 .pixelSize = 4,
198                 .bufferId = static_cast<uint32_t>(count),
199                 .deviceId = "Mock EvsCamera",
200         };
201 
202         *(reinterpret_cast<AHardwareBuffer_Desc*>(&aBuffer.buffer.description)) = desc;
203         mBufferRecord.insert_or_assign(count, ahwb);
204         mBufferPool.push_back(std::move(aBuffer));
205     }
206 
207     return mBufferPool.size();
208 }
209 
deinitializeBufferPoolLocked()210 void MockHidlEvsHal::deinitializeBufferPoolLocked() {
211     for (auto&& descriptor : mBuffersInUse) {
212         auto it = mBufferRecord.find(descriptor.bufferId);
213         if (it == mBufferRecord.end()) {
214             LOG(WARNING) << "Ignoring unknown buffer id, " << descriptor.bufferId;
215         } else {
216             LOG(WARNING) << "Releasing buffer in use, id = " << descriptor.bufferId;
217             AHardwareBuffer_release(it->second);
218             mBufferRecord.erase(it);
219         }
220     }
221 
222     for (auto&& descriptor : mBufferPool) {
223         auto it = mBufferRecord.find(descriptor.bufferId);
224         if (it == mBufferRecord.end()) {
225             LOG(WARNING) << "Ignoring unknown buffer id, " << descriptor.bufferId;
226         } else {
227             AHardwareBuffer_release(it->second);
228             mBufferRecord.erase(it);
229         }
230     }
231 
232     mBuffersInUse.clear();
233     mBufferPool.clear();
234 }
235 
configureCameras(size_t n)236 void MockHidlEvsHal::configureCameras(size_t n) {
237     // Initializes a list of the camera parameters each mock camera
238     // supports with their default values.
239     mCameraParams = {{CameraParam::BRIGHTNESS, 80},
240                      {CameraParam::CONTRAST, 60},
241                      {CameraParam::AUTOGAIN, 3},
242                      {CameraParam::AUTO_EXPOSURE, 1}};
243 
244     for (auto i = 0; i < n; ++i) {
245         (void)addMockCameraDevice(kMockCameraDeviceNamePrefix + std::to_string(i));
246     }
247 }
248 
addMockCameraDevice(const std::string & deviceId)249 bool MockHidlEvsHal::addMockCameraDevice(const std::string& deviceId) {
250     ::android::sp<NiceMockHidlEvsCamera> mockCamera =
251             new (std::nothrow) NiceMockHidlEvsCamera(deviceId);
252 
253     // For the testing purpose, this method will return
254     // EvsResult::INVALID_ARG if the client returns any buffer with
255     // unknown identifier.
256     ON_CALL(*mockCamera, doneWithFrame)
257             .WillByDefault([this](const hidlevs::V1_0::BufferDesc& buffer) {
258                 std::lock_guard lock(mLock);
259                 auto it = std::find_if(mBuffersInUse.begin(), mBuffersInUse.end(),
260                                        [id = buffer.bufferId](const BufferDesc& desc) {
261                                            return id == desc.bufferId;
262                                        });
263                 if (it == mBuffersInUse.end()) {
264                     return ::android::hardware::Void();
265                 }
266 
267                 mBufferPool.push_back(std::move(*it));
268                 mBuffersInUse.erase(it);
269 
270                 return ::android::hardware::Void();
271             });
272 
273     ON_CALL(*mockCamera, doneWithFrame_1_1)
274             .WillByDefault([this](const ::android::hardware::hidl_vec<BufferDesc>& buffers) {
275                 size_t returned = 0;
276                 std::lock_guard lock(mLock);
277                 for (auto& b : buffers) {
278                     auto it = std::find_if(mBuffersInUse.begin(), mBuffersInUse.end(),
279                                            [id = b.bufferId](const BufferDesc& desc) {
280                                                return id == desc.bufferId;
281                                            });
282                     if (it == mBuffersInUse.end()) {
283                         continue;
284                     }
285 
286                     ++returned;
287                     mBufferPool.push_back(std::move(*it));
288                     mBuffersInUse.erase(it);
289                 }
290 
291                 if (returned > 0) {
292                     mBufferAvailableSignal.notify_all();
293                     return EvsResult::OK;
294                 } else {
295                     return EvsResult::INVALID_ARG;
296                 }
297             });
298 
299     // EVS HAL accepts only a single client; therefore, this method
300     // returns a success always.
301     ON_CALL(*mockCamera, forceMaster)
302             .WillByDefault(
303                     [](const ::android::sp<hidlevs::V1_0::IEvsDisplay>&) { return EvsResult::OK; });
304 
305     // We return a mock camera descriptor with the metadata but empty vendor
306     // flag.
307     ON_CALL(*mockCamera, getCameraInfo)
308             .WillByDefault([deviceId](MockHidlEvsCamera::getCameraInfo_cb callback) {
309                 hidlevs::V1_0::CameraDesc mockDesc = {
310                         .cameraId = deviceId,
311                         .vendorFlags = 0x0,
312                 };
313 
314                 callback(mockDesc);
315                 return ::android::hardware::Void();
316             });
317 
318     ON_CALL(*mockCamera, getCameraInfo_1_1)
319             .WillByDefault([deviceId, this](MockHidlEvsCamera::getCameraInfo_1_1_cb callback) {
320                 CameraDesc mockDesc = {
321                         .v1 =
322                                 {
323                                         .cameraId = deviceId,
324                                         .vendorFlags = 0x0,
325                                 },
326                         .metadata = {},
327                 };
328 
329                 if (!buildCameraMetadata(/* width= */ 640, /* height= */ 480,
330                                          /* format= */ HAL_PIXEL_FORMAT_RGBA_8888,
331                                          &mockDesc.metadata)) {
332                     return ::android::hardware::Void();
333                 }
334 
335                 callback(mockDesc);
336                 return ::android::hardware::Void();
337             });
338 
339     // This method will return a value associated with a given
340     // identifier if exists.
341     ON_CALL(*mockCamera, getExtendedInfo).WillByDefault([this](uint32_t id) {
342         auto it = mCameraExtendedInfo.find(id);
343         if (it == mCameraExtendedInfo.end()) {
344             // A requested information does not exist.
345             return 0;
346         }
347 
348         if (it->second.size() < 4) {
349             // Stored information is in an invalid size.
350             return 0;
351         }
352 
353         int value = *(reinterpret_cast<int32_t*>(it->second.data()));
354         return value;
355     });
356 
357     ON_CALL(*mockCamera, getExtendedInfo_1_1)
358             .WillByDefault([this](uint32_t id, MockHidlEvsCamera::getExtendedInfo_1_1_cb callback) {
359                 auto it = mCameraExtendedInfo.find(id);
360                 if (it == mCameraExtendedInfo.end()) {
361                     // A requested information does not exist.
362                     callback(EvsResult::INVALID_ARG, 0);
363                     return ::android::hardware::Void();
364                 }
365 
366                 ::android::hardware::hidl_vec<uint8_t> value = it->second;
367                 callback(EvsResult::OK, value);
368                 return ::android::hardware::Void();
369             });
370 
371     // This method will return a value of a requested camera parameter
372     // if it is supported by a mock EVS camera.
373     ON_CALL(*mockCamera, getIntParameter)
374             .WillByDefault([this](CameraParam id, MockHidlEvsCamera::getIntParameter_cb callback) {
375                 auto it = mCameraParams.find(id);
376                 if (it == mCameraParams.end()) {
377                     LOG(ERROR) << "Ignore a request to read an unsupported parameter, " << (int)id;
378                     callback(EvsResult::INVALID_ARG, 0);
379                     return ::android::hardware::Void();
380                 }
381 
382                 // EVS HAL always returns a single integer value.
383                 ::android::hardware::hidl_vec<int32_t> values;
384                 values.resize(1);
385                 values[0] = it->second;
386                 callback(EvsResult::OK, values);
387                 return ::android::hardware::Void();
388             });
389 
390     // This method returns the same range values if a requested camera
391     // parameter is supported by a mock EVS camera.
392     ON_CALL(*mockCamera, getIntParameterRange)
393             .WillByDefault(
394                     [this](CameraParam id, MockHidlEvsCamera::getIntParameterRange_cb callback) {
395                         auto it = mCameraParams.find(id);
396                         if (it == mCameraParams.end()) {
397                             callback(0, 0, 0);
398                             return ::android::hardware::Void();
399                         }
400 
401                         // For the testing purpose, this mock EVS HAL always returns the
402                         // same values.
403                         callback(kCameraParamDefaultMinValue, kCameraParamDefaultMaxValue,
404                                  kCameraParamDefaultStepValue);
405                         return ::android::hardware::Void();
406                     });
407 
408     // This method returns a list of camera parameters supported by a
409     // mock EVS camera.
410     ON_CALL(*mockCamera, getParameterList)
411             .WillByDefault([this](MockHidlEvsCamera::getParameterList_cb callback) {
412                 ::android::hardware::hidl_vec<CameraParam> list;
413                 list.resize(mCameraParams.size());
414                 unsigned idx = 0;
415                 for (auto& [k, _] : mCameraParams) {
416                     list[idx++] = k;
417                 }
418 
419                 callback(list);
420                 return ::android::hardware::Void();
421             });
422 
423     // This method behaves exactly the same as getCameraInfo() because
424     // the EVS HAL does not support a concept of the group (or logical)
425     // camera.
426     ON_CALL(*mockCamera, getPhysicalCameraInfo)
427             .WillByDefault([deviceId]([[maybe_unused]] const ::android::hardware::hidl_string& id,
428                                       MockHidlEvsCamera::getPhysicalCameraInfo_cb callback) {
429                 CameraDesc mockDesc = {
430                         .v1 =
431                                 {
432                                         .cameraId = deviceId,
433                                         .vendorFlags = 0x0,
434                                 },
435                         .metadata = {},
436                 };
437 
438                 callback(mockDesc);
439                 return ::android::hardware::Void();
440             });
441 
442     // This method adds given buffer descriptors to the internal buffer
443     // pool if their identifiers do not conflict to existing ones.
444     ON_CALL(*mockCamera, importExternalBuffers)
445             .WillByDefault([this](const ::android::hardware::hidl_vec<BufferDesc>& buffers,
446                                   MockHidlEvsCamera::importExternalBuffers_cb callback) {
447                 std::lock_guard l(mLock);
448                 size_t count = 0;
449                 for (auto i = 0; i < buffers.size(); ++i) {
450                     auto it = std::find_if(mBufferPool.begin(), mBufferPool.end(),
451                                            [&](const BufferDesc& b) {
452                                                return b.bufferId == buffers[i].bufferId;
453                                            });
454                     if (it != mBufferPool.end()) {
455                         // Ignores external buffers with a conflicting
456                         // identifier.
457                         continue;
458                     }
459 
460                     // TODO(b/235110887): Add external buffers to the pool.
461                     //
462                     // Temporarily, we count the number of buffers that
463                     // identifiers do not conflict with existing buffers.
464                     ++count;
465                 }
466 
467                 callback(EvsResult::OK, count);
468                 return ::android::hardware::Void();
469             });
470 
471     ON_CALL(*mockCamera, pauseVideoStream).WillByDefault([]() {
472         return EvsResult::UNDERLYING_SERVICE_ERROR;
473     });
474 
475     ON_CALL(*mockCamera, resumeVideoStream).WillByDefault([]() {
476         return EvsResult::UNDERLYING_SERVICE_ERROR;
477     });
478 
479     // This method stores a given vector with id.
480     ON_CALL(*mockCamera, setExtendedInfo).WillByDefault([this](uint32_t id, int32_t v) {
481         ::android::hardware::hidl_vec<uint8_t> value;
482         value.resize(sizeof(v));
483         *(reinterpret_cast<int32_t*>(value.data())) = v;
484         mCameraExtendedInfo.insert_or_assign(id, value);
485         return EvsResult::OK;
486     });
487 
488     ON_CALL(*mockCamera, setExtendedInfo_1_1)
489             .WillByDefault([this](uint32_t id, const ::android::hardware::hidl_vec<uint8_t>& v) {
490                 mCameraExtendedInfo.insert_or_assign(id, v);
491                 return EvsResult::OK;
492             });
493 
494     // This method updates a parameter value if exists.
495     ON_CALL(*mockCamera, setIntParameter)
496             .WillByDefault([this](CameraParam id, int32_t in,
497                                   MockHidlEvsCamera::setIntParameter_cb callback) {
498                 auto it = mCameraParams.find(id);
499                 if (it == mCameraParams.end()) {
500                     LOG(ERROR) << "Ignore a request to program an unsupported parameter, "
501                                << (int)id;
502                     callback(EvsResult::INVALID_ARG, {});
503                     return ::android::hardware::Void();
504                 }
505 
506                 in = in > kCameraParamDefaultMaxValue      ? kCameraParamDefaultMaxValue
507                         : in < kCameraParamDefaultMinValue ? kCameraParamDefaultMinValue
508                                                            : in;
509                 mCameraParams.insert_or_assign(id, in);
510                 ::android::hardware::hidl_vec<int32_t> values;
511                 values.resize(1);
512                 values[0] = in;
513                 callback(EvsResult::OK, values);
514                 return ::android::hardware::Void();
515             });
516 
517     // We always return a success because EVS HAL does not allow
518     // multiple camera clients exist.
519     ON_CALL(*mockCamera, setMaster).WillByDefault([]() { return EvsResult::OK; });
520 
521     // Because EVS HAL does allow multiple camera clients exist, we simply
522     // set the size of the buffer pool.
523     ON_CALL(*mockCamera, setMaxFramesInFlight)
524             .WillByDefault([this, id = mockCamera->getId()](uint32_t bufferCount) {
525                 std::lock_guard l(mLock);
526                 if (bufferCount < kMinimumNumBuffers) {
527                     LOG(WARNING) << "Requested buffer pool size is too small to run a camera; "
528                                     "adjusting the pool size to "
529                                  << kMinimumNumBuffers;
530                     bufferCount = kMinimumNumBuffers;
531                 }
532 
533                 int64_t delta = bufferCount;
534                 auto it = mCameraBufferPoolSize.find(id);
535                 if (it != mCameraBufferPoolSize.end()) {
536                     delta -= it->second;
537                 }
538 
539                 if (!delta) {
540                     // No further action required.
541                     return EvsResult::OK;
542                 }
543 
544                 size_t totalSize = mBufferPoolSize + delta;
545                 if (totalSize > kMaximumNumBuffers) {
546                     LOG(ERROR) << "Requested size, " << totalSize << ", exceeds the limitation.";
547                     return EvsResult::INVALID_ARG;
548                 }
549 
550                 mBufferPoolSize = totalSize;
551                 mCameraBufferPoolSize.insert_or_assign(id, bufferCount);
552                 return EvsResult::OK;
553             });
554 
555     // We manage the camera ownership on recency-basis; therefore we simply
556     // replace the client in this method.
557     ON_CALL(*mockCamera, startVideoStream)
558             .WillByDefault([this, id = mockCamera->getId()](
559                                    const ::android::sp<hidlevs::V1_0::IEvsCameraStream>& cb) {
560                 // TODO(b/235110887): Notifies a camera loss to the current
561                 //                    client.
562                 size_t n = 0;
563                 {
564                     std::lock_guard l(mLock);
565                     auto client = IEvsCameraStream::castFrom(cb).withDefault(nullptr);
566                     if (!client) {
567                         // This mock implementation supports v1.1 hidl
568                         // client only.
569                         return EvsResult::INVALID_ARG;
570                     }
571                     mCameraClient.insert_or_assign(id, client);
572                     n = mNumberOfFramesToSend;
573                 }
574 
575                 std::packaged_task<void(MockHidlEvsHal*, size_t, const std::string&)> task(
576                         &MockHidlEvsHal::forwardFrames);
577                 std::thread t(std::move(task), this, /* numberOfFramesForward= */ n, id);
578                 std::lock_guard l(mLock);
579                 mCameraFrameThread.insert_or_assign(id, std::move(t));
580 
581                 return EvsResult::OK;
582             });
583 
584     // We simply drop a current client.
585     ON_CALL(*mockCamera, stopVideoStream).WillByDefault([this, id = mockCamera->getId()]() {
586         ::android::sp<IEvsCameraStream> cb;
587         std::thread threadToJoin;
588         {
589             std::lock_guard l(mLock);
590             auto state = mStreamState.find(id);
591             if (state == mStreamState.end() || state->second != StreamState::kRunning) {
592                 return ::android::hardware::Void();
593             }
594 
595             auto callback = mCameraClient.find(id);
596             if (callback == mCameraClient.end()) {
597                 return ::android::hardware::Void();
598             }
599 
600             cb = callback->second;
601             callback->second = nullptr;
602             state->second = StreamState::kStopping;
603 
604             auto it = mCameraFrameThread.find(id);
605             if (it == mCameraFrameThread.end() || !it->second.joinable()) {
606                 return ::android::hardware::Void();
607             }
608 
609             threadToJoin = std::move(it->second);
610             mCameraFrameThread.erase(it);
611         }
612 
613         if (cb) {
614             EvsEventDesc e = {
615                     .aType = EvsEventType::STREAM_STOPPED,
616                     .deviceId = id,
617             };
618             cb->notify(e);
619         }
620 
621         // Join a frame-forward thread
622         threadToJoin.join();
623         return ::android::hardware::Void();
624     });
625 
626     // We don't take any action because EVS HAL allows only a single camera
627     // client exists at a time.
628     ON_CALL(*mockCamera, unsetMaster).WillByDefault([]() { return EvsResult::OK; });
629 
630     std::lock_guard l(mLock);
631     mMockHidlEvsCameras.push_back(std::move(mockCamera));
632     mMockDeviceStatus.insert_or_assign(deviceId, true);
633 
634     return true;
635 }
636 
removeMockCameraDevice(const std::string & deviceId)637 void MockHidlEvsHal::removeMockCameraDevice(const std::string& deviceId) {
638     std::lock_guard l(mLock);
639     auto it = mMockDeviceStatus.find(deviceId);
640     if (it == mMockDeviceStatus.end()) {
641         // Nothing to do.
642         return;
643     }
644 
645     mMockDeviceStatus[deviceId] = false;
646 }
647 
configureDisplays(size_t n)648 void MockHidlEvsHal::configureDisplays(size_t n) {
649     // Build mock IEvsDisplcy instances
650     std::vector<::android::sp<NiceMockHidlEvsDisplay>> displays(n);
651 
652     for (auto i = 0; i < n; ++i) {
653         (void)addMockDisplayDevice(i);
654     }
655 }
656 
addMockDisplayDevice(int id)657 bool MockHidlEvsHal::addMockDisplayDevice(int id) {
658     ::android::sp<NiceMockHidlEvsDisplay> mockDisplay = new (std::nothrow) NiceMockHidlEvsDisplay();
659 
660     ON_CALL(*mockDisplay, getDisplayInfo)
661             .WillByDefault([id](MockHidlEvsDisplay::getDisplayInfo_cb callback) {
662                 DisplayDesc desc = {
663                         .displayId = "MockDisplay" + std::to_string(id),
664                         // For the testing purpose, we put a display id in the vendor
665                         // flag field.
666                         .vendorFlags = static_cast<uint32_t>(id),
667                 };
668 
669                 callback(desc);
670                 return ::android::hardware::Void();
671             });
672 
673     ON_CALL(*mockDisplay, getDisplayInfo_1_1)
674             .WillByDefault([id, this](MockHidlEvsDisplay::getDisplayInfo_1_1_cb callback) {
675                 DisplayDesc desc = {
676                         .displayId = "MockDisplay" + std::to_string(id),
677                         // For the testing purpose, we put a display id in the vendor
678                         // flag field.
679                         .vendorFlags = static_cast<uint32_t>(id),
680                 };
681 
682                 ::android::hardware::hidl_vec<uint8_t> config;
683                 config.resize(sizeof(::android::ui::DisplayMode));
684                 ::android::ui::DisplayMode* p =
685                         reinterpret_cast<::android::ui::DisplayMode*>(config.data());
686                 p->resolution = ::android::ui::Size(64, 32);
687 
688                 ::android::hardware::hidl_vec<uint8_t> state;
689                 state.resize(sizeof(mCurrentDisplayState));
690                 *(reinterpret_cast<DisplayState*>(state.data())) = mCurrentDisplayState;
691 
692                 callback(config, state);
693                 return ::android::hardware::Void();
694             });
695 
696     ON_CALL(*mockDisplay, getDisplayState).WillByDefault([this]() { return mCurrentDisplayState; });
697 
698     ON_CALL(*mockDisplay, getTargetBuffer)
699             .WillByDefault([](MockHidlEvsDisplay::getTargetBuffer_cb callback) {
700                 // TODO(b/263438927): implement this method.
701                 callback({});
702                 return ::android::hardware::Void();
703             });
704 
705     ON_CALL(*mockDisplay, returnTargetBufferForDisplay)
706             .WillByDefault([](const hidlevs::V1_0::BufferDesc& in) {
707                 // TODO(b/263438927): implement this method.
708                 (void)in;
709                 return EvsResult::OK;
710             });
711 
712     ON_CALL(*mockDisplay, setDisplayState).WillByDefault([this](DisplayState in) {
713         mCurrentDisplayState = in;
714         return EvsResult::OK;
715     });
716 
717     std::lock_guard l(mLock);
718     mMockHidlEvsDisplays.push_back(std::move(mockDisplay));
719     mMockDeviceStatus.insert_or_assign(std::to_string(id), true);
720 
721     return true;
722 }
723 
removeMockDisplayDevice(int id)724 void MockHidlEvsHal::removeMockDisplayDevice(int id) {
725     std::lock_guard l(mLock);
726     auto key = std::to_string(id);
727     auto it = mMockDeviceStatus.find(key);
728     if (it == mMockDeviceStatus.end()) {
729         // Nothing to do.
730         return;
731     }
732 
733     mMockDeviceStatus[key] = false;
734 }
735 
setNumberOfFramesToSend(size_t n)736 size_t MockHidlEvsHal::setNumberOfFramesToSend(size_t n) {
737     std::lock_guard l(mLock);
738     return mNumberOfFramesToSend = n;
739 }
740 
configureEnumerator()741 void MockHidlEvsHal::configureEnumerator() {
742     ::android::sp<NiceMockHidlEvsEnumerator> mockEnumerator =
743             new (std::nothrow) NiceMockHidlEvsEnumerator();
744 
745     ON_CALL(*mockEnumerator, closeCamera)
746             .WillByDefault([this](const ::android::sp<hidlevs::V1_0::IEvsCamera>& handle) {
747                 ::android::sp<IEvsCamera> c = IEvsCamera::castFrom(handle);
748                 CameraDesc desc;
749                 c->getCameraInfo_1_1([&desc](auto& read) { desc = read; });
750 
751                 std::lock_guard l(mLock);
752                 auto it = mCameraBufferPoolSize.find(desc.v1.cameraId);
753                 if (it == mCameraBufferPoolSize.end()) {
754                     // Safely ignore a request if we fail to find a corresponding mock
755                     // camera.
756                     return ::android::hardware::Void();
757                 }
758 
759                 mBufferPoolSize -= it->second;
760                 if (mBufferPoolSize < 0) {
761                     LOG(WARNING) << "mBuffeRPoolSize should not have a negative value, "
762                                  << mBufferPoolSize;
763                     mBufferPoolSize = 0;
764                 }
765                 mCameraBufferPoolSize.insert_or_assign(desc.v1.cameraId, 0);
766                 return ::android::hardware::Void();
767             });
768 
769     ON_CALL(*mockEnumerator, closeDisplay)
770             .WillByDefault([this]([[maybe_unused]] const ::android::sp<hidlevs::V1_0::IEvsDisplay>&
771                                           displayObj) {
772                 auto pActiveDisplay = mActiveDisplay.promote();
773                 if (!pActiveDisplay) {
774                     LOG(WARNING) << "Got a request to close a display already destroyed.";
775                 }
776 
777                 // Nothing else to do.
778                 return ::android::hardware::Void();
779             });
780 
781     ON_CALL(*mockEnumerator, closeUltrasonicsArray)
782             .WillByDefault([](const ::android::sp<IEvsUltrasonicsArray>&) {
783                 // Mock EVS HAL does not support IEvsUltrasonicsArray.
784                 return ::android::hardware::Void();
785             });
786 
787     ON_CALL(*mockEnumerator, getCameraList)
788             .WillByDefault([this](MockHidlEvsEnumerator::getCameraList_cb callback) {
789                 ::android::hardware::hidl_vec<hidlevs::V1_0::CameraDesc> list(
790                         mMockHidlEvsCameras.size());
791 
792                 for (auto i = 0; i < mMockHidlEvsCameras.size(); ++i) {
793                     mMockHidlEvsCameras[i]->getCameraInfo([&](auto& desc) { list[i] = desc; });
794 
795                     // Inserts a camera record if it does not exist.
796                     if (mCameraList.find(list[i].cameraId) == mCameraList.end()) {
797                         CameraDesc newDevice = {
798                                 .v1 = list[i],
799                         };
800                         mCameraList.insert_or_assign(list[i].cameraId, newDevice);
801                     }
802                 }
803 
804                 callback(list);
805                 return ::android::hardware::Void();
806             });
807 
808     ON_CALL(*mockEnumerator, getCameraList_1_1)
809             .WillByDefault([this](MockHidlEvsEnumerator::getCameraList_1_1_cb callback) {
810                 std::vector<CameraDesc> list(mMockHidlEvsCameras.size());
811 
812                 for (auto i = 0; i < mMockHidlEvsCameras.size(); ++i) {
813                     mMockHidlEvsCameras[i]->getCameraInfo_1_1([&](auto& desc) { list[i] = desc; });
814 
815                     // Inserts a camera record if it does not exist.
816                     if (mCameraList.find(list[i].v1.cameraId) == mCameraList.end()) {
817                         mCameraList.insert_or_assign(list[i].v1.cameraId, list[i]);
818                     }
819                 }
820 
821                 callback(list);
822                 return ::android::hardware::Void();
823             });
824 
825     ON_CALL(*mockEnumerator, getDisplayIdList)
826             .WillByDefault([this](MockHidlEvsEnumerator::getDisplayIdList_cb callback) {
827                 ::android::hardware::hidl_vec<uint8_t> list;
828                 list.resize(mMockHidlEvsDisplays.size());
829 
830                 for (auto i = 0; i < mMockHidlEvsDisplays.size(); ++i) {
831                     mMockHidlEvsDisplays[i]->getDisplayInfo([&](auto& desc) {
832                         // MockHidlEvsDisplay contains a display ID in its vendor flags.
833                         list[i] = desc.vendorFlags;
834                     });
835                 }
836 
837                 callback(list);
838                 return ::android::hardware::Void();
839             });
840 
841     ON_CALL(*mockEnumerator, getDisplayState).WillByDefault([this]() {
842         return mCurrentDisplayState;
843     });
844 
845     ON_CALL(*mockEnumerator, getUltrasonicsArrayList)
846             .WillByDefault([]([[maybe_unused]] MockHidlEvsEnumerator::getUltrasonicsArrayList_cb
847                                       callback) {
848                 // Mock EVS HAL does not support IEvsUltrasonicsArray yet.
849                 return ::android::hardware::Void();
850             });
851 
852     ON_CALL(*mockEnumerator, isHardware).WillByDefault([]() { return false; });
853 
854     ON_CALL(*mockEnumerator, openCamera)
855             .WillByDefault([this](const ::android::hardware::hidl_string& id)
856                                    -> ::android::sp<hidlevs::V1_0::IEvsCamera> {
857                 auto it = std::find_if(mMockHidlEvsCameras.begin(), mMockHidlEvsCameras.end(),
858                                        [id](const ::android::sp<NiceMockHidlEvsCamera>& c) {
859                                            hidlevs::V1_0::CameraDesc desc;
860                                            c->getCameraInfo([&desc](auto& read) { desc = read; });
861                                            return desc.cameraId == id;
862                                        });
863 
864                 if (it == mMockHidlEvsCameras.end()) {
865                     return nullptr;
866                 }
867 
868                 auto instance = mCameraList.find(id);  // Guaranteed to exist always.
869                 instance->second.activeInstance = *it;
870                 return *it;
871             });
872 
873     ON_CALL(*mockEnumerator, openCamera_1_1)
874             .WillByDefault(
875                     [this](const ::android::hardware::hidl_string& id,
876                            [[maybe_unused]] const Stream& config) -> ::android::sp<IEvsCamera> {
877                         auto it =
878                                 std::find_if(mMockHidlEvsCameras.begin(), mMockHidlEvsCameras.end(),
879                                              [id](const ::android::sp<NiceMockHidlEvsCamera>& c) {
880                                                  CameraDesc desc;
881                                                  c->getCameraInfo_1_1(
882                                                          [&desc](auto& read) { desc = read; });
883                                                  return desc.v1.cameraId == id;
884                                              });
885 
886                         if (it == mMockHidlEvsCameras.end()) {
887                             return nullptr;
888                         }
889 
890                         auto instance = mCameraList.find(id);  // Guaranteed to exist always.
891                         instance->second.activeInstance = *it;
892                         return *it;
893                     });
894 
895     ON_CALL(*mockEnumerator, openDisplay).WillByDefault([]() {
896         // TODO(b/263438927): implement this method.
897         return nullptr;
898     });
899 
900     ON_CALL(*mockEnumerator, openDisplay_1_1)
901             .WillByDefault([this](uint8_t id) -> ::android::sp<IEvsDisplay> {
902                 if (id == kExclusiveDisplayId) {
903                     if (mDisplayOwnedExclusively && !mActiveDisplay.promote()) {
904                         return nullptr;
905                     }
906 
907                     DisplayDesc desc;
908                     mMockHidlEvsDisplays[0]->getDisplayInfo([&desc](auto& read) { desc = read; });
909                     id = desc.vendorFlags;  // the first display in the list is
910                                             // the main display.
911                     mDisplayOwnedExclusively = true;
912                 }
913 
914                 auto it = std::find_if(mMockHidlEvsDisplays.begin(), mMockHidlEvsDisplays.end(),
915                                        [id](const ::android::sp<NiceMockHidlEvsDisplay>& d) {
916                                            DisplayDesc desc;
917                                            d->getDisplayInfo([&desc](auto& read) { desc = read; });
918                                            return desc.vendorFlags == id;
919                                        });
920 
921                 if (it == mMockHidlEvsDisplays.end()) {
922                     return nullptr;
923                 }
924 
925                 mActiveDisplay = *it;
926                 mCurrentDisplayState = DisplayState::NOT_VISIBLE;
927                 return *it;
928             });
929 
930     ON_CALL(*mockEnumerator, openUltrasonicsArray)
931             .WillByDefault([]([[maybe_unused]] const ::android::hardware::hidl_string& id) {
932                 // Mock EVS HAL does not support IEvsUltrasonicsArray yet.
933                 return nullptr;
934             });
935 
936     mMockHidlEvsEnumerator = std::move(mockEnumerator);
937 }
938 
939 }  // namespace aidl::android::automotive::evs::implementation
940