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 || 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 
~CameraDevice()56 CameraDevice::~CameraDevice() {}
57 
initStatus() const58 Status 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 
setConnectionStatus(bool connected)69 void 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 
getHidlStatus(int status)87 Status 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.
getResourceCost(getResourceCost_cb _hidl_cb)102 Return<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 
getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb)142 Return<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 
setTorchMode(TorchMode mode)160 Return<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 
open(const sp<ICameraDeviceCallback> & callback,open_cb _hidl_cb)173 Return<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(getHidlStatus(res), 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         struct camera_info info;
233         res = mModule->getCameraInfo(mCameraIdInt, &info);
234         if (res != OK) {
235             ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
236             device->common.close(&device->common);
237             mLock.unlock();
238             _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
239             return Void();
240         }
241 
242         session = new CameraDeviceSession(
243                 device, info.static_camera_characteristics, callback);
244         if (session == nullptr) {
245             ALOGE("%s: camera device session allocation failed", __FUNCTION__);
246             mLock.unlock();
247             _hidl_cb(Status::INTERNAL_ERROR, nullptr);
248             return Void();
249         }
250         if (session->isInitFailed()) {
251             ALOGE("%s: camera device session init failed", __FUNCTION__);
252             session = nullptr;
253             mLock.unlock();
254             _hidl_cb(Status::INTERNAL_ERROR, nullptr);
255             return Void();
256         }
257         mSession = session;
258         mLock.unlock();
259     }
260     _hidl_cb(status, session);
261     return Void();
262 }
263 
dumpState(const::android::hardware::hidl_handle & handle)264 Return<void> CameraDevice::dumpState(const ::android::hardware::hidl_handle& handle)  {
265     Mutex::Autolock _l(mLock);
266     if (handle.getNativeHandle() == nullptr) {
267         ALOGE("%s: handle must not be null", __FUNCTION__);
268         return Void();
269     }
270     if (handle->numFds != 1 || handle->numInts != 0) {
271         ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
272                 __FUNCTION__, handle->numFds, handle->numInts);
273         return Void();
274     }
275     int fd = handle->data[0];
276     if (mSession == nullptr) {
277         dprintf(fd, "No active camera device session instance\n");
278         return Void();
279     }
280     sp<CameraDeviceSession> session = mSession.promote();
281     if (session == nullptr) {
282         dprintf(fd, "No active camera device session instance\n");
283         return Void();
284     }
285     // Call into active session to dump states
286     session->dumpState(handle);
287     return Void();
288 }
289 // End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
290 
291 } // namespace implementation
292 }  // namespace V3_2
293 }  // namespace device
294 }  // namespace camera
295 }  // namespace hardware
296 }  // namespace android
297