1 /*
2 * Copyright (C) 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 "AidlCameraStream.h"
18
19 #include "utils/include/Utils.h"
20
21 #include <aidl/android/hardware/automotive/evs/BufferDesc.h>
22 #include <aidl/android/hardware/automotive/evs/EvsEventDesc.h>
23 #include <aidl/android/hardware/automotive/evs/EvsEventType.h>
24 #include <android-base/logging.h>
25
26 namespace aidl::android::automotive::evs::implementation {
27
28 namespace hidlevs = ::android::hardware::automotive::evs;
29
30 using ::aidl::android::hardware::automotive::evs::BufferDesc;
31 using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
32 using ::aidl::android::hardware::automotive::evs::EvsEventType;
33 using ::aidl::android::hardware::automotive::evs::EvsResult;
34 using ::ndk::ScopedAStatus;
35
AidlCameraStream(const::android::sp<hidlevs::V1_0::IEvsCameraStream> & hidlStream)36 AidlCameraStream::AidlCameraStream(
37 const ::android::sp<hidlevs::V1_0::IEvsCameraStream>& hidlStream) {
38 auto hidlStreamV1 = hidlevs::V1_1::IEvsCameraStream::castFrom(hidlStream).withDefault(nullptr);
39 if (!hidlStreamV1) {
40 mImpl = std::make_shared<ImplV0>(hidlStream);
41 } else {
42 mImpl = std::make_shared<ImplV1>(hidlStreamV1);
43 }
44
45 if (!mImpl) {
46 LOG(ERROR) << "Failed to initialize AidlCameraStream instance";
47 }
48 }
49
deliverFrame(const std::vector<BufferDesc> & buffers)50 ScopedAStatus AidlCameraStream::deliverFrame(const std::vector<BufferDesc>& buffers) {
51 return mImpl->deliverFrame(buffers);
52 }
53
notify(const EvsEventDesc & event)54 ScopedAStatus AidlCameraStream::notify(const EvsEventDesc& event) {
55 return mImpl->notify(event);
56 }
57
getBuffer(int id,BufferDesc * _return)58 bool AidlCameraStream::getBuffer(int id, BufferDesc* _return) {
59 return mImpl->getBuffer(id, _return);
60 }
61
getBuffer(int id,BufferDesc * _return)62 bool AidlCameraStream::IHidlCameraStream::getBuffer(int id, BufferDesc* _return) {
63 auto it = std::find_if(mBuffers.begin(), mBuffers.end(),
64 [id](const BufferDesc& buffer) { return id == buffer.bufferId; });
65 if (it == mBuffers.end()) {
66 return false;
67 }
68
69 *_return = std::move(*it);
70 mBuffers.erase(it);
71 return true;
72 }
73
ImplV0(const::android::sp<hidlevs::V1_0::IEvsCameraStream> & stream)74 AidlCameraStream::ImplV0::ImplV0(const ::android::sp<hidlevs::V1_0::IEvsCameraStream>& stream) :
75 IHidlCameraStream(stream) {}
76
deliverFrame(const std::vector<BufferDesc> & buffers)77 ScopedAStatus AidlCameraStream::ImplV0::deliverFrame(const std::vector<BufferDesc>& buffers) {
78 auto hidlBuffer = Utils::makeToHidlV1_0(buffers[0], /* doDup= */ false);
79 mBuffers.push_back(std::move(Utils::dupBufferDesc(buffers[0], /* doDup= */ true)));
80 if (auto status = mStream->deliverFrame(std::move(hidlBuffer)); !status.isOk()) {
81 LOG(ERROR) << "Failed to forward a frame to HIDL v1.0 client";
82 return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
83 }
84
85 return ScopedAStatus::ok();
86 }
87
notify(const EvsEventDesc & event)88 ScopedAStatus AidlCameraStream::ImplV0::notify(const EvsEventDesc& event) {
89 switch (event.aType) {
90 case EvsEventType::STREAM_STOPPED:
91 if (auto status = mStream->deliverFrame({}); !status.isOk()) {
92 LOG(ERROR) << "Error delivering the end of stream marker";
93 return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
94 }
95 break;
96
97 default:
98 // HIDL v1.0 interface does not support events
99 LOG(INFO) << "Event " << Utils::toString(event.aType)
100 << " is received but ignored for HIDL v1.0 client";
101 break;
102 }
103
104 return ScopedAStatus::ok();
105 }
106
ImplV1(const::android::sp<hidlevs::V1_1::IEvsCameraStream> & stream)107 AidlCameraStream::ImplV1::ImplV1(const ::android::sp<hidlevs::V1_1::IEvsCameraStream>& stream) :
108 IHidlCameraStream(stream), mStream(stream) {}
109
deliverFrame(const std::vector<BufferDesc> & buffers)110 ScopedAStatus AidlCameraStream::ImplV1::deliverFrame(const std::vector<BufferDesc>& buffers) {
111 const auto n = buffers.size();
112 ::android::hardware::hidl_vec<hidlevs::V1_1::BufferDesc> hidlBuffers(n);
113 for (auto i = 0; i < n; ++i) {
114 BufferDesc buffer = std::move(Utils::dupBufferDesc(buffers[i], /* doDup= */ true));
115 hidlBuffers[i] = std::move(Utils::makeToHidlV1_1(buffer, /* doDup= */ false));
116 mBuffers.push_back(std::move(buffer));
117 }
118
119 if (auto status = mStream->deliverFrame_1_1(hidlBuffers); !status.isOk()) {
120 LOG(ERROR) << "Failed to forward a frame to HIDL v1.1 client";
121 return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
122 }
123
124 return ScopedAStatus::ok();
125 }
126
notify(const EvsEventDesc & event)127 ScopedAStatus AidlCameraStream::ImplV1::notify(const EvsEventDesc& event) {
128 hidlevs::V1_1::EvsEventDesc hidlEvent;
129 if (!Utils::makeToHidl(event, &hidlEvent)) {
130 return ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::INVALID_ARG));
131 }
132
133 if (auto status = mStream->notify(hidlEvent); !status.isOk()) {
134 LOG(ERROR) << "Failed to forward an event, " << Utils::toString(event.aType);
135 return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
136 }
137
138 return ScopedAStatus::ok();
139 }
140
141 } // namespace aidl::android::automotive::evs::implementation
142