• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 //#define LOG_NDEBUG 0
18 
19 #include <jni.h>
20 #include <fstream>
21 #include <iostream>
22 #include <utility>
23 #include <vector>
24 
25 #include <glob.h>
26 #include <linux/usb/g_uvc.h>
27 #include <linux/usb/video.h>
28 #include <sys/epoll.h>
29 #include <sys/inotify.h>
30 #include <sys/mman.h>
31 
32 #include <DeviceAsWebcamNative.h>
33 #include <SdkFrameProvider.h>
34 #include <UVCProvider.h>
35 #include <Utils.h>
36 #include <log/log.h>
37 
38 constexpr int MAX_EVENTS = 10;
39 constexpr uint32_t NUM_BUFFERS_ALLOC = 4;
40 constexpr uint32_t USB_PAYLOAD_TRANSFER_SIZE = 3072;
41 constexpr char kDeviceGlobPattern[] = "/dev/video*";
42 
43 // Taken from UVC UAPI. The kernel handles mapping these back to actual USB interfaces set up by the
44 // UVC gadget function.
45 constexpr uint32_t CONTROL_INTERFACE_IDX = 0;
46 constexpr uint32_t STREAMING_INTERFACE_IDX = 1;
47 
48 constexpr uint32_t FRAME_INTERVAL_NUM = 10'000'000;
49 
50 namespace android {
51 namespace webcam {
52 
init()53 Status EpollW::init() {
54     int fd = epoll_create1(EPOLL_CLOEXEC);
55     if (fd < 0) {
56         ALOGE("%s epoll_create failed: %s", __FUNCTION__, strerror(errno));
57         return Status::ERROR;
58     }
59     mEpollFd.reset(fd);
60     return Status::OK;
61 }
62 
add(int fd,uint32_t eventsIn)63 Status EpollW::add(int fd, uint32_t eventsIn) {
64     struct epoll_event event {};
65     event.data.fd = fd;
66     event.events = eventsIn;
67     if (epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &event) != 0) {
68         ALOGE("%s Epoll_ctl ADD failed %s \n", __FUNCTION__, strerror(errno));
69         return Status::ERROR;
70     }
71     return Status::OK;
72 }
73 
modify(int fd,uint32_t newEvents)74 Status EpollW::modify(int fd, uint32_t newEvents) {
75     struct epoll_event event {};
76     event.data.fd = fd;
77     event.events = newEvents;
78     // TODO(b/267794640): Could we use CTL_MOD instead with UVC, reliably.
79     if (epoll_ctl(mEpollFd.get(), EPOLL_CTL_DEL, fd, &event) != 0) {
80         ALOGE("%s Epoll_ctl DEL failed %s \n", __FUNCTION__, strerror(errno));
81         return Status::ERROR;
82     }
83     if (epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &event) != 0) {
84         ALOGE("%s Epoll_ctl ADD failed %s \n", __FUNCTION__, strerror(errno));
85         return Status::ERROR;
86     }
87     return Status::OK;
88 }
89 
remove(int fd)90 Status EpollW::remove(int fd) {
91     struct epoll_event event {};
92     if (epoll_ctl(mEpollFd.get(), EPOLL_CTL_DEL, fd, &event) != 0) {
93         ALOGE("%s Epoll_ctl DEL failed %s \n", __FUNCTION__, strerror(errno));
94         return Status::ERROR;
95     }
96     return Status::OK;
97 }
98 
waitForEvents()99 Events EpollW::waitForEvents() {
100     struct epoll_event events[MAX_EVENTS];
101     Events eventsVec;
102     int nFds = epoll_wait(mEpollFd.get(), events, MAX_EVENTS, /*msWait for 15 fps*/ 66);
103 
104     if (nFds < 0) {
105         ALOGE("%s nFds was < 0 %s", __FUNCTION__, strerror(errno));
106         return eventsVec;
107     }
108     for (int i = 0; i < nFds; i++) {
109         eventsVec.emplace_back(events[i]);
110     }
111     return eventsVec;
112 }
113 
openV4L2DeviceAndSubscribe(const std::string & videoNode)114 Status UVCProvider::UVCDevice::openV4L2DeviceAndSubscribe(const std::string& videoNode) {
115     struct v4l2_capability cap {};
116     int fd = open(videoNode.c_str(), O_RDWR);
117     if (fd < 0) {
118         ALOGE("%s Couldn't open V4L2 device %s err: %d fd %d, err str %s", __FUNCTION__,
119               videoNode.c_str(), errno, fd, strerror(errno));
120         return Status::ERROR;
121     }
122 
123     ALOGI("%s Start to listen to device fd %d", __FUNCTION__, fd);
124     mUVCFd.reset(fd);
125 
126     // Set up inotify to watch for V4L2 node removal before before setting up anything else.
127     int inotifyFd = inotify_init();
128     if (inotifyFd < 0) {
129         ALOGE("%s: Couldn't create an inotify fd. Error(%d): %s", __FUNCTION__,
130               errno, strerror(errno));
131         return Status::ERROR;
132     }
133     mINotifyFd.reset(inotifyFd);
134     // Watch for IN_ATTRIB which is returned on link/unlink among other things.
135     // As the videoNode is already linked, this should only be called during unlink.
136     // NOTE: We don't watch for IN_DELETE_SELF because it isn't triggered when the
137     // V4L2 node is removed.
138     int ret = inotify_add_watch(inotifyFd, videoNode.c_str(), IN_ATTRIB);
139     if (ret < 0) {
140         ALOGE("%s: Couldn't add watch for %s. Error(%d): %s", __FUNCTION__, videoNode.c_str(),
141               errno, strerror(errno));
142         return Status::ERROR;
143     }
144 
145     memset(&cap, 0, sizeof(cap));
146 
147     if (ioctl(mUVCFd.get(), VIDIOC_QUERYCAP, &cap) < 0) {
148         ALOGE("%s Couldn't get V4L2 device capabilities fd %d", __FUNCTION__, mUVCFd.get());
149         return Status::ERROR;
150     }
151 
152     // Check that it is indeed a video output device
153     if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
154         ALOGE("%s V4L2 device capabilities don't contain video output, caps:  %zu", __FUNCTION__,
155               (size_t)cap.capabilities);
156         return Status::ERROR;
157     }
158 
159     mUVCProperties = parseUvcProperties();
160 
161     // Subscribe to events
162     struct v4l2_event_subscription subscription {};
163     std::vector<unsigned long> events = {UVC_EVENT_SETUP, UVC_EVENT_DATA, UVC_EVENT_STREAMON,
164                                          UVC_EVENT_STREAMOFF, UVC_EVENT_DISCONNECT};
165 
166     for (auto event : events) {
167         subscription.type = event;
168         if (ioctl(mUVCFd.get(), VIDIOC_SUBSCRIBE_EVENT, &subscription) < 0) {
169             ALOGE("%s Couldn't subscribe to V4L2 event %lu error %s", __FUNCTION__, event,
170                   strerror(errno));
171             return Status::ERROR;
172         }
173     }
174     return Status::OK;
175 }
176 
isVideoOutputDevice(const char * dev)177 static bool isVideoOutputDevice(const char* dev) {
178     base::unique_fd fd(open(dev, O_RDWR));
179     if (fd.get() < 0) {
180         ALOGW("%s Opening V4L2 node %s failed %s", __FUNCTION__, dev, strerror(errno));
181         return false;
182     }
183 
184     struct v4l2_capability capability {};
185     int ret = ioctl(fd.get(), VIDIOC_QUERYCAP, &capability);
186     if (ret < 0) {
187         ALOGV("%s v4l2 QUERYCAP %s failed %s", __FUNCTION__, dev, strerror(errno));
188         return false;
189     }
190 
191     if (capability.device_caps & V4L2_CAP_VIDEO_OUTPUT) {
192         ALOGI("%s device %s supports VIDEO_OUTPUT", __FUNCTION__, dev);
193         return true;
194     }
195     ALOGV("%s device %s does not support VIDEO_OUTPUT", __FUNCTION__, dev);
196     return false;
197 }
198 
getFrameIntervals(ConfigFrame * frame,ConfigFormat * format)199 void UVCProvider::UVCDevice::getFrameIntervals(ConfigFrame* frame, ConfigFormat* format) {
200     uint32_t index = 0;
201     while (true) {
202         struct v4l2_frmivalenum intervalDesc {};
203         intervalDesc.index = index;
204         intervalDesc.pixel_format = format->fcc;
205         intervalDesc.width = frame->width;
206         intervalDesc.height = frame->height;
207         int ret = ioctl(mUVCFd.get(), VIDIOC_ENUM_FRAMEINTERVALS, &intervalDesc);
208         if (ret != 0) {
209             return;
210         }
211         if (intervalDesc.index != index) {
212             ALOGE("%s V4L2 api returned different index %u from expected %u", __FUNCTION__,
213                   intervalDesc.index, index);
214         }
215         uint32_t ival = 0;
216         switch (intervalDesc.type) {
217             case V4L2_FRMIVAL_TYPE_DISCRETE:
218                 ival = (intervalDesc.discrete.numerator * FRAME_INTERVAL_NUM) /
219                        intervalDesc.discrete.denominator;
220                 break;
221             case V4L2_FRMIVAL_TYPE_STEPWISE:
222                 // We only take the min here
223                 ival = intervalDesc.stepwise.min.numerator / intervalDesc.stepwise.min.denominator;
224                 break;
225             default:
226                 ALOGE("%s frame type %u invalid", __FUNCTION__, intervalDesc.type);
227                 break;
228         }
229         frame->intervals.emplace_back(ival);
230         index++;
231     }
232 }
233 
getFormatFrames(ConfigFormat * format)234 void UVCProvider::UVCDevice::getFormatFrames(ConfigFormat* format) {
235     uint32_t index = 0;
236     while (true) {
237         struct v4l2_frmsizeenum frameDesc {};
238         frameDesc.index = index;
239         frameDesc.pixel_format = format->fcc;
240         ALOGI("Getting frames for format index %u", index);
241         int ret = ioctl(mUVCFd.get(), VIDIOC_ENUM_FRAMESIZES, &frameDesc);
242         if (ret != 0) {
243             return;
244         }
245         if (frameDesc.index != index) {
246             ALOGE("%s V4L2 api returned different index %u from expected %u", __FUNCTION__,
247                   frameDesc.index, index);
248         }
249         ConfigFrame configFrame{};
250         configFrame.index = index;
251         switch (frameDesc.type) {
252             case V4L2_FRMSIZE_TYPE_DISCRETE:
253                 configFrame.width = frameDesc.discrete.width;
254                 configFrame.height = frameDesc.discrete.height;
255                 break;
256             case V4L2_FRMSIZE_TYPE_STEPWISE:
257                 // We only take the min here
258                 configFrame.width = frameDesc.stepwise.min_width;
259                 configFrame.height = frameDesc.stepwise.min_height;
260                 break;
261             default:
262                 ALOGE("%s frame type %u invalid", __FUNCTION__, frameDesc.type);
263                 break;
264         }
265         getFrameIntervals(&configFrame, format);
266         format->frames.emplace_back(configFrame);
267         index++;
268     }
269 }
270 
getFormats()271 std::vector<ConfigFormat> UVCProvider::UVCDevice::getFormats() {
272     std::vector<ConfigFormat> retVal;
273     for (uint32_t index = 0; true; ++index) {
274         ALOGI("Getting formats for index %u", index);
275         struct v4l2_fmtdesc formatDesc {};
276         formatDesc.index = index;
277         formatDesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
278         int ret = ioctl(mUVCFd.get(), VIDIOC_ENUM_FMT, &formatDesc);
279         if (ret != 0) {
280             return retVal;
281         }
282         if (formatDesc.index != index) {
283             ALOGE("%s V4L2 api returned different index %u from expected %u", __FUNCTION__,
284                   formatDesc.index, index);
285         }
286 
287         ConfigFormat configFormat{};
288         configFormat.formatIndex = formatDesc.index;  // TODO: Double check with jchowdhary@
289         configFormat.fcc = formatDesc.pixelformat;
290         getFormatFrames(&configFormat);
291         retVal.emplace_back(configFormat);
292     }
293 }
294 
parseUvcProperties()295 std::shared_ptr<UVCProperties> UVCProvider::UVCDevice::parseUvcProperties() {
296     std::shared_ptr<UVCProperties> ret = std::make_shared<UVCProperties>();
297     ret->videoNode = mVideoNode;
298     ret->streaming.formats = getFormats();
299     ret->controlInterfaceNumber = CONTROL_INTERFACE_IDX;
300     ret->streaming.interfaceNumber = STREAMING_INTERFACE_IDX;
301     return ret;
302 }
303 
UVCDevice(std::weak_ptr<UVCProvider> parent,const std::unordered_set<std::string> & ignoredNodes)304 UVCProvider::UVCDevice::UVCDevice(std::weak_ptr<UVCProvider> parent,
305                                   const std::unordered_set<std::string>& ignoredNodes) {
306     mParent = std::move(parent);
307 
308     // Initialize probe and commit controls with default values
309     FormatTriplet defaultFormatTriplet(/*formatIndex*/ 1, /*frameSizeIndex*/ 1,
310                                        /*frameInterval*/ 0);
311 
312     mVideoNode = getVideoNode(ignoredNodes);
313 
314     if (mVideoNode.empty()) {
315         ALOGE("%s: mVideoNode is empty, what ?", __FUNCTION__);
316         return;
317     }
318 
319     if (openV4L2DeviceAndSubscribe(mVideoNode) != Status::OK) {
320         ALOGE("%s: Unable to open and subscribe to V4l2 node %s ?", __FUNCTION__,
321               mVideoNode.c_str());
322         return;
323     }
324     setStreamingControl(&mCommit, &defaultFormatTriplet);
325     mInited = true;
326 }
327 
closeUVCFd()328 void UVCProvider::UVCDevice::closeUVCFd() {
329     mINotifyFd.reset(); // No need to inotify_rm_watch as closing the fd frees up resources
330 
331     if (mUVCFd.get() >= 0) {
332         struct v4l2_event_subscription subscription {};
333         subscription.type = V4L2_EVENT_ALL;
334 
335         if (ioctl(mUVCFd.get(), VIDIOC_UNSUBSCRIBE_EVENT, subscription) < 0) {
336             ALOGE("%s Couldn't unsubscribe from V4L2 events error %s", __FUNCTION__,
337                   strerror(errno));
338         }
339     }
340     mUVCFd.reset();
341 }
342 
getVideoNode(const std::unordered_set<std::string> & ignoredNodes)343 std::string UVCProvider::getVideoNode(const std::unordered_set<std::string>& ignoredNodes) {
344     std::string devNode;
345     ALOGV("%s start scanning for existing V4L2 OUTPUT devices", __FUNCTION__);
346     glob_t globRes;
347     glob(kDeviceGlobPattern, /*flags*/ 0, /*error_callback*/ nullptr, &globRes);
348     for (unsigned int i = 0; i < globRes.gl_pathc; ++i) {
349         auto& node = globRes.gl_pathv[i];
350         ALOGV("%s file: %s", __FUNCTION__, node);
351 
352         // Skip if the node should be ignored
353         if (ignoredNodes.find(node) != ignoredNodes.end()) { continue; }
354 
355         if (isVideoOutputDevice(node)) {
356             devNode = globRes.gl_pathv[i];
357             break;
358         }
359     }
360     globfree(&globRes);
361     return devNode;
362 }
363 
isInited() const364 bool UVCProvider::UVCDevice::isInited() const {
365     return mInited;
366 }
367 
processSetupControlEvent(const struct usb_ctrlrequest * control,struct uvc_request_data * resp)368 void UVCProvider::UVCDevice::processSetupControlEvent(const struct usb_ctrlrequest* control,
369                                                       struct uvc_request_data* resp) {
370     // TODO(b/267794640): Support control requests
371     resp->data[0] = 0x3;
372     resp->length = control->wLength;
373 }
374 
processSetupStreamingEvent(const struct usb_ctrlrequest * request,struct uvc_request_data * response)375 void UVCProvider::UVCDevice::processSetupStreamingEvent(const struct usb_ctrlrequest* request,
376                                                         struct uvc_request_data* response) {
377     uint8_t requestType = request->bRequest;
378     uint8_t controlSelect = request->wValue >> 8;
379     if (controlSelect != UVC_VS_PROBE_CONTROL && controlSelect != UVC_VS_COMMIT_CONTROL) {
380         ALOGE("%s: control select %u is invalid", __FUNCTION__, controlSelect);
381         return;
382     }
383 
384     struct uvc_streaming_control* ctrl =
385             reinterpret_cast<struct uvc_streaming_control*>(response->data);
386     response->length = sizeof(struct uvc_streaming_control);
387     FormatTriplet maxFormatTriplet(/*formatIndex*/ UINT8_MAX,
388                                    /*frameSizeIndex*/ UINT8_MAX,
389                                    /*frameInterval*/ UINT32_MAX);
390     FormatTriplet defaultFormatTriplet(/*formatIndex*/ 1, /*frameSizeIndex*/ 1,
391                                        /*frameInterval*/ 0);
392 
393     switch (requestType) {
394         case UVC_SET_CUR:
395             mCurrentControlState = controlSelect;
396             // UVC 1.5 spec section 4.3.1
397             response->length = 48;
398             break;
399         case UVC_GET_CUR:
400             if (controlSelect == UVC_VS_PROBE_CONTROL) {
401                 memcpy(ctrl, &mProbe, sizeof(struct uvc_streaming_control));
402             } else {
403                 memcpy(ctrl, &mCommit, sizeof(struct uvc_streaming_control));
404             }
405             break;
406         case UVC_GET_MAX:
407             setStreamingControl(ctrl, &maxFormatTriplet);
408             break;
409         case UVC_GET_MIN:
410         case UVC_GET_DEF:
411             setStreamingControl(ctrl, &defaultFormatTriplet);
412             break;
413         case UVC_GET_RES:
414             memset(ctrl, 0, sizeof(struct uvc_streaming_control));
415             break;
416         case UVC_GET_LEN:
417             response->data[0] = 0x00;
418             // UVC 1.5 spec section 4.3.1
419             response->data[0] = 0x30;
420             response->length = 2;
421             break;
422         case UVC_GET_INFO:
423             // UVC 1.5 Spec Section 4.1.2 "Get Request"
424             response->data[0] = 0x3;
425             response->length = 1;
426             break;
427         default:
428             ALOGE("%s requestType %u not supported", __FUNCTION__, requestType);
429             break;
430     }
431 }
432 
processSetupClassEvent(const struct usb_ctrlrequest * request,struct uvc_request_data * response)433 void UVCProvider::UVCDevice::processSetupClassEvent(const struct usb_ctrlrequest* request,
434                                                     struct uvc_request_data* response) {
435     uint8_t interface = request->wIndex & 0xff;
436     ALOGV("%s: Interface %u", __FUNCTION__, interface);
437 
438     if ((request->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE) {
439         ALOGE("Invalid bRequestType byte %u", request->bRequestType);
440         return;
441     }
442 
443     if (interface == mUVCProperties->controlInterfaceNumber) {
444         processSetupControlEvent(request, response);
445     } else if (interface == mUVCProperties->streaming.interfaceNumber) {
446         processSetupStreamingEvent(request, response);
447     }
448 }
449 
processSetupEvent(const struct usb_ctrlrequest * request,struct uvc_request_data * response)450 void UVCProvider::UVCDevice::processSetupEvent(const struct usb_ctrlrequest* request,
451                                                struct uvc_request_data* response) {
452     uint8_t type = request->bRequestType;
453     uint8_t requestCode = request->bRequest;
454     uint16_t length = request->wLength;
455     uint16_t index = request->wIndex;
456     uint16_t value = request->wValue;
457     ALOGV("%s: type %u requestCode %u length %u index %u value %u", __FUNCTION__, type, requestCode,
458           length, index, value);
459     switch (type & USB_TYPE_MASK) {
460         case USB_TYPE_STANDARD:
461             ALOGW("USB_TYPE_STANDARD request not being handled");
462             break;
463         case USB_TYPE_CLASS:
464             processSetupClassEvent(request, response);
465             break;
466         default:
467             ALOGE("%s: Unknown request type %u", __FUNCTION__, type);
468     }
469 }
470 
setStreamingControl(struct uvc_streaming_control * streamingControl,const FormatTriplet * req)471 void UVCProvider::UVCDevice::setStreamingControl(struct uvc_streaming_control* streamingControl,
472                                                  const FormatTriplet* req) {
473     // frame and format index start from 1.
474     uint8_t chosenFormatIndex = req->formatIndex > mUVCProperties->streaming.formats.size()
475                                         ? mUVCProperties->streaming.formats.size()
476                                         : req->formatIndex;
477     if (chosenFormatIndex <= 0) {
478         return;
479     }
480     const ConfigFormat& chosenFormat = mUVCProperties->streaming.formats[chosenFormatIndex - 1];
481     uint8_t chosenFrameIndex = req->frameSizeIndex > chosenFormat.frames.size()
482                                        ? chosenFormat.frames.size()
483                                        : req->frameSizeIndex;
484     if (chosenFrameIndex <= 0) {
485         return;
486     }
487     ALOGV("%s: chosenFormatIndex %d chosenFrameIndex: %d", __FUNCTION__, chosenFormatIndex,
488             chosenFrameIndex);
489     const ConfigFrame& chosenFrame = chosenFormat.frames[chosenFrameIndex - 1];
490     uint32_t reqFrameInterval = req->frameInterval;
491     bool largerFound = false;
492     // Choose the first frame interval >= requested. Frame intervals are expected to be in
493     // ascending order.
494     for (auto frameInterval : chosenFrame.intervals) {
495         if (reqFrameInterval <= frameInterval) {
496             reqFrameInterval = frameInterval;
497             largerFound = true;
498             break;
499         }
500     }
501     if (!largerFound) {
502         reqFrameInterval = chosenFrame.intervals[chosenFrame.intervals.size() - 1];
503     }
504     memset(streamingControl, 0, sizeof(*streamingControl));
505 
506     // TODO((b/267794640): Add documentation for magic numbers used here and elsewhere.
507     streamingControl->bmHint = 1;
508     streamingControl->bmFramingInfo = 3;
509     streamingControl->bPreferedVersion = 1;
510     streamingControl->bMaxVersion = 1;
511 
512     streamingControl->bFormatIndex = chosenFormatIndex;
513     streamingControl->bFrameIndex = chosenFrameIndex;
514     streamingControl->dwFrameInterval = reqFrameInterval;
515     streamingControl->dwMaxPayloadTransferSize = USB_PAYLOAD_TRANSFER_SIZE;
516     switch (chosenFormat.fcc) {
517         case V4L2_PIX_FMT_YUYV:
518         case V4L2_PIX_FMT_MJPEG:
519             streamingControl->dwMaxVideoFrameSize = chosenFrame.width * chosenFrame.height * 2;
520             break;
521         default:
522             ALOGE("%s Video format is not YUYV or MJPEG ??", __FUNCTION__);
523     }
524 }
525 
commitControls()526 void UVCProvider::UVCDevice::commitControls() {
527     const ConfigFormat& commitFormat = mUVCProperties->streaming.formats[mCommit.bFormatIndex - 1];
528     const ConfigFrame& commitFrame = commitFormat.frames[mCommit.bFrameIndex - 1];
529     mFps = FRAME_INTERVAL_NUM / mCommit.dwFrameInterval;
530 
531     memset(&mV4l2Format, 0, sizeof(mV4l2Format));
532     mV4l2Format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
533     mV4l2Format.fmt.pix.width = commitFrame.width;
534     mV4l2Format.fmt.pix.height = commitFrame.height;
535     mV4l2Format.fmt.pix.pixelformat = commitFormat.fcc;
536     mV4l2Format.fmt.pix.field = V4L2_FIELD_ANY;
537     mV4l2Format.fmt.pix.sizeimage = mCommit.dwMaxVideoFrameSize;
538 
539     // Call ioctl VIDIOC_S_FMT which may change the fields in mV4l2Format
540     if (ioctl(mUVCFd.get(), VIDIOC_S_FMT, &mV4l2Format) < 0) {
541         ALOGE("%s Unable to set pixel format with the uvc gadget driver: %s", __FUNCTION__,
542               strerror(errno));
543         return;
544     }
545     ALOGV("%s controls committed frame width %u, height %u, format %u, sizeimage %u"
546           " frame rate %u mjpeg fourcc %u",
547           __FUNCTION__, mV4l2Format.fmt.pix.width, mV4l2Format.fmt.pix.height,
548           mV4l2Format.fmt.pix.pixelformat, mV4l2Format.fmt.pix.sizeimage, mFps, V4L2_PIX_FMT_MJPEG);
549 }
550 
processDataEvent(const struct uvc_request_data * data)551 void UVCProvider::UVCDevice::processDataEvent(const struct uvc_request_data* data) {
552     const struct uvc_streaming_control* controlReq =
553             reinterpret_cast<const struct uvc_streaming_control*>(&data->data);
554 
555     FormatTriplet triplet(controlReq->bFormatIndex, controlReq->bFrameIndex,
556                           controlReq->dwFrameInterval);
557 
558     switch (mCurrentControlState) {
559         case UVC_VS_PROBE_CONTROL:
560             setStreamingControl(&mProbe, &triplet);
561             break;
562         case UVC_VS_COMMIT_CONTROL:
563             setStreamingControl(&mCommit, &triplet);
564             commitControls();
565             break;
566         default:
567             ALOGE("mCurrentControlState is UNDEFINED");
568             break;
569     }
570 }
571 
mapBuffer(uint32_t i)572 std::shared_ptr<Buffer> UVCProvider::UVCDevice::mapBuffer(uint32_t i) {
573     struct v4l2_buffer buffer {};
574 
575     buffer.index = i;
576     buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
577     buffer.memory = V4L2_MEMORY_MMAP;
578 
579     if (ioctl(mUVCFd.get(), VIDIOC_QUERYBUF, &buffer) < 0) {
580         ALOGE("%s: Unable to query V4L2 buffer index %u from gadget driver: %s", __FUNCTION__, i,
581               strerror(errno));
582         return nullptr;
583     }
584 
585     void* mem = mmap(/*addr*/ nullptr, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
586                      mUVCFd.get(), buffer.m.offset);
587     if (mem == MAP_FAILED) {
588         ALOGE("%s: Unable to map V4L2 buffer index %u from gadget driver: %s", __FUNCTION__, i,
589               strerror(errno));
590         return nullptr;
591     }
592     ALOGV("%s: Allocated and mapped buffer at %p of size %u", __FUNCTION__, mem, buffer.length);
593     return std::make_shared<V4L2Buffer>(mem, &buffer);
594 }
595 
allocateAndMapBuffers(std::shared_ptr<Buffer> * consumerBuffer,std::vector<std::shared_ptr<Buffer>> * producerBuffers)596 Status UVCProvider::UVCDevice::allocateAndMapBuffers(
597         std::shared_ptr<Buffer>* consumerBuffer,
598         std::vector<std::shared_ptr<Buffer>>* producerBuffers) {
599     if (consumerBuffer == nullptr || producerBuffers == nullptr) {
600         ALOGE("%s: ConsumerBuffer / producerBuffers are null", __FUNCTION__);
601         return Status::ERROR;
602     }
603     *consumerBuffer = nullptr;
604     producerBuffers->clear();
605     struct v4l2_requestbuffers requestBuffers {};
606 
607     requestBuffers.count = NUM_BUFFERS_ALLOC;
608     requestBuffers.memory = V4L2_MEMORY_MMAP;
609     requestBuffers.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
610 
611     // Request the driver to allocate buffers
612     if (ioctl(mUVCFd.get(), VIDIOC_REQBUFS, &requestBuffers) < 0) {
613         ALOGE("%s: Unable to request V4L2 buffers from gadget driver: %s", __FUNCTION__,
614               strerror(errno));
615         return Status::ERROR;
616     }
617 
618     if (requestBuffers.count != NUM_BUFFERS_ALLOC) {
619         ALOGE("%s: Gadget driver could only allocate %u buffers instead of %u", __FUNCTION__,
620               requestBuffers.count, NUM_BUFFERS_ALLOC);
621         // TODO: We should probably be freeing buffers here
622         return Status::ERROR;
623     }
624 
625     // First buffer is consumer buffer
626     *consumerBuffer = mapBuffer(0);
627     if (*consumerBuffer == nullptr) {
628         ALOGE("%s: Mapping consumer buffer failed", __FUNCTION__);
629         return Status::ERROR;
630     }
631 
632     // The rest are producer buffers
633     for (uint32_t i = 1; i < NUM_BUFFERS_ALLOC; i++) {
634         std::shared_ptr<Buffer> buffer = mapBuffer(i);
635         if (buffer == nullptr) {
636             ALOGE("%s: Mapping producer buffer index %u failed", __FUNCTION__, i);
637             *consumerBuffer = nullptr;
638             producerBuffers->clear();
639             return Status::ERROR;
640         }
641         producerBuffers->push_back(buffer);
642     }
643     return Status::OK;
644 }
645 
unmapBuffer(std::shared_ptr<Buffer> & buffer)646 Status UVCProvider::UVCDevice::unmapBuffer(std::shared_ptr<Buffer>& buffer) {
647     if (buffer->getMem() != nullptr) {
648         if (munmap(buffer->getMem(), buffer->getLength()) < 0) {
649             ALOGE("%s: munmap failed for buffer with pointer %p", __FUNCTION__, buffer->getMem());
650             return Status::ERROR;
651         }
652     }
653     return Status::OK;
654 }
655 
destroyBuffers(std::shared_ptr<Buffer> & consumerBuffer,std::vector<std::shared_ptr<Buffer>> & producerBuffers)656 void UVCProvider::UVCDevice::destroyBuffers(std::shared_ptr<Buffer>& consumerBuffer,
657                                             std::vector<std::shared_ptr<Buffer>>& producerBuffers) {
658     if (unmapBuffer(consumerBuffer) != Status::OK) {
659         ALOGE("%s: Failed to unmap consumer buffer, continuing producer buffer cleanup anyway",
660               __FUNCTION__);
661     }
662     for (auto& buf : producerBuffers) {
663         if (unmapBuffer(buf) != Status::OK) {
664             ALOGE("%s: Failed to unmap producer buffer, continuing buffer cleanup anyway",
665                   __FUNCTION__);
666         }
667     }
668     struct v4l2_requestbuffers zeroRequest {};
669     zeroRequest.count = 0;
670     zeroRequest.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
671     zeroRequest.memory = V4L2_MEMORY_MMAP;
672 
673     if (ioctl(mUVCFd.get(), VIDIOC_REQBUFS, &zeroRequest) < 0) {
674         ALOGE("%s: request to free buffers from uvc gadget driver failed %s", __FUNCTION__,
675               strerror(errno));
676     }
677 }
678 
getFrameAndQueueBufferToGadgetDriver(bool firstBuffer)679 Status UVCProvider::UVCDevice::getFrameAndQueueBufferToGadgetDriver(bool firstBuffer) {
680     // If first buffer, also call the STREAMON ioctl on uvc device
681     ALOGV("%s: E", __FUNCTION__);
682     if (firstBuffer) {
683         int type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
684         if (ioctl(mUVCFd.get(), VIDIOC_STREAMON, &type) < 0) {
685             ALOGE("%s: VIDIOC_STREAMON failed %s", __FUNCTION__, strerror(errno));
686             return Status::ERROR;
687         }
688     }
689     Buffer* buffer = mBufferManager->getFilledBufferAndSwap();
690     struct v4l2_buffer v4L2Buffer = *(static_cast<V4L2Buffer*>(buffer)->getV4L2Buffer());
691     ALOGV("%s: got buffer, queueing it with index %u", __FUNCTION__, v4L2Buffer.index);
692 
693     if (ioctl(mUVCFd.get(), VIDIOC_QBUF, &v4L2Buffer) < 0) {
694         ALOGE("%s: VIDIOC_QBUF failed on gadget driver: %s", __FUNCTION__, strerror(errno));
695         return Status::ERROR;
696     }
697     ALOGV("%s: X", __FUNCTION__);
698     return Status::OK;
699 }
700 
processStreamOffEvent()701 void UVCProvider::UVCDevice::processStreamOffEvent() {
702     int type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
703     if (ioctl(mUVCFd.get(), VIDIOC_STREAMOFF, &type) < 0) {
704         ALOGE("%s: uvc gadget driver request to switch stream off failed %s", __FUNCTION__,
705               strerror(errno));
706         return;
707     }
708 
709     mFrameProvider.reset();
710     mBufferManager.reset();
711     memset(&mCommit, 0, sizeof(mCommit));
712     memset(&mProbe, 0, sizeof(mProbe));
713     memset(&mV4l2Format, 0, sizeof(mV4l2Format));
714     mFps = 0;
715 }
716 
processStreamOnEvent()717 void UVCProvider::UVCDevice::processStreamOnEvent() {
718     // Allocate V4L2 and map buffers for circulation between camera and UVCDevice
719     mBufferManager = std::make_shared<BufferManager>(this);
720     CameraConfig config;
721     config.width = mV4l2Format.fmt.pix.width;
722     config.height = mV4l2Format.fmt.pix.height;
723     config.fcc = mV4l2Format.fmt.pix.pixelformat;
724     config.fps = mFps;
725 
726     mFrameProvider = std::make_shared<SdkFrameProvider>(mBufferManager, config);
727     mFrameProvider->setStreamConfig();
728     mFrameProvider->startStreaming();
729 
730     // Queue first buffer to start the stream
731     if (getFrameAndQueueBufferToGadgetDriver(true) != Status::OK) {
732         ALOGE("%s: Queueing first buffer to gadget driver failed, stream not started",
733               __FUNCTION__);
734         return;
735     }
736     auto parent = mParent.lock();
737     parent->watchStreamEvent();
738 }
739 
~UVCProvider()740 UVCProvider::~UVCProvider() {
741     if (mUVCListenerThread.joinable()) {
742         mListenToUVCFds = false;
743         mUVCListenerThread.join();
744     }
745 
746     if (mUVCDevice) {
747         if (mUVCDevice->getUVCFd() >= 0) {
748             mEpollW.remove(mUVCDevice->getUVCFd());
749         }
750         if (mUVCDevice->getINotifyFd() >= 0) {
751             mEpollW.remove(mUVCDevice->getINotifyFd());
752         }
753     }
754     mUVCDevice = nullptr;
755 }
756 
init()757 Status UVCProvider::init() {
758     // TODO: What in the world?
759     return mEpollW.init();
760 }
761 
processStreamEvent()762 void UVCProvider::UVCDevice::processStreamEvent() {
763     // Dequeue producer buffer
764     struct v4l2_buffer v4L2Buffer {};
765     v4L2Buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
766     v4L2Buffer.memory = V4L2_MEMORY_MMAP;
767 
768     if (ioctl(mUVCFd.get(), VIDIOC_DQBUF, &v4L2Buffer) < 0) {
769         ALOGE("%s: VIDIOC_DQBUF failed %s", __FUNCTION__, strerror(errno));
770         return;
771     }
772     // Get camera frame and queue it to gadget driver
773     if (getFrameAndQueueBufferToGadgetDriver() != Status::OK) {
774         return;
775     }
776 }
encodeImage(AHardwareBuffer * buffer,long timestamp,int rotation)777 Status UVCProvider::UVCDevice::encodeImage(AHardwareBuffer* buffer, long timestamp, int rotation) {
778     if (mFrameProvider == nullptr) {
779         ALOGE("%s: encodeImage called but there is no frame provider active", __FUNCTION__);
780         return Status::ERROR;
781     }
782     return mFrameProvider->encodeImage(buffer, timestamp, rotation);
783 }
784 
processUVCEvent()785 void UVCProvider::processUVCEvent() {
786     struct v4l2_event event {};
787     int deviceFd = mUVCDevice->getUVCFd();
788 
789     if (ioctl(deviceFd, VIDIOC_DQEVENT, &event) < 0) {
790         ALOGE("%s Failed to dequeue V4L2 event : %s", __FUNCTION__, strerror(errno));
791         return;
792     }
793     struct uvc_event* uvcEvent = reinterpret_cast<struct uvc_event*>(&event.u.data);
794     struct uvc_request_data uvcResponse {};
795     switch (event.type) {
796         case UVC_EVENT_CONNECT:
797             return;
798         case UVC_EVENT_DISCONNECT:
799             ALOGI("%s Disconnect event", __FUNCTION__);
800             stopService();
801             return;
802         case UVC_EVENT_SETUP:
803             ALOGV(" %s: Setup event ", __FUNCTION__);
804             mUVCDevice->processSetupEvent(&(uvcEvent->req), &uvcResponse);
805             break;
806         case UVC_EVENT_DATA:
807             ALOGV(" %s: Data event", __FUNCTION__);
808             mUVCDevice->processDataEvent(&(uvcEvent->data));
809             return;
810         case UVC_EVENT_STREAMON:
811             ALOGI("%s STREAMON event", __FUNCTION__);
812             mUVCDevice->processStreamOnEvent();
813             return;
814         case UVC_EVENT_STREAMOFF:
815             ALOGI("%s STREAMOFF event", __FUNCTION__);
816             mUVCDevice->processStreamOffEvent();
817             mEpollW.modify(mUVCDevice->getUVCFd(), EPOLLPRI);
818             return;
819         default:
820             ALOGI(" UVC Event unsupported %u", event.type);
821             break;
822     }
823 
824     if (ioctl(deviceFd, UVCIOC_SEND_RESPONSE, &uvcResponse) < 0) {
825         ALOGE("%s Unable to send response to uvc gadget driver %s", __FUNCTION__, strerror(errno));
826         return;
827     }
828 }
829 
830 // TODO: seems unnecessary
watchStreamEvent()831 void UVCProvider::watchStreamEvent() {
832     mEpollW.modify(mUVCDevice->getUVCFd(), EPOLLPRI | EPOLLOUT);
833 }
834 
ListenToUVCFds()835 void UVCProvider::ListenToUVCFds() {
836     // For UVC events
837     ALOGI("%s Start to listen to device fd %d and inotify_fd %d", __FUNCTION__,
838           mUVCDevice->getUVCFd(), mUVCDevice->getINotifyFd());
839 
840     // Listen to inotify events for node removal
841     mEpollW.add(mUVCDevice->getINotifyFd(), EPOLLIN);
842     // Listen to V4L2 events
843     mEpollW.add(mUVCDevice->getUVCFd(), EPOLLPRI);
844     // For stream events : dequeue and queue buffers
845     while (mListenToUVCFds) {
846         Events events = mEpollW.waitForEvents();
847         for (auto event : events) {
848             if (mUVCDevice->getINotifyFd() == event.data.fd && (event.events & EPOLLIN)) {
849                 // File system event on the V4L2 node
850                 if (processINotifyEvent()) {
851                     break; // Stop handling current events if the service was stopped.
852                 }
853             } else {
854                 // V4L2 event
855                 // Priority event might come with regular events, so one event could have both
856                 if (event.events & EPOLLPRI) {
857                     processUVCEvent();
858                 }
859 
860                 if (event.events & EPOLLOUT) {
861                     if (mUVCDevice != nullptr) {
862                         mUVCDevice->processStreamEvent();
863                     } else {
864                         ALOGW("mUVCDevice is null we've disconnected");
865                     }
866                 } else if (!(event.events & EPOLLPRI)) {
867                     ALOGW("Which event fd is %d ? event %u", event.data.fd, event.events);
868                 }
869             }
870         }
871     }
872 }
873 
processINotifyEvent()874 bool UVCProvider::processINotifyEvent() {
875     // minimum size to read one event fully
876     ALOGV("%s: Processing inotify event", __FUNCTION__);
877     constexpr size_t BUF_SIZE = sizeof(struct inotify_event) + NAME_MAX + 1;
878     char buf[BUF_SIZE];
879     int len = 0;
880     while ((len = read(mUVCDevice->getINotifyFd(), buf, BUF_SIZE)) >= 0) {
881         for (int i = 0; i < len;) {
882             struct inotify_event* event = reinterpret_cast<inotify_event*>(&buf[i]);
883             i += sizeof(struct inotify_event) + event->len;
884 
885             ALOGV("%s: Read inotify_event: wd(%d); mask(%u); cookie(%u); len(%u); name(%s)",
886                   __FUNCTION__, event->wd, event->mask, event->cookie, event->cookie,
887                   &event->name[0]);
888 
889             // Make sure the V4L2 node is actually removed before stopping service.
890             if ((event->mask & IN_ATTRIB) && access(mUVCDevice->getCurrentVideoNode(), F_OK)) {
891                 // V4L2 node unlinked. Stop service as "UVC_EVENT_DISCONNECT" won't be coming in
892                 // anymore.
893                 ALOGW("%s: V4L2 node removed without UVC_EVENT_DISCONNECT. Stopping Service.",
894                       __FUNCTION__);
895                 stopService();
896                 return true;
897             }
898         }
899     }
900     ALOGV("%s: Could not read from inotify_fd(%d). Error(%d): %s", __FUNCTION__,
901           mUVCDevice->getINotifyFd(), errno, strerror(errno));
902     return false;
903 }
904 
encodeImage(AHardwareBuffer * buffer,long timestamp,int rotation)905 int UVCProvider::encodeImage(AHardwareBuffer* buffer, long timestamp, int rotation) {
906     if (mUVCDevice == nullptr) {
907         ALOGE("%s: Request to encode Image without UVCDevice Running.", __FUNCTION__);
908         return -1;
909     }
910     return mUVCDevice->encodeImage(buffer, timestamp, rotation) == Status::OK ? 0 : -1;
911 }
912 
startUVCListenerThread()913 void UVCProvider::startUVCListenerThread() {
914     mListenToUVCFds = true;
915     mUVCListenerThread =
916             DeviceAsWebcamNative::createJniAttachedThread(&UVCProvider::ListenToUVCFds, this);
917     ALOGI("Started new UVCListenerThread");
918 }
919 
stopAndWaitForUVCListenerThread()920 void UVCProvider::stopAndWaitForUVCListenerThread() {
921     // This thread stays alive till onDestroy is called.
922     if (mUVCListenerThread.joinable()) {
923         mListenToUVCFds = false;
924         mUVCListenerThread.join();
925     }
926 }
927 
startService(const std::unordered_set<std::string> & ignoredNodes)928 Status UVCProvider::startService(const std::unordered_set<std::string>& ignoredNodes) {
929     // Resets old state for epoll since this is a new start for the service.
930     mEpollW.init();
931     if (mUVCDevice != nullptr) {
932         mUVCDevice->closeUVCFd();
933     }
934     mUVCDevice = std::make_shared<UVCDevice>(shared_from_this(), ignoredNodes);
935     if (!mUVCDevice->isInited()) {
936         return Status::ERROR;
937     }
938     stopAndWaitForUVCListenerThread();  // Just in case it is already running
939     startUVCListenerThread();
940     return Status::OK;
941 }
942 
stopService()943 void UVCProvider::stopService() {
944     // TODO: Try removing this
945     mUVCDevice->processStreamOffEvent();
946     mEpollW.remove(mUVCDevice->getUVCFd());
947     mEpollW.remove(mUVCDevice->getINotifyFd());
948     // Signal the service to stop.
949     // UVC Provider will get destructed when the Java Service is destroyed.
950     DeviceAsWebcamServiceManager::kInstance->stopService();
951     mUVCDevice = nullptr;
952     mListenToUVCFds = false;
953 }
954 
955 }  // namespace webcam
956 }  // namespace android
957