blob: a74233554824f59a1b0fd99f04faf2c6b7a1d32a [file] [log] [blame]
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001/*
2 * Copyright (C) 2016 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 "CamDev@3.2-impl"
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080018#include <utils/Log.h>
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070019
20#include <utils/Vector.h>
21#include <utils/Trace.h>
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080022#include "CameraDevice_3_2.h"
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070023#include <include/convert.h>
24
25namespace android {
26namespace hardware {
27namespace camera {
28namespace device {
29namespace V3_2 {
30namespace implementation {
31
32using ::android::hardware::camera::common::V1_0::Status;
33
34CameraDevice::CameraDevice(
35 sp<CameraModule> module, const std::string& cameraId,
36 const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames) :
37 mModule(module),
38 mCameraId(cameraId),
39 mDisconnected(false),
40 mCameraDeviceNames(cameraDeviceNames) {
41 mCameraIdInt = atoi(mCameraId.c_str());
42 // Should not reach here as provider also validate ID
43 if (mCameraIdInt < 0 || mCameraIdInt >= module->getNumberOfCameras()) {
44 ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str());
45 mInitFail = true;
46 }
47
48 mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt);
49 if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) {
50 ALOGE("%s: Camera id %s does not support HAL3.2+",
51 __FUNCTION__, mCameraId.c_str());
52 mInitFail = true;
53 }
54}
55
56CameraDevice::~CameraDevice() {}
57
58Status CameraDevice::initStatus() const {
59 Mutex::Autolock _l(mLock);
60 Status status = Status::OK;
61 if (mInitFail) {
62 status = Status::INTERNAL_ERROR;
63 } else if (mDisconnected) {
64 status = Status::CAMERA_DISCONNECTED;
65 }
66 return status;
67}
68
69void CameraDevice::setConnectionStatus(bool connected) {
70 Mutex::Autolock _l(mLock);
71 mDisconnected = !connected;
72 if (mSession == nullptr) {
73 return;
74 }
75 sp<CameraDeviceSession> session = mSession.promote();
76 if (session == nullptr) {
77 return;
78 }
79 // Only notify active session disconnect events.
80 // Users will need to re-open camera after disconnect event
81 if (!connected) {
82 session->disconnect();
83 }
84 return;
85}
86
87Status CameraDevice::getHidlStatus(int status) {
88 switch (status) {
89 case 0: return Status::OK;
90 case -ENOSYS: return Status::OPERATION_NOT_SUPPORTED;
91 case -EBUSY : return Status::CAMERA_IN_USE;
92 case -EUSERS: return Status::MAX_CAMERAS_IN_USE;
93 case -ENODEV: return Status::INTERNAL_ERROR;
94 case -EINVAL: return Status::ILLEGAL_ARGUMENT;
95 default:
96 ALOGE("%s: unknown HAL status code %d", __FUNCTION__, status);
97 return Status::INTERNAL_ERROR;
98 }
99}
100
101// Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow.
102Return<void> CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
103 Status status = initStatus();
104 CameraResourceCost resCost;
105 if (status == Status::OK) {
106 int cost = 100;
107 std::vector<std::string> conflicting_devices;
108 struct camera_info info;
109
110 // If using post-2.4 module version, query the cost + conflicting devices from the HAL
111 if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
112 int ret = mModule->getCameraInfo(mCameraIdInt, &info);
113 if (ret == OK) {
114 cost = info.resource_cost;
115 for (size_t i = 0; i < info.conflicting_devices_length; i++) {
116 std::string cameraId(info.conflicting_devices[i]);
117 for (const auto& pair : mCameraDeviceNames) {
118 if (cameraId == pair.first) {
119 conflicting_devices.push_back(pair.second);
120 }
121 }
122 }
123 } else {
124 status = Status::INTERNAL_ERROR;
125 }
126 }
127
128 if (status == Status::OK) {
129 resCost.resourceCost = cost;
130 resCost.conflictingDevices.resize(conflicting_devices.size());
131 for (size_t i = 0; i < conflicting_devices.size(); i++) {
132 resCost.conflictingDevices[i] = conflicting_devices[i];
133 ALOGV("CamDevice %s is conflicting with camDevice %s",
134 mCameraId.c_str(), resCost.conflictingDevices[i].c_str());
135 }
136 }
137 }
138 _hidl_cb(status, resCost);
139 return Void();
140}
141
142Return<void> CameraDevice::getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) {
143 Status status = initStatus();
144 CameraMetadata cameraCharacteristics;
145 if (status == Status::OK) {
146 //Module 2.1+ codepath.
147 struct camera_info info;
148 int ret = mModule->getCameraInfo(mCameraIdInt, &info);
149 if (ret == OK) {
150 convertToHidl(info.static_camera_characteristics, &cameraCharacteristics);
151 } else {
152 ALOGE("%s: get camera info failed!", __FUNCTION__);
153 status = Status::INTERNAL_ERROR;
154 }
155 }
156 _hidl_cb(status, cameraCharacteristics);
157 return Void();
158}
159
160Return<Status> CameraDevice::setTorchMode(TorchMode mode) {
161 if (!mModule->isSetTorchModeSupported()) {
162 return Status::METHOD_NOT_SUPPORTED;
163 }
164
165 Status status = initStatus();
166 if (status == Status::OK) {
167 bool enable = (mode == TorchMode::ON) ? true : false;
168 status = getHidlStatus(mModule->setTorchMode(mCameraId.c_str(), enable));
169 }
170 return status;
171}
172
173Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
174 Status status = initStatus();
175 sp<CameraDeviceSession> session = nullptr;
176
177 if (callback == nullptr) {
178 ALOGE("%s: cannot open camera %s. callback is null!",
179 __FUNCTION__, mCameraId.c_str());
180 _hidl_cb(Status::ILLEGAL_ARGUMENT, session);
181 return Void();
182 }
183
184 if (status != Status::OK) {
185 // Provider will never pass initFailed device to client, so
186 // this must be a disconnected camera
187 ALOGE("%s: cannot open camera %s. camera is disconnected!",
188 __FUNCTION__, mCameraId.c_str());
189 _hidl_cb(Status::CAMERA_DISCONNECTED, session);
190 return Void();
191 } else {
192 mLock.lock();
193
194 ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mCameraIdInt);
195 session = mSession.promote();
196 if (session != nullptr && !session->isClosed()) {
197 ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
198 mLock.unlock();
199 _hidl_cb(Status::CAMERA_IN_USE, nullptr);
200 return Void();
201 }
202
203 /** Open HAL device */
204 status_t res;
205 camera3_device_t *device;
206
207 ATRACE_BEGIN("camera3->open");
208 res = mModule->open(mCameraId.c_str(),
209 reinterpret_cast<hw_device_t**>(&device));
210 ATRACE_END();
211
212 if (res != OK) {
213 ALOGE("%s: cannot open camera %s!", __FUNCTION__, mCameraId.c_str());
214 mLock.unlock();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800215 _hidl_cb(getHidlStatus(res), nullptr);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700216 return Void();
217 }
218
219 /** Cross-check device version */
220 if (device->common.version < CAMERA_DEVICE_API_VERSION_3_2) {
221 ALOGE("%s: Could not open camera: "
222 "Camera device should be at least %x, reports %x instead",
223 __FUNCTION__,
224 CAMERA_DEVICE_API_VERSION_3_2,
225 device->common.version);
226 device->common.close(&device->common);
227 mLock.unlock();
228 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
229 return Void();
230 }
231
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800232 struct camera_info info;
233 res = mModule->getCameraInfo(mCameraIdInt, &info);
234 if (res != OK) {
235 ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
236 device->common.close(&device->common);
237 mLock.unlock();
238 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
239 return Void();
240 }
241
242 session = new CameraDeviceSession(
243 device, info.static_camera_characteristics, callback);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700244 if (session == nullptr) {
245 ALOGE("%s: camera device session allocation failed", __FUNCTION__);
246 mLock.unlock();
247 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
248 return Void();
249 }
250 if (session->isInitFailed()) {
251 ALOGE("%s: camera device session init failed", __FUNCTION__);
252 session = nullptr;
253 mLock.unlock();
254 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
255 return Void();
256 }
257 mSession = session;
258 mLock.unlock();
259 }
260 _hidl_cb(status, session);
261 return Void();
262}
263
264Return<void> CameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
265 Mutex::Autolock _l(mLock);
266 if (handle.getNativeHandle() == nullptr) {
267 ALOGE("%s: handle must not be null", __FUNCTION__);
268 return Void();
269 }
270 if (handle->numFds != 1 || handle->numInts != 0) {
271 ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
272 __FUNCTION__, handle->numFds, handle->numInts);
273 return Void();
274 }
275 int fd = handle->data[0];
276 if (mSession == nullptr) {
277 dprintf(fd, "No active camera device session instance\n");
278 return Void();
279 }
280 sp<CameraDeviceSession> session = mSession.promote();
281 if (session == nullptr) {
282 dprintf(fd, "No active camera device session instance\n");
283 return Void();
284 }
285 // Call into active session to dump states
286 session->dumpState(handle);
287 return Void();
288}
289// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
290
291} // namespace implementation
292} // namespace V3_2
293} // namespace device
294} // namespace camera
295} // namespace hardware
296} // namespace android