CameraDevice.cpp revision faef8f92c95a1e0868c1ec8fd220b9d957831022
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 <android/log.h> 19 20#include <utils/Vector.h> 21#include <utils/Trace.h> 22#include "CameraDevice.h" 23#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(); 215 _hidl_cb(Status::INTERNAL_ERROR, nullptr); 216 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 232 session = new CameraDeviceSession(device, callback); 233 if (session == nullptr) { 234 ALOGE("%s: camera device session allocation failed", __FUNCTION__); 235 mLock.unlock(); 236 _hidl_cb(Status::INTERNAL_ERROR, nullptr); 237 return Void(); 238 } 239 if (session->isInitFailed()) { 240 ALOGE("%s: camera device session init failed", __FUNCTION__); 241 session = nullptr; 242 mLock.unlock(); 243 _hidl_cb(Status::INTERNAL_ERROR, nullptr); 244 return Void(); 245 } 246 mSession = session; 247 mLock.unlock(); 248 } 249 _hidl_cb(status, session); 250 return Void(); 251} 252 253Return<void> CameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) { 254 Mutex::Autolock _l(mLock); 255 if (handle.getNativeHandle() == nullptr) { 256 ALOGE("%s: handle must not be null", __FUNCTION__); 257 return Void(); 258 } 259 if (handle->numFds != 1 || handle->numInts != 0) { 260 ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints", 261 __FUNCTION__, handle->numFds, handle->numInts); 262 return Void(); 263 } 264 int fd = handle->data[0]; 265 if (mSession == nullptr) { 266 dprintf(fd, "No active camera device session instance\n"); 267 return Void(); 268 } 269 sp<CameraDeviceSession> session = mSession.promote(); 270 if (session == nullptr) { 271 dprintf(fd, "No active camera device session instance\n"); 272 return Void(); 273 } 274 // Call into active session to dump states 275 session->dumpState(handle); 276 return Void(); 277} 278// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice. 279 280} // namespace implementation 281} // namespace V3_2 282} // namespace device 283} // namespace camera 284} // namespace hardware 285} // namespace android 286