Home | History | Annotate | Download | only in default
      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