You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
11 KiB
318 lines
11 KiB
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "CamDev@3.2-impl"
|
|
#include <log/log.h>
|
|
|
|
#include <utils/Vector.h>
|
|
#include <utils/Trace.h>
|
|
#include "CameraDevice_3_2.h"
|
|
#include <include/convert.h>
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace camera {
|
|
namespace device {
|
|
namespace V3_2 {
|
|
namespace implementation {
|
|
|
|
using ::android::hardware::camera::common::V1_0::Status;
|
|
|
|
CameraDevice::CameraDevice(
|
|
sp<CameraModule> module, const std::string& cameraId,
|
|
const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames) :
|
|
mModule(module),
|
|
mCameraId(cameraId),
|
|
mDisconnected(false),
|
|
mCameraDeviceNames(cameraDeviceNames) {
|
|
mCameraIdInt = atoi(mCameraId.c_str());
|
|
// Should not reach here as provider also validate ID
|
|
if (mCameraIdInt < 0) {
|
|
ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str());
|
|
mInitFail = true;
|
|
} else if (mCameraIdInt >= mModule->getNumberOfCameras()) {
|
|
ALOGI("%s: Adding a new camera id: %s", __FUNCTION__, mCameraId.c_str());
|
|
}
|
|
|
|
mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt);
|
|
if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) {
|
|
ALOGE("%s: Camera id %s does not support HAL3.2+",
|
|
__FUNCTION__, mCameraId.c_str());
|
|
mInitFail = true;
|
|
}
|
|
}
|
|
|
|
CameraDevice::~CameraDevice() {}
|
|
|
|
Status CameraDevice::initStatus() const {
|
|
Mutex::Autolock _l(mLock);
|
|
Status status = Status::OK;
|
|
if (mInitFail) {
|
|
status = Status::INTERNAL_ERROR;
|
|
} else if (mDisconnected) {
|
|
status = Status::CAMERA_DISCONNECTED;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void CameraDevice::setConnectionStatus(bool connected) {
|
|
Mutex::Autolock _l(mLock);
|
|
mDisconnected = !connected;
|
|
if (mSession == nullptr) {
|
|
return;
|
|
}
|
|
sp<CameraDeviceSession> session = mSession.promote();
|
|
if (session == nullptr) {
|
|
return;
|
|
}
|
|
// Only notify active session disconnect events.
|
|
// Users will need to re-open camera after disconnect event
|
|
if (!connected) {
|
|
session->disconnect();
|
|
}
|
|
return;
|
|
}
|
|
|
|
Status CameraDevice::getHidlStatus(int status) {
|
|
switch (status) {
|
|
case 0: return Status::OK;
|
|
case -ENOSYS: return Status::OPERATION_NOT_SUPPORTED;
|
|
case -EBUSY : return Status::CAMERA_IN_USE;
|
|
case -EUSERS: return Status::MAX_CAMERAS_IN_USE;
|
|
case -ENODEV: return Status::INTERNAL_ERROR;
|
|
case -EINVAL: return Status::ILLEGAL_ARGUMENT;
|
|
default:
|
|
ALOGE("%s: unknown HAL status code %d", __FUNCTION__, status);
|
|
return Status::INTERNAL_ERROR;
|
|
}
|
|
}
|
|
|
|
// Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow.
|
|
Return<void> CameraDevice::getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb) {
|
|
Status status = initStatus();
|
|
CameraResourceCost resCost;
|
|
if (status == Status::OK) {
|
|
int cost = 100;
|
|
std::vector<std::string> conflicting_devices;
|
|
struct camera_info info;
|
|
|
|
// If using post-2.4 module version, query the cost + conflicting devices from the HAL
|
|
if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
|
|
int ret = mModule->getCameraInfo(mCameraIdInt, &info);
|
|
if (ret == OK) {
|
|
cost = info.resource_cost;
|
|
for (size_t i = 0; i < info.conflicting_devices_length; i++) {
|
|
std::string cameraId(info.conflicting_devices[i]);
|
|
for (const auto& pair : mCameraDeviceNames) {
|
|
if (cameraId == pair.first) {
|
|
conflicting_devices.push_back(pair.second);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
status = Status::INTERNAL_ERROR;
|
|
}
|
|
}
|
|
|
|
if (status == Status::OK) {
|
|
resCost.resourceCost = cost;
|
|
resCost.conflictingDevices.resize(conflicting_devices.size());
|
|
for (size_t i = 0; i < conflicting_devices.size(); i++) {
|
|
resCost.conflictingDevices[i] = conflicting_devices[i];
|
|
ALOGV("CamDevice %s is conflicting with camDevice %s",
|
|
mCameraId.c_str(), resCost.conflictingDevices[i].c_str());
|
|
}
|
|
}
|
|
}
|
|
_hidl_cb(status, resCost);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> CameraDevice::getCameraCharacteristics(
|
|
ICameraDevice::getCameraCharacteristics_cb _hidl_cb) {
|
|
Status status = initStatus();
|
|
CameraMetadata cameraCharacteristics;
|
|
if (status == Status::OK) {
|
|
//Module 2.1+ codepath.
|
|
struct camera_info info;
|
|
int ret = mModule->getCameraInfo(mCameraIdInt, &info);
|
|
if (ret == OK) {
|
|
convertToHidl(info.static_camera_characteristics, &cameraCharacteristics);
|
|
} else {
|
|
ALOGE("%s: get camera info failed!", __FUNCTION__);
|
|
status = Status::INTERNAL_ERROR;
|
|
}
|
|
}
|
|
_hidl_cb(status, cameraCharacteristics);
|
|
return Void();
|
|
}
|
|
|
|
Return<Status> CameraDevice::setTorchMode(TorchMode mode) {
|
|
if (!mModule->isSetTorchModeSupported()) {
|
|
return Status::METHOD_NOT_SUPPORTED;
|
|
}
|
|
|
|
Status status = initStatus();
|
|
if (status == Status::OK) {
|
|
bool enable = (mode == TorchMode::ON) ? true : false;
|
|
status = getHidlStatus(mModule->setTorchMode(mCameraId.c_str(), enable));
|
|
}
|
|
return status;
|
|
}
|
|
|
|
Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback,
|
|
ICameraDevice::open_cb _hidl_cb) {
|
|
Status status = initStatus();
|
|
sp<CameraDeviceSession> session = nullptr;
|
|
|
|
if (callback == nullptr) {
|
|
ALOGE("%s: cannot open camera %s. callback is null!",
|
|
__FUNCTION__, mCameraId.c_str());
|
|
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
if (status != Status::OK) {
|
|
// Provider will never pass initFailed device to client, so
|
|
// this must be a disconnected camera
|
|
ALOGE("%s: cannot open camera %s. camera is disconnected!",
|
|
__FUNCTION__, mCameraId.c_str());
|
|
_hidl_cb(Status::CAMERA_DISCONNECTED, nullptr);
|
|
return Void();
|
|
} else {
|
|
mLock.lock();
|
|
|
|
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mCameraIdInt);
|
|
session = mSession.promote();
|
|
if (session != nullptr && !session->isClosed()) {
|
|
ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
|
|
mLock.unlock();
|
|
_hidl_cb(Status::CAMERA_IN_USE, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
/** Open HAL device */
|
|
status_t res;
|
|
camera3_device_t *device;
|
|
|
|
ATRACE_BEGIN("camera3->open");
|
|
res = mModule->open(mCameraId.c_str(),
|
|
reinterpret_cast<hw_device_t**>(&device));
|
|
ATRACE_END();
|
|
|
|
if (res != OK) {
|
|
ALOGE("%s: cannot open camera %s!", __FUNCTION__, mCameraId.c_str());
|
|
mLock.unlock();
|
|
_hidl_cb(getHidlStatus(res), nullptr);
|
|
return Void();
|
|
}
|
|
|
|
/** Cross-check device version */
|
|
if (device->common.version < CAMERA_DEVICE_API_VERSION_3_2) {
|
|
ALOGE("%s: Could not open camera: "
|
|
"Camera device should be at least %x, reports %x instead",
|
|
__FUNCTION__,
|
|
CAMERA_DEVICE_API_VERSION_3_2,
|
|
device->common.version);
|
|
device->common.close(&device->common);
|
|
mLock.unlock();
|
|
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
struct camera_info info;
|
|
res = mModule->getCameraInfo(mCameraIdInt, &info);
|
|
if (res != OK) {
|
|
ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
|
|
device->common.close(&device->common);
|
|
mLock.unlock();
|
|
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
session = createSession(
|
|
device, info.static_camera_characteristics, callback);
|
|
if (session == nullptr) {
|
|
ALOGE("%s: camera device session allocation failed", __FUNCTION__);
|
|
mLock.unlock();
|
|
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
|
|
return Void();
|
|
}
|
|
if (session->isInitFailed()) {
|
|
ALOGE("%s: camera device session init failed", __FUNCTION__);
|
|
session = nullptr;
|
|
mLock.unlock();
|
|
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
|
|
return Void();
|
|
}
|
|
mSession = session;
|
|
|
|
IF_ALOGV() {
|
|
session->getInterface()->interfaceChain([](
|
|
::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
|
|
ALOGV("Session interface chain:");
|
|
for (const auto& iface : interfaceChain) {
|
|
ALOGV(" %s", iface.c_str());
|
|
}
|
|
});
|
|
}
|
|
mLock.unlock();
|
|
}
|
|
_hidl_cb(status, session->getInterface());
|
|
return Void();
|
|
}
|
|
|
|
Return<void> CameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
|
|
Mutex::Autolock _l(mLock);
|
|
if (handle.getNativeHandle() == nullptr) {
|
|
ALOGE("%s: handle must not be null", __FUNCTION__);
|
|
return Void();
|
|
}
|
|
if (handle->numFds != 1 || handle->numInts != 0) {
|
|
ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
|
|
__FUNCTION__, handle->numFds, handle->numInts);
|
|
return Void();
|
|
}
|
|
int fd = handle->data[0];
|
|
if (mSession == nullptr) {
|
|
dprintf(fd, "No active camera device session instance\n");
|
|
return Void();
|
|
}
|
|
sp<CameraDeviceSession> session = mSession.promote();
|
|
if (session == nullptr) {
|
|
dprintf(fd, "No active camera device session instance\n");
|
|
return Void();
|
|
}
|
|
// Call into active session to dump states
|
|
session->dumpState(handle);
|
|
return Void();
|
|
}
|
|
|
|
sp<CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
|
|
const camera_metadata_t* deviceInfo,
|
|
const sp<ICameraDeviceCallback>& callback) {
|
|
return new CameraDeviceSession(device, deviceInfo, callback);
|
|
}
|
|
|
|
// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
|
|
|
|
} // namespace implementation
|
|
} // namespace V3_2
|
|
} // namespace device
|
|
} // namespace camera
|
|
} // namespace hardware
|
|
} // namespace android
|