• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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_TAG "CamPrvdr@2.4-external"
18 //#define LOG_NDEBUG 0
19 #include <log/log.h>
20 
21 #include <regex>
22 #include <sys/inotify.h>
23 #include <errno.h>
24 #include <linux/videodev2.h>
25 #include <cutils/properties.h>
26 #include "ExternalCameraProviderImpl_2_4.h"
27 #include "ExternalCameraDevice_3_4.h"
28 #include "ExternalCameraDevice_3_5.h"
29 
30 namespace android {
31 namespace hardware {
32 namespace camera {
33 namespace provider {
34 namespace V2_4 {
35 namespace implementation {
36 
37 template struct CameraProvider<ExternalCameraProviderImpl_2_4>;
38 
39 namespace {
40 // "device@<version>/external/<id>"
41 const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
42 const int kMaxDevicePathLen = 256;
43 const char* kDevicePath = "/dev/";
44 constexpr char kPrefix[] = "video";
45 constexpr int kPrefixLen = sizeof(kPrefix) - 1;
46 
matchDeviceName(const hidl_string & deviceName,std::string * deviceVersion,std::string * cameraId)47 bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion,
48                      std::string* cameraId) {
49     std::string deviceNameStd(deviceName.c_str());
50     std::smatch sm;
51     if (std::regex_match(deviceNameStd, sm, kDeviceNameRE)) {
52         if (deviceVersion != nullptr) {
53             *deviceVersion = sm[1];
54         }
55         if (cameraId != nullptr) {
56             *cameraId = sm[2];
57         }
58         return true;
59     }
60     return false;
61 }
62 
63 } // anonymous namespace
64 
ExternalCameraProviderImpl_2_4()65 ExternalCameraProviderImpl_2_4::ExternalCameraProviderImpl_2_4() :
66         mCfg(ExternalCameraConfig::loadFromCfg()),
67         mHotPlugThread(this) {
68     mHotPlugThread.run("ExtCamHotPlug", PRIORITY_BACKGROUND);
69 
70     mPreferredHal3MinorVersion =
71         property_get_int32("ro.vendor.camera.external.hal3TrebleMinorVersion", 4);
72     ALOGV("Preferred HAL 3 minor version is %d", mPreferredHal3MinorVersion);
73     switch(mPreferredHal3MinorVersion) {
74         case 4:
75         case 5:
76             // OK
77             break;
78         default:
79             ALOGW("Unknown minor camera device HAL version %d in property "
80                     "'camera.external.hal3TrebleMinorVersion', defaulting to 4",
81                     mPreferredHal3MinorVersion);
82             mPreferredHal3MinorVersion = 4;
83     }
84 }
85 
~ExternalCameraProviderImpl_2_4()86 ExternalCameraProviderImpl_2_4::~ExternalCameraProviderImpl_2_4() {
87     mHotPlugThread.requestExit();
88 }
89 
90 
setCallback(const sp<ICameraProviderCallback> & callback)91 Return<Status> ExternalCameraProviderImpl_2_4::setCallback(
92         const sp<ICameraProviderCallback>& callback) {
93     {
94         Mutex::Autolock _l(mLock);
95         mCallbacks = callback;
96     }
97     if (mCallbacks == nullptr) {
98         return Status::OK;
99     }
100     // Send a callback for all devices to initialize
101     {
102         for (const auto& pair : mCameraStatusMap) {
103             mCallbacks->cameraDeviceStatusChange(pair.first, pair.second);
104         }
105     }
106 
107     return Status::OK;
108 }
109 
getVendorTags(ICameraProvider::getVendorTags_cb _hidl_cb)110 Return<void> ExternalCameraProviderImpl_2_4::getVendorTags(
111         ICameraProvider::getVendorTags_cb _hidl_cb) {
112     // No vendor tag support for USB camera
113     hidl_vec<VendorTagSection> zeroSections;
114     _hidl_cb(Status::OK, zeroSections);
115     return Void();
116 }
117 
getCameraIdList(ICameraProvider::getCameraIdList_cb _hidl_cb)118 Return<void> ExternalCameraProviderImpl_2_4::getCameraIdList(
119         ICameraProvider::getCameraIdList_cb _hidl_cb) {
120     // External camera HAL always report 0 camera, and extra cameras
121     // are just reported via cameraDeviceStatusChange callbacks
122     hidl_vec<hidl_string> hidlDeviceNameList;
123     _hidl_cb(Status::OK, hidlDeviceNameList);
124     return Void();
125 }
126 
isSetTorchModeSupported(ICameraProvider::isSetTorchModeSupported_cb _hidl_cb)127 Return<void> ExternalCameraProviderImpl_2_4::isSetTorchModeSupported(
128         ICameraProvider::isSetTorchModeSupported_cb _hidl_cb) {
129     // setTorchMode API is supported, though right now no external camera device
130     // has a flash unit.
131     _hidl_cb (Status::OK, true);
132     return Void();
133 }
134 
getCameraDeviceInterface_V1_x(const hidl_string &,ICameraProvider::getCameraDeviceInterface_V1_x_cb _hidl_cb)135 Return<void> ExternalCameraProviderImpl_2_4::getCameraDeviceInterface_V1_x(
136         const hidl_string&,
137         ICameraProvider::getCameraDeviceInterface_V1_x_cb _hidl_cb) {
138     // External Camera HAL does not support HAL1
139     _hidl_cb(Status::OPERATION_NOT_SUPPORTED, nullptr);
140     return Void();
141 }
142 
getCameraDeviceInterface_V3_x(const hidl_string & cameraDeviceName,ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb)143 Return<void> ExternalCameraProviderImpl_2_4::getCameraDeviceInterface_V3_x(
144         const hidl_string& cameraDeviceName,
145         ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb) {
146 
147     std::string cameraId, deviceVersion;
148     bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
149     if (!match) {
150         _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
151         return Void();
152     }
153 
154     if (mCameraStatusMap.count(cameraDeviceName) == 0 ||
155             mCameraStatusMap[cameraDeviceName] != CameraDeviceStatus::PRESENT) {
156         _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
157         return Void();
158     }
159 
160     sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl;
161     switch (mPreferredHal3MinorVersion) {
162         case 4: {
163             ALOGV("Constructing v3.4 external camera device");
164             deviceImpl = new device::V3_4::implementation::ExternalCameraDevice(
165                     cameraId, mCfg);
166             break;
167         }
168         case 5: {
169             ALOGV("Constructing v3.5 external camera device");
170             deviceImpl = new device::V3_5::implementation::ExternalCameraDevice(
171                     cameraId, mCfg);
172             break;
173         }
174         default:
175             ALOGE("%s: Unknown HAL minor version %d!", __FUNCTION__, mPreferredHal3MinorVersion);
176             _hidl_cb(Status::INTERNAL_ERROR, nullptr);
177             return Void();
178     }
179 
180     if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
181         ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
182         _hidl_cb(Status::INTERNAL_ERROR, nullptr);
183         return Void();
184     }
185 
186     IF_ALOGV() {
187         deviceImpl->getInterface()->interfaceChain([](
188             ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
189                 ALOGV("Device interface chain:");
190                 for (auto iface : interfaceChain) {
191                     ALOGV("  %s", iface.c_str());
192                 }
193             });
194     }
195 
196     _hidl_cb (Status::OK, deviceImpl->getInterface());
197 
198     return Void();
199 }
200 
addExternalCamera(const char * devName)201 void ExternalCameraProviderImpl_2_4::addExternalCamera(const char* devName) {
202     ALOGI("ExtCam: adding %s to External Camera HAL!", devName);
203     Mutex::Autolock _l(mLock);
204     std::string deviceName;
205     if (mPreferredHal3MinorVersion == 5) {
206         deviceName = std::string("device@3.5/external/") + devName;
207     } else {
208         deviceName = std::string("device@3.4/external/") + devName;
209     }
210     mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
211     if (mCallbacks != nullptr) {
212         mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::PRESENT);
213     }
214 }
215 
deviceAdded(const char * devName)216 void ExternalCameraProviderImpl_2_4::deviceAdded(const char* devName) {
217     {
218         base::unique_fd fd(::open(devName, O_RDWR));
219         if (fd.get() < 0) {
220             ALOGE("%s open v4l2 device %s failed:%s", __FUNCTION__, devName, strerror(errno));
221             return;
222         }
223 
224         struct v4l2_capability capability;
225         int ret = ioctl(fd.get(), VIDIOC_QUERYCAP, &capability);
226         if (ret < 0) {
227             ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName);
228             return;
229         }
230 
231         if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) {
232             ALOGW("%s device %s does not support VIDEO_CAPTURE", __FUNCTION__, devName);
233             return;
234         }
235     }
236     // See if we can initialize ExternalCameraDevice correctly
237     sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl =
238             new device::V3_4::implementation::ExternalCameraDevice(devName, mCfg);
239     if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
240         ALOGW("%s: Attempt to init camera device %s failed!", __FUNCTION__, devName);
241         return;
242     }
243     deviceImpl.clear();
244 
245     addExternalCamera(devName);
246     return;
247 }
248 
deviceRemoved(const char * devName)249 void ExternalCameraProviderImpl_2_4::deviceRemoved(const char* devName) {
250     Mutex::Autolock _l(mLock);
251     std::string deviceName;
252     if (mPreferredHal3MinorVersion == 5) {
253         deviceName = std::string("device@3.5/external/") + devName;
254     } else {
255         deviceName = std::string("device@3.4/external/") + devName;
256     }
257     if (mCameraStatusMap.find(deviceName) != mCameraStatusMap.end()) {
258         mCameraStatusMap.erase(deviceName);
259         if (mCallbacks != nullptr) {
260             mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::NOT_PRESENT);
261         }
262     } else {
263         ALOGE("%s: cannot find camera device %s", __FUNCTION__, devName);
264     }
265 }
266 
HotplugThread(ExternalCameraProviderImpl_2_4 * parent)267 ExternalCameraProviderImpl_2_4::HotplugThread::HotplugThread(
268         ExternalCameraProviderImpl_2_4* parent) :
269         Thread(/*canCallJava*/false),
270         mParent(parent),
271         mInternalDevices(parent->mCfg.mInternalDevices) {}
272 
~HotplugThread()273 ExternalCameraProviderImpl_2_4::HotplugThread::~HotplugThread() {}
274 
threadLoop()275 bool ExternalCameraProviderImpl_2_4::HotplugThread::threadLoop() {
276     // Find existing /dev/video* devices
277     DIR* devdir = opendir(kDevicePath);
278     if(devdir == 0) {
279         ALOGE("%s: cannot open %s! Exiting threadloop", __FUNCTION__, kDevicePath);
280         return false;
281     }
282 
283     struct dirent* de;
284     while ((de = readdir(devdir)) != 0) {
285         // Find external v4l devices that's existing before we start watching and add them
286         if (!strncmp(kPrefix, de->d_name, kPrefixLen)) {
287             // TODO: This might reject some valid devices. Ex: internal is 33 and a device named 3
288             //       is added.
289             std::string deviceId(de->d_name + kPrefixLen);
290             if (mInternalDevices.count(deviceId) == 0) {
291                 ALOGV("Non-internal v4l device %s found", de->d_name);
292                 char v4l2DevicePath[kMaxDevicePathLen];
293                 snprintf(v4l2DevicePath, kMaxDevicePathLen,
294                         "%s%s", kDevicePath, de->d_name);
295                 mParent->deviceAdded(v4l2DevicePath);
296             }
297         }
298     }
299     closedir(devdir);
300 
301     // Watch new video devices
302     mINotifyFD = inotify_init();
303     if (mINotifyFD < 0) {
304         ALOGE("%s: inotify init failed! Exiting threadloop", __FUNCTION__);
305         return true;
306     }
307 
308     mWd = inotify_add_watch(mINotifyFD, kDevicePath, IN_CREATE | IN_DELETE);
309     if (mWd < 0) {
310         ALOGE("%s: inotify add watch failed! Exiting threadloop", __FUNCTION__);
311         return true;
312     }
313 
314     ALOGI("%s start monitoring new V4L2 devices", __FUNCTION__);
315 
316     bool done = false;
317     char eventBuf[512];
318     while (!done) {
319         int offset = 0;
320         int ret = read(mINotifyFD, eventBuf, sizeof(eventBuf));
321         if (ret >= (int)sizeof(struct inotify_event)) {
322             while (offset < ret) {
323                 struct inotify_event* event = (struct inotify_event*)&eventBuf[offset];
324                 if (event->wd == mWd) {
325                     if (!strncmp(kPrefix, event->name, kPrefixLen)) {
326                         std::string deviceId(event->name + kPrefixLen);
327                         if (mInternalDevices.count(deviceId) == 0) {
328                             char v4l2DevicePath[kMaxDevicePathLen];
329                             snprintf(v4l2DevicePath, kMaxDevicePathLen,
330                                     "%s%s", kDevicePath, event->name);
331                             if (event->mask & IN_CREATE) {
332                                 mParent->deviceAdded(v4l2DevicePath);
333                             }
334                             if (event->mask & IN_DELETE) {
335                                 mParent->deviceRemoved(v4l2DevicePath);
336                             }
337                         }
338                     }
339                 }
340                 offset += sizeof(struct inotify_event) + event->len;
341             }
342         }
343     }
344 
345     return true;
346 }
347 
348 }  // namespace implementation
349 }  // namespace V2_4
350 }  // namespace provider
351 }  // namespace camera
352 }  // namespace hardware
353 }  // namespace android
354