blob: 3d36bef0d32646e0384ea095f9db15aba6471eb2 [file] [log] [blame]
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001/*
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 CameraFactory that manages cameras
19 * available
20 */
21
22#define LOG_NDEBUG 0
Andres Rodriguez937775c2012-04-19 23:38:00 +080023#define CONFIG_FILE "/etc/camera.cfg"
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080024#define LOG_TAG "Camera_Factory"
Andres Rodriguez937775c2012-04-19 23:38:00 +080025
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080026#include <cutils/log.h>
27#include <cutils/properties.h>
28#include "CameraFactory.h"
29
30extern camera_module_t HAL_MODULE_INFO_SYM;
31
32/* A global instance of CameraFactory is statically instantiated and
33 * initialized when camera HAL is loaded.
34 */
35android::CameraFactory gCameraFactory;
36
37namespace android {
38
Andres Rodriguez937775c2012-04-19 23:38:00 +080039CameraFactory::CameraFactory()
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080040{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +080041 ALOGD("CameraFactory::CameraFactory");
Andres Rodriguez937775c2012-04-19 23:38:00 +080042 mCamera = NULL;
43 mCameraDevices = NULL;
Alberto Panizzobbbfb372013-07-06 18:23:53 +020044 mCameraFacing = NULL;
Andres Rodriguez937775c2012-04-19 23:38:00 +080045 mCameraOrientation = NULL;
46 parseConfig(CONFIG_FILE);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080047}
48
49CameraFactory::~CameraFactory()
50{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +080051 ALOGD("CameraFactory::~CameraFactory");
Andres Rodriguez937775c2012-04-19 23:38:00 +080052 for (int i=0; i < getCameraNum(); i++) {
53 delete mCamera[i];
Chih-Wei Huang3aeaabb2019-03-22 15:29:19 +080054 free(mCameraDevices[i]);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080055 }
Andres Rodriguez937775c2012-04-19 23:38:00 +080056 free(mCamera);
Chih-Wei Huang3aeaabb2019-03-22 15:29:19 +080057 free(mCameraDevices);
58 free(mCameraFacing);
59 free(mCameraOrientation);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080060}
61
62/****************************************************************************
63 * Camera HAL API handlers.
64 *
65 * Each handler simply verifies existence of an appropriate Camera
66 * instance, and dispatches the call to that instance.
67 *
68 ***************************************************************************/
69
70int CameraFactory::cameraDeviceOpen(const hw_module_t* module,int camera_id, hw_device_t** device)
71{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +080072 ALOGD("CameraFactory::cameraDeviceOpen: id = %d", camera_id);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080073
74 *device = NULL;
75
Andres Rodriguez937775c2012-04-19 23:38:00 +080076 if (!mCamera || camera_id < 0 || camera_id >= getCameraNum()) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +080077 ALOGE("%s: Camera id %d is out of bounds (%d)",
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080078 __FUNCTION__, camera_id, getCameraNum());
79 return -EINVAL;
80 }
81
Andres Rodriguez937775c2012-04-19 23:38:00 +080082 if (!mCamera[camera_id]) {
83 mCamera[camera_id] = new CameraHardware(module, mCameraDevices[camera_id]);
84 }
85 return mCamera[camera_id]->connectCamera(device);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080086}
87
88/* Returns the number of available cameras */
89int CameraFactory::getCameraNum()
90{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +080091 ALOGD("CameraFactory::getCameraNum: %d", mCameraNum);
Andres Rodriguez937775c2012-04-19 23:38:00 +080092 return mCameraNum;
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080093}
94
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080095int CameraFactory::getCameraInfo(int camera_id, struct camera_info* info)
96{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +080097 ALOGD("CameraFactory::getCameraInfo: id = %d, info = %p", camera_id, info);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +080098
99 if (camera_id < 0 || camera_id >= getCameraNum()) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800100 ALOGE("%s: Camera id %d is out of bounds (%d)",
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800101 __FUNCTION__, camera_id, getCameraNum());
102 return -EINVAL;
103 }
104
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200105 return CameraHardware::getCameraInfo(info, mCameraFacing[camera_id],
106 mCameraOrientation[camera_id]);
Andres Rodriguez937775c2012-04-19 23:38:00 +0800107}
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800108
Andres Rodriguez937775c2012-04-19 23:38:00 +0800109// Parse a simple configuration file
110void CameraFactory::parseConfig(const char* configFile)
111{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800112 ALOGD("CameraFactory::parseConfig: configFile = %s", configFile);
Andres Rodriguez937775c2012-04-19 23:38:00 +0800113
114 FILE* config = fopen(configFile, "r");
115 if (config != NULL) {
116 char line[128];
117 char arg1[128];
118 char arg2[128];
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200119 int arg3;
Andres Rodriguez937775c2012-04-19 23:38:00 +0800120
121 while (fgets(line, sizeof line, config) != NULL) {
122 int lineStart = strspn(line, " \t\n\v" );
123
124 if (line[lineStart] == '#')
125 continue;
126
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200127 sscanf(line, "%s %s %d", arg1, arg2, &arg3);
128 if (arg3 != 0 && arg3 != 90 && arg3 != 180 && arg3 != 270)
129 arg3 = 0;
Andres Rodriguez937775c2012-04-19 23:38:00 +0800130
Alberto Panizzo5e3ac0d2013-07-07 09:19:40 +0200131 if (strcmp(arg1, "front") == 0) {
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200132 newCameraConfig(CAMERA_FACING_FRONT, arg2, arg3);
Alberto Panizzo5e3ac0d2013-07-07 09:19:40 +0200133 } else if (strcmp(arg1, "back") == 0) {
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200134 newCameraConfig(CAMERA_FACING_BACK, arg2, arg3);
Andres Rodriguez937775c2012-04-19 23:38:00 +0800135 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800136 ALOGD("CameraFactory::parseConfig: Unrecognized config line '%s'", line);
Andres Rodriguez937775c2012-04-19 23:38:00 +0800137 }
138 }
139 } else {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800140 ALOGD("%s not found, using camera configuration defaults", CONFIG_FILE);
Chih-Wei Huang4e2b7312019-03-22 23:53:23 +0800141 char camera_node[] = "/dev/video0";
142 char camera_prop[] = "hal.camera.0";
143 char prop[PROPERTY_VALUE_MAX] = "";
Chih-Wei Huangcdab6262020-05-05 10:01:40 +0800144 bool no_prop = true;
Chih-Wei Huang4e2b7312019-03-22 23:53:23 +0800145 while (camera_node[10] <= '9' && mCameraNum < 3) {
146 if (!access(camera_node, F_OK)) {
147 int facing = mCameraNum, orientation = 0;
148 if (property_get(camera_prop, prop, "")) {
Chih-Wei Huangcdab6262020-05-05 10:01:40 +0800149 no_prop = false;
Chih-Wei Huang4e2b7312019-03-22 23:53:23 +0800150 sscanf(prop, "%d,%d", &facing, &orientation);
151 ALOGI("%s got facing=%d orient=%d from property %s", __FUNCTION__, facing, orientation, camera_prop);
152 }
153 newCameraConfig(facing, camera_node, orientation);
154 }
155 camera_node[10]++, camera_prop[11]++;
Andres Rodriguez937775c2012-04-19 23:38:00 +0800156 }
Chih-Wei Huang4e2b7312019-03-22 23:53:23 +0800157
158 // If there is only one camera, assume its facing is front
Chih-Wei Huangcdab6262020-05-05 10:01:40 +0800159 if (mCameraNum == 1 && no_prop) {
Chih-Wei Huang4e2b7312019-03-22 23:53:23 +0800160 mCameraFacing[0] = CAMERA_FACING_FRONT;
Chih-Wei Huangcdab6262020-05-05 10:01:40 +0800161 ALOGI("%s assume %s is front", __FUNCTION__, mCameraDevices[0]);
Andres Rodriguez937775c2012-04-19 23:38:00 +0800162 }
163 }
164}
165
166// Although realloc could be a costly operation, we only execute this function usually 2 times
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200167void CameraFactory::newCameraConfig(int facing, const char* location, int orientation)
Andres Rodriguez937775c2012-04-19 23:38:00 +0800168{
Chih-Wei Huang342584c2018-06-20 18:04:58 +0800169 V4L2Camera camera;
170 if (camera.Open(location) || !camera.getBestPreviewFmt().getFps()) {
171 ALOGW("ignore invalid camera: %s", location);
172 return;
173 }
174
Andres Rodriguez937775c2012-04-19 23:38:00 +0800175 // Keep track of cameras
176 mCameraNum++;
177
178 // Grow the information arrays
179 mCamera = (CameraHardware**) realloc(mCamera, mCameraNum * sizeof(CameraHardware*));
180 mCameraDevices = (char**) realloc(mCameraDevices, mCameraNum * sizeof(char*));
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200181 mCameraFacing = (int*) realloc(mCameraFacing, mCameraNum * sizeof(int));
Andres Rodriguez937775c2012-04-19 23:38:00 +0800182 mCameraOrientation = (int*) realloc(mCameraOrientation, mCameraNum * sizeof(int));
183
184 // Store the values for each camera_id
185 mCamera[mCameraNum - 1] = NULL;
186 mCameraDevices[mCameraNum - 1] = strdup(location);
Alberto Panizzobbbfb372013-07-06 18:23:53 +0200187 mCameraFacing[mCameraNum - 1] = facing;
188 mCameraOrientation[mCameraNum - 1] = orientation;
189 ALOGD("CameraFactory::newCameraConfig: %d -> %s (%d)",
190 mCameraFacing[mCameraNum - 1], mCameraDevices[mCameraNum - 1],
191 mCameraOrientation[mCameraNum - 1]);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800192}
193
194/****************************************************************************
195 * Camera HAL API callbacks.
196 ***************************************************************************/
197
198int CameraFactory::device_open(const hw_module_t* module,
199 const char* name,
200 hw_device_t** device)
201{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800202 ALOGD("CameraFactory::device_open: name = %s", name);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800203
204 /*
205 * Simply verify the parameters, and dispatch the call inside the
206 * CameraFactory instance.
207 */
208
209 if (module != &HAL_MODULE_INFO_SYM.common) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800210 ALOGE("%s: Invalid module %p expected %p",
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800211 __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common);
212 return -EINVAL;
213 }
214 if (name == NULL) {
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800215 ALOGE("%s: NULL name is not expected here", __FUNCTION__);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800216 return -EINVAL;
217 }
218
Andres Rodriguez937775c2012-04-19 23:38:00 +0800219 int camera_id = atoi(name);
220 return gCameraFactory.cameraDeviceOpen(module, camera_id, device);
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800221}
222
223int CameraFactory::get_number_of_cameras(void)
224{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800225 ALOGD("CameraFactory::get_number_of_cameras");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800226 return gCameraFactory.getCameraNum();
227}
228
229int CameraFactory::get_camera_info(int camera_id,
230 struct camera_info* info)
231{
Chih-Wei Huangdf9613f2013-02-20 15:46:19 +0800232 ALOGD("CameraFactory::get_camera_info");
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800233 return gCameraFactory.getCameraInfo(camera_id, info);
234}
235
236/********************************************************************************
237 * Initializer for the static member structure.
238 *******************************************************************************/
239
240/* Entry point for camera HAL API. */
241struct hw_module_methods_t CameraFactory::mCameraModuleMethods = {
Chih-Wei Huang3277dcd2019-02-26 18:08:29 +0800242 .open = CameraFactory::device_open
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +0800243};
244
245}; /* namespace android */