blob: dfbb9768a465493b00e0091642228b8b599cb501 [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"
Steven Moreland3eb7df72017-04-06 12:15:23 -070018#include <log/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
Guennadi Liakhovetski7b7ede72017-11-28 09:28:56 +010043 if (mCameraIdInt < 0) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070044 ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str());
45 mInitFail = true;
Guennadi Liakhovetski7b7ede72017-11-28 09:28:56 +010046 } else if (mCameraIdInt >= mModule->getNumberOfCameras()) {
47 ALOGI("%s: Adding a new camera id: %s", __FUNCTION__, mCameraId.c_str());
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070048 }
49
50 mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt);
51 if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) {
52 ALOGE("%s: Camera id %s does not support HAL3.2+",
53 __FUNCTION__, mCameraId.c_str());
54 mInitFail = true;
55 }
56}
57
58CameraDevice::~CameraDevice() {}
59
60Status CameraDevice::initStatus() const {
61 Mutex::Autolock _l(mLock);
62 Status status = Status::OK;
63 if (mInitFail) {
64 status = Status::INTERNAL_ERROR;
65 } else if (mDisconnected) {
66 status = Status::CAMERA_DISCONNECTED;
67 }
68 return status;
69}
70
71void CameraDevice::setConnectionStatus(bool connected) {
72 Mutex::Autolock _l(mLock);
73 mDisconnected = !connected;
74 if (mSession == nullptr) {
75 return;
76 }
77 sp<CameraDeviceSession> session = mSession.promote();
78 if (session == nullptr) {
79 return;
80 }
81 // Only notify active session disconnect events.
82 // Users will need to re-open camera after disconnect event
83 if (!connected) {
84 session->disconnect();
85 }
86 return;
87}
88
89Status CameraDevice::getHidlStatus(int status) {
90 switch (status) {
91 case 0: return Status::OK;
92 case -ENOSYS: return Status::OPERATION_NOT_SUPPORTED;
93 case -EBUSY : return Status::CAMERA_IN_USE;
94 case -EUSERS: return Status::MAX_CAMERAS_IN_USE;
95 case -ENODEV: return Status::INTERNAL_ERROR;
96 case -EINVAL: return Status::ILLEGAL_ARGUMENT;
97 default:
98 ALOGE("%s: unknown HAL status code %d", __FUNCTION__, status);
99 return Status::INTERNAL_ERROR;
100 }
101}
102
103// Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow.
104Return<void> CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
105 Status status = initStatus();
106 CameraResourceCost resCost;
107 if (status == Status::OK) {
108 int cost = 100;
109 std::vector<std::string> conflicting_devices;
110 struct camera_info info;
111
112 // If using post-2.4 module version, query the cost + conflicting devices from the HAL
113 if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
114 int ret = mModule->getCameraInfo(mCameraIdInt, &info);
115 if (ret == OK) {
116 cost = info.resource_cost;
117 for (size_t i = 0; i < info.conflicting_devices_length; i++) {
118 std::string cameraId(info.conflicting_devices[i]);
119 for (const auto& pair : mCameraDeviceNames) {
120 if (cameraId == pair.first) {
121 conflicting_devices.push_back(pair.second);
122 }
123 }
124 }
125 } else {
126 status = Status::INTERNAL_ERROR;
127 }
128 }
129
130 if (status == Status::OK) {
131 resCost.resourceCost = cost;
132 resCost.conflictingDevices.resize(conflicting_devices.size());
133 for (size_t i = 0; i < conflicting_devices.size(); i++) {
134 resCost.conflictingDevices[i] = conflicting_devices[i];
135 ALOGV("CamDevice %s is conflicting with camDevice %s",
136 mCameraId.c_str(), resCost.conflictingDevices[i].c_str());
137 }
138 }
139 }
140 _hidl_cb(status, resCost);
141 return Void();
142}
143
144Return<void> CameraDevice::getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) {
145 Status status = initStatus();
146 CameraMetadata cameraCharacteristics;
147 if (status == Status::OK) {
148 //Module 2.1+ codepath.
149 struct camera_info info;
150 int ret = mModule->getCameraInfo(mCameraIdInt, &info);
151 if (ret == OK) {
152 convertToHidl(info.static_camera_characteristics, &cameraCharacteristics);
153 } else {
154 ALOGE("%s: get camera info failed!", __FUNCTION__);
155 status = Status::INTERNAL_ERROR;
156 }
157 }
158 _hidl_cb(status, cameraCharacteristics);
159 return Void();
160}
161
162Return<Status> CameraDevice::setTorchMode(TorchMode mode) {
163 if (!mModule->isSetTorchModeSupported()) {
164 return Status::METHOD_NOT_SUPPORTED;
165 }
166
167 Status status = initStatus();
168 if (status == Status::OK) {
169 bool enable = (mode == TorchMode::ON) ? true : false;
170 status = getHidlStatus(mModule->setTorchMode(mCameraId.c_str(), enable));
171 }
172 return status;
173}
174
175Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
176 Status status = initStatus();
177 sp<CameraDeviceSession> session = nullptr;
178
179 if (callback == nullptr) {
180 ALOGE("%s: cannot open camera %s. callback is null!",
181 __FUNCTION__, mCameraId.c_str());
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700182 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700183 return Void();
184 }
185
186 if (status != Status::OK) {
187 // Provider will never pass initFailed device to client, so
188 // this must be a disconnected camera
189 ALOGE("%s: cannot open camera %s. camera is disconnected!",
190 __FUNCTION__, mCameraId.c_str());
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700191 _hidl_cb(Status::CAMERA_DISCONNECTED, nullptr);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700192 return Void();
193 } else {
194 mLock.lock();
195
196 ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mCameraIdInt);
197 session = mSession.promote();
198 if (session != nullptr && !session->isClosed()) {
199 ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
200 mLock.unlock();
201 _hidl_cb(Status::CAMERA_IN_USE, nullptr);
202 return Void();
203 }
204
205 /** Open HAL device */
206 status_t res;
207 camera3_device_t *device;
208
209 ATRACE_BEGIN("camera3->open");
210 res = mModule->open(mCameraId.c_str(),
211 reinterpret_cast<hw_device_t**>(&device));
212 ATRACE_END();
213
214 if (res != OK) {
215 ALOGE("%s: cannot open camera %s!", __FUNCTION__, mCameraId.c_str());
216 mLock.unlock();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800217 _hidl_cb(getHidlStatus(res), nullptr);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700218 return Void();
219 }
220
221 /** Cross-check device version */
222 if (device->common.version < CAMERA_DEVICE_API_VERSION_3_2) {
223 ALOGE("%s: Could not open camera: "
224 "Camera device should be at least %x, reports %x instead",
225 __FUNCTION__,
226 CAMERA_DEVICE_API_VERSION_3_2,
227 device->common.version);
228 device->common.close(&device->common);
229 mLock.unlock();
230 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
231 return Void();
232 }
233
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800234 struct camera_info info;
235 res = mModule->getCameraInfo(mCameraIdInt, &info);
236 if (res != OK) {
237 ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
238 device->common.close(&device->common);
239 mLock.unlock();
240 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
241 return Void();
242 }
243
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700244 session = createSession(
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800245 device, info.static_camera_characteristics, callback);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700246 if (session == nullptr) {
247 ALOGE("%s: camera device session allocation failed", __FUNCTION__);
248 mLock.unlock();
249 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
250 return Void();
251 }
252 if (session->isInitFailed()) {
253 ALOGE("%s: camera device session init failed", __FUNCTION__);
254 session = nullptr;
255 mLock.unlock();
256 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
257 return Void();
258 }
259 mSession = session;
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700260
261 IF_ALOGV() {
262 session->getInterface()->interfaceChain([](
263 ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
264 ALOGV("Session interface chain:");
265 for (auto iface : interfaceChain) {
266 ALOGV(" %s", iface.c_str());
267 }
268 });
269 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700270 mLock.unlock();
271 }
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700272 _hidl_cb(status, session->getInterface());
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700273 return Void();
274}
275
276Return<void> CameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
277 Mutex::Autolock _l(mLock);
278 if (handle.getNativeHandle() == nullptr) {
279 ALOGE("%s: handle must not be null", __FUNCTION__);
280 return Void();
281 }
282 if (handle->numFds != 1 || handle->numInts != 0) {
283 ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
284 __FUNCTION__, handle->numFds, handle->numInts);
285 return Void();
286 }
287 int fd = handle->data[0];
288 if (mSession == nullptr) {
289 dprintf(fd, "No active camera device session instance\n");
290 return Void();
291 }
292 sp<CameraDeviceSession> session = mSession.promote();
293 if (session == nullptr) {
294 dprintf(fd, "No active camera device session instance\n");
295 return Void();
296 }
297 // Call into active session to dump states
298 session->dumpState(handle);
299 return Void();
300}
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700301
302sp<CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
303 const camera_metadata_t* deviceInfo,
304 const sp<ICameraDeviceCallback>& callback) {
305 return new CameraDeviceSession(device, deviceInfo, callback);
306}
307
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700308// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
309
310} // namespace implementation
311} // namespace V3_2
312} // namespace device
313} // namespace camera
314} // namespace hardware
315} // namespace android