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