Camera: expose external camera to API1

- Cleanup legacy camera_module_t callbacks
- Order API1 compatible cameras by their ID: numeric strings first
- Dynamically updating number of cameras when device is
  added/removed
- Make sure the following methods are always called without holding
  mServiceLock
    - onDeviceStatusChange
    - updateStatus
    - addStates/removeStates
- Centralized all addState/removeState calls in onDeviceStatusChange
- Passing api1CameraId (number) and cameraDeviceId (string) to various
  client classes.
- Allow FOV information to not present for external camera
- Update API1 preview/video size logic to exclude < ~30fps sizes

Bug: 64874137
Change-Id: Ied6b7141fdad30e3d1c3fcacc5b69ca350fdeb24
gugelfrei
Yin-Chia Yeh 7 years ago
parent 98c15702ca
commit c3e9d6f704

@ -32,13 +32,15 @@
namespace android {
using hardware::camera::common::V1_0::TorchModeStatus;
/////////////////////////////////////////////////////////////////////
// CameraFlashlight implementation begins
// used by camera service to control flashflight.
/////////////////////////////////////////////////////////////////////
CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
camera_module_callbacks_t* callbacks) :
CameraProviderManager::StatusListener* callbacks) :
mProviderManager(providerManager),
mCallbacks(callbacks),
mFlashlightMapInitialized(false) {
@ -59,7 +61,7 @@ status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
} else {
// Only HAL1 devices do not support setTorchMode
mFlashControl =
new CameraHardwareInterfaceFlashControl(mProviderManager, *mCallbacks);
new CameraHardwareInterfaceFlashControl(mProviderManager, mCallbacks);
}
return OK;
@ -119,7 +121,8 @@ status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
}
int CameraFlashlight::getNumberOfCameras() {
return mProviderManager->getAPI1CompatibleCameraCount();
size_t len = mProviderManager->getAPI1CompatibleCameraDeviceIds().size();
return static_cast<int>(len);
}
status_t CameraFlashlight::findFlashUnits() {
@ -221,9 +224,8 @@ status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
int numCameras = getNumberOfCameras();
for (int i = 0; i < numCameras; i++) {
if (hasFlashUnitLocked(String8::format("%d", i))) {
mCallbacks->torch_mode_status_change(mCallbacks,
String8::format("%d", i).string(),
TORCH_MODE_STATUS_NOT_AVAILABLE);
mCallbacks->onTorchStatusChanged(
String8::format("%d", i), TorchModeStatus::NOT_AVAILABLE);
}
}
}
@ -266,9 +268,8 @@ status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
int numCameras = getNumberOfCameras();
for (int i = 0; i < numCameras; i++) {
if (hasFlashUnitLocked(String8::format("%d", i))) {
mCallbacks->torch_mode_status_change(mCallbacks,
String8::format("%d", i).string(),
TORCH_MODE_STATUS_AVAILABLE_OFF);
mCallbacks->onTorchStatusChanged(
String8::format("%d", i), TorchModeStatus::AVAILABLE_OFF);
}
}
}
@ -315,9 +316,9 @@ status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enable
CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
sp<CameraProviderManager> manager,
const camera_module_callbacks_t& callbacks) :
CameraProviderManager::StatusListener* callbacks) :
mProviderManager(manager),
mCallbacks(&callbacks),
mCallbacks(callbacks),
mTorchEnabled(false) {
}
@ -333,8 +334,7 @@ CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
if (mCallbacks) {
ALOGV("%s: notify the framework that torch was turned off",
__FUNCTION__);
mCallbacks->torch_mode_status_change(mCallbacks,
mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
mCallbacks->onTorchStatusChanged(mCameraId, TorchModeStatus::AVAILABLE_OFF);
}
}
}
@ -368,8 +368,7 @@ status_t CameraHardwareInterfaceFlashControl::setTorchMode(
// disabling the torch mode of currently opened device
disconnectCameraDevice();
mTorchEnabled = false;
mCallbacks->torch_mode_status_change(mCallbacks,
cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_OFF);
return OK;
}
@ -379,8 +378,7 @@ status_t CameraHardwareInterfaceFlashControl::setTorchMode(
}
mTorchEnabled = true;
mCallbacks->torch_mode_status_change(mCallbacks,
cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_ON);
return OK;
}

@ -19,7 +19,6 @@
#include <gui/GLConsumer.h>
#include <gui/Surface.h>
#include <hardware/camera_common.h>
#include <utils/KeyedVector.h>
#include <utils/SortedVector.h>
#include "common/CameraProviderManager.h"
@ -55,7 +54,7 @@ class FlashControlBase : public virtual VirtualLightRefBase {
class CameraFlashlight : public virtual VirtualLightRefBase {
public:
CameraFlashlight(sp<CameraProviderManager> providerManager,
camera_module_callbacks_t* callbacks);
CameraProviderManager::StatusListener* callbacks);
virtual ~CameraFlashlight();
// Find all flash units. This must be called before other methods. All
@ -99,7 +98,7 @@ class CameraFlashlight : public virtual VirtualLightRefBase {
sp<CameraProviderManager> mProviderManager;
const camera_module_callbacks_t *mCallbacks;
CameraProviderManager::StatusListener* mCallbacks;
SortedVector<String8> mOpenedCameraIds;
// camera id -> if it has a flash unit
@ -134,7 +133,7 @@ class CameraHardwareInterfaceFlashControl : public FlashControlBase {
public:
CameraHardwareInterfaceFlashControl(
sp<CameraProviderManager> manager,
const camera_module_callbacks_t& callbacks);
CameraProviderManager::StatusListener* callbacks);
virtual ~CameraHardwareInterfaceFlashControl();
// FlashControlBase
@ -166,7 +165,7 @@ class CameraHardwareInterfaceFlashControl : public FlashControlBase {
status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash, bool keepDeviceOpen);
sp<CameraProviderManager> mProviderManager;
const camera_module_callbacks_t *mCallbacks;
CameraProviderManager::StatusListener* mCallbacks;
sp<CameraHardwareInterface> mDevice;
String8 mCameraId;
CameraParameters mParameters;

@ -107,79 +107,13 @@ static void setLogLevel(int level) {
// ----------------------------------------------------------------------------
extern "C" {
static void camera_device_status_change(
const struct camera_module_callbacks* callbacks,
int camera_id,
int new_status) {
sp<CameraService> cs = const_cast<CameraService*>(
static_cast<const CameraService*>(callbacks));
String8 id = String8::format("%d", camera_id);
CameraDeviceStatus newStatus{CameraDeviceStatus::NOT_PRESENT};
switch (new_status) {
case CAMERA_DEVICE_STATUS_NOT_PRESENT:
newStatus = CameraDeviceStatus::NOT_PRESENT;
break;
case CAMERA_DEVICE_STATUS_PRESENT:
newStatus = CameraDeviceStatus::PRESENT;
break;
case CAMERA_DEVICE_STATUS_ENUMERATING:
newStatus = CameraDeviceStatus::ENUMERATING;
break;
default:
ALOGW("Unknown device status change to %d", new_status);
break;
}
cs->onDeviceStatusChanged(id, newStatus);
}
static void torch_mode_status_change(
const struct camera_module_callbacks* callbacks,
const char* camera_id,
int new_status) {
if (!callbacks || !camera_id) {
ALOGE("%s invalid parameters. callbacks %p, camera_id %p", __FUNCTION__,
callbacks, camera_id);
}
sp<CameraService> cs = const_cast<CameraService*>(
static_cast<const CameraService*>(callbacks));
TorchModeStatus status;
switch (new_status) {
case TORCH_MODE_STATUS_NOT_AVAILABLE:
status = TorchModeStatus::NOT_AVAILABLE;
break;
case TORCH_MODE_STATUS_AVAILABLE_OFF:
status = TorchModeStatus::AVAILABLE_OFF;
break;
case TORCH_MODE_STATUS_AVAILABLE_ON:
status = TorchModeStatus::AVAILABLE_ON;
break;
default:
ALOGE("Unknown torch status %d", new_status);
return;
}
cs->onTorchStatusChanged(
String8(camera_id),
status);
}
} // extern "C"
// ----------------------------------------------------------------------------
static const String16 sManageCameraPermission("android.permission.MANAGE_CAMERA");
CameraService::CameraService() :
mEventLog(DEFAULT_EVENT_LOG_LENGTH),
mNumberOfCameras(0), mNumberOfNormalCameras(0),
mNumberOfCameras(0),
mSoundRef(0), mInitialized(false) {
ALOGI("CameraService started (pid=%d)", getpid());
this->camera_device_status_change = android::camera_device_status_change;
this->torch_mode_status_change = android::torch_mode_status_change;
mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
}
@ -209,52 +143,42 @@ void CameraService::onFirstRef()
status_t CameraService::enumerateProviders() {
status_t res;
Mutex::Autolock l(mServiceLock);
if (nullptr == mCameraProviderManager.get()) {
mCameraProviderManager = new CameraProviderManager();
res = mCameraProviderManager->initialize(this);
if (res != OK) {
ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
std::vector<std::string> deviceIds;
{
Mutex::Autolock l(mServiceLock);
if (nullptr == mCameraProviderManager.get()) {
mCameraProviderManager = new CameraProviderManager();
res = mCameraProviderManager->initialize(this);
if (res != OK) {
ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
}
}
mNumberOfCameras = mCameraProviderManager->getCameraCount();
mNumberOfNormalCameras =
mCameraProviderManager->getAPI1CompatibleCameraCount();
// Setup vendor tags before we call get_camera_info the first time
// because HAL might need to setup static vendor keys in get_camera_info
// TODO: maybe put this into CameraProviderManager::initialize()?
mCameraProviderManager->setUpVendorTags();
// Setup vendor tags before we call get_camera_info the first time
// because HAL might need to setup static vendor keys in get_camera_info
// TODO: maybe put this into CameraProviderManager::initialize()?
mCameraProviderManager->setUpVendorTags();
if (nullptr == mFlashlight.get()) {
mFlashlight = new CameraFlashlight(mCameraProviderManager, this);
}
res = mFlashlight->findFlashUnits();
if (res != OK) {
ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
}
for (auto& cameraId : mCameraProviderManager->getCameraDeviceIds()) {
String8 id8 = String8(cameraId.c_str());
bool cameraFound = false;
{
Mutex::Autolock lock(mCameraStatesLock);
auto iter = mCameraStates.find(id8);
if (iter != mCameraStates.end()) {
cameraFound = true;
}
if (nullptr == mFlashlight.get()) {
mFlashlight = new CameraFlashlight(mCameraProviderManager, this);
}
if (!cameraFound) {
addStates(id8);
res = mFlashlight->findFlashUnits();
if (res != OK) {
ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
}
deviceIds = mCameraProviderManager->getCameraDeviceIds();
}
for (auto& cameraId : deviceIds) {
String8 id8 = String8(cameraId.c_str());
onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
}
@ -291,6 +215,13 @@ void CameraService::onNewProviderRegistered() {
enumerateProviders();
}
void CameraService::updateCameraNumAndIds() {
Mutex::Autolock l(mServiceLock);
mNumberOfCameras = mCameraProviderManager->getCameraCount();
mNormalDeviceIds =
mCameraProviderManager->getAPI1CompatibleCameraDeviceIds();
}
void CameraService::addStates(const String8 id) {
std::string cameraId(id.c_str());
hardware::camera::common::V1_0::CameraResourceCost cost;
@ -313,10 +244,13 @@ void CameraService::addStates(const String8 id) {
if (mFlashlight->hasFlashUnit(id)) {
mTorchStatusMap.add(id, TorchModeStatus::AVAILABLE_OFF);
}
updateCameraNumAndIds();
logDeviceAdded(id, "Device added");
}
void CameraService::removeStates(const String8 id) {
updateCameraNumAndIds();
if (mFlashlight->hasFlashUnit(id)) {
mTorchStatusMap.removeItem(id);
}
@ -361,15 +295,16 @@ void CameraService::onDeviceStatusChanged(const String8& id,
if (newStatus == StatusInternal::NOT_PRESENT) {
logDeviceRemoved(id, String8::format("Device status changed from %d to %d", oldStatus,
newStatus));
// Set the device status to NOT_PRESENT, clients will no longer be able to connect
// to this device until the status changes
updateStatus(StatusInternal::NOT_PRESENT, id);
sp<BasicClient> clientToDisconnect;
{
// Don't do this in updateStatus to avoid deadlock over mServiceLock
Mutex::Autolock lock(mServiceLock);
// Set the device status to NOT_PRESENT, clients will no longer be able to connect
// to this device until the status changes
updateStatus(StatusInternal::NOT_PRESENT, id);
// Remove cached shim parameters
state->setShimParams(CameraParameters());
@ -472,7 +407,7 @@ Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) {
Mutex::Autolock l(mServiceLock);
switch (type) {
case CAMERA_TYPE_BACKWARD_COMPATIBLE:
*numCameras = mNumberOfNormalCameras;
*numCameras = static_cast<int>(mNormalDeviceIds.size());
break;
case CAMERA_TYPE_ALL:
*numCameras = mNumberOfCameras;
@ -502,7 +437,8 @@ Status CameraService::getCameraInfo(int cameraId,
}
Status ret = Status::ok();
status_t err = mCameraProviderManager->getCameraInfo(std::to_string(cameraId), cameraInfo);
status_t err = mCameraProviderManager->getCameraInfo(
cameraIdIntToStrLocked(cameraId), cameraInfo);
if (err != OK) {
ret = STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Error retrieving camera info from device %d: %s (%d)", cameraId,
@ -512,13 +448,19 @@ Status CameraService::getCameraInfo(int cameraId,
return ret;
}
int CameraService::cameraIdToInt(const String8& cameraId) {
int id;
bool success = base::ParseInt(cameraId.string(), &id, 0);
if (!success) {
return -1;
std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt) {
if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(mNormalDeviceIds.size())) {
ALOGE("%s: input id %d invalid: valid range (0, %zu)",
__FUNCTION__, cameraIdInt, mNormalDeviceIds.size());
return std::string{};
}
return id;
return mNormalDeviceIds[cameraIdInt];
}
String8 CameraService::cameraIdIntToStr(int cameraIdInt) {
Mutex::Autolock lock(mServiceLock);
return String8(cameraIdIntToStrLocked(cameraIdInt).c_str());
}
Status CameraService::getCameraCharacteristics(const String16& cameraId,
@ -635,8 +577,8 @@ Status CameraService::filterGetInfoErrorCode(status_t err) {
Status CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
bool legacyMode, int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client) {
if (halVersion < 0 || halVersion == deviceVersion) {
@ -646,8 +588,9 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService,
case CAMERA_DEVICE_API_VERSION_1_0:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
facing, clientPid, clientUid, getpid(), legacyMode);
*client = new CameraClient(cameraService, tmp, packageName,
api1CameraId, facing, clientPid, clientUid,
getpid(), legacyMode);
} else { // Camera2 API route
ALOGW("Camera using old HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
@ -662,8 +605,10 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService,
case CAMERA_DEVICE_API_VERSION_3_4:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName, cameraIdToInt(cameraId),
facing, clientPid, clientUid, servicePid, legacyMode);
*client = new Camera2Client(cameraService, tmp, packageName,
cameraId, api1CameraId,
facing, clientPid, clientUid,
servicePid, legacyMode);
} else { // Camera2 API route
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
@ -685,8 +630,9 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService,
halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
// Only support higher HAL version device opened as HAL1.0 device.
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
facing, clientPid, clientUid, servicePid, legacyMode);
*client = new CameraClient(cameraService, tmp, packageName,
api1CameraId, facing, clientPid, clientUid,
servicePid, legacyMode);
} else {
// Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
@ -782,7 +728,8 @@ Status CameraService::initializeShimMetadata(int cameraId) {
Status ret = Status::ok();
sp<Client> tmp = nullptr;
if (!(ret = connectHelper<ICameraClient,Client>(
sp<ICameraClient>{nullptr}, id, static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED),
sp<ICameraClient>{nullptr}, id, cameraId,
static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED),
internalPackageName, uid, USE_CALLING_PID,
API_1, /*legacyMode*/ false, /*shimUpdateOnly*/ true,
/*out*/ tmp)
@ -1235,7 +1182,7 @@ status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clien
Status CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
int api1CameraId,
const String16& clientPackageName,
int clientUid,
int clientPid,
@ -1244,9 +1191,10 @@ Status CameraService::connect(
ATRACE_CALL();
Status ret = Status::ok();
String8 id = String8::format("%d", cameraId);
String8 id = cameraIdIntToStr(api1CameraId);
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id,
ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1,
/*legacyMode*/ false, /*shimUpdateOnly*/ false,
/*out*/client);
@ -1263,18 +1211,18 @@ Status CameraService::connect(
Status CameraService::connectLegacy(
const sp<ICameraClient>& cameraClient,
int cameraId, int halVersion,
int api1CameraId, int halVersion,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>* device) {
ATRACE_CALL();
String8 id = String8::format("%d", cameraId);
String8 id = cameraIdIntToStr(api1CameraId);
Status ret = Status::ok();
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion,
ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId, halVersion,
clientPackageName, clientUid, USE_CALLING_PID, API_1,
/*legacyMode*/ true, /*shimUpdateOnly*/ false,
/*out*/client);
@ -1302,6 +1250,7 @@ Status CameraService::connectDevice(
String8 id = String8(cameraId);
sp<CameraDeviceClient> client = nullptr;
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
/*api1CameraId*/-1,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
clientUid, USE_CALLING_PID, API_2,
/*legacyMode*/ false, /*shimUpdateOnly*/ false,
@ -1319,8 +1268,8 @@ Status CameraService::connectDevice(
template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,
int clientPid, apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();
@ -1403,8 +1352,10 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8&
}
sp<BasicClient> tmp = nullptr;
if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
if(!(ret = makeClient(this, cameraCb, clientPackageName,
cameraId, api1CameraId, facing,
clientPid, clientUid, getpid(), legacyMode,
halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)).isOk()) {
return ret;
}
@ -2112,7 +2063,8 @@ void CameraService::playSound(sound_kind kind) {
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
const String16& clientPackageName,
const String8& cameraIdStr, int cameraFacing,
const String8& cameraIdStr,
int api1CameraId, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid) :
CameraService::BasicClient(cameraService,
@ -2121,7 +2073,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
cameraIdStr, cameraFacing,
clientPid, clientUid,
servicePid),
mCameraId(CameraService::cameraIdToInt(cameraIdStr))
mCameraId(api1CameraId)
{
int callingPid = getCallingPid();
LOG1("Client::Client E (pid %d, id %d)", callingPid, mCameraId);
@ -2676,7 +2628,10 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
}
dprintf(fd, "\n== Service global info: ==\n\n");
dprintf(fd, "Number of camera devices: %d\n", mNumberOfCameras);
dprintf(fd, "Number of normal camera devices: %d\n", mNumberOfNormalCameras);
dprintf(fd, "Number of normal camera devices: %zu\n", mNormalDeviceIds.size());
for (size_t i = 0; i < mNormalDeviceIds.size(); i++) {
dprintf(fd, " Device %zu maps to \"%s\"\n", i, mNormalDeviceIds[i].c_str());
}
String8 activeClientString = mActiveClientManager.toString();
dprintf(fd, "Active Camera Clients:\n%s", activeClientString.string());
dprintf(fd, "Allowed user IDs: %s\n", toString(mAllowedUsers).string());

@ -62,7 +62,6 @@ class CameraService :
public BinderService<CameraService>,
public virtual ::android::hardware::BnCameraService,
public virtual IBinder::DeathRecipient,
public camera_module_callbacks_t,
public virtual CameraProviderManager::StatusListener
{
friend class BinderService<CameraService>;
@ -333,6 +332,7 @@ public:
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
const String8& cameraIdStr,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
@ -551,7 +551,8 @@ private:
// Eumerate all camera providers in the system
status_t enumerateProviders();
// Add a new camera to camera and torch state lists or remove an unplugged one
// Add/remove a new camera to camera and torch state lists or remove an unplugged one
// Caller must not hold mServiceLock
void addStates(const String8 id);
void removeStates(const String8 id);
@ -578,7 +579,7 @@ private:
// Single implementation shared between the various connect calls
template<class CALLBACK, class CLIENT>
binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName,
int api1CameraId, int halVersion, const String16& clientPackageName,
int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device);
@ -640,9 +641,16 @@ private:
void finishConnectLocked(const sp<BasicClient>& client, const DescriptorPtr& desc);
/**
* Returns the integer corresponding to the given camera ID string, or -1 on failure.
* Returns the underlying camera Id string mapped to a camera id int
* Empty string is returned when the cameraIdInt is invalid.
*/
static int cameraIdToInt(const String8& cameraId);
String8 cameraIdIntToStr(int cameraIdInt);
/**
* Returns the underlying camera Id string mapped to a camera id int
* Empty string is returned when the cameraIdInt is invalid.
*/
std::string cameraIdIntToStrLocked(int cameraIdInt);
/**
* Remove a single client corresponding to the given camera id from the list of active clients.
@ -710,8 +718,14 @@ private:
*/
void dumpEventLog(int fd);
/**
* This method will acquire mServiceLock
*/
void updateCameraNumAndIds();
int mNumberOfCameras;
int mNumberOfNormalCameras;
std::vector<std::string> mNormalDeviceIds;
// sounds
MediaPlayer* newMediaPlayer(const char *file);
@ -821,8 +835,8 @@ private:
static binder::Status makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
bool legacyMode, int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client);
status_t checkCameraAccess(const String16& opPackageName);

@ -49,16 +49,17 @@ static int getCallingPid() {
Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
int cameraId,
const String8& cameraDeviceId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid,
bool legacyMode):
Camera2ClientBase(cameraService, cameraClient, clientPackageName,
String8::format("%d", cameraId), cameraFacing,
cameraDeviceId, api1CameraId, cameraFacing,
clientPid, clientUid, servicePid),
mParameters(cameraId, cameraFacing)
mParameters(api1CameraId, cameraFacing)
{
ATRACE_CALL();

@ -91,7 +91,8 @@ public:
Camera2Client(const sp<CameraService>& cameraService,
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
int cameraId,
const String8& cameraDeviceId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,

@ -42,7 +42,7 @@ CameraClient::CameraClient(const sp<CameraService>& cameraService,
int clientPid, int clientUid,
int servicePid, bool legacyMode):
Client(cameraService, cameraClient, clientPackageName,
String8::format("%d", cameraId), cameraFacing, clientPid,
String8::format("%d", cameraId), cameraId, cameraFacing, clientPid,
clientUid, servicePid)
{
int callingPid = getCallingPid();

@ -759,12 +759,17 @@ status_t Parameters::initialize(const CameraMetadata *info, int deviceVersion) {
focusingAreas.clear();
focusingAreas.add(Parameters::Area(0,0,0,0,0));
camera_metadata_ro_entry_t availableFocalLengths =
staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, 0, 0, false);
if (!availableFocalLengths.count) return NO_INIT;
if (fastInfo.isExternalCamera) {
params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, -1.0);
} else {
camera_metadata_ro_entry_t availableFocalLengths =
staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, 0, 0, false);
if (!availableFocalLengths.count) return NO_INIT;
float minFocalLength = availableFocalLengths.data.f[0];
params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength);
}
float minFocalLength = availableFocalLengths.data.f[0];
params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength);
float horizFov, vertFov;
res = calculatePictureFovs(&horizFov, &vertFov);
@ -1091,9 +1096,15 @@ status_t Parameters::buildFastInfo() {
focusDistanceCalibration.data.u8[0] !=
ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED);
camera_metadata_ro_entry_t hwLevel = staticInfo(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
if (!hwLevel.count) return NO_INIT;
fastInfo.isExternalCamera =
hwLevel.data.u8[0] == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
camera_metadata_ro_entry_t availableFocalLengths =
staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
if (!availableFocalLengths.count) return NO_INIT;
staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, 0, 0, /*required*/false);
if (!availableFocalLengths.count && !fastInfo.isExternalCamera) return NO_INIT;
SortedVector<int32_t> availableFormats = getAvailableOutputFormats();
if (!availableFormats.size()) return NO_INIT;
@ -1178,10 +1189,14 @@ status_t Parameters::buildFastInfo() {
// Find smallest (widest-angle) focal length to use as basis of still
// picture FOV reporting.
fastInfo.minFocalLength = availableFocalLengths.data.f[0];
for (size_t i = 1; i < availableFocalLengths.count; i++) {
if (fastInfo.minFocalLength > availableFocalLengths.data.f[i]) {
fastInfo.minFocalLength = availableFocalLengths.data.f[i];
if (fastInfo.isExternalCamera) {
fastInfo.minFocalLength = -1.0;
} else {
fastInfo.minFocalLength = availableFocalLengths.data.f[0];
for (size_t i = 1; i < availableFocalLengths.count; i++) {
if (fastInfo.minFocalLength > availableFocalLengths.data.f[i]) {
fastInfo.minFocalLength = availableFocalLengths.data.f[i];
}
}
}
@ -2870,8 +2885,13 @@ status_t Parameters::getFilteredSizes(Size limit, Vector<Size> *sizes) {
if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
sc.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
sc.width <= limit.width && sc.height <= limit.height) {
Size sz = {sc.width, sc.height};
sizes->push(sz);
int64_t minFrameDuration = getMinFrameDurationNs(
{sc.width, sc.height}, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
if (minFrameDuration > MAX_PREVIEW_RECORD_DURATION_NS) {
// Filter slow sizes from preview/record
continue;
}
sizes->push({sc.width, sc.height});
}
}
@ -3081,6 +3101,16 @@ Parameters::CropRegion Parameters::calculateCropRegion(bool previewOnly) const {
status_t Parameters::calculatePictureFovs(float *horizFov, float *vertFov)
const {
if (fastInfo.isExternalCamera) {
if (horizFov != NULL) {
*horizFov = -1.0;
}
if (vertFov != NULL) {
*vertFov = -1.0;
}
return OK;
}
camera_metadata_ro_entry_t sensorSize =
staticInfo(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, 2, 2);
if (!sensorSize.count) return NO_INIT;

@ -207,6 +207,11 @@ struct Parameters {
static const int32_t FPS_MARGIN = 1;
// Max FPS for default parameters
static const int32_t MAX_DEFAULT_FPS = 30;
// Minimum FPS for a size to be listed in supported preview/video sizes
// Set to slightly less than 30.0 to have some tolerance margin
static constexpr double MIN_PREVIEW_RECORD_FPS = 29.97;
// Maximum frame duration for a size to be listed in supported preview/video sizes
static constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS = 1e9 / MIN_PREVIEW_RECORD_FPS;
// Full static camera info, object owned by someone else, such as
// Camera2Device.
@ -233,6 +238,7 @@ struct Parameters {
}
};
DefaultKeyedVector<uint8_t, OverrideModes> sceneModeOverrides;
bool isExternalCamera;
float minFocalLength;
bool useFlexibleYuv;
Size maxJpegSize;
@ -380,6 +386,7 @@ private:
Vector<Size> availablePreviewSizes;
Vector<Size> availableVideoSizes;
// Get size list (that are no larger than limit) from static metadata.
// This method filtered size with minFrameDuration < MAX_PREVIEW_RECORD_DURATION_NS
status_t getFilteredSizes(Size limit, Vector<Size> *sizes);
// Get max size (from the size array) that matches the given aspect ratio.
Size getMaxSizeForRatio(float ratio, const int32_t* sizeArray, size_t count);

@ -47,6 +47,7 @@ CameraDeviceClientBase::CameraDeviceClientBase(
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
@ -60,6 +61,8 @@ CameraDeviceClientBase::CameraDeviceClientBase(
clientUid,
servicePid),
mRemoteCallback(remoteCallback) {
// We don't need it for API2 clients, but Camera2ClientBase requires it.
(void) api1CameraId;
}
// Interface used by CameraService
@ -73,7 +76,8 @@ CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
uid_t clientUid,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
cameraId, /*API1 camera ID*/ -1,
cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0) {

@ -45,6 +45,7 @@ protected:
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,

@ -48,15 +48,16 @@ Camera2ClientBase<TClientBase>::Camera2ClientBase(
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
TClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
mDeviceActive(false)
mDeviceActive(false), mApi1CameraId(api1CameraId)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
@ -329,7 +330,7 @@ void Camera2ClientBase<TClientBase>::notifyRepeatingRequestError(long lastFrameN
template <typename TClientBase>
int Camera2ClientBase<TClientBase>::getCameraId() const {
return std::stoi(TClientBase::mCameraIdStr.string());
return mApi1CameraId;
}
template <typename TClientBase>

@ -49,6 +49,7 @@ public:
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
@ -140,6 +141,8 @@ protected:
bool mDeviceActive;
const int mApi1CameraId; // -1 if client is API2
private:
template<typename TProviderPtr>
status_t initializeImpl(TProviderPtr providerPtr);

@ -20,11 +20,13 @@
#include "CameraProviderManager.h"
#include <algorithm>
#include <chrono>
#include <inttypes.h>
#include <hidl/ServiceManagement.h>
#include <functional>
#include <camera_metadata_hidden.h>
#include <android-base/parseint.h>
namespace android {
@ -38,7 +40,7 @@ const std::string kLegacyProviderName("legacy/0");
const std::string kExternalProviderName("external/0");
// Slash-separated list of provider types to consider for use via the old camera API
const std::string kStandardProviderTypes("internal/legacy");
const std::string kStandardProviderTypes("internal/legacy/external");
} // anonymous namespace
@ -79,18 +81,7 @@ int CameraProviderManager::getCameraCount() const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
int count = 0;
for (auto& provider : mProviders) {
count += provider->mUniqueDeviceCount;
}
return count;
}
int CameraProviderManager::getAPI1CompatibleCameraCount() const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
int count = 0;
for (auto& provider : mProviders) {
if (kStandardProviderTypes.find(provider->getType()) != std::string::npos) {
count += provider->mUniqueAPI1CompatibleCameraIds.size();
}
count += provider->mUniqueCameraIds.size();
}
return count;
}
@ -116,6 +107,24 @@ std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds
}
}
}
std::sort(deviceIds.begin(), deviceIds.end(),
[](const std::string& a, const std::string& b) -> bool {
uint32_t aUint = 0, bUint = 0;
bool aIsUint = base::ParseUint(a, &aUint);
bool bIsUint = base::ParseUint(b, &bUint);
// Uint device IDs first
if (aIsUint && bIsUint) {
return aUint < bUint;
} else if (aIsUint) {
return true;
} else if (bIsUint) {
return false;
}
// Simple string compare if both id are not uint
return a < b;
});
return deviceIds;
}
@ -480,6 +489,8 @@ status_t CameraProviderManager::ProviderInfo::initialize() {
}
ALOGI("Connecting to new camera provider: %s, isRemote? %d",
mProviderName.c_str(), mInterface->isRemote());
// cameraDeviceStatusChange callbacks may be called (and causing new devices added)
// before setCallback returns
hardware::Return<Status> status = mInterface->setCallback(this);
if (!status.isOk()) {
ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
@ -536,17 +547,10 @@ status_t CameraProviderManager::ProviderInfo::initialize() {
}
}
for (auto& device : mDevices) {
mUniqueCameraIds.insert(device->mId);
if (device->isAPI1Compatible()) {
mUniqueAPI1CompatibleCameraIds.insert(device->mId);
}
}
mUniqueDeviceCount = mUniqueCameraIds.size();
ALOGI("Camera provider %s ready with %zu camera devices",
mProviderName.c_str(), mDevices.size());
mInitialized = true;
return OK;
}
@ -594,9 +598,15 @@ status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
}
if (deviceInfo == nullptr) return BAD_VALUE;
deviceInfo->mStatus = initialStatus;
bool isAPI1Compatible = deviceInfo->isAPI1Compatible();
mDevices.push_back(std::move(deviceInfo));
mUniqueCameraIds.insert(id);
if (isAPI1Compatible) {
mUniqueAPI1CompatibleCameraIds.insert(id);
}
if (parsedId != nullptr) {
*parsedId = id;
}
@ -606,6 +616,10 @@ status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
void CameraProviderManager::ProviderInfo::removeDevice(std::string id) {
for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
if ((*it)->mId == id) {
mUniqueCameraIds.erase(id);
if ((*it)->isAPI1Compatible()) {
mUniqueAPI1CompatibleCameraIds.erase(id);
}
mDevices.erase(it);
break;
}
@ -671,6 +685,7 @@ hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusCh
CameraDeviceStatus newStatus) {
sp<StatusListener> listener;
std::string id;
bool initialized = false;
{
std::lock_guard<std::mutex> lock(mLock);
bool known = false;
@ -697,9 +712,13 @@ hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusCh
removeDevice(id);
}
listener = mManager->getStatusListener();
initialized = mInitialized;
}
// Call without lock held to allow reentrancy into provider manager
if (listener != nullptr) {
// Don't send the callback if providerInfo hasn't been initialized.
// CameraService will initialize device status after provider is
// initialized
if (listener != nullptr && initialized) {
listener->onDeviceStatusChanged(String8(id.c_str()), newStatus);
}
return hardware::Void();

@ -18,7 +18,7 @@
#define ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_H
#include <vector>
#include <set>
#include <unordered_set>
#include <string>
#include <mutex>
@ -125,16 +125,14 @@ public:
*/
int getCameraCount() const;
std::vector<std::string> getCameraDeviceIds() const;
/**
* Retrieve the number of API1 compatible cameras; these are internal and
* backwards-compatible. This is the set of cameras that will be
* accessible via the old camera API, with IDs in range of
* [0, getAPI1CompatibleCameraCount()-1]. This value is not expected to change dynamically.
* accessible via the old camera API.
* The return value may change dynamically due to external camera hotplug.
*/
int getAPI1CompatibleCameraCount() const;
std::vector<std::string> getCameraDeviceIds() const;
std::vector<std::string> getAPI1CompatibleCameraDeviceIds() const;
/**
@ -314,9 +312,9 @@ private:
static status_t setTorchMode(InterfaceT& interface, bool enabled);
};
std::vector<std::unique_ptr<DeviceInfo>> mDevices;
std::set<std::string> mUniqueCameraIds;
std::unordered_set<std::string> mUniqueCameraIds;
int mUniqueDeviceCount;
std::set<std::string> mUniqueAPI1CompatibleCameraIds;
std::unordered_set<std::string> mUniqueAPI1CompatibleCameraIds;
// HALv1-specific camera fields, including the actual device interface
struct DeviceInfo1 : public DeviceInfo {
@ -366,6 +364,8 @@ private:
CameraProviderManager *mManager;
bool mInitialized = false;
// Templated method to instantiate the right kind of DeviceInfo and call the
// right CameraProvider getCameraDeviceInterface_* method.
template<class DeviceInfoT>

Loading…
Cancel
Save