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
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index e06a81f..394701a 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -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 @@
} else {
// Only HAL1 devices do not support setTorchMode
mFlashControl =
- new CameraHardwareInterfaceFlashControl(mProviderManager, *mCallbacks);
+ new CameraHardwareInterfaceFlashControl(mProviderManager, mCallbacks);
}
return OK;
@@ -119,7 +121,8 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
mTorchEnabled = true;
- mCallbacks->torch_mode_status_change(mCallbacks,
- cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
+ mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_ON);
return OK;
}
diff --git a/services/camera/libcameraservice/CameraFlashlight.h b/services/camera/libcameraservice/CameraFlashlight.h
index c86ee85..07ce829 100644
--- a/services/camera/libcameraservice/CameraFlashlight.h
+++ b/services/camera/libcameraservice/CameraFlashlight.h
@@ -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 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 @@
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 @@
public:
CameraHardwareInterfaceFlashControl(
sp<CameraProviderManager> manager,
- const camera_module_callbacks_t& callbacks);
+ CameraProviderManager::StatusListener* callbacks);
virtual ~CameraHardwareInterfaceFlashControl();
// FlashControlBase
@@ -166,7 +165,7 @@
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;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index e7609ed..89ca6bb 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -107,79 +107,13 @@
// ----------------------------------------------------------------------------
-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 @@
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);
- 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();
-
- 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 == 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;
}
}
- if (!cameraFound) {
- addStates(id8);
+
+ // 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);
+ }
+
+ deviceIds = mCameraProviderManager->getCameraDeviceIds();
+ }
+
+
+ for (auto& cameraId : deviceIds) {
+ String8 id8 = String8(cameraId.c_str());
onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
}
@@ -291,6 +215,13 @@
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 @@
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 @@
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 @@
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 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 @@
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::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 @@
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 @@
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 @@
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 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 CameraService::connect(
const sp<ICameraClient>& cameraClient,
- int cameraId,
+ int api1CameraId,
const String16& clientPackageName,
int clientUid,
int clientPid,
@@ -1244,9 +1191,10 @@
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::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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
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());
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 67db7ec..81048e6 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -62,7 +62,6 @@
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 @@
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
const String8& cameraIdStr,
+ int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
@@ -551,7 +551,8 @@
// 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 @@
// 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 @@
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 @@
*/
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 @@
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);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 585d2eb..0a82cb9 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -49,16 +49,17 @@
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();
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 5af74eb..1ebf4b0 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -91,7 +91,8 @@
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,
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index e848a3f..8c6cd3d 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -42,7 +42,7 @@
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();
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 050c3f7..b4c7e9d 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -759,12 +759,17 @@
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 @@
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 @@
// 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 @@
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 @@
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;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index 17e3d75..fe725fd 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -207,6 +207,11 @@
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 @@
}
};
DefaultKeyedVector<uint8_t, OverrideModes> sceneModeOverrides;
+ bool isExternalCamera;
float minFocalLength;
bool useFlexibleYuv;
Size maxJpegSize;
@@ -380,6 +386,7 @@
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);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 8e112a1..8ff8ac5 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -47,6 +47,7 @@
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 @@
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 @@
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) {
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 435c99d..ca2d988 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -45,6 +45,7 @@
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
+ int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 4ce82dc..db26027 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -48,15 +48,16 @@
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 @@
template <typename TClientBase>
int Camera2ClientBase<TClientBase>::getCameraId() const {
- return std::stoi(TClientBase::mCameraIdStr.string());
+ return mApi1CameraId;
}
template <typename TClientBase>
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index e898d5d..edeae5b 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -49,6 +49,7 @@
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
+ int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
@@ -140,6 +141,8 @@
bool mDeviceActive;
+ const int mApi1CameraId; // -1 if client is API2
+
private:
template<typename TProviderPtr>
status_t initializeImpl(TProviderPtr providerPtr);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 70e7761..b37f004 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -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 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 @@
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::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 @@
}
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 @@
}
}
- 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 @@
}
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 @@
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 @@
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 @@
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();
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index d02abb0..bbe6789 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -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 @@
*/
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 @@
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 @@
CameraProviderManager *mManager;
+ bool mInitialized = false;
+
// Templated method to instantiate the right kind of DeviceInfo and call the
// right CameraProvider getCameraDeviceInterface_* method.
template<class DeviceInfoT>