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