• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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