1 /*
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"
18 #include <log/log.h>
19
20 #include <utils/Vector.h>
21 #include <utils/Trace.h>
22 #include "CameraDevice_3_2.h"
23 #include <include/convert.h>
24
25 namespace android {
26 namespace hardware {
27 namespace camera {
28 namespace device {
29 namespace V3_2 {
30 namespace implementation {
31
32 using ::android::hardware::camera::common::V1_0::Status;
33
CameraDevice(sp<CameraModule> module,const std::string & cameraId,const SortedVector<std::pair<std::string,std::string>> & cameraDeviceNames)34 CameraDevice::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) {
44 ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str());
45 mInitFail = true;
46 } else if (mCameraIdInt >= mModule->getNumberOfCameras()) {
47 ALOGI("%s: Adding a new camera id: %s", __FUNCTION__, mCameraId.c_str());
48 }
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
~CameraDevice()58 CameraDevice::~CameraDevice() {}
59
initStatus() const60 Status 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
setConnectionStatus(bool connected)71 void 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
getHidlStatus(int status)89 Status 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.
getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb)104 Return<void> CameraDevice::getResourceCost(ICameraDevice::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
getCameraCharacteristics(ICameraDevice::getCameraCharacteristics_cb _hidl_cb)144 Return<void> CameraDevice::getCameraCharacteristics(
145 ICameraDevice::getCameraCharacteristics_cb _hidl_cb) {
146 Status status = initStatus();
147 CameraMetadata cameraCharacteristics;
148 if (status == Status::OK) {
149 //Module 2.1+ codepath.
150 struct camera_info info;
151 int ret = mModule->getCameraInfo(mCameraIdInt, &info);
152 if (ret == OK) {
153 convertToHidl(info.static_camera_characteristics, &cameraCharacteristics);
154 } else {
155 ALOGE("%s: get camera info failed!", __FUNCTION__);
156 status = Status::INTERNAL_ERROR;
157 }
158 }
159 _hidl_cb(status, cameraCharacteristics);
160 return Void();
161 }
162
setTorchMode(TorchMode mode)163 Return<Status> CameraDevice::setTorchMode(TorchMode mode) {
164 if (!mModule->isSetTorchModeSupported()) {
165 return Status::METHOD_NOT_SUPPORTED;
166 }
167
168 Status status = initStatus();
169 if (status == Status::OK) {
170 bool enable = (mode == TorchMode::ON) ? true : false;
171 status = getHidlStatus(mModule->setTorchMode(mCameraId.c_str(), enable));
172 }
173 return status;
174 }
175
open(const sp<ICameraDeviceCallback> & callback,ICameraDevice::open_cb _hidl_cb)176 Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback,
177 ICameraDevice::open_cb _hidl_cb) {
178 Status status = initStatus();
179 sp<CameraDeviceSession> session = nullptr;
180
181 if (callback == nullptr) {
182 ALOGE("%s: cannot open camera %s. callback is null!",
183 __FUNCTION__, mCameraId.c_str());
184 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
185 return Void();
186 }
187
188 if (status != Status::OK) {
189 // Provider will never pass initFailed device to client, so
190 // this must be a disconnected camera
191 ALOGE("%s: cannot open camera %s. camera is disconnected!",
192 __FUNCTION__, mCameraId.c_str());
193 _hidl_cb(Status::CAMERA_DISCONNECTED, nullptr);
194 return Void();
195 } else {
196 mLock.lock();
197
198 ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mCameraIdInt);
199 session = mSession.promote();
200 if (session != nullptr && !session->isClosed()) {
201 ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
202 mLock.unlock();
203 _hidl_cb(Status::CAMERA_IN_USE, nullptr);
204 return Void();
205 }
206
207 /** Open HAL device */
208 status_t res;
209 camera3_device_t *device;
210
211 ATRACE_BEGIN("camera3->open");
212 res = mModule->open(mCameraId.c_str(),
213 reinterpret_cast<hw_device_t**>(&device));
214 ATRACE_END();
215
216 if (res != OK) {
217 ALOGE("%s: cannot open camera %s!", __FUNCTION__, mCameraId.c_str());
218 mLock.unlock();
219 _hidl_cb(getHidlStatus(res), nullptr);
220 return Void();
221 }
222
223 /** Cross-check device version */
224 if (device->common.version < CAMERA_DEVICE_API_VERSION_3_2) {
225 ALOGE("%s: Could not open camera: "
226 "Camera device should be at least %x, reports %x instead",
227 __FUNCTION__,
228 CAMERA_DEVICE_API_VERSION_3_2,
229 device->common.version);
230 device->common.close(&device->common);
231 mLock.unlock();
232 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
233 return Void();
234 }
235
236 struct camera_info info;
237 res = mModule->getCameraInfo(mCameraIdInt, &info);
238 if (res != OK) {
239 ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
240 device->common.close(&device->common);
241 mLock.unlock();
242 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
243 return Void();
244 }
245
246 session = createSession(
247 device, info.static_camera_characteristics, callback);
248 if (session == nullptr) {
249 ALOGE("%s: camera device session allocation failed", __FUNCTION__);
250 mLock.unlock();
251 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
252 return Void();
253 }
254 if (session->isInitFailed()) {
255 ALOGE("%s: camera device session init failed", __FUNCTION__);
256 session = nullptr;
257 mLock.unlock();
258 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
259 return Void();
260 }
261 mSession = session;
262
263 IF_ALOGV() {
264 session->getInterface()->interfaceChain([](
265 ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
266 ALOGV("Session interface chain:");
267 for (const auto& iface : interfaceChain) {
268 ALOGV(" %s", iface.c_str());
269 }
270 });
271 }
272 mLock.unlock();
273 }
274 _hidl_cb(status, session->getInterface());
275 return Void();
276 }
277
dumpState(const::android::hardware::hidl_handle & handle)278 Return<void> CameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
279 Mutex::Autolock _l(mLock);
280 if (handle.getNativeHandle() == nullptr) {
281 ALOGE("%s: handle must not be null", __FUNCTION__);
282 return Void();
283 }
284 if (handle->numFds != 1 || handle->numInts != 0) {
285 ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
286 __FUNCTION__, handle->numFds, handle->numInts);
287 return Void();
288 }
289 int fd = handle->data[0];
290 if (mSession == nullptr) {
291 dprintf(fd, "No active camera device session instance\n");
292 return Void();
293 }
294 sp<CameraDeviceSession> session = mSession.promote();
295 if (session == nullptr) {
296 dprintf(fd, "No active camera device session instance\n");
297 return Void();
298 }
299 // Call into active session to dump states
300 session->dumpState(handle);
301 return Void();
302 }
303
createSession(camera3_device_t * device,const camera_metadata_t * deviceInfo,const sp<ICameraDeviceCallback> & callback)304 sp<CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
305 const camera_metadata_t* deviceInfo,
306 const sp<ICameraDeviceCallback>& callback) {
307 return new CameraDeviceSession(device, deviceInfo, callback);
308 }
309
310 // End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
311
312 } // namespace implementation
313 } // namespace V3_2
314 } // namespace device
315 } // namespace camera
316 } // namespace hardware
317 } // namespace android
318