• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 /*
18  * Contains implementation of a class EmulatedCameraFactory that manages cameras
19  * available for emulation.
20  */
21 
22 //#define LOG_NDEBUG 0
23 #define LOG_TAG "EmulatedCamera_Factory"
24 
25 #include "EmulatedCameraFactory.h"
26 #include "EmulatedCameraHotplugThread.h"
27 #include "EmulatedFakeCamera.h"
28 #include "EmulatedFakeCamera2.h"
29 #include "EmulatedFakeCamera3.h"
30 #include "EmulatedQemuCamera.h"
31 #include "EmulatedQemuCamera3.h"
32 
33 #include <log/log.h>
34 #include <cutils/properties.h>
35 
36 extern camera_module_t HAL_MODULE_INFO_SYM;
37 
38 /*
39  * A global instance of EmulatedCameraFactory is statically instantiated and
40  * initialized when camera emulation HAL is loaded.
41  */
42 android::EmulatedCameraFactory gEmulatedCameraFactory;
43 
44 namespace android {
45 
EmulatedCameraFactory()46 EmulatedCameraFactory::EmulatedCameraFactory() :
47         mQemuClient(),
48         mEmulatedCameras(nullptr),
49         mEmulatedCameraNum(0),
50         mFakeCameraNum(0),
51         mConstructedOK(false),
52         mCallbacks(nullptr) {
53 
54     /*
55      * Figure out how many cameras need to be created, so we can allocate the
56      * array of emulated cameras before populating it.
57      */
58     int emulatedCamerasSize = 0;
59 
60     // QEMU Cameras
61     std::vector<QemuCameraInfo> qemuCameras;
62     if (mQemuClient.connectClient(nullptr) == NO_ERROR) {
63         findQemuCameras(&qemuCameras);
64         emulatedCamerasSize += qemuCameras.size();
65     }
66 
67     waitForQemuSfFakeCameraPropertyAvailable();
68     // Fake Cameras
69     if (isFakeCameraEmulationOn(/* backCamera */ true)) {
70         mFakeCameraNum++;
71     }
72     if (isFakeCameraEmulationOn(/* backCamera */ false)) {
73         mFakeCameraNum++;
74     }
75     emulatedCamerasSize += mFakeCameraNum;
76 
77     /*
78      * We have the number of cameras we need to create, now allocate space for
79      * them.
80      */
81     mEmulatedCameras = new EmulatedBaseCamera*[emulatedCamerasSize];
82     if (mEmulatedCameras == nullptr) {
83         ALOGE("%s: Unable to allocate emulated camera array for %d entries",
84                 __FUNCTION__, mEmulatedCameraNum);
85         return;
86     }
87 
88     createQemuCameras(qemuCameras);
89 
90     // Create fake cameras, if enabled.
91     if (isFakeCameraEmulationOn(/* backCamera */ true)) {
92         createFakeCamera(/* backCamera */ true);
93     }
94     if (isFakeCameraEmulationOn(/* backCamera */ false)) {
95         createFakeCamera(/* backCamera */ false);
96     }
97 
98     ALOGE("%d cameras are being emulated. %d of them are fake cameras.",
99             mEmulatedCameraNum, mFakeCameraNum);
100 
101     // Create hotplug thread.
102     {
103         Vector<int> cameraIdVector;
104         for (int i = 0; i < mEmulatedCameraNum; ++i) {
105             cameraIdVector.push_back(i);
106         }
107         mHotplugThread = new EmulatedCameraHotplugThread(&cameraIdVector[0],
108                                                          mEmulatedCameraNum);
109         mHotplugThread->run("EmulatedCameraHotplugThread");
110     }
111 
112     mConstructedOK = true;
113 }
114 
~EmulatedCameraFactory()115 EmulatedCameraFactory::~EmulatedCameraFactory() {
116     if (mEmulatedCameras != nullptr) {
117         for (int n = 0; n < mEmulatedCameraNum; n++) {
118             if (mEmulatedCameras[n] != nullptr) {
119                 delete mEmulatedCameras[n];
120             }
121         }
122         delete[] mEmulatedCameras;
123     }
124 
125     if (mHotplugThread != nullptr) {
126         mHotplugThread->requestExit();
127         mHotplugThread->join();
128     }
129 }
130 
131 /******************************************************************************
132  * Camera HAL API handlers.
133  *
134  * Each handler simply verifies existence of an appropriate EmulatedBaseCamera
135  * instance, and dispatches the call to that instance.
136  *
137  *****************************************************************************/
138 
cameraDeviceOpen(int cameraId,hw_device_t ** device)139 int EmulatedCameraFactory::cameraDeviceOpen(int cameraId,
140                                             hw_device_t **device) {
141     ALOGV("%s: id = %d", __FUNCTION__, cameraId);
142 
143     *device = nullptr;
144 
145     if (!isConstructedOK()) {
146         ALOGE("%s: EmulatedCameraFactory has failed to initialize",
147                 __FUNCTION__);
148         return -EINVAL;
149     }
150 
151     if (cameraId < 0 || cameraId >= getEmulatedCameraNum()) {
152         ALOGE("%s: Camera id %d is out of bounds (%d)",
153                 __FUNCTION__, cameraId, getEmulatedCameraNum());
154         return -ENODEV;
155     }
156 
157     return mEmulatedCameras[cameraId]->connectCamera(device);
158 }
159 
getCameraInfo(int cameraId,struct camera_info * info)160 int EmulatedCameraFactory::getCameraInfo(int cameraId,
161                                          struct camera_info *info) {
162     ALOGV("%s: id = %d", __FUNCTION__, cameraId);
163 
164     if (!isConstructedOK()) {
165         ALOGE("%s: EmulatedCameraFactory has failed to initialize",
166                 __FUNCTION__);
167         return -EINVAL;
168     }
169 
170     if (cameraId < 0 || cameraId >= getEmulatedCameraNum()) {
171         ALOGE("%s: Camera id %d is out of bounds (%d)",
172                 __FUNCTION__, cameraId, getEmulatedCameraNum());
173         return -ENODEV;
174     }
175 
176     return mEmulatedCameras[cameraId]->getCameraInfo(info);
177 }
178 
setCallbacks(const camera_module_callbacks_t * callbacks)179 int EmulatedCameraFactory::setCallbacks(
180         const camera_module_callbacks_t *callbacks) {
181     ALOGV("%s: callbacks = %p", __FUNCTION__, callbacks);
182 
183     mCallbacks = callbacks;
184 
185     return OK;
186 }
187 
getVendorTagOps(vendor_tag_ops_t * ops)188 void EmulatedCameraFactory::getVendorTagOps(vendor_tag_ops_t* ops) {
189     ALOGV("%s: ops = %p", __FUNCTION__, ops);
190     // No vendor tags defined for emulator yet, so not touching ops.
191 }
192 
193 /****************************************************************************
194  * Camera HAL API callbacks.
195  ***************************************************************************/
196 
device_open(const hw_module_t * module,const char * name,hw_device_t ** device)197 int EmulatedCameraFactory::device_open(const hw_module_t *module, const char
198         *name, hw_device_t **device) {
199     /*
200      * Simply verify the parameters, and dispatch the call inside the
201      * EmulatedCameraFactory instance.
202      */
203 
204     if (module != &HAL_MODULE_INFO_SYM.common) {
205         ALOGE("%s: Invalid module %p expected %p",
206                 __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common);
207         return -EINVAL;
208     }
209     if (name == nullptr) {
210         ALOGE("%s: NULL name is not expected here", __FUNCTION__);
211         return -EINVAL;
212     }
213 
214     return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device);
215 }
216 
get_number_of_cameras()217 int EmulatedCameraFactory::get_number_of_cameras() {
218     return gEmulatedCameraFactory.getEmulatedCameraNum();
219 }
220 
get_camera_info(int camera_id,struct camera_info * info)221 int EmulatedCameraFactory::get_camera_info(int camera_id,
222                         struct camera_info *info) {
223     return gEmulatedCameraFactory.getCameraInfo(camera_id, info);
224 }
225 
set_callbacks(const camera_module_callbacks_t * callbacks)226 int EmulatedCameraFactory::set_callbacks(
227         const camera_module_callbacks_t *callbacks) {
228     return gEmulatedCameraFactory.setCallbacks(callbacks);
229 }
230 
get_vendor_tag_ops(vendor_tag_ops_t * ops)231 void EmulatedCameraFactory::get_vendor_tag_ops(vendor_tag_ops_t *ops) {
232     gEmulatedCameraFactory.getVendorTagOps(ops);
233 }
234 
open_legacy(const struct hw_module_t * module,const char * id,uint32_t halVersion,struct hw_device_t ** device)235 int EmulatedCameraFactory::open_legacy(const struct hw_module_t *module,
236         const char *id, uint32_t halVersion, struct hw_device_t **device) {
237     // Not supporting legacy open.
238     return -ENOSYS;
239 }
240 
241 /********************************************************************************
242  * Internal API
243  *******************************************************************************/
244 
245 /*
246  * Camera information tokens passed in response to the "list" factory query.
247  */
248 
249 // Device name token.
250 static const char *kListNameToken = "name=";
251 // Frame dimensions token.
252 static const char *kListDimsToken = "framedims=";
253 // Facing direction token.
254 static const char *kListDirToken = "dir=";
255 
256 
getTokenValue(const char * token,const std::string & s,char ** value)257 bool EmulatedCameraFactory::getTokenValue(const char *token,
258         const std::string &s, char **value) {
259     // Find the start of the token.
260     size_t tokenStart = s.find(token);
261     if (tokenStart == std::string::npos) {
262         return false;
263     }
264 
265     // Advance to the beginning of the token value.
266     size_t valueStart = tokenStart + strlen(token);
267 
268     // Find the length of the token value.
269     size_t valueLength = s.find(' ', valueStart) - valueStart;
270 
271     // Extract the value substring.
272     std::string valueStr = s.substr(valueStart, valueLength);
273 
274     // Convert to char*.
275     *value = new char[valueStr.length() + 1];
276     if (*value == nullptr) {
277         return false;
278     }
279     strcpy(*value, valueStr.c_str());
280 
281     ALOGV("%s: Parsed value is \"%s\"", __FUNCTION__, *value);
282 
283     return true;
284 }
285 
findQemuCameras(std::vector<QemuCameraInfo> * qemuCameras)286 void EmulatedCameraFactory::findQemuCameras(
287         std::vector<QemuCameraInfo> *qemuCameras) {
288     // Obtain camera list.
289     char *cameraList = nullptr;
290     status_t res = mQemuClient.listCameras(&cameraList);
291 
292     /*
293      * Empty list, or list containing just an EOL means that there were no
294      * connected cameras found.
295      */
296     if (res != NO_ERROR || cameraList == nullptr || *cameraList == '\0' ||
297         *cameraList == '\n') {
298         if (cameraList != nullptr) {
299             free(cameraList);
300         }
301         return;
302     }
303 
304     /*
305      * Calculate number of connected cameras. Number of EOLs in the camera list
306      * is the number of the connected cameras.
307      */
308 
309     std::string cameraListStr(cameraList);
310     free(cameraList);
311 
312     size_t lineBegin = 0;
313     size_t lineEnd = cameraListStr.find('\n');
314     while (lineEnd != std::string::npos) {
315         std::string cameraStr = cameraListStr.substr(lineBegin, lineEnd - lineBegin);
316         // Parse the 'name', 'framedims', and 'dir' tokens.
317         char *name, *frameDims, *dir;
318         if (getTokenValue(kListNameToken, cameraStr, &name) &&
319                 getTokenValue(kListDimsToken, cameraStr, &frameDims) &&
320                 getTokenValue(kListDirToken, cameraStr, &dir)) {
321             // Push the camera info if it was all successfully parsed.
322             qemuCameras->push_back(QemuCameraInfo{
323                 .name = name,
324                 .frameDims = frameDims,
325                 .dir = dir,
326             });
327         } else {
328             ALOGW("%s: Bad camera information: %s", __FUNCTION__,
329                     cameraStr.c_str());
330         }
331         // Skip over the newline for the beginning of the next line.
332         lineBegin = lineEnd + 1;
333         lineEnd = cameraListStr.find('\n', lineBegin);
334     }
335 }
336 
createQemuCameras(const std::vector<QemuCameraInfo> & qemuCameras)337 void EmulatedCameraFactory::createQemuCameras(
338         const std::vector<QemuCameraInfo> &qemuCameras) {
339     /*
340      * Iterate the list, creating, and initializing emulated QEMU cameras for each
341      * entry in the list.
342      */
343 
344     /*
345      * We use this index only for determining which direction the webcam should
346      * face. Otherwise, mEmulatedCameraNum represents the camera ID and the
347      * index into mEmulatedCameras.
348      */
349     int qemuIndex = 0;
350     for (const auto &cameraInfo : qemuCameras) {
351         /*
352          * Here, we're assuming the first webcam is intended to be the back
353          * camera and any other webcams are front cameras.
354          */
355         int halVersion = 0;
356         if (qemuIndex == 0) {
357             halVersion = getCameraHalVersion(/* backCamera */ true);
358         } else {
359             halVersion = getCameraHalVersion(/* backCamera */ false);
360         }
361 
362         // Create and initialize QEMU camera.
363         EmulatedBaseCamera *qemuCam = nullptr;
364         status_t res;
365         switch (halVersion) {
366             case 1:
367                 EmulatedQemuCamera *qemuCamOne;
368                 qemuCamOne = new EmulatedQemuCamera(
369                         mEmulatedCameraNum, &HAL_MODULE_INFO_SYM.common);
370                 if (qemuCamOne == nullptr) {
371                     ALOGE("%s: Unable to instantiate EmulatedQemuCamera",
372                             __FUNCTION__);
373                 } else {
374                     /*
375                      * We have to initialize in each switch case, because
376                      * EmulatedBaseCamera::Initialize has a different method
377                      * signature.
378                      *
379                      * TODO: Having an EmulatedBaseQemuCamera class
380                      * could fix this issue.
381                      */
382                     res = qemuCamOne->Initialize(
383                             cameraInfo.name,
384                             cameraInfo.frameDims,
385                             cameraInfo.dir);
386                 }
387                 qemuCam = qemuCamOne;
388                 break;
389             case 2:
390                 ALOGE("%s: QEMU support for camera hal version %d is not "
391                         "implemented", __FUNCTION__, halVersion);
392                 break;
393             case 3:
394                 EmulatedQemuCamera3 *qemuCamThree;
395                 qemuCamThree = new EmulatedQemuCamera3(
396                         mEmulatedCameraNum, &HAL_MODULE_INFO_SYM.common);
397                 if (qemuCamThree == nullptr) {
398                     ALOGE("%s: Unable to instantiate EmulatedQemuCamera3",
399                             __FUNCTION__);
400                 } else {
401                     res = qemuCamThree->Initialize(
402                             cameraInfo.name,
403                             cameraInfo.frameDims,
404                             cameraInfo.dir);
405                 }
406                 qemuCam = qemuCamThree;
407                 break;
408             default:
409                 ALOGE("%s: Unknown camera hal version requested: %d",
410                         __FUNCTION__, halVersion);
411         }
412 
413         if (qemuCam == nullptr) {
414             ALOGE("%s: Unable to instantiate EmulatedQemuCamera",
415                     __FUNCTION__);
416         } else {
417             if (res == NO_ERROR) {
418                 mEmulatedCameras[mEmulatedCameraNum] = qemuCam;
419                 qemuIndex++;
420                 mEmulatedCameraNum++;
421             } else {
422                 delete qemuCam;
423             }
424         }
425     }
426 }
427 
createFakeCamera(bool backCamera)428 void EmulatedCameraFactory::createFakeCamera(bool backCamera) {
429     int halVersion = getCameraHalVersion(backCamera);
430 
431     /*
432      * Create and initialize the fake camera, using the index into
433      * mEmulatedCameras as the camera ID.
434      */
435     switch (halVersion) {
436         case 1:
437             mEmulatedCameras[mEmulatedCameraNum] =
438                     new EmulatedFakeCamera(mEmulatedCameraNum, backCamera,
439                             &HAL_MODULE_INFO_SYM.common);
440             break;
441         case 2:
442             mEmulatedCameras[mEmulatedCameraNum] =
443                     new EmulatedFakeCamera2(mEmulatedCameraNum, backCamera,
444                             &HAL_MODULE_INFO_SYM.common);
445             break;
446         case 3:
447             {
448                 const char *key = "ro.kernel.qemu.camera.fake.rotating";
449                 char prop[PROPERTY_VALUE_MAX];
450                 if (property_get(key, prop, nullptr) > 0) {
451                     mEmulatedCameras[mEmulatedCameraNum] =
452                         new EmulatedFakeCamera(mEmulatedCameraNum, backCamera,
453                                 &HAL_MODULE_INFO_SYM.common);
454                 } else {
455                     mEmulatedCameras[mEmulatedCameraNum] =
456                         new EmulatedFakeCamera3(mEmulatedCameraNum, backCamera,
457                                 &HAL_MODULE_INFO_SYM.common);
458                 }
459             }
460             break;
461         default:
462             ALOGE("%s: Unknown %s camera hal version requested: %d",
463                     __FUNCTION__, backCamera ? "back" : "front", halVersion);
464     }
465 
466     if (mEmulatedCameras[mEmulatedCameraNum] == nullptr) {
467         ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__);
468     } else {
469         ALOGV("%s: %s camera device version is %d", __FUNCTION__,
470                 backCamera ? "Back" : "Front", halVersion);
471         status_t res = mEmulatedCameras[mEmulatedCameraNum]->Initialize();
472         if (res == NO_ERROR) {
473             // Camera creation and initialization was successful.
474             mEmulatedCameraNum++;
475         } else {
476             ALOGE("%s: Unable to initialize %s camera %d: %s (%d)",
477                     __FUNCTION__, backCamera ? "back" : "front",
478                     mEmulatedCameraNum, strerror(-res), res);
479             delete mEmulatedCameras[mEmulatedCameraNum];
480         }
481     }
482 }
483 
waitForQemuSfFakeCameraPropertyAvailable()484 void EmulatedCameraFactory::waitForQemuSfFakeCameraPropertyAvailable() {
485     /*
486      * Camera service may start running before qemu-props sets
487      * qemu.sf.fake_camera to any of the follwing four values:
488      * "none,front,back,both"; so we need to wait.
489      *
490      * android/camera/camera-service.c
491      * bug: 30768229
492      */
493     int numAttempts = 100;
494     char prop[PROPERTY_VALUE_MAX];
495     bool timeout = true;
496     for (int i = 0; i < numAttempts; ++i) {
497         if (property_get("qemu.sf.fake_camera", prop, nullptr) != 0 ) {
498             timeout = false;
499             break;
500         }
501         usleep(5000);
502     }
503     if (timeout) {
504         ALOGE("timeout (%dms) waiting for property qemu.sf.fake_camera to be set\n", 5 * numAttempts);
505     }
506 }
507 
isFakeCameraEmulationOn(bool backCamera)508 bool EmulatedCameraFactory::isFakeCameraEmulationOn(bool backCamera) {
509     /*
510      * Defined by 'qemu.sf.fake_camera' boot property. If the property exists,
511      * and if it's set to 'both', then fake cameras are used to emulate both
512      * sides. If it's set to 'back' or 'front', then a fake camera is used only
513      * to emulate the back or front camera, respectively.
514      */
515     char prop[PROPERTY_VALUE_MAX];
516     if ((property_get("qemu.sf.fake_camera", prop, nullptr) > 0) &&
517         (!strcmp(prop, "both") ||
518          !strcmp(prop, backCamera ? "back" : "front"))) {
519         return true;
520     } else {
521         return false;
522     }
523 }
524 
getCameraHalVersion(bool backCamera)525 int EmulatedCameraFactory::getCameraHalVersion(bool backCamera) {
526     /*
527      * Defined by 'qemu.sf.front_camera_hal_version' and
528      * 'qemu.sf.back_camera_hal_version' boot properties. If the property
529      * doesn't exist, it is assumed we are working with HAL v1.
530      */
531     char prop[PROPERTY_VALUE_MAX];
532     const char *propQuery = backCamera ?
533             "qemu.sf.back_camera_hal" :
534             "qemu.sf.front_camera_hal";
535     if (property_get(propQuery, prop, nullptr) > 0) {
536         char *propEnd = prop;
537         int val = strtol(prop, &propEnd, 10);
538         if (*propEnd == '\0') {
539             return val;
540         }
541         // Badly formatted property. It should just be a number.
542         ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop);
543     }
544     return 3;
545 }
546 
onStatusChanged(int cameraId,int newStatus)547 void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus) {
548 
549     EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
550     if (!cam) {
551         ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
552         return;
553     }
554 
555     /*
556      * (Order is important)
557      * Send the callback first to framework, THEN close the camera.
558      */
559 
560     if (newStatus == cam->getHotplugStatus()) {
561         ALOGW("%s: Ignoring transition to the same status", __FUNCTION__);
562         return;
563     }
564 
565     const camera_module_callbacks_t* cb = mCallbacks;
566     if (cb != nullptr && cb->camera_device_status_change != nullptr) {
567         cb->camera_device_status_change(cb, cameraId, newStatus);
568     }
569 
570     if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
571         cam->unplugCamera();
572     } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) {
573         cam->plugCamera();
574     }
575 }
576 
577 /********************************************************************************
578  * Initializer for the static member structure.
579  *******************************************************************************/
580 
581 // Entry point for camera HAL API.
582 struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
583     .open = EmulatedCameraFactory::device_open
584 };
585 
586 }; // end of namespace android
587