blob: 5dddd29c74bd7b6d3ef4f74f3032c1f1a5c8543c [file] [log] [blame]
/*
* Copyright (C) 2015 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 "ACameraManager"
#include "ACameraManager.h"
#include <android_companion_virtualdevice_flags.h>
#include <camera/CameraUtils.h>
#include <camera/StringUtils.h>
#include <camera/VendorTagDescriptor.h>
#include <cutils/properties.h>
#include <stdlib.h>
#include <utils/Vector.h>
#include <memory>
#include "ACameraDevice.h"
#include "ACameraMetadata.h"
#include <com_android_internal_camera_flags.h>
using namespace android::acam;
namespace vd_flags = android::companion::virtualdevice::flags;
namespace flags = com::android::internal::camera::flags;
namespace android {
namespace acam {
namespace {
using ::android::binder::Status;
using ::android::companion::virtualnative::IVirtualDeviceManagerNative;
// Return binder connection to VirtualDeviceManager.
//
// Subsequent calls return the same cached instance.
sp<IVirtualDeviceManagerNative> getVirtualDeviceManager() {
auto connectToVirtualDeviceManagerNative = []() {
sp<IBinder> binder =
defaultServiceManager()->checkService(String16("virtualdevice_native"));
if (binder == nullptr) {
ALOGW("%s: Cannot get virtualdevice_native service", __func__);
return interface_cast<IVirtualDeviceManagerNative>(nullptr);
}
return interface_cast<IVirtualDeviceManagerNative>(binder);
};
static sp<IVirtualDeviceManagerNative> vdm = connectToVirtualDeviceManagerNative();
return vdm;
}
// Returns device id calling process is running on.
// If the process cannot be attributed to single virtual device id, returns default device id.
int getCurrentDeviceId() {
if (!vd_flags::camera_device_awareness()) {
return kDefaultDeviceId;
}
auto vdm = getVirtualDeviceManager();
if (vdm == nullptr) {
return kDefaultDeviceId;
}
const uid_t myUid = getuid();
std::vector<int> deviceIds;
Status status = vdm->getDeviceIdsForUid(myUid, &deviceIds);
if (!status.isOk() || deviceIds.empty()) {
ALOGE("%s: Failed to call getDeviceIdsForUid to determine device id for uid %d: %s",
__func__, myUid, status.toString8().c_str());
return kDefaultDeviceId;
}
// If the UID is associated with multiple virtual devices, use the default device's
// camera as we cannot disambiguate here. This effectively means that the app has
// activities on different devices at the same time.
if (deviceIds.size() != 1) {
return kDefaultDeviceId;
}
return deviceIds[0];
}
// Returns device policy for POLICY_TYPE_CAMERA corresponding to deviceId.
DevicePolicy getDevicePolicyForDeviceId(const int deviceId) {
if (!vd_flags::camera_device_awareness() || deviceId == kDefaultDeviceId) {
return DevicePolicy::DEVICE_POLICY_DEFAULT;
}
auto vdm = getVirtualDeviceManager();
if (vdm == nullptr) {
return DevicePolicy::DEVICE_POLICY_DEFAULT;
}
int policy = IVirtualDeviceManagerNative::DEVICE_POLICY_DEFAULT;
Status status = vdm->getDevicePolicy(deviceId, IVirtualDeviceManagerNative::POLICY_TYPE_CAMERA,
&policy);
if (!status.isOk()) {
ALOGE("%s: Failed to call getDevicePolicy to determine camera policy for device id %d: %s",
__func__, deviceId, status.toString8().c_str());
return DevicePolicy::DEVICE_POLICY_DEFAULT;
}
return static_cast<DevicePolicy>(policy);
}
// Returns true if camera owned by device cameraDeviceId can be accessed within deviceContext.
bool isCameraAccessible(const DeviceContext deviceContext, const int cameraDeviceId) {
if (!vd_flags::camera_device_awareness() ||
deviceContext.policy == DevicePolicy::DEVICE_POLICY_DEFAULT) {
return cameraDeviceId == kDefaultDeviceId;
}
return deviceContext.deviceId == cameraDeviceId;
}
} // namespace
// 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;
wp<CameraManagerGlobal> CameraManagerGlobal::sInstance = nullptr;
DeviceContext::DeviceContext() {
deviceId = getCurrentDeviceId();
policy = getDevicePolicyForDeviceId(deviceId);
}
sp<CameraManagerGlobal> CameraManagerGlobal::getInstance() {
Mutex::Autolock _l(sLock);
sp<CameraManagerGlobal> instance = sInstance.promote();
if (instance == nullptr) {
instance = new CameraManagerGlobal();
sInstance = instance;
}
return instance;
}
CameraManagerGlobal::~CameraManagerGlobal() {
// clear sInstance so next getInstance call knows to create a new one
Mutex::Autolock _sl(sLock);
sInstance = nullptr;
Mutex::Autolock _l(mLock);
if (mCameraService != nullptr) {
IInterface::asBinder(mCameraService)->unlinkToDeath(mDeathNotifier);
mCameraService->removeListener(mCameraServiceListener);
}
mDeathNotifier.clear();
if (mCbLooper != nullptr) {
mCbLooper->unregisterHandler(mHandler->id());
mCbLooper->stop();
}
mCbLooper.clear();
mHandler.clear();
mCameraServiceListener.clear();
mCameraService.clear();
}
sp<hardware::ICameraService> CameraManagerGlobal::getCameraService() {
Mutex::Autolock _l(mLock);
return getCameraServiceLocked();
}
sp<hardware::ICameraService> CameraManagerGlobal::getCameraServiceLocked() {
if (mCameraService.get() != nullptr) {
return mCameraService;
}
if (CameraUtils::isCameraServiceDisabled()) {
return mCameraService;
}
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
binder = sm->checkService(String16(kCameraServiceName));
if (binder == nullptr) {
ALOGE("%s: Could not get CameraService instance.", __FUNCTION__);
return nullptr;
}
sp<hardware::ICameraService> cameraService = interface_cast<hardware::ICameraService>(binder);
if (mDeathNotifier == nullptr) {
mDeathNotifier = new DeathNotifier(this);
binder->linkToDeath(mDeathNotifier);
}
// 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(this);
}
mCbLooper->registerHandler(mHandler);
}
// register ICameraServiceListener
std::vector<hardware::CameraStatus> cameraStatuses{};
if (mCameraServiceListener == nullptr) {
mCameraServiceListener = new CameraServiceListener(this);
cameraService->addListener(mCameraServiceListener, &cameraStatuses);
}
for (auto& c : cameraStatuses) {
onStatusChangedLocked(c.status, c.deviceId, c.cameraId);
for (auto& unavailablePhysicalId : c.unavailablePhysicalIds) {
onStatusChangedLocked(hardware::ICameraServiceListener::STATUS_NOT_PRESENT,
c.deviceId, c.cameraId, unavailablePhysicalId);
}
}
// setup vendor tags
if (!setupVendorTags(cameraService)) {
ALOGE("%s: Vendor tag descriptor cache couldn't be set up", __FUNCTION__);
return nullptr;
}
mCameraService = cameraService;
ALOGE_IF(mCameraService == nullptr, "no CameraService!?");
return mCameraService;
}
bool CameraManagerGlobal::setupVendorTags(sp<hardware::ICameraService> &cameraService) {
sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
binder::Status ret = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
if (!ret.isOk()) {
if (ret.serviceSpecificErrorCode() ==
hardware::ICameraService::ERROR_DEPRECATED_HAL) {
ALOGW("%s: Camera HAL too old; does not support vendor tags",
__FUNCTION__);
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
} else {
ALOGE("%s: Failed to get vendor tag descriptors: %s",
__FUNCTION__, ret.toString8().c_str());
}
return false;
}
if (0 < desc->getTagCount()) {
status_t err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
if (err != OK) {
ALOGE("%s: Failed to set vendor tag descriptors, received error %s (%d)",
__FUNCTION__, strerror(-err), err);
return false;
}
} else {
sp<VendorTagDescriptorCache> cache =
new VendorTagDescriptorCache();
binder::Status res =
cameraService->getCameraVendorTagCache(
/*out*/cache.get());
if (res.serviceSpecificErrorCode() ==
hardware::ICameraService::ERROR_DISCONNECTED) {
// No camera module available, not an error on devices with no cameras
VendorTagDescriptorCache::clearGlobalVendorTagCache();
} else if (res.isOk()) {
status_t err =
VendorTagDescriptorCache::setAsGlobalVendorTagCache(
cache);
if (err != OK) {
ALOGE("%s: Failed to set vendor tag cache,"
"received error %s (%d)", __FUNCTION__,
strerror(-err), err);
return false;
}
} else {
VendorTagDescriptorCache::clearGlobalVendorTagCache();
ALOGE("%s: Failed to setup vendor tag cache: %s",
__FUNCTION__, res.toString8().c_str());
return false;
}
}
return true;
}
void CameraManagerGlobal::DeathNotifier::binderDied(const wp<IBinder>&)
{
ALOGE("Camera service binderDied!");
sp<CameraManagerGlobal> cm = mCameraManager.promote();
if (cm != nullptr) {
AutoMutex lock(cm->mLock);
std::vector<DeviceStatusMapKey> keysToRemove;
keysToRemove.reserve(cm->mDeviceStatusMap.size());
for (auto& pair : cm->mDeviceStatusMap) {
keysToRemove.push_back(pair.first);
}
for (const DeviceStatusMapKey& key : keysToRemove) {
cm->onStatusChangedLocked(CameraServiceListener::STATUS_NOT_PRESENT, key.deviceId,
key.cameraId);
}
cm->mCameraService.clear();
cm->mCameraServiceListener.clear();
cm->mDeathNotifier.clear();
// TODO: consider adding re-connect call here?
}
}
void CameraManagerGlobal::registerExtendedAvailabilityCallback(
const DeviceContext& deviceContext,
const ACameraManager_ExtendedAvailabilityCallbacks* callback) {
return registerAvailCallback<ACameraManager_ExtendedAvailabilityCallbacks>(deviceContext,
callback);
}
void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
const DeviceContext& deviceContext,
const ACameraManager_ExtendedAvailabilityCallbacks* callback) {
Mutex::Autolock _l(mLock);
drainPendingCallbacksLocked();
Callback cb(deviceContext, callback);
mCallbacks.erase(cb);
}
void CameraManagerGlobal::registerAvailabilityCallback(
const DeviceContext& deviceContext, const ACameraManager_AvailabilityCallbacks* callback) {
return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(deviceContext, callback);
}
void CameraManagerGlobal::unregisterAvailabilityCallback(
const DeviceContext& deviceContext, const ACameraManager_AvailabilityCallbacks* callback) {
Mutex::Autolock _l(mLock);
drainPendingCallbacksLocked();
Callback cb(deviceContext, 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 DeviceContext& deviceContext,
const T* callback) {
Mutex::Autolock _l(mLock);
getCameraServiceLocked();
Callback cb(deviceContext, callback);
const auto& [_, newlyRegistered] = mCallbacks.insert(cb);
// Send initial callbacks if callback is newly registered
if (newlyRegistered) {
for (auto& [key, statusAndHAL3Support] : mDeviceStatusMap) {
if (!isCameraAccessible(deviceContext, key.deviceId)) {
continue;
}
const std::string& cameraId = key.cameraId;
int32_t status = statusAndHAL3Support.getStatus();
// Don't send initial callbacks for camera ids which don't support
// camera2
if (!statusAndHAL3Support.supportsHAL3) {
continue;
}
// 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> unavailablePhysicalCameras =
statusAndHAL3Support.getUnavailablePhysicalIds();
for (const auto& physicalCameraId : unavailablePhysicalCameras) {
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();
}
}
}
}
bool CameraManagerGlobal::supportsCamera2ApiLocked(const std::string &cameraId) {
bool camera2Support = false;
auto cs = getCameraServiceLocked();
if (cs == nullptr) {
return false;
}
binder::Status serviceRet =
cs->supportsCameraApi(cameraId,
hardware::ICameraService::API_VERSION_2, &camera2Support);
if (!serviceRet.isOk()) {
ALOGE("%s: supportsCameraApi2Locked() call failed for cameraId %s",
__FUNCTION__, cameraId.c_str());
return false;
}
return camera2Support;
}
void CameraManagerGlobal::getCameraIdList(const DeviceContext& context,
std::vector<std::string>* cameraIds) {
// Ensure that we have initialized/refreshed the list of available devices
Mutex::Autolock _l(mLock);
// Needed to make sure we're connected to cameraservice
getCameraServiceLocked();
for (auto& [key, statusAndHAL3Support] : mDeviceStatusMap) {
if (!isCameraAccessible(context, key.deviceId)) {
continue;
}
int32_t status = statusAndHAL3Support.getStatus();
if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
status == hardware::ICameraServiceListener::STATUS_ENUMERATING) {
continue;
}
if (!statusAndHAL3Support.supportsHAL3) {
continue;
}
cameraIds->push_back(key.cameraId);
}
}
bool CameraManagerGlobal::validStatus(int32_t status) {
switch (status) {
case hardware::ICameraServiceListener::STATUS_NOT_PRESENT:
case hardware::ICameraServiceListener::STATUS_PRESENT:
case hardware::ICameraServiceListener::STATUS_ENUMERATING:
case hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE:
return true;
default:
return false;
}
}
bool CameraManagerGlobal::isStatusAvailable(int32_t status) {
switch (status) {
case hardware::ICameraServiceListener::STATUS_PRESENT:
return true;
default:
return false;
}
}
void CameraManagerGlobal::CallbackHandler::onMessageReceived(
const sp<AMessage> &msg) {
onMessageReceivedInternal(msg);
if (msg->what() == kWhatSendSingleCallback ||
msg->what() == kWhatSendSingleAccessCallback ||
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 kWhatSendSingleAccessCallback:
{
ACameraManager_AccessPrioritiesChangedCallback 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;
}
(*cb)(context);
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() {
sp<CameraManagerGlobal> parent = mParent.promote();
if (parent != nullptr) {
parent->onCallbackCalled();
}
}
binder::Status CameraManagerGlobal::CameraServiceListener::onCameraAccessPrioritiesChanged() {
sp<CameraManagerGlobal> cm = mCameraManager.promote();
if (cm != nullptr) {
cm->onCameraAccessPrioritiesChanged();
} else {
ALOGE("Cannot deliver camera access priority callback. Global camera manager died");
}
return binder::Status::ok();
}
binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
int32_t status, const std::string& cameraId, int deviceId) {
sp<CameraManagerGlobal> cm = mCameraManager.promote();
if (cm != nullptr) {
cm->onStatusChanged(status, deviceId, cameraId);
}
ALOGE_IF(cm == nullptr,
"Cannot deliver physical camera status change. Global camera manager died");
return binder::Status::ok();
}
binder::Status CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
int32_t status, const std::string& cameraId, const std::string& physicalCameraId,
int deviceId) {
sp<CameraManagerGlobal> cm = mCameraManager.promote();
if (cm != nullptr) {
cm->onStatusChanged(status, deviceId, cameraId, physicalCameraId);
}
ALOGE_IF(cm == nullptr,
"Cannot deliver physical camera status change. Global camera manager died");
return binder::Status::ok();
}
void CameraManagerGlobal::onCameraAccessPrioritiesChanged() {
Mutex::Autolock _l(mLock);
for (auto cb : mCallbacks) {
sp<AMessage> msg = new AMessage(kWhatSendSingleAccessCallback, mHandler);
ACameraManager_AccessPrioritiesChangedCallback cbFp = cb.mAccessPriorityChanged;
if (cbFp != nullptr) {
msg->setPointer(kCallbackFpKey, (void *) cbFp);
msg->setPointer(kContextKey, cb.mContext);
mPendingCallbackCnt++;
msg->post();
}
}
}
void CameraManagerGlobal::onStatusChanged(int32_t status, const int deviceId,
const std::string& cameraId) {
Mutex::Autolock _l(mLock);
onStatusChangedLocked(status, deviceId, cameraId);
}
void CameraManagerGlobal::onStatusChangedLocked(int32_t status, const int deviceId,
const std::string& cameraId) {
if (!validStatus(status)) {
ALOGE("%s: Invalid status %d", __FUNCTION__, status);
return;
}
DeviceStatusMapKey key{.deviceId = deviceId, .cameraId = cameraId};
bool firstStatus = (mDeviceStatusMap.count(key) == 0);
int32_t oldStatus = firstStatus ? status : // first status
mDeviceStatusMap[key].getStatus();
if (!firstStatus &&
isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
// No status update. No need to send callback
return;
}
bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
if (firstStatus) {
mDeviceStatusMap.emplace(std::piecewise_construct, std::forward_as_tuple(key),
std::forward_as_tuple(status, supportsHAL3));
} else {
mDeviceStatusMap[key].updateStatus(status);
}
// Iterate through all registered callbacks
if (supportsHAL3) {
for (auto cb : mCallbacks) {
if (!isCameraAccessible(cb.mDeviceContext, deviceId)) {
continue;
}
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 == hardware::ICameraServiceListener::STATUS_NOT_PRESENT) {
mDeviceStatusMap.erase(key);
}
}
void CameraManagerGlobal::onStatusChanged(int32_t status, const int deviceId,
const std::string& cameraId, const std::string& physicalCameraId) {
Mutex::Autolock _l(mLock);
onStatusChangedLocked(status, deviceId, cameraId, physicalCameraId);
}
void CameraManagerGlobal::onStatusChangedLocked(int32_t status, const int deviceId,
const std::string& cameraId, const std::string& physicalCameraId) {
if (!validStatus(status)) {
ALOGE("%s: Invalid status %d", __FUNCTION__, status);
return;
}
DeviceStatusMapKey key{.deviceId = deviceId, .cameraId = cameraId};
auto logicalStatus = mDeviceStatusMap.find(key);
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;
}
int32_t logicalCamStatus = mDeviceStatusMap[key].getStatus();
if (logicalCamStatus != hardware::ICameraServiceListener::STATUS_PRESENT &&
logicalCamStatus != hardware::ICameraServiceListener::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 supportsHAL3 = supportsCamera2ApiLocked(cameraId);
bool updated = false;
if (status == hardware::ICameraServiceListener::STATUS_PRESENT) {
updated = mDeviceStatusMap[key].removeUnavailablePhysicalId(physicalCameraId);
} else {
updated = mDeviceStatusMap[key].addUnavailablePhysicalId(physicalCameraId);
}
// Iterate through all registered callbacks
if (supportsHAL3 && updated) {
for (auto cb : mCallbacks) {
if (!isCameraAccessible(cb.mDeviceContext, deviceId)) {
continue;
}
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();
}
}
}
int32_t CameraManagerGlobal::StatusAndHAL3Support::getStatus() {
std::lock_guard<std::mutex> lock(mLock);
return status;
}
void CameraManagerGlobal::StatusAndHAL3Support::updateStatus(int32_t newStatus) {
std::lock_guard<std::mutex> lock(mLock);
status = newStatus;
}
bool CameraManagerGlobal::StatusAndHAL3Support::addUnavailablePhysicalId(
const std::string& physicalCameraId) {
std::lock_guard<std::mutex> lock(mLock);
auto result = unavailablePhysicalIds.insert(physicalCameraId);
return result.second;
}
bool CameraManagerGlobal::StatusAndHAL3Support::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::StatusAndHAL3Support::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;
mGlobalManager->getCameraIdList(mDeviceContext, &idList);
int numCameras = idList.size();
ACameraIdList *out = new ACameraIdList;
if (!out) {
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) {
Mutex::Autolock _l(mLock);
sp<hardware::ICameraService> cs = mGlobalManager->getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
CameraMetadata rawMetadata;
int targetSdkVersion = android_get_application_target_sdk_version();
AttributionSourceState clientAttribution;
clientAttribution.uid = hardware::ICameraService::USE_CALLING_UID;
clientAttribution.pid = hardware::ICameraService::USE_CALLING_PID;
clientAttribution.deviceId = mDeviceContext.deviceId;
binder::Status serviceRet = cs->getCameraCharacteristics(cameraIdStr,
targetSdkVersion, /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_NONE,
clientAttribution, static_cast<int32_t>(mDeviceContext.policy),
&rawMetadata);
if (!serviceRet.isOk()) {
switch(serviceRet.serviceSpecificErrorCode()) {
case hardware::ICameraService::ERROR_DISCONNECTED:
ALOGE("%s: Camera %s has been disconnected", __FUNCTION__, cameraIdStr);
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
return ACAMERA_ERROR_INVALID_PARAMETER;
default:
ALOGE("Get camera characteristics from camera service failed: %s",
serviceRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN; // should not reach here
}
}
*characteristics = new ACameraMetadata(
rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
return ACAMERA_OK;
}
camera_status_t
ACameraManager::isCameraDeviceSharingSupported(
const char* cameraId,
/*out*/bool* isSharingSupported) {
if (!flags::camera_multi_client()) {
return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
}
sp<ACameraMetadata> spChars;
camera_status_t ret = getCameraCharacteristics(cameraId, &spChars);
if (ret != ACAMERA_OK) {
ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
__FUNCTION__, cameraId, ret);
return ret;
}
ACameraMetadata* chars = spChars.get();
ACameraMetadata_const_entry entry;
ret = ACameraMetadata_getConstEntry(chars, ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS,
&entry);
if (ret != ACAMERA_OK) {
return ret;
}
*isSharingSupported = (entry.count > 0) ? true : false;
return ACAMERA_OK;
}
camera_status_t
ACameraManager::openCamera(
const char* cameraId, bool sharedMode,
ACameraDevice_StateCallbacks* callback,
/*out*/ACameraDevice** outDevice, /*out*/bool* primaryClient) {
sp<ACameraMetadata> chars;
camera_status_t ret = getCameraCharacteristics(cameraId, &chars);
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, chars, sharedMode);
sp<hardware::ICameraService> cs = mGlobalManager->getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
delete device;
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
sp<hardware::camera2::ICameraDeviceUser> deviceRemote;
int targetSdkVersion = android_get_application_target_sdk_version();
AttributionSourceState clientAttribution;
clientAttribution.uid = hardware::ICameraService::USE_CALLING_UID;
clientAttribution.pid = hardware::ICameraService::USE_CALLING_PID;
clientAttribution.deviceId = mDeviceContext.deviceId;
clientAttribution.packageName = "";
clientAttribution.attributionTag = std::nullopt;
// No way to get package name from native.
// Send a zero length package name and let camera service figure it out from UID
binder::Status serviceRet = cs->connectDevice(
callbacks, cameraId, /*oomScoreOffset*/0,
targetSdkVersion, /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_NONE,
clientAttribution, static_cast<int32_t>(mDeviceContext.policy), sharedMode,
/*out*/&deviceRemote);
if (!serviceRet.isOk()) {
ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().c_str());
// Convert serviceRet to camera_status_t
switch(serviceRet.serviceSpecificErrorCode()) {
case hardware::ICameraService::ERROR_DISCONNECTED:
ret = ACAMERA_ERROR_CAMERA_DISCONNECTED;
break;
case hardware::ICameraService::ERROR_CAMERA_IN_USE:
ret = ACAMERA_ERROR_CAMERA_IN_USE;
break;
case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
ret = ACAMERA_ERROR_MAX_CAMERA_IN_USE;
break;
case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
ret = ACAMERA_ERROR_INVALID_PARAMETER;
break;
case hardware::ICameraService::ERROR_DEPRECATED_HAL:
// Should not reach here since we filtered legacy HALs earlier
ret = ACAMERA_ERROR_INVALID_PARAMETER;
break;
case hardware::ICameraService::ERROR_DISABLED:
ret = ACAMERA_ERROR_CAMERA_DISABLED;
break;
case hardware::ICameraService::ERROR_PERMISSION_DENIED:
ret = ACAMERA_ERROR_PERMISSION_DENIED;
break;
case hardware::ICameraService::ERROR_INVALID_OPERATION:
default:
ret = ACAMERA_ERROR_UNKNOWN;
break;
}
delete device;
return ret;
}
if (deviceRemote == nullptr) {
ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
delete device;
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
device->setRemoteDevice(deviceRemote);
if (flags::camera_multi_client() && sharedMode) {
binder::Status remoteRet = deviceRemote->isPrimaryClient(primaryClient);
if (!remoteRet.isOk()) {
delete device;
return ACAMERA_ERROR_UNKNOWN;
}
device->setPrimaryClient(*primaryClient);
}
*outDevice = device;
return ACAMERA_OK;
}
void ACameraManager::registerAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks* callback) {
mGlobalManager->registerAvailabilityCallback(mDeviceContext, callback);
}
void ACameraManager::unregisterAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks* callback) {
mGlobalManager->unregisterAvailabilityCallback(mDeviceContext, callback);
}
void ACameraManager::registerExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks* callback) {
mGlobalManager->registerExtendedAvailabilityCallback(mDeviceContext, callback);
}
void ACameraManager::unregisterExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks* callback) {
mGlobalManager->unregisterExtendedAvailabilityCallback(mDeviceContext, callback);
}