• 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 <cutils/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);
316 
317         // Parse the 'name', 'framedims', and 'dir' tokens.
318         char *name, *frameDims, *dir;
319         if (getTokenValue(kListNameToken, cameraStr, &name) &&
320                 getTokenValue(kListDimsToken, cameraStr, &frameDims) &&
321                 getTokenValue(kListDirToken, cameraStr, &dir)) {
322             // Push the camera info if it was all successfully parsed.
323             qemuCameras->push_back(QemuCameraInfo{
324                 .name = name,
325                 .frameDims = frameDims,
326                 .dir = dir,
327             });
328         } else {
329             ALOGW("%s: Bad camera information: %s", __FUNCTION__,
330                     cameraStr.c_str());
331         }
332         // Skip over the newline for the beginning of the next line.
333         lineBegin = lineEnd + 1;
334         lineEnd = cameraListStr.find('\n', lineBegin);
335     }
336 }
337 
createQemuCameras(const std::vector<QemuCameraInfo> & qemuCameras)338 void EmulatedCameraFactory::createQemuCameras(
339         const std::vector<QemuCameraInfo> &qemuCameras) {
340     /*
341      * Iterate the list, creating, and initializing emulated QEMU cameras for each
342      * entry in the list.
343      */
344 
345     /*
346      * We use this index only for determining which direction the webcam should
347      * face. Otherwise, mEmulatedCameraNum represents the camera ID and the
348      * index into mEmulatedCameras.
349      */
350     int qemuIndex = 0;
351     for (const auto &cameraInfo : qemuCameras) {
352         /*
353          * Here, we're assuming the first webcam is intended to be the back
354          * camera and any other webcams are front cameras.
355          */
356         int halVersion = 0;
357         if (qemuIndex == 0) {
358             halVersion = getCameraHalVersion(/* backCamera */ true);
359         } else {
360             halVersion = getCameraHalVersion(/* backCamera */ false);
361         }
362 
363         // Create and initialize QEMU camera.
364         EmulatedBaseCamera *qemuCam = nullptr;
365         status_t res;
366         switch (halVersion) {
367             case 1:
368                 EmulatedQemuCamera *qemuCamOne;
369                 qemuCamOne = new EmulatedQemuCamera(
370                         mEmulatedCameraNum, &HAL_MODULE_INFO_SYM.common);
371                 if (qemuCamOne == nullptr) {
372                     ALOGE("%s: Unable to instantiate EmulatedQemuCamera",
373                             __FUNCTION__);
374                 } else {
375                     /*
376                      * We have to initialize in each switch case, because
377                      * EmulatedBaseCamera::Initialize has a different method
378                      * signature.
379                      *
380                      * TODO: Having an EmulatedBaseQemuCamera class
381                      * could fix this issue.
382                      */
383                     res = qemuCamOne->Initialize(
384                             cameraInfo.name,
385                             cameraInfo.frameDims,
386                             cameraInfo.dir);
387                 }
388                 qemuCam = qemuCamOne;
389                 break;
390             case 2:
391                 ALOGE("%s: QEMU support for camera hal version %d is not "
392                         "implemented", __FUNCTION__, halVersion);
393                 break;
394             case 3:
395                 EmulatedQemuCamera3 *qemuCamThree;
396                 qemuCamThree = new EmulatedQemuCamera3(
397                         mEmulatedCameraNum, &HAL_MODULE_INFO_SYM.common);
398                 if (qemuCamThree == nullptr) {
399                     ALOGE("%s: Unable to instantiate EmulatedQemuCamera3",
400                             __FUNCTION__);
401                 } else {
402                     res = qemuCamThree->Initialize(
403                             cameraInfo.name,
404                             cameraInfo.frameDims,
405                             cameraInfo.dir);
406                 }
407                 qemuCam = qemuCamThree;
408                 break;
409             default:
410                 ALOGE("%s: Unknown camera hal version requested: %d",
411                         __FUNCTION__, halVersion);
412         }
413 
414         if (qemuCam == nullptr) {
415             ALOGE("%s: Unable to instantiate EmulatedQemuCamera",
416                     __FUNCTION__);
417         } else {
418             if (res == NO_ERROR) {
419                 mEmulatedCameras[mEmulatedCameraNum] = qemuCam;
420                 qemuIndex++;
421                 mEmulatedCameraNum++;
422             } else {
423                 delete qemuCam;
424             }
425         }
426     }
427 }
428 
createFakeCamera(bool backCamera)429 void EmulatedCameraFactory::createFakeCamera(bool backCamera) {
430     int halVersion = getCameraHalVersion(backCamera);
431 
432     /*
433      * Create and initialize the fake camera, using the index into
434      * mEmulatedCameras as the camera ID.
435      */
436     switch (halVersion) {
437         case 1:
438             mEmulatedCameras[mEmulatedCameraNum] =
439                     new EmulatedFakeCamera(mEmulatedCameraNum, backCamera,
440                             &HAL_MODULE_INFO_SYM.common);
441             break;
442         case 2:
443             mEmulatedCameras[mEmulatedCameraNum] =
444                     new EmulatedFakeCamera2(mEmulatedCameraNum, backCamera,
445                             &HAL_MODULE_INFO_SYM.common);
446             break;
447         case 3:
448             {
449                 const char *key = "ro.kernel.qemu.camera.fake.rotating";
450                 char prop[PROPERTY_VALUE_MAX];
451                 if (property_get(key, prop, nullptr) > 0) {
452                     mEmulatedCameras[mEmulatedCameraNum] =
453                         new EmulatedFakeCamera(mEmulatedCameraNum, backCamera,
454                                 &HAL_MODULE_INFO_SYM.common);
455                 } else {
456                     mEmulatedCameras[mEmulatedCameraNum] =
457                         new EmulatedFakeCamera3(mEmulatedCameraNum, backCamera,
458                                 &HAL_MODULE_INFO_SYM.common);
459                 }
460             }
461             break;
462         default:
463             ALOGE("%s: Unknown %s camera hal version requested: %d",
464                     __FUNCTION__, backCamera ? "back" : "front", halVersion);
465     }
466 
467     if (mEmulatedCameras[mEmulatedCameraNum] == nullptr) {
468         ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__);
469     } else {
470         ALOGV("%s: %s camera device version is %d", __FUNCTION__,
471                 backCamera ? "Back" : "Front", halVersion);
472         status_t res = mEmulatedCameras[mEmulatedCameraNum]->Initialize();
473         if (res == NO_ERROR) {
474             // Camera creation and initialization was successful.
475             mEmulatedCameraNum++;
476         } else {
477             ALOGE("%s: Unable to initialize %s camera %d: %s (%d)",
478                     __FUNCTION__, backCamera ? "back" : "front",
479                     mEmulatedCameraNum, strerror(-res), res);
480             delete mEmulatedCameras[mEmulatedCameraNum];
481         }
482     }
483 }
484 
waitForQemuSfFakeCameraPropertyAvailable()485 void EmulatedCameraFactory::waitForQemuSfFakeCameraPropertyAvailable() {
486     /*
487      * Camera service may start running before qemu-props sets
488      * qemu.sf.fake_camera to any of the follwing four values:
489      * "none,front,back,both"; so we need to wait.
490      *
491      * android/camera/camera-service.c
492      * bug: 30768229
493      */
494     int numAttempts = 100;
495     char prop[PROPERTY_VALUE_MAX];
496     bool timeout = true;
497     for (int i = 0; i < numAttempts; ++i) {
498         if (property_get("qemu.sf.fake_camera", prop, nullptr) != 0 ) {
499             timeout = false;
500             break;
501         }
502         usleep(5000);
503     }
504     if (timeout) {
505         ALOGE("timeout (%dms) waiting for property qemu.sf.fake_camera to be set\n", 5 * numAttempts);
506     }
507 }
508 
isFakeCameraEmulationOn(bool backCamera)509 bool EmulatedCameraFactory::isFakeCameraEmulationOn(bool backCamera) {
510     /*
511      * Defined by 'qemu.sf.fake_camera' boot property. If the property exists,
512      * and if it's set to 'both', then fake cameras are used to emulate both
513      * sides. If it's set to 'back' or 'front', then a fake camera is used only
514      * to emulate the back or front camera, respectively.
515      */
516     char prop[PROPERTY_VALUE_MAX];
517     if ((property_get("qemu.sf.fake_camera", prop, nullptr) > 0) &&
518         (!strcmp(prop, "both") ||
519          !strcmp(prop, backCamera ? "back" : "front"))) {
520         return true;
521     } else {
522         return false;
523     }
524 }
525 
getCameraHalVersion(bool backCamera)526 int EmulatedCameraFactory::getCameraHalVersion(bool backCamera) {
527     /*
528      * Defined by 'qemu.sf.front_camera_hal_version' and
529      * 'qemu.sf.back_camera_hal_version' boot properties. If the property
530      * doesn't exist, it is assumed we are working with HAL v1.
531      */
532     char prop[PROPERTY_VALUE_MAX];
533     const char *propQuery = backCamera ?
534             "qemu.sf.back_camera_hal" :
535             "qemu.sf.front_camera_hal";
536     if (property_get(propQuery, prop, nullptr) > 0) {
537         char *propEnd = prop;
538         int val = strtol(prop, &propEnd, 10);
539         if (*propEnd == '\0') {
540             return val;
541         }
542         // Badly formatted property. It should just be a number.
543         ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop);
544     }
545     return 3;
546 }
547 
onStatusChanged(int cameraId,int newStatus)548 void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus) {
549 
550     EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
551     if (!cam) {
552         ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
553         return;
554     }
555 
556     /*
557      * (Order is important)
558      * Send the callback first to framework, THEN close the camera.
559      */
560 
561     if (newStatus == cam->getHotplugStatus()) {
562         ALOGW("%s: Ignoring transition to the same status", __FUNCTION__);
563         return;
564     }
565 
566     const camera_module_callbacks_t* cb = mCallbacks;
567     if (cb != nullptr && cb->camera_device_status_change != nullptr) {
568         cb->camera_device_status_change(cb, cameraId, newStatus);
569     }
570 
571     if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
572         cam->unplugCamera();
573     } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) {
574         cam->plugCamera();
575     }
576 }
577 
578 /********************************************************************************
579  * Initializer for the static member structure.
580  *******************************************************************************/
581 
582 // Entry point for camera HAL API.
583 struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
584     open: EmulatedCameraFactory::device_open
585 };
586 
587 }; // end of namespace android
588