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 (at) 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 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 58 CameraDevice::~CameraDevice() {} 59 60 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 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 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. 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 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 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 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 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 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