blob: 3aa7817f1b9b856b1fd312a84b6c99b8cf1bdf01 [file] [log] [blame]
/*
* Copyright (C) 2018 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_NDEBUG 0
#define LOG_TAG "ACameraManagerVendor"
#include "ACameraMetadata.h"
#include "ndk_vendor/impl/ACameraDevice.h"
#include "ndk_vendor/impl/ACameraManager.h"
#include "utils.h"
#include <CameraMetadata.h>
#include <VendorTagDescriptor.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <camera_metadata_hidden.h>
#include <cutils/properties.h>
#include <memory>
#include <utils/Vector.h>
using namespace android::acam;
namespace android {
namespace acam {
using ::aidl::android::frameworks::cameraservice::common::ProviderIdAndVendorTagSections;
using ::android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
using ::android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
using ::ndk::ScopedAStatus;
// Static member definitions
const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
const char* CameraManagerGlobal::kPhysicalCameraIdKey = "PhysicalCameraId";
const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
const char* CameraManagerGlobal::kContextKey = "CallbackContext";
const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
Mutex CameraManagerGlobal::sLock;
std::weak_ptr<CameraManagerGlobal> CameraManagerGlobal::sInstance =
std::weak_ptr<CameraManagerGlobal>();
/**
* The vendor tag descriptor class that takes AIDL vendor tag information as
* input. Not part of vendor available VendorTagDescriptor class because that class is used by
* default HAL implementation code as well.
*
* This is a class instead of a free-standing function because VendorTagDescriptor has some
* protected fields that need to be initialized during conversion.
*/
class AidlVendorTagDescriptor : public VendorTagDescriptor {
public:
/**
* Create a VendorTagDescriptor object from the AIDL VendorTagSection
* vector.
*
* Returns OK on success, or a negative error code.
*/
static status_t createDescriptorFromAidl(const std::vector<VendorTagSection>& vts,
/*out*/ sp<VendorTagDescriptor> *descriptor);
};
status_t AidlVendorTagDescriptor::createDescriptorFromAidl(const std::vector<VendorTagSection>& vts,
sp<VendorTagDescriptor>* descriptor){
size_t tagCount = 0;
for (size_t s = 0; s < vts.size(); s++) {
tagCount += vts[s].tags.size();
}
if (tagCount < 0 || tagCount > INT32_MAX) {
ALOGE("%s: tag count %zu from vendor tag sections is invalid.", __FUNCTION__, tagCount);
return BAD_VALUE;
}
std::vector<int64_t> tagArray;
tagArray.resize(tagCount);
sp<AidlVendorTagDescriptor> desc = new AidlVendorTagDescriptor();
desc->mTagCount = tagCount;
std::map<int64_t, std::string> tagToSectionMap;
int idx = 0;
for (size_t s = 0; s < vts.size(); s++) {
const VendorTagSection& section = vts[s];
const char *sectionName = section.sectionName.c_str();
if (sectionName == nullptr) {
ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
return BAD_VALUE;
}
String8 sectionString(sectionName);
desc->mSections.add(sectionString);
for (size_t j = 0; j < section.tags.size(); j++) {
uint32_t tag = section.tags[j].tagId;
if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
return BAD_VALUE;
}
tagArray[idx++] = section.tags[j].tagId;
const char *tagName = section.tags[j].tagName.c_str();
if (tagName == nullptr) {
ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
return BAD_VALUE;
}
desc->mTagToNameMap.add(tag, String8(tagName));
tagToSectionMap.insert({tag, section.sectionName});
int tagType = (int) section.tags[j].tagType;
if (tagType < 0 || tagType >= NUM_TYPES) {
ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
return BAD_VALUE;
}
desc->mTagToTypeMap.emplace(tag, tagType);
}
}
for (size_t i = 0; i < tagArray.size(); ++i) {
uint32_t tag = tagArray[i];
auto itr = tagToSectionMap.find(tag);
if (itr == tagToSectionMap.end()) {
ALOGE("%s: Couldn't find previously added tag in map.", __FUNCTION__);
return UNKNOWN_ERROR;
}
String8 sectionString = String8(itr->second.c_str());
// Set up tag to section index map
ssize_t index = desc->mSections.indexOf(sectionString);
LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
// Set up reverse mapping
ssize_t reverseIndex = -1;
if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
}
desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
}
*descriptor = std::move(desc);
return OK;
}
std::shared_ptr<CameraManagerGlobal> CameraManagerGlobal::getInstance() {
Mutex::Autolock _l(sLock);
std::shared_ptr<CameraManagerGlobal> instance = sInstance.lock();
if (instance == nullptr) {
instance = std::make_shared<CameraManagerGlobal>();
sInstance = instance;
}
return instance;
}
CameraManagerGlobal::~CameraManagerGlobal() {
Mutex::Autolock _sl(sLock);
Mutex::Autolock _l(mLock);
if (mCameraService != nullptr) {
AIBinder_unlinkToDeath(mCameraService->asBinder().get(),
mDeathRecipient.get(), this);
auto stat = mCameraService->removeListener(mCameraServiceListener);
if (!stat.isOk()) {
ALOGE("Failed to remove listener to camera service %d:%d", stat.getExceptionCode(),
stat.getServiceSpecificError());
}
}
if (mCbLooper != nullptr) {
mCbLooper->unregisterHandler(mHandler->id());
mCbLooper->stop();
}
mCbLooper.clear();
mHandler.clear();
mCameraServiceListener.reset();
mCameraService.reset();
}
static bool isCameraServiceDisabled() {
char value[PROPERTY_VALUE_MAX];
property_get("config.disable_cameraservice", value, "0");
return (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0);
}
bool CameraManagerGlobal::setupVendorTags() {
sp<VendorTagDescriptorCache> tagCache = new VendorTagDescriptorCache();
Status status = Status::NO_ERROR;
std::vector<ProviderIdAndVendorTagSections> providerIdsAndVts;
ScopedAStatus remoteRet = mCameraService->getCameraVendorTagSections(&providerIdsAndVts);
if (!remoteRet.isOk()) {
if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());
ALOGE("%s: Failed to retrieve VendorTagSections %s",
__FUNCTION__, toString(status).c_str());
} else {
ALOGE("%s: Binder error when retrieving VendorTagSections: %d", __FUNCTION__,
remoteRet.getExceptionCode());
}
return false;
}
// Convert each providers VendorTagSections into a VendorTagDescriptor and
// add it to the cache
for (auto &providerIdAndVts : providerIdsAndVts) {
sp<VendorTagDescriptor> vendorTagDescriptor;
status_t ret = AidlVendorTagDescriptor::createDescriptorFromAidl(
providerIdAndVts.vendorTagSections, &vendorTagDescriptor);
if (ret != OK) {
ALOGE("Failed to convert from Aidl: VendorTagDescriptor: %d", ret);
return false;
}
tagCache->addVendorDescriptor(providerIdAndVts.providerId, vendorTagDescriptor);
}
VendorTagDescriptorCache::setAsGlobalVendorTagCache(tagCache);
return true;
}
std::shared_ptr<ICameraService> CameraManagerGlobal::getCameraService() {
Mutex::Autolock _l(mLock);
if (mCameraService != nullptr) {
// Camera service already set up. Return existing value.
return mCameraService;
}
if (isCameraServiceDisabled()) {
// Camera service is disabled. return nullptr.
return mCameraService;
}
std::string serviceName = ICameraService::descriptor;
serviceName += "/default";
bool isDeclared = AServiceManager_isDeclared(serviceName.c_str());
if (!isDeclared) {
ALOGE("%s: No ICameraService instance declared: %s", __FUNCTION__, serviceName.c_str());
return nullptr;
}
// Before doing any more make sure there is a binder threadpool alive
// This is a no-op if the binder threadpool was already started by this process.
ABinderProcess_startThreadPool();
std::shared_ptr<ICameraService> cameraService =
ICameraService::fromBinder(ndk::SpAIBinder(
AServiceManager_waitForService(serviceName.c_str())));
if (cameraService == nullptr) {
ALOGE("%s: Could not get ICameraService instance.", __FUNCTION__);
return nullptr;
}
if (mDeathRecipient.get() == nullptr) {
mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
AIBinder_DeathRecipient_new(CameraManagerGlobal::binderDeathCallback));
}
AIBinder_linkToDeath(cameraService->asBinder().get(),
mDeathRecipient.get(), /*cookie=*/ this);
mCameraService = cameraService;
// Setup looper thread to perform availability callbacks
if (mCbLooper == nullptr) {
mCbLooper = new ALooper;
mCbLooper->setName("C2N-mgr-looper");
status_t err = mCbLooper->start(
/*runOnCallingThread*/false,
/*canCallJava*/ true,
PRIORITY_DEFAULT);
if (err != OK) {
ALOGE("%s: Unable to start camera service listener looper: %s (%d)",
__FUNCTION__, strerror(-err), err);
mCbLooper.clear();
return nullptr;
}
if (mHandler == nullptr) {
mHandler = new CallbackHandler(weak_from_this());
}
mCbLooper->registerHandler(mHandler);
}
// register ICameraServiceListener
if (mCameraServiceListener == nullptr) {
mCameraServiceListener = ndk::SharedRefBase::make<CameraServiceListener>(weak_from_this());
}
std::vector<CameraStatusAndId> cameraStatuses;
Status status = Status::NO_ERROR;
ScopedAStatus remoteRet = mCameraService->addListener(mCameraServiceListener,
&cameraStatuses);
if (!remoteRet.isOk()) {
if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());
ALOGE("%s: Failed to add listener to camera service: %s", __FUNCTION__,
toString(errStatus).c_str());
} else {
ALOGE("%s: Transaction failed when adding listener to camera service: %d",
__FUNCTION__, remoteRet.getExceptionCode());
}
}
// Setup vendor tags
if (!setupVendorTags()) {
ALOGE("Unable to set up vendor tags");
return nullptr;
}
for (auto& csi: cameraStatuses){
onStatusChangedLocked(csi.deviceStatus, csi.cameraId);
for (auto& unavailablePhysicalId : csi.unavailPhysicalCameraIds) {
onStatusChangedLocked(CameraDeviceStatus::STATUS_NOT_PRESENT,
csi.cameraId, unavailablePhysicalId);
}
}
return mCameraService;
}
void CameraManagerGlobal::binderDeathCallback(void* /*cookie*/) {
AutoMutex _l(sLock);
ALOGE("Camera service binderDied!");
std::shared_ptr<CameraManagerGlobal> instance = sInstance.lock();
if (instance == nullptr) {
return;
}
// Remove cameraService from the static instance
AutoMutex lock(instance->mLock);
for (auto& pair : instance->mDeviceStatusMap) {
const auto &cameraId = pair.first;
const auto &deviceStatus = pair.second.getStatus();
instance->onStatusChangedLocked(deviceStatus, cameraId);
}
instance->mCameraService.reset();
// TODO: consider adding re-connect call here?
}
void CameraManagerGlobal::registerAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback) {
return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(callback);
}
void CameraManagerGlobal::unregisterAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
drainPendingCallbacksLocked();
Callback cb(callback);
mCallbacks.erase(cb);
}
void CameraManagerGlobal::registerExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
return registerAvailCallback<ACameraManager_ExtendedAvailabilityCallbacks>(callback);
}
void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
drainPendingCallbacksLocked();
Callback cb(callback);
mCallbacks.erase(cb);
}
void CameraManagerGlobal::onCallbackCalled() {
Mutex::Autolock _l(mLock);
if (mPendingCallbackCnt > 0) {
mPendingCallbackCnt--;
}
mCallbacksCond.signal();
}
void CameraManagerGlobal::drainPendingCallbacksLocked() {
while (mPendingCallbackCnt > 0) {
auto res = mCallbacksCond.waitRelative(mLock, kCallbackDrainTimeout);
if (res != NO_ERROR) {
ALOGE("%s: Error waiting to drain callbacks: %s(%d)",
__FUNCTION__, strerror(-res), res);
break;
}
}
}
template <class T>
void CameraManagerGlobal::registerAvailCallback(const T *callback) {
Mutex::Autolock _l(mLock);
Callback cb(callback);
auto res = mCallbacks.insert(cb);
if (!res.second) {
ALOGE("%s: Failed to register callback. Couldn't insert in map.", __FUNCTION__);
return;
}
// Send initial callbacks if callback is newly registered
for (auto& pair : mDeviceStatusMap) {
const std::string& cameraId = pair.first;
CameraDeviceStatus status = pair.second.getStatus();
{
// Camera available/unavailable callback
sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
cb.mAvailable : cb.mUnavailable;
msg->setPointer(kCallbackFpKey, (void *) cbFunc);
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId.c_str()));
mPendingCallbackCnt++;
msg->post();
}
// Physical camera unavailable callback
std::set<std::string> unavailPhysicalIds = pair.second.getUnavailablePhysicalIds();
for (const auto& physicalCameraId : unavailPhysicalIds) {
sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
cb.mPhysicalCamUnavailable;
msg->setPointer(kCallbackFpKey, (void *) cbFunc);
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId.c_str()));
msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
mPendingCallbackCnt++;
msg->post();
}
}
}
void CameraManagerGlobal::getCameraIdList(std::vector<std::string>* cameraIds) {
// Ensure that we have initialized/refreshed the list of available devices
auto cs = getCameraService();
Mutex::Autolock _l(mLock);
for(auto& deviceStatus : mDeviceStatusMap) {
CameraDeviceStatus status = deviceStatus.second.getStatus();
if (status == CameraDeviceStatus::STATUS_NOT_PRESENT ||
status == CameraDeviceStatus::STATUS_ENUMERATING) {
continue;
}
cameraIds->push_back(deviceStatus.first);
}
}
bool CameraManagerGlobal::validStatus(CameraDeviceStatus status) {
switch (status) {
case CameraDeviceStatus::STATUS_NOT_PRESENT:
case CameraDeviceStatus::STATUS_PRESENT:
case CameraDeviceStatus::STATUS_ENUMERATING:
case CameraDeviceStatus::STATUS_NOT_AVAILABLE:
return true;
default:
return false;
}
}
bool CameraManagerGlobal::isStatusAvailable(CameraDeviceStatus status) {
switch (status) {
case CameraDeviceStatus::STATUS_PRESENT:
return true;
default:
return false;
}
}
void CameraManagerGlobal::CallbackHandler::onMessageReceived(
const sp<AMessage> &msg) {
onMessageReceivedInternal(msg);
if (msg->what() == kWhatSendSingleCallback ||
msg->what() == kWhatSendSinglePhysicalCameraCallback) {
notifyParent();
}
}
void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal(
const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSendSingleCallback:
{
ACameraManager_AvailabilityCallback cb;
void* context;
AString cameraId;
bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
if (!found) {
ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
return;
}
found = msg->findPointer(kContextKey, &context);
if (!found) {
ALOGE("%s: Cannot find callback context!", __FUNCTION__);
return;
}
found = msg->findString(kCameraIdKey, &cameraId);
if (!found) {
ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
return;
}
(*cb)(context, cameraId.c_str());
break;
}
case kWhatSendSinglePhysicalCameraCallback:
{
ACameraManager_PhysicalCameraAvailabilityCallback cb;
void* context;
AString cameraId;
AString physicalCameraId;
bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
if (!found) {
ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
return;
}
if (cb == nullptr) {
// Physical camera callback is null
return;
}
found = msg->findPointer(kContextKey, &context);
if (!found) {
ALOGE("%s: Cannot find callback context!", __FUNCTION__);
return;
}
found = msg->findString(kCameraIdKey, &cameraId);
if (!found) {
ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
return;
}
found = msg->findString(kPhysicalCameraIdKey, &physicalCameraId);
if (!found) {
ALOGE("%s: Cannot find physical camera ID!", __FUNCTION__);
return;
}
(*cb)(context, cameraId.c_str(), physicalCameraId.c_str());
break;
}
default:
ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
break;
}
}
void CameraManagerGlobal::CallbackHandler::notifyParent() {
std::shared_ptr<CameraManagerGlobal> parent = mParent.lock();
if (parent != nullptr) {
parent->onCallbackCalled();
}
}
ScopedAStatus CameraManagerGlobal::CameraServiceListener::onStatusChanged(
CameraDeviceStatus status, const std::string &cameraId) {
std::shared_ptr<CameraManagerGlobal> cm = mCameraManager.lock();
if (cm != nullptr) {
cm->onStatusChanged(status, cameraId);
} else {
ALOGE("Cannot deliver status change. Global camera manager died");
}
return ScopedAStatus::ok();
}
void CameraManagerGlobal::onStatusChanged(
const CameraDeviceStatus &status, const std::string &cameraId) {
Mutex::Autolock _l(mLock);
onStatusChangedLocked(status, cameraId);
}
void CameraManagerGlobal::onStatusChangedLocked(
const CameraDeviceStatus &status, const std::string &cameraId) {
if (!validStatus(status)) {
ALOGE("%s: Invalid status %d", __FUNCTION__, status);
return;
}
bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
CameraDeviceStatus oldStatus = firstStatus ?
status : // first status
mDeviceStatusMap[cameraId].getStatus();
if (!firstStatus &&
isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
// No status update. No need to send callback
return;
}
// Iterate through all registered callbacks
mDeviceStatusMap[cameraId].updateStatus(status);
for (auto cb : mCallbacks) {
sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
cb.mAvailable : cb.mUnavailable;
msg->setPointer(kCallbackFpKey, (void *) cbFp);
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId.c_str()));
mPendingCallbackCnt++;
msg->post();
}
if (status == CameraDeviceStatus::STATUS_NOT_PRESENT) {
mDeviceStatusMap.erase(cameraId);
}
}
ScopedAStatus CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
CameraDeviceStatus in_status, const std::string& in_cameraId,
const std::string& in_physicalCameraId) {
std::shared_ptr<CameraManagerGlobal> cm = mCameraManager.lock();
if (cm != nullptr) {
cm->onStatusChanged(in_status, in_cameraId, in_physicalCameraId);
} else {
ALOGE("Cannot deliver status change. Global camera manager died");
}
return ScopedAStatus::ok();
}
void CameraManagerGlobal::onStatusChanged(
const CameraDeviceStatus &status, const std::string& cameraId,
const std::string& physicalCameraId) {
Mutex::Autolock _l(mLock);
onStatusChangedLocked(status, cameraId, physicalCameraId);
}
void CameraManagerGlobal::onStatusChangedLocked(
const CameraDeviceStatus &status, const std::string& cameraId,
const std::string& physicalCameraId) {
if (!validStatus(status)) {
ALOGE("%s: Invalid status %d", __FUNCTION__, status);
return;
}
auto logicalStatus = mDeviceStatusMap.find(cameraId);
if (logicalStatus == mDeviceStatusMap.end()) {
ALOGE("%s: Physical camera id %s status change on a non-present id %s",
__FUNCTION__, physicalCameraId.c_str(), cameraId.c_str());
return;
}
CameraDeviceStatus logicalCamStatus = mDeviceStatusMap[cameraId].getStatus();
if (logicalCamStatus != CameraDeviceStatus::STATUS_PRESENT &&
logicalCamStatus != CameraDeviceStatus::STATUS_NOT_AVAILABLE) {
ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
__FUNCTION__, physicalCameraId.c_str(), status, logicalCamStatus);
return;
}
bool updated = false;
if (status == CameraDeviceStatus::STATUS_PRESENT) {
updated = mDeviceStatusMap[cameraId].removeUnavailablePhysicalId(physicalCameraId);
} else {
updated = mDeviceStatusMap[cameraId].addUnavailablePhysicalId(physicalCameraId);
}
// Iterate through all registered callbacks
if (updated) {
for (auto cb : mCallbacks) {
sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
ACameraManager_PhysicalCameraAvailabilityCallback cbFp = isStatusAvailable(status) ?
cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable;
msg->setPointer(kCallbackFpKey, (void *) cbFp);
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId.c_str()));
msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
mPendingCallbackCnt++;
msg->post();
}
}
}
CameraDeviceStatus CameraManagerGlobal::CameraStatus::getStatus() {
std::lock_guard<std::mutex> lock(mLock);
return status;
}
void CameraManagerGlobal::CameraStatus::updateStatus(CameraDeviceStatus newStatus) {
std::lock_guard<std::mutex> lock(mLock);
status = newStatus;
}
bool CameraManagerGlobal::CameraStatus::addUnavailablePhysicalId(
const std::string& physicalCameraId) {
std::lock_guard<std::mutex> lock(mLock);
auto result = unavailablePhysicalIds.insert(physicalCameraId);
return result.second;
}
bool CameraManagerGlobal::CameraStatus::removeUnavailablePhysicalId(
const std::string& physicalCameraId) {
std::lock_guard<std::mutex> lock(mLock);
auto count = unavailablePhysicalIds.erase(physicalCameraId);
return count > 0;
}
std::set<std::string> CameraManagerGlobal::CameraStatus::getUnavailablePhysicalIds() {
std::lock_guard<std::mutex> lock(mLock);
return unavailablePhysicalIds;
}
} // namespace acam
} // namespace android
/**
* ACameraManger Implementation
*/
camera_status_t ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
Mutex::Autolock _l(mLock);
std::vector<std::string> idList;
CameraManagerGlobal::getInstance()->getCameraIdList(&idList);
int numCameras = idList.size();
ACameraIdList *out = new ACameraIdList;
if (out == nullptr) {
ALOGE("Allocate memory for ACameraIdList failed!");
return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
}
out->numCameras = numCameras;
out->cameraIds = new const char*[numCameras];
if (!out->cameraIds) {
ALOGE("Allocate memory for ACameraIdList failed!");
deleteCameraIdList(out);
return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
}
for (int i = 0; i < numCameras; i++) {
const char* src = idList[i].c_str();
size_t dstSize = strlen(src) + 1;
char* dst = new char[dstSize];
if (!dst) {
ALOGE("Allocate memory for ACameraIdList failed!");
deleteCameraIdList(out);
return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
}
strlcpy(dst, src, dstSize);
out->cameraIds[i] = dst;
}
*cameraIdList = out;
return ACAMERA_OK;
}
void
ACameraManager::deleteCameraIdList(ACameraIdList* cameraIdList) {
if (cameraIdList != nullptr) {
if (cameraIdList->cameraIds != nullptr) {
for (int i = 0; i < cameraIdList->numCameras; i ++) {
if (cameraIdList->cameraIds[i] != nullptr) {
delete[] cameraIdList->cameraIds[i];
}
}
delete[] cameraIdList->cameraIds;
}
delete cameraIdList;
}
}
camera_status_t ACameraManager::getCameraCharacteristics(const char *cameraIdStr,
sp<ACameraMetadata> *characteristics) {
using AidlCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
Mutex::Autolock _l(mLock);
std::shared_ptr<ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
AidlCameraMetadata rawMetadata;
ScopedAStatus serviceRet = cs->getCameraCharacteristics(cameraIdStr, &rawMetadata);
if (!serviceRet.isOk()) {
if (serviceRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
Status errStatus = static_cast<Status>(serviceRet.getServiceSpecificError());
ALOGE("%s: Get camera characteristics from camera service failed: %s",
__FUNCTION__, toString(errStatus).c_str());
} else {
ALOGE("%s: Transaction error when getting camera "
"characteristics from camera service: %d",
__FUNCTION__, serviceRet.getExceptionCode());
}
return ACAMERA_ERROR_UNKNOWN; // should not reach here
}
camera_metadata_t* metadataBuffer;
::android::acam::utils::cloneFromAidl(rawMetadata, &metadataBuffer);
*characteristics = new ACameraMetadata(metadataBuffer,
ACameraMetadata::ACM_CHARACTERISTICS);
return ACAMERA_OK;
}
camera_status_t
ACameraManager::openCamera(
const char* cameraId,
ACameraDevice_StateCallbacks* callback,
/*out*/ACameraDevice** outDevice) {
sp<ACameraMetadata> rawChars;
camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
Mutex::Autolock _l(mLock);
if (ret != ACAMERA_OK) {
ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
__FUNCTION__, cameraId, ret);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(rawChars));
std::shared_ptr<ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
delete device;
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
std::shared_ptr<BnCameraDeviceCallback> deviceCallback = device->getServiceCallback();
std::shared_ptr<ICameraDeviceUser> deviceRemote;
// No way to get package name from native.
// Send a zero length package name and let camera service figure it out from UID
ScopedAStatus serviceRet = cs->connectDevice(deviceCallback,
std::string(cameraId), &deviceRemote);
if (!serviceRet.isOk()) {
if (serviceRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
Status errStatus = static_cast<Status>(serviceRet.getServiceSpecificError());
ALOGE("%s: connect camera device failed: %s",
__FUNCTION__, toString(errStatus).c_str());
delete device;
return utils::convertFromAidl(errStatus);
} else {
ALOGE("%s: Transaction failed when connecting camera device: %d",
__FUNCTION__, serviceRet.getExceptionCode());
delete device;
return ACAMERA_ERROR_UNKNOWN;
}
}
if (deviceRemote == nullptr) {
ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
delete device;
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
device->setRemoteDevice(deviceRemote);
device->setDeviceMetadataQueues();
*outDevice = device;
return ACAMERA_OK;
}
camera_status_t
ACameraManager::getTagFromName(const char *cameraId, const char *name, uint32_t *tag) {
sp<ACameraMetadata> rawChars;
camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
if (ret != ACAMERA_OK) {
ALOGE("%s, Cannot retrieve camera characteristics for camera id %s", __FUNCTION__,
cameraId);
return ACAMERA_ERROR_METADATA_NOT_FOUND;
}
const CameraMetadata& metadata = rawChars->getInternalData();
const camera_metadata_t *rawMetadata = metadata.getAndLock();
metadata_vendor_id_t vendorTagId = get_camera_metadata_vendor_id(rawMetadata);
metadata.unlock(rawMetadata);
sp<VendorTagDescriptorCache> vtCache = VendorTagDescriptorCache::getGlobalVendorTagCache();
sp<VendorTagDescriptor> vTags = nullptr;
vtCache->getVendorTagDescriptor(vendorTagId, &vTags);
status_t status = CameraMetadata::getTagFromName(name, vTags.get(), tag);
return status == OK ? ACAMERA_OK : ACAMERA_ERROR_METADATA_NOT_FOUND;
}
ACameraManager::~ACameraManager() {
}