Camera: Add support for hidden physical camera IDs

Support 3_5 HAL device version for querying physical camera
characteristics.

Test: Camera CTS on Pixel devices
Bug: 79523700
Change-Id: I804cdb5dc75553d6b6f9fb42187a76bd69168179
gugelfrei
Shuzhen Wang 6 years ago
parent dd6f1835aa
commit f9d2c02eca

@ -149,8 +149,10 @@ interface ICameraService
const int API_VERSION_1 = 1;
const int API_VERSION_2 = 2;
// Determines if a particular API version is supported directly
// Determines if a particular API version is supported directly for a cameraId.
boolean supportsCameraApi(String cameraId, int apiVersion);
// Determines if a cameraId is a hidden physical camera of a logical multi-camera.
boolean isHiddenPhysicalCamera(String cameraId);
void setTorchMode(String cameraId, boolean enabled, IBinder clientBinder);

@ -7209,8 +7209,14 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities {
ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING = 10,
/**
* <p>The camera device is a logical camera backed by two or more physical cameras that are
* also exposed to the application.</p>
* <p>The camera device is a logical camera backed by two or more physical cameras. In
* API level 28, the physical cameras must also be exposed to the application via
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraIdList">CameraManager#getCameraIdList</a>. Starting from API
* level 29, some or all physical cameras may not be independently exposed to the
* application, in which case the physical camera IDs will not be available in
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraIdList">CameraManager#getCameraIdList</a>. But the application
* can still query the physical cameras' characteristics by calling
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraCharacteristics">CameraManager#getCameraCharacteristics</a>.</p>
* <p>Camera application shouldn't assume that there are at most 1 rear camera and 1 front
* camera in the system. For an application that switches between front and back cameras,
* the recommendation is to switch between the first rear camera and the first front

@ -82,6 +82,7 @@ cc_library_shared {
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
"android.hardware.camera.device@3.5",
],
export_shared_lib_headers: [

@ -607,6 +607,7 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService,
case CAMERA_DEVICE_API_VERSION_3_2:
case CAMERA_DEVICE_API_VERSION_3_3:
case CAMERA_DEVICE_API_VERSION_3_4:
case CAMERA_DEVICE_API_VERSION_3_5:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName,
@ -1687,7 +1688,7 @@ Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion
}
int deviceVersion = getDeviceVersion(id);
switch(deviceVersion) {
switch (deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
case CAMERA_DEVICE_API_VERSION_3_0:
case CAMERA_DEVICE_API_VERSION_3_1:
@ -1704,6 +1705,7 @@ Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion
case CAMERA_DEVICE_API_VERSION_3_2:
case CAMERA_DEVICE_API_VERSION_3_3:
case CAMERA_DEVICE_API_VERSION_3_4:
case CAMERA_DEVICE_API_VERSION_3_5:
ALOGV("%s: Camera id %s uses HAL3.2 or newer, supports api1/api2 directly",
__FUNCTION__, id.string());
*isSupported = true;
@ -1724,6 +1726,18 @@ Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion
return Status::ok();
}
Status CameraService::isHiddenPhysicalCamera(const String16& cameraId,
/*out*/ bool *isSupported) {
ATRACE_CALL();
const String8 id = String8(cameraId);
ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string());
*isSupported = mCameraProviderManager->isHiddenPhysicalCamera(id.string());
return Status::ok();
}
void CameraService::removeByClient(const BasicClient* client) {
Mutex::Autolock lock(mServiceLock);
for (auto& i : mActiveClientManager.getAll()) {

@ -159,6 +159,11 @@ public:
/*out*/
bool *isSupported);
virtual binder::Status isHiddenPhysicalCamera(
const String16& cameraId,
/*out*/
bool *isSupported);
// Extra permissions checks
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);

@ -20,9 +20,12 @@
#include "CameraProviderManager.h"
#include <android/hardware/camera/device/3.5/ICameraDevice.h>
#include <algorithm>
#include <chrono>
#include <inttypes.h>
#include <hardware/camera_common.h>
#include <hidl/ServiceManagement.h>
#include <functional>
#include <camera_metadata_hidden.h>
@ -424,6 +427,48 @@ bool CameraProviderManager::isLogicalCamera(const CameraMetadata& staticInfo,
return true;
}
bool CameraProviderManager::isHiddenPhysicalCamera(const std::string& cameraId) {
for (auto& provider : mProviders) {
for (auto& deviceInfo : provider->mDevices) {
if (deviceInfo->mId == cameraId) {
// cameraId is found in public camera IDs advertised by the
// provider.
return false;
}
}
}
for (auto& provider : mProviders) {
for (auto& deviceInfo : provider->mDevices) {
CameraMetadata info;
status_t res = deviceInfo->getCameraCharacteristics(&info);
if (res != OK) {
ALOGE("%s: Failed to getCameraCharacteristics for id %s", __FUNCTION__,
deviceInfo->mId.c_str());
return false;
}
std::vector<std::string> physicalIds;
if (isLogicalCamera(info, &physicalIds)) {
if (std::find(physicalIds.begin(), physicalIds.end(), cameraId) !=
physicalIds.end()) {
int deviceVersion = HARDWARE_DEVICE_API_VERSION(
deviceInfo->mVersion.get_major(), deviceInfo->mVersion.get_minor());
if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_5) {
ALOGE("%s: Wrong deviceVersion %x for hiddenPhysicalCameraId %s",
__FUNCTION__, deviceVersion, cameraId.c_str());
return false;
} else {
return true;
}
}
}
}
}
return false;
}
status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
for (const auto& providerInfo : mProviders) {
if (providerInfo->mProviderName == newProvider) {
@ -544,13 +589,22 @@ status_t CameraProviderManager::ProviderInfo::initialize() {
// Get initial list of camera devices, if any
std::vector<std::string> devices;
hardware::Return<void> ret = mInterface->getCameraIdList([&status, &devices](
hardware::Return<void> ret = mInterface->getCameraIdList([&status, this, &devices](
Status idStatus,
const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
status = idStatus;
if (status == Status::OK) {
for (size_t i = 0; i < cameraDeviceNames.size(); i++) {
devices.push_back(cameraDeviceNames[i]);
for (auto& name : cameraDeviceNames) {
uint16_t major, minor;
std::string type, id;
status_t res = parseDeviceName(name, &major, &minor, &type, &id);
if (res != OK) {
ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
status = Status::INTERNAL_ERROR;
} else {
devices.push_back(name);
mProviderPublicCameraIds.push_back(id);
}
}
} });
if (!ret.isOk()) {
@ -705,6 +759,25 @@ status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector<String16
info2.dump(fd, /*verbosity*/ 2, /*indentation*/ 4);
}
// Dump characteristics of non-standalone physical camera
std::vector<std::string> physicalIds;
if (isLogicalCamera(info2, &physicalIds)) {
for (auto& id : physicalIds) {
// Skip if physical id is an independent camera
if (std::find(mProviderPublicCameraIds.begin(), mProviderPublicCameraIds.end(), id)
!= mProviderPublicCameraIds.end()) {
continue;
}
CameraMetadata physicalInfo;
status_t status = device->getPhysicalCameraCharacteristics(id, &physicalInfo);
if (status == OK) {
dprintf(fd, " Physical camera %s characteristics:\n", id.c_str());
physicalInfo.dump(fd, /*verbosity*/ 2, /*indentation*/ 4);
}
}
}
dprintf(fd, "== Camera HAL device %s (v%d.%d) dumpState: ==\n", device->mName.c_str(),
device->mVersion.get_major(), device->mVersion.get_minor());
res = device->dumpState(fd);
@ -838,7 +911,7 @@ std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
return std::unique_ptr<DeviceInfo>(
new DeviceInfoT(name, tagId, id, minorVersion, resourceCost,
cameraInterface));
mProviderPublicCameraIds, cameraInterface));
}
template<class InterfaceT>
@ -912,9 +985,10 @@ CameraProviderManager::ProviderInfo::DeviceInfo1::DeviceInfo1(const std::string&
const metadata_vendor_id_t tagId, const std::string &id,
uint16_t minorVersion,
const CameraResourceCost& resourceCost,
const std::vector<std::string>& publicCameraIds,
sp<InterfaceT> interface) :
DeviceInfo(name, tagId, id, hardware::hidl_version{1, minorVersion},
resourceCost),
publicCameraIds, resourceCost),
mInterface(interface) {
// Get default parameters and initialize flash unit availability
// Requires powering on the camera device
@ -1011,9 +1085,10 @@ CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string&
const metadata_vendor_id_t tagId, const std::string &id,
uint16_t minorVersion,
const CameraResourceCost& resourceCost,
const std::vector<std::string>& publicCameraIds,
sp<InterfaceT> interface) :
DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion},
resourceCost),
publicCameraIds, resourceCost),
mInterface(interface) {
// Get camera characteristics and initialize flash unit availability
Status status;
@ -1054,6 +1129,59 @@ CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string&
} else {
mHasFlashUnit = false;
}
// Get physical camera characteristics if applicable
auto castResult = device::V3_5::ICameraDevice::castFrom(mInterface);
if (!castResult.isOk()) {
ALOGV("%s: Unable to convert ICameraDevice instance to version 3.5", __FUNCTION__);
return;
}
sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult;
if (interface_3_5 == nullptr) {
ALOGE("%s: Converted ICameraDevice instance to nullptr", __FUNCTION__);
return;
}
std::vector<std::string> physicalIds;
if (CameraProviderManager::isLogicalCamera(mCameraCharacteristics, &physicalIds)) {
for (auto& id : physicalIds) {
if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) !=
mPublicCameraIds.end()) {
continue;
}
hardware::hidl_string hidlId(id);
ret = interface_3_5->getPhysicalCameraCharacteristics(hidlId,
[&status, &id, this](Status s, device::V3_2::CameraMetadata metadata) {
status = s;
if (s == Status::OK) {
camera_metadata_t *buffer =
reinterpret_cast<camera_metadata_t*>(metadata.data());
size_t expectedSize = metadata.size();
int res = validate_camera_metadata_structure(buffer, &expectedSize);
if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
set_camera_metadata_vendor_id(buffer, mProviderTagid);
mPhysicalCameraCharacteristics[id] = buffer;
} else {
ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
status = Status::INTERNAL_ERROR;
}
}
});
if (!ret.isOk()) {
ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s",
__FUNCTION__, id.c_str(), mId.c_str(), ret.description().c_str());
return;
}
if (status != Status::OK) {
ALOGE("%s: Unable to get physical camera %s characteristics for device %s: %s (%d)",
__FUNCTION__, id.c_str(), mId.c_str(),
CameraProviderManager::statusToString(status), status);
return;
}
}
}
}
CameraProviderManager::ProviderInfo::DeviceInfo3::~DeviceInfo3() {}
@ -1129,6 +1257,18 @@ status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraCharacterist
return OK;
}
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getPhysicalCameraCharacteristics(
const std::string& physicalCameraId, CameraMetadata *characteristics) const {
if (characteristics == nullptr) return BAD_VALUE;
if (mPhysicalCameraCharacteristics.find(physicalCameraId) ==
mPhysicalCameraCharacteristics.end()) {
return NAME_NOT_FOUND;
}
*characteristics = mPhysicalCameraCharacteristics.at(physicalCameraId);
return OK;
}
status_t CameraProviderManager::ProviderInfo::parseProviderName(const std::string& name,
std::string *type, uint32_t *id) {
// Format must be "<type>/<id>"
@ -1460,10 +1600,20 @@ status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id,
CameraMetadata* characteristics) const {
auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
if (deviceInfo == nullptr) return NAME_NOT_FOUND;
auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {5,0});
if (deviceInfo != nullptr) {
return deviceInfo->getCameraCharacteristics(characteristics);
}
// Find hidden physical camera characteristics
for (auto& provider : mProviders) {
for (auto& deviceInfo : provider->mDevices) {
status_t res = deviceInfo->getPhysicalCameraCharacteristics(id, characteristics);
if (res != NAME_NOT_FOUND) return res;
}
}
return deviceInfo->getCameraCharacteristics(characteristics);
return NAME_NOT_FOUND;
}
void CameraProviderManager::filterLogicalCameraIdsLocked(
@ -1482,7 +1632,7 @@ void CameraProviderManager::filterLogicalCameraIdsLocked(
// idCombo contains the ids of a logical camera and its physical cameras
std::vector<std::string> idCombo;
bool logicalCamera = CameraProviderManager::isLogicalCamera(info, &idCombo);
bool logicalCamera = isLogicalCamera(info, &idCombo);
if (!logicalCamera) {
continue;
}

@ -237,6 +237,7 @@ public:
static bool isLogicalCamera(const CameraMetadata& staticInfo,
std::vector<std::string>* physicalCameraIds);
bool isHiddenPhysicalCamera(const std::string& cameraId);
private:
// All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use
mutable std::mutex mInterfaceMutex;
@ -306,17 +307,25 @@ private:
(void) characteristics;
return INVALID_OPERATION;
}
virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
CameraMetadata *characteristics) const {
(void) physicalCameraId;
(void) characteristics;
return INVALID_OPERATION;
}
DeviceInfo(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, const hardware::hidl_version& version,
const std::vector<std::string>& publicCameraIds,
const hardware::camera::common::V1_0::CameraResourceCost& resourceCost) :
mName(name), mId(id), mVersion(version), mProviderTagid(tagId),
mResourceCost(resourceCost),
mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
mHasFlashUnit(false) {}
mHasFlashUnit(false), mPublicCameraIds(publicCameraIds) {}
virtual ~DeviceInfo();
protected:
bool mHasFlashUnit;
const std::vector<std::string>& mPublicCameraIds;
template<class InterfaceT>
static status_t setTorchMode(InterfaceT& interface, bool enabled);
@ -325,6 +334,12 @@ private:
std::unordered_set<std::string> mUniqueCameraIds;
int mUniqueDeviceCount;
std::vector<std::string> mUniqueAPI1CompatibleCameraIds;
// The initial public camera IDs published by the camera provider.
// Currently logical multi-camera is not supported for hot-plug camera.
// And we use this list to keep track of initial public camera IDs
// advertised by the provider, and to distinguish against "hidden"
// physical camera IDs.
std::vector<std::string> mProviderPublicCameraIds;
// HALv1-specific camera fields, including the actual device interface
struct DeviceInfo1 : public DeviceInfo {
@ -339,6 +354,7 @@ private:
DeviceInfo1(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, uint16_t minorVersion,
const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
const std::vector<std::string>& publicCameraIds,
sp<InterfaceT> interface);
virtual ~DeviceInfo1();
private:
@ -356,14 +372,17 @@ private:
virtual status_t dumpState(int fd) const override;
virtual status_t getCameraCharacteristics(
CameraMetadata *characteristics) const override;
virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
CameraMetadata *characteristics) const override;
DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, uint16_t minorVersion,
const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
sp<InterfaceT> interface);
const std::vector<std::string>& publicCameraIds, sp<InterfaceT> interface);
virtual ~DeviceInfo3();
private:
CameraMetadata mCameraCharacteristics;
std::unordered_map<std::string, CameraMetadata> mPhysicalCameraCharacteristics;
};
private:

Loading…
Cancel
Save