1 /*
2 * Copyright (C) 2019 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 "Enumerator.h"
18 #include "HalCamera.h"
19 #include "VirtualCamera.h"
20
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <android-base/strings.h>
24
25 namespace android {
26 namespace automotive {
27 namespace evs {
28 namespace V1_1 {
29 namespace implementation {
30
31
32 // TODO(changyeon):
33 // We need to hook up death monitoring to detect stream death so we can attempt a reconnect
34
35 using ::android::base::StringAppendF;
36 using ::android::base::WriteStringToFd;
37
~HalCamera()38 HalCamera::~HalCamera() {
39 // Reports the usage statistics before the destruction
40 // EvsUsageStatsReported atom is defined in
41 // frameworks/base/cmds/statsd/src/atoms.proto
42 mUsageStats->writeStats();
43 }
44
makeVirtualCamera()45 sp<VirtualCamera> HalCamera::makeVirtualCamera() {
46
47 // Create the client camera interface object
48 std::vector<sp<HalCamera>> sourceCameras;
49 sourceCameras.reserve(1);
50 sourceCameras.emplace_back(this);
51 sp<VirtualCamera> client = new VirtualCamera(sourceCameras);
52 if (client == nullptr) {
53 LOG(ERROR) << "Failed to create client camera object";
54 return nullptr;
55 }
56
57 if (!ownVirtualCamera(client)) {
58 LOG(ERROR) << "Failed to own a client camera object";
59 client = nullptr;
60 }
61
62 return client;
63 }
64
65
ownVirtualCamera(sp<VirtualCamera> virtualCamera)66 bool HalCamera::ownVirtualCamera(sp<VirtualCamera> virtualCamera) {
67
68 if (virtualCamera == nullptr) {
69 LOG(ERROR) << "Failed to create virtualCamera camera object";
70 return false;
71 }
72
73 // Make sure we have enough buffers available for all our clients
74 if (!changeFramesInFlight(virtualCamera->getAllowedBuffers())) {
75 // Gah! We couldn't get enough buffers, so we can't support this virtualCamera
76 // Null the pointer, dropping our reference, thus destroying the virtualCamera object
77 return false;
78 }
79
80 if (mSyncSupported) {
81 // Create a timeline
82 std::lock_guard<std::mutex> lock(mFrameMutex);
83 auto timeline = make_unique<UniqueTimeline>(0);
84 if (timeline != nullptr) {
85 mTimelines[(uint64_t)virtualCamera.get()] = std::move(timeline);
86 } else {
87 LOG(WARNING) << "Failed to create a timeline. "
88 << "Client " << std::hex << virtualCamera.get()
89 << " will use v1.0 frame delivery mechanism.";
90 }
91 }
92
93 // Add this virtualCamera to our ownership list via weak pointer
94 mClients.emplace_back(virtualCamera);
95
96 // Update statistics
97 mUsageStats->updateNumClients(mClients.size());
98
99 return true;
100 }
101
102
disownVirtualCamera(sp<VirtualCamera> virtualCamera)103 void HalCamera::disownVirtualCamera(sp<VirtualCamera> virtualCamera) {
104 // Ignore calls with null pointers
105 if (virtualCamera.get() == nullptr) {
106 LOG(WARNING) << "Ignoring disownVirtualCamera call with null pointer";
107 return;
108 }
109
110 // Remove the virtual camera from our client list
111 unsigned clientCount = mClients.size();
112 mClients.remove(virtualCamera);
113 if (clientCount != mClients.size() + 1) {
114 LOG(ERROR) << "Couldn't find camera in our client list to remove it";
115 }
116
117 // Recompute the number of buffers required with the target camera removed from the list
118 if (!changeFramesInFlight(0)) {
119 LOG(ERROR) << "Error when trying to reduce the in flight buffer count";
120 }
121
122 // Update statistics
123 mUsageStats->updateNumClients(mClients.size());
124 }
125
126
changeFramesInFlight(int delta)127 bool HalCamera::changeFramesInFlight(int delta) {
128 // Walk all our clients and count their currently required frames
129 unsigned bufferCount = 0;
130 for (auto&& client : mClients) {
131 sp<VirtualCamera> virtCam = client.promote();
132 if (virtCam != nullptr) {
133 bufferCount += virtCam->getAllowedBuffers();
134 }
135 }
136
137 // Add the requested delta
138 bufferCount += delta;
139
140 // Never drop below 1 buffer -- even if all client cameras get closed
141 if (bufferCount < 1) {
142 bufferCount = 1;
143 }
144
145 // Ask the hardware for the resulting buffer count
146 Return<EvsResult> result = mHwCamera->setMaxFramesInFlight(bufferCount);
147 bool success = (result.isOk() && result == EvsResult::OK);
148
149 // Update the size of our array of outstanding frame records
150 if (success) {
151 std::vector<FrameRecord> newRecords;
152 newRecords.reserve(bufferCount);
153
154 // Copy and compact the old records that are still active
155 for (const auto& rec : mFrames) {
156 if (rec.refCount > 0) {
157 newRecords.emplace_back(rec);
158 }
159 }
160 if (newRecords.size() > (unsigned)bufferCount) {
161 LOG(WARNING) << "We found more frames in use than requested.";
162 }
163
164 mFrames.swap(newRecords);
165 }
166
167 return success;
168 }
169
170
changeFramesInFlight(const hidl_vec<BufferDesc_1_1> & buffers,int * delta)171 bool HalCamera::changeFramesInFlight(const hidl_vec<BufferDesc_1_1>& buffers,
172 int* delta) {
173 // Return immediately if a list is empty.
174 if (buffers.size() < 1) {
175 LOG(DEBUG) << "No external buffers to add.";
176 return true;
177 }
178
179 // Walk all our clients and count their currently required frames
180 auto bufferCount = 0;
181 for (auto&& client : mClients) {
182 sp<VirtualCamera> virtCam = client.promote();
183 if (virtCam != nullptr) {
184 bufferCount += virtCam->getAllowedBuffers();
185 }
186 }
187
188 EvsResult status = EvsResult::OK;
189 // Ask the hardware for the resulting buffer count
190 mHwCamera->importExternalBuffers(buffers,
191 [&](auto result, auto added) {
192 status = result;
193 *delta = added;
194 });
195 if (status != EvsResult::OK) {
196 LOG(ERROR) << "Failed to add external capture buffers.";
197 return false;
198 }
199
200 bufferCount += *delta;
201
202 // Update the size of our array of outstanding frame records
203 std::vector<FrameRecord> newRecords;
204 newRecords.reserve(bufferCount);
205
206 // Copy and compact the old records that are still active
207 for (const auto& rec : mFrames) {
208 if (rec.refCount > 0) {
209 newRecords.emplace_back(rec);
210 }
211 }
212
213 if (newRecords.size() > (unsigned)bufferCount) {
214 LOG(WARNING) << "We found more frames in use than requested.";
215 }
216
217 mFrames.swap(newRecords);
218
219 return true;
220 }
221
222
requestNewFrame(sp<VirtualCamera> client,const int64_t lastTimestamp)223 UniqueFence HalCamera::requestNewFrame(sp<VirtualCamera> client,
224 const int64_t lastTimestamp) {
225 if (!mSyncSupported) {
226 LOG(ERROR) << "This HalCamera does not support a fence-based "
227 << "frame delivery.";
228 return {};
229 }
230
231 FrameRequest req;
232 req.client = client;
233 req.timestamp = lastTimestamp;
234
235 const uint64_t id = (uint64_t)client.get();
236
237 std::lock_guard<std::mutex> lock(mFrameMutex);
238
239 mTimelines[id]->BumpFenceEventCounter();
240 UniqueFence fence = mTimelines[id]->CreateFence("FrameFence");
241
242 mNextRequests->push_back(req);
243
244 return fence.Dup();
245 }
246
247
clientStreamStarting()248 Return<EvsResult> HalCamera::clientStreamStarting() {
249 Return<EvsResult> result = EvsResult::OK;
250
251 if (mStreamState == STOPPED) {
252 mStreamState = RUNNING;
253 result = mHwCamera->startVideoStream(this);
254 }
255
256 return result;
257 }
258
259
clientStreamEnding(const VirtualCamera * client)260 void HalCamera::clientStreamEnding(const VirtualCamera* client) {
261 {
262 std::lock_guard<std::mutex> lock(mFrameMutex);
263 auto itReq = mNextRequests->begin();
264 while (itReq != mNextRequests->end()) {
265 if (itReq->client == client) {
266 break;
267 } else {
268 ++itReq;
269 }
270 }
271
272 const uint64_t clientId = reinterpret_cast<const uint64_t>(client);
273 if (itReq != mNextRequests->end()) {
274 mNextRequests->erase(itReq);
275
276 // Signal a pending fence and delete associated timeline.
277 if (mTimelines.find(clientId) != mTimelines.end()) {
278 mTimelines[clientId]->BumpTimelineEventCounter();
279 mTimelines.erase(clientId);
280 }
281 }
282
283 auto itCam = mClients.begin();
284 while (itCam != mClients.end()) {
285 if (itCam->promote() == client) {
286 break;
287 } else {
288 ++itCam;
289 }
290 }
291
292 if (itCam != mClients.end()) {
293 // Remove a client, which requested to stop, from the list.
294 mClients.erase(itCam);
295 }
296 }
297
298 // Do we still have a running client?
299 bool stillRunning = false;
300 for (auto&& client : mClients) {
301 sp<VirtualCamera> virtCam = client.promote();
302 if (virtCam != nullptr) {
303 stillRunning |= virtCam->isStreaming();
304 }
305 }
306
307 // If not, then stop the hardware stream
308 if (!stillRunning) {
309 mStreamState = STOPPING;
310 mHwCamera->stopVideoStream();
311 }
312 }
313
314
doneWithFrame(const BufferDesc_1_0 & buffer)315 Return<void> HalCamera::doneWithFrame(const BufferDesc_1_0& buffer) {
316 // Find this frame in our list of outstanding frames
317 unsigned i;
318 for (i = 0; i < mFrames.size(); i++) {
319 if (mFrames[i].frameId == buffer.bufferId) {
320 break;
321 }
322 }
323 if (i == mFrames.size()) {
324 LOG(ERROR) << "We got a frame back with an ID we don't recognize!";
325 } else {
326 // Are there still clients using this buffer?
327 mFrames[i].refCount--;
328 if (mFrames[i].refCount <= 0) {
329 // Since all our clients are done with this buffer, return it to the device layer
330 mHwCamera->doneWithFrame(buffer);
331
332 // Counts a returned buffer
333 mUsageStats->framesReturned();
334 }
335 }
336
337 return Void();
338 }
339
340
doneWithFrame(const BufferDesc_1_1 & buffer)341 Return<void> HalCamera::doneWithFrame(const BufferDesc_1_1& buffer) {
342 // Find this frame in our list of outstanding frames
343 unsigned i;
344 for (i = 0; i < mFrames.size(); i++) {
345 if (mFrames[i].frameId == buffer.bufferId) {
346 break;
347 }
348 }
349 if (i == mFrames.size()) {
350 LOG(ERROR) << "We got a frame back with an ID we don't recognize!";
351 } else {
352 // Are there still clients using this buffer?
353 mFrames[i].refCount--;
354 if (mFrames[i].refCount <= 0) {
355 // Since all our clients are done with this buffer, return it to the device layer
356 hardware::hidl_vec<BufferDesc_1_1> returnedBuffers;
357 returnedBuffers.resize(1);
358 returnedBuffers[0] = buffer;
359 mHwCamera->doneWithFrame_1_1(returnedBuffers);
360
361 // Counts a returned buffer
362 mUsageStats->framesReturned(returnedBuffers);
363 }
364 }
365
366 return Void();
367 }
368
369
370 // Methods from ::android::hardware::automotive::evs::V1_0::IEvsCameraStream follow.
deliverFrame(const BufferDesc_1_0 & buffer)371 Return<void> HalCamera::deliverFrame(const BufferDesc_1_0& buffer) {
372 /* Frames are delivered via deliverFrame_1_1 callback for clients that implement
373 * IEvsCameraStream v1.1 interfaces and therefore this method must not be
374 * used.
375 */
376 LOG(INFO) << "A delivered frame from EVS v1.0 HW module is rejected.";
377 mHwCamera->doneWithFrame(buffer);
378
379 // Reports a received and returned buffer
380 mUsageStats->framesReceived();
381 mUsageStats->framesReturned();
382
383 return Void();
384 }
385
386
387 // Methods from ::android::hardware::automotive::evs::V1_1::IEvsCameraStream follow.
deliverFrame_1_1(const hardware::hidl_vec<BufferDesc_1_1> & buffer)388 Return<void> HalCamera::deliverFrame_1_1(const hardware::hidl_vec<BufferDesc_1_1>& buffer) {
389 LOG(VERBOSE) << "Received a frame";
390 // Frames are being forwarded to v1.1 clients only who requested new frame.
391 const auto timestamp = buffer[0].timestamp;
392 // TODO(b/145750636): For now, we are using a approximately half of 1 seconds / 30 frames = 33ms
393 // but this must be derived from current framerate.
394 constexpr int64_t kThreshold = 16 * 1e+3; // ms
395 unsigned frameDeliveriesV1 = 0;
396 if (mSyncSupported) {
397 std::lock_guard<std::mutex> lock(mFrameMutex);
398 std::swap(mCurrentRequests, mNextRequests);
399 while (!mCurrentRequests->empty()) {
400 auto req = mCurrentRequests->front(); mCurrentRequests->pop_front();
401 sp<VirtualCamera> vCam = req.client.promote();
402 if (vCam == nullptr) {
403 // Ignore a client already dead.
404 continue;
405 } else if (timestamp - req.timestamp < kThreshold) {
406 // Skip current frame because it arrives too soon.
407 LOG(DEBUG) << "Skips a frame from " << getId();
408 mNextRequests->push_back(req);
409
410 // Reports a skipped frame
411 mUsageStats->framesSkippedToSync();
412 } else if (vCam != nullptr && vCam->deliverFrame(buffer[0])) {
413 // Forward a frame and move a timeline.
414 LOG(DEBUG) << getId() << " forwarded the buffer #" << buffer[0].bufferId;
415 mTimelines[(uint64_t)vCam.get()]->BumpTimelineEventCounter();
416 ++frameDeliveriesV1;
417 }
418 }
419 }
420
421 // Reports the number of received buffers
422 mUsageStats->framesReceived(buffer);
423
424 // Frames are being forwarded to active v1.0 clients and v1.1 clients if we
425 // failed to create a timeline.
426 unsigned frameDeliveries = 0;
427 for (auto&& client : mClients) {
428 sp<VirtualCamera> vCam = client.promote();
429 if (vCam == nullptr || (mSyncSupported && vCam->getVersion() > 0)) {
430 continue;
431 }
432
433 if (vCam->deliverFrame(buffer[0])) {
434 ++frameDeliveries;
435 }
436 }
437
438 frameDeliveries += frameDeliveriesV1;
439 if (frameDeliveries < 1) {
440 // If none of our clients could accept the frame, then return it
441 // right away.
442 LOG(INFO) << "Trivially rejecting frame (" << buffer[0].bufferId
443 << ") from " << getId() << " with no acceptance";
444 mHwCamera->doneWithFrame_1_1(buffer);
445
446 // Reports a returned buffer
447 mUsageStats->framesReturned(buffer);
448 } else {
449 // Add an entry for this frame in our tracking list.
450 unsigned i;
451 for (i = 0; i < mFrames.size(); ++i) {
452 if (mFrames[i].refCount == 0) {
453 break;
454 }
455 }
456
457 if (i == mFrames.size()) {
458 mFrames.emplace_back(buffer[0].bufferId);
459 } else {
460 mFrames[i].frameId = buffer[0].bufferId;
461 }
462 mFrames[i].refCount = frameDeliveries;
463 }
464
465 return Void();
466 }
467
468
notify(const EvsEventDesc & event)469 Return<void> HalCamera::notify(const EvsEventDesc& event) {
470 LOG(DEBUG) << "Received an event id: " << static_cast<int32_t>(event.aType);
471 if(event.aType == EvsEventType::STREAM_STOPPED) {
472 // This event happens only when there is no more active client.
473 if (mStreamState != STOPPING) {
474 LOG(WARNING) << "Stream stopped unexpectedly";
475 }
476
477 mStreamState = STOPPED;
478 }
479
480 // Forward all other events to the clients
481 for (auto&& client : mClients) {
482 sp<VirtualCamera> vCam = client.promote();
483 if (vCam != nullptr) {
484 if (!vCam->notify(event)) {
485 LOG(INFO) << "Failed to forward an event";
486 }
487 }
488 }
489
490 return Void();
491 }
492
493
setMaster(sp<VirtualCamera> virtualCamera)494 Return<EvsResult> HalCamera::setMaster(sp<VirtualCamera> virtualCamera) {
495 if (mMaster == nullptr) {
496 LOG(DEBUG) << __FUNCTION__
497 << ": " << virtualCamera.get() << " becomes a master.";
498 mMaster = virtualCamera;
499 return EvsResult::OK;
500 } else {
501 LOG(INFO) << "This camera already has a master client.";
502 return EvsResult::OWNERSHIP_LOST;
503 }
504 }
505
506
forceMaster(sp<VirtualCamera> virtualCamera)507 Return<EvsResult> HalCamera::forceMaster(sp<VirtualCamera> virtualCamera) {
508 sp<VirtualCamera> prevMaster = mMaster.promote();
509 if (prevMaster == virtualCamera) {
510 LOG(DEBUG) << "Client " << virtualCamera.get()
511 << " is already a master client";
512 } else {
513 mMaster = virtualCamera;
514 if (prevMaster != nullptr) {
515 LOG(INFO) << "High priority client " << virtualCamera.get()
516 << " steals a master role from " << prevMaster.get();
517
518 /* Notify a previous master client the loss of a master role */
519 EvsEventDesc event;
520 event.aType = EvsEventType::MASTER_RELEASED;
521 if (!prevMaster->notify(event)) {
522 LOG(ERROR) << "Fail to deliver a master role lost notification";
523 }
524 }
525 }
526
527 return EvsResult::OK;
528 }
529
530
unsetMaster(sp<VirtualCamera> virtualCamera)531 Return<EvsResult> HalCamera::unsetMaster(sp<VirtualCamera> virtualCamera) {
532 if (mMaster.promote() != virtualCamera) {
533 return EvsResult::INVALID_ARG;
534 } else {
535 LOG(INFO) << "Unset a master camera client";
536 mMaster = nullptr;
537
538 /* Notify other clients that a master role becomes available. */
539 EvsEventDesc event;
540 event.aType = EvsEventType::MASTER_RELEASED;
541 auto cbResult = this->notify(event);
542 if (!cbResult.isOk()) {
543 LOG(ERROR) << "Fail to deliver a parameter change notification";
544 }
545
546 return EvsResult::OK;
547 }
548 }
549
550
setParameter(sp<VirtualCamera> virtualCamera,CameraParam id,int32_t & value)551 Return<EvsResult> HalCamera::setParameter(sp<VirtualCamera> virtualCamera,
552 CameraParam id, int32_t& value) {
553 EvsResult result = EvsResult::INVALID_ARG;
554 if (virtualCamera == mMaster.promote()) {
555 mHwCamera->setIntParameter(id, value,
556 [&result, &value](auto status, auto readValue) {
557 result = status;
558 value = readValue[0];
559 });
560
561 if (result == EvsResult::OK) {
562 /* Notify a parameter change */
563 EvsEventDesc event;
564 event.aType = EvsEventType::PARAMETER_CHANGED;
565 event.payload[0] = static_cast<uint32_t>(id);
566 event.payload[1] = static_cast<uint32_t>(value);
567 auto cbResult = this->notify(event);
568 if (!cbResult.isOk()) {
569 LOG(ERROR) << "Fail to deliver a parameter change notification";
570 }
571 }
572 } else {
573 LOG(WARNING) << "A parameter change request from a non-master client is declined.";
574
575 /* Read a current value of a requested camera parameter */
576 getParameter(id, value);
577 }
578
579 return result;
580 }
581
582
getParameter(CameraParam id,int32_t & value)583 Return<EvsResult> HalCamera::getParameter(CameraParam id, int32_t& value) {
584 EvsResult result = EvsResult::OK;
585 mHwCamera->getIntParameter(id, [&result, &value](auto status, auto readValue) {
586 result = status;
587 if (result == EvsResult::OK) {
588 value = readValue[0];
589 }
590 });
591
592 return result;
593 }
594
595
getStats() const596 CameraUsageStatsRecord HalCamera::getStats() const {
597 return mUsageStats->snapshot();
598 }
599
600
getStreamConfiguration() const601 Stream HalCamera::getStreamConfiguration() const {
602 return mStreamConfig;
603 }
604
605
toString(const char * indent) const606 std::string HalCamera::toString(const char* indent) const {
607 std::string buffer;
608
609 const auto timeElapsedMs = android::uptimeMillis() - mTimeCreatedMs;
610 StringAppendF(&buffer, "%sCreated: @%" PRId64 " (elapsed %" PRId64 " ms)\n",
611 indent, mTimeCreatedMs, timeElapsedMs);
612
613 std::string double_indent(indent);
614 double_indent += indent;
615 buffer += CameraUsageStats::toString(getStats(), double_indent.c_str());
616 for (auto&& client : mClients) {
617 auto handle = client.promote();
618 if (!handle) {
619 continue;
620 }
621
622 StringAppendF(&buffer, "%sClient %p\n",
623 indent, handle.get());
624 buffer += handle->toString(double_indent.c_str());
625 }
626
627 StringAppendF(&buffer, "%sMaster client: %p\n"
628 "%sSynchronization support: %s\n",
629 indent, mMaster.promote().get(),
630 indent, mSyncSupported ? "T":"F");
631
632 buffer += HalCamera::toString(mStreamConfig, indent);
633
634 return buffer;
635 }
636
637
toString(Stream configuration,const char * indent)638 std::string HalCamera::toString(Stream configuration, const char* indent) {
639 std::string streamInfo;
640 std::string double_indent(indent);
641 double_indent += indent;
642 StringAppendF(&streamInfo, "%sActive Stream Configuration\n"
643 "%sid: %d\n"
644 "%swidth: %d\n"
645 "%sheight: %d\n"
646 "%sformat: 0x%X\n"
647 "%susage: 0x%" PRIx64 "\n"
648 "%srotation: 0x%X\n\n",
649 indent,
650 double_indent.c_str(), configuration.id,
651 double_indent.c_str(), configuration.width,
652 double_indent.c_str(), configuration.height,
653 double_indent.c_str(), configuration.format,
654 double_indent.c_str(), configuration.usage,
655 double_indent.c_str(), configuration.rotation);
656
657 return streamInfo;
658 }
659
660
661 } // namespace implementation
662 } // namespace V1_1
663 } // namespace evs
664 } // namespace automotive
665 } // namespace android
666