1 /*
2  * Copyright 2021 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 "StreamHandler.h"
18 
19 #include <android-base/chrono_utils.h>
20 #include <android-base/logging.h>
21 #include <cutils/native_handle.h>
22 
23 #include <cstring>
24 
25 using namespace ::android::hardware::automotive::evs::V1_1;
26 
27 using ::android::sp;
28 using ::android::hardware::hidl_handle;
29 using ::android::hardware::hidl_vec;
30 using ::android::hardware::Return;
31 using ::android::hardware::Void;
32 using ::android::hardware::automotive::evs::V1_0::EvsResult;
33 using ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
34 
35 using EvsDisplayState = ::android::hardware::automotive::evs::V1_0::DisplayState;
36 using BufferDesc_1_0 = ::android::hardware::automotive::evs::V1_0::BufferDesc;
37 using BufferDesc_1_1 = ::android::hardware::automotive::evs::V1_1::BufferDesc;
38 
39 namespace android {
40 namespace automotive {
41 namespace evs {
42 
StreamHandler(sp<IEvsCamera> & camera,EvsServiceCallback * callback,int maxNumFramesInFlight)43 StreamHandler::StreamHandler(sp<IEvsCamera>& camera, EvsServiceCallback* callback,
44                              int maxNumFramesInFlight) :
45       mEvsCamera(camera), mCallback(callback), mMaxNumFramesInFlight(maxNumFramesInFlight) {
46     if (camera == nullptr) {
47         LOG(ERROR) << "IEvsCamera is invalid.";
48     } else {
49         // We rely on the camera having at least two buffers available since we'll hold one and
50         // expect the camera to be able to capture a new image in the background.
51         auto status = camera->setMaxFramesInFlight(maxNumFramesInFlight);
52         if (!status.isOk()) {
53             LOG(WARNING) << "Failed to adjust the maximum number of frames in flight.";
54         }
55     }
56 }
57 
58 /*
59  * Shuts down a stream handler
60  */
~StreamHandler()61 StreamHandler::~StreamHandler() {
62     shutdown();
63 }
64 
65 /*
66  * Stops an active stream and releases the camera device in use
67  */
shutdown()68 void StreamHandler::shutdown() {
69     // Make sure we're not still streaming
70     blockingStopStream();
71 
72     // At this point, the receiver thread is no longer running, so we can safely drop
73     // our remote object references so they can be freed
74     mEvsCamera = nullptr;
75 }
76 
77 /*
78  * Requests EVS to start a video stream
79  */
startStream()80 bool StreamHandler::startStream() {
81     std::lock_guard<std::mutex> lock(mLock);
82     if (!mRunning) {
83         auto result = mEvsCamera->startVideoStream(this);
84         if (!result.isOk() or result != EvsResult::OK) {
85             LOG(ERROR) << "StreamHandler failed to start a video stream.";
86             return false;
87         }
88 
89         // Marks ourselves as running
90         mRunning = true;
91     }
92 
93     return true;
94 }
95 
96 /*
97  * Requests to stop a video stream
98  */
asyncStopStream()99 bool StreamHandler::asyncStopStream() {
100     bool success = true;
101 
102     // This will result in STREAM_STOPPED event; the client may want to wait
103     // this event to confirm the closure.
104     {
105         std::lock_guard<std::mutex> lock(mLock);
106         auto it = mReceivedBuffers.begin();
107         while (it != mReceivedBuffers.end()) {
108             // Packages a returned buffer and sends it back to the camera
109             hidl_vec<BufferDesc_1_1> frames;
110             frames.resize(1);
111             frames[0] = *it;
112             auto status = mEvsCamera->doneWithFrame_1_1(frames);
113             if (!status.isOk()) {
114                 LOG(WARNING) << "Failed to return a frame to EVS service; "
115                              << "this may leak the memory.";
116                 success = false;
117             }
118 
119             it = mReceivedBuffers.erase(it);
120         }
121     }
122 
123     auto status = mEvsCamera->stopVideoStream();
124     if (!status.isOk()) {
125         LOG(WARNING) << "stopVideoStream() failed but ignored.";
126         success = false;
127     }
128 
129     return success;
130 }
131 
132 /*
133  * Requests to stop a video stream and waits for a confirmation
134  */
blockingStopStream()135 void StreamHandler::blockingStopStream() {
136     if (!asyncStopStream()) {
137         // EVS service may die so no stream-stop event occurs.
138         std::lock_guard<std::mutex> lock(mLock);
139         mRunning = false;
140         return;
141     }
142 
143     // Waits until the stream has actually stopped
144     std::unique_lock<std::mutex> lock(mLock);
145     while (mRunning) {
146         if (!mCondition.wait_for(lock, 1s, [this]() { return !mRunning; })) {
147             LOG(WARNING) << "STREAM_STOPPED event timer expired.  EVS service may die.";
148             break;
149         }
150     }
151 }
152 
isRunning()153 bool StreamHandler::isRunning() {
154     std::lock_guard<std::mutex> lock(mLock);
155     return mRunning;
156 }
157 
doneWithFrame(const BufferDesc_1_1 & buffer)158 void StreamHandler::doneWithFrame(const BufferDesc_1_1& buffer) {
159     {
160         std::lock_guard<std::mutex> lock(mLock);
161         auto it = mReceivedBuffers.begin();
162         while (it != mReceivedBuffers.end()) {
163             if (it->bufferId == buffer.bufferId) {
164                 // We intentionally do not update the iterator to detect a
165                 // request to return an unknown buffer.
166                 mReceivedBuffers.erase(it);
167                 break;
168             }
169             ++it;
170         }
171 
172         if (it == mReceivedBuffers.end()) {
173             LOG(DEBUG) << "Ignores a request to return unknown buffer";
174             return;
175         }
176     }
177 
178     // Packages a returned buffer and sends it back to the camera
179     hidl_vec<BufferDesc_1_1> frames;
180     frames.resize(1);
181     frames[0] = buffer;
182     auto status = mEvsCamera->doneWithFrame_1_1(frames);
183     if (!status.isOk()) {
184         LOG(ERROR) << "Failed to return a frame to EVS service; this may leak the memory.";
185     }
186 }
187 
deliverFrame(const BufferDesc_1_0 & buffer)188 Return<void> StreamHandler::deliverFrame(const BufferDesc_1_0& buffer) {
189     LOG(WARNING) << "Ignores a frame delivered from v1.0 EVS service.";
190     auto status = mEvsCamera->doneWithFrame(buffer);
191     if (!status.isOk()) {
192         LOG(ERROR) << "Failed to return a frame to EVS service; this may leak the memory.";
193     }
194     return {};
195 }
196 
deliverFrame_1_1(const hidl_vec<BufferDesc_1_1> & buffers)197 Return<void> StreamHandler::deliverFrame_1_1(const hidl_vec<BufferDesc_1_1>& buffers) {
198     LOG(DEBUG) << "Received frames from the camera, bufferId = " << buffers[0].bufferId;
199 
200     // Takes the lock to protect our frameDesc slots and running state variable
201     BufferDesc_1_1 frameDesc = buffers[0];
202     if (frameDesc.buffer.nativeHandle.getNativeHandle() == nullptr) {
203         // Signals that the last frameDesc has been received and the stream is stopped
204         LOG(WARNING) << "Invalid null frameDesc (id: 0x" << std::hex << frameDesc.bufferId
205                      << ") is ignored";
206 
207         return {};
208     }
209 
210     size_t numBuffersInUse;
211     {
212         std::lock_guard<std::mutex> lock(mLock);
213         numBuffersInUse = mReceivedBuffers.size();
214     }
215 
216     if (numBuffersInUse > mMaxNumFramesInFlight) {
217         // We're holding more than what allowed; returns this buffer
218         // immediately.
219         doneWithFrame(frameDesc);
220     } else {
221         {
222             std::lock_guard<std::mutex> lock(mLock);
223             // Records a new frameDesc and forwards to clients
224             mReceivedBuffers.emplace_back(frameDesc);
225             LOG(DEBUG) << "Got buffer " << frameDesc.bufferId
226                        << ", total = " << mReceivedBuffers.size();
227 
228             // Notify anybody who cares that things have changed
229             mCondition.notify_all();
230         }
231 
232         // Forwards a new frame
233         mCallback->onNewFrame(frameDesc);
234     }
235 
236     return {};
237 }
238 
notify(const EvsEventDesc & event)239 Return<void> StreamHandler::notify(const EvsEventDesc& event) {
240     switch (event.aType) {
241         case EvsEventType::STREAM_STOPPED: {
242             {
243                 std::lock_guard<std::mutex> lock(mLock);
244                 // Signal that the last frame has been received and the stream is stopped
245                 mRunning = false;
246             }
247             LOG(DEBUG) << "Received a STREAM_STOPPED event";
248             break;
249         }
250         case EvsEventType::PARAMETER_CHANGED:
251             LOG(DEBUG) << "Camera parameter 0x" << std::hex << event.payload[0] << " is set to 0x"
252                        << std::hex << event.payload[1];
253             break;
254         // Below events are ignored in reference implementation.
255         case EvsEventType::STREAM_STARTED:
256             [[fallthrough]];
257         case EvsEventType::FRAME_DROPPED:
258             [[fallthrough]];
259         case EvsEventType::TIMEOUT:
260             LOG(INFO) << "Event 0x" << std::hex << static_cast<int32_t>(event.aType)
261                       << " is received but ignored";
262             break;
263         default:
264             LOG(ERROR) << "Unknown event id 0x" << std::hex << static_cast<int32_t>(event.aType);
265             break;
266     }
267 
268     mCallback->onNewEvent(event);
269 
270     return {};
271 }
272 
273 }  // namespace evs
274 }  // namespace automotive
275 }  // namespace android
276