| From f584caaf5f6cd31cc6b8e30a4b62893d6d85818e Mon Sep 17 00:00:00 2001 |
| From: Jackeagle <jackeagle102@gmail.com> |
| Date: Thu, 18 Oct 2018 04:21:22 -0400 |
| Subject: [PATCH 1/5] [SQUASH] Revert Camera Specific AOSP Reverts |
| |
| Revert "Revert "CameraService: fix camera removal paths"" |
| |
| This reverts commit e1922854c4bf71d9170011b904b701d1b38e303e. |
| |
| Revert "Revert "CameraService: Update camera and torch state lists also at runtime"" |
| |
| This reverts commit cb343b767cd41829bb994c9c0e671a9c3e5d7cfb. |
| |
| Revert "Revert "Camera: Add API level to service proxy notification"" |
| |
| This reverts commit 48888c68523e50038e92b8d73fa4d471fe266972. |
| |
| Revert "Revert "Camera: expose external camera to API1"" |
| |
| This reverts commit 92607517666eca78bb94817f780977c7024cdda4. |
| |
| Revert "Revert "Camera: fix camera ID in flashlight control"" |
| |
| This reverts commit 2c7225b2fe3017d1fd146e55420c6b616f44d16b. |
| |
| Revert "Revert "Camera: Support all API1 compatible camera devices"" |
| |
| This reverts commit 842255a5aff37bb06d43a06bb44be0a67c4570ac. |
| |
| Revert "Revert "Camera: Filter logical camera ids to API1 app"" |
| |
| This reverts commit 4e10dacc6a5edc0b4382e570173e9f7ff89af9bd. |
| --- |
| .../aidl/android/hardware/ICameraServiceProxy.aidl | 8 +- |
| camera/ndk/impl/ACameraManager.cpp | 3 + |
| .../camera/libcameraservice/CameraFlashlight.cpp | 52 ++-- |
| .../camera/libcameraservice/CameraFlashlight.h | 11 +- |
| services/camera/libcameraservice/CameraService.cpp | 317 ++++++++++----------- |
| services/camera/libcameraservice/CameraService.h | 35 ++- |
| .../camera/libcameraservice/api1/Camera2Client.cpp | 7 +- |
| .../camera/libcameraservice/api1/Camera2Client.h | 3 +- |
| .../camera/libcameraservice/api1/CameraClient.cpp | 14 +- |
| .../libcameraservice/api1/client2/Parameters.cpp | 56 +++- |
| .../libcameraservice/api1/client2/Parameters.h | 7 + |
| .../libcameraservice/api2/CameraDeviceClient.cpp | 59 ++-- |
| .../libcameraservice/api2/CameraDeviceClient.h | 1 + |
| .../libcameraservice/common/Camera2ClientBase.cpp | 15 +- |
| .../libcameraservice/common/Camera2ClientBase.h | 3 + |
| .../common/CameraProviderManager.cpp | 173 ++++++++--- |
| .../common/CameraProviderManager.h | 30 +- |
| 17 files changed, 476 insertions(+), 318 deletions(-) |
| |
| diff --git a/camera/aidl/android/hardware/ICameraServiceProxy.aidl b/camera/aidl/android/hardware/ICameraServiceProxy.aidl |
| index 5dc23eb..7575948 100644 |
| --- a/camera/aidl/android/hardware/ICameraServiceProxy.aidl |
| +++ b/camera/aidl/android/hardware/ICameraServiceProxy.aidl |
| @@ -46,8 +46,14 @@ interface ICameraServiceProxy |
| const int CAMERA_FACING_EXTERNAL = 2; |
| |
| /** |
| + * Values for notifyCameraState api level |
| + */ |
| + const int CAMERA_API_LEVEL_1 = 1; |
| + const int CAMERA_API_LEVEL_2 = 2; |
| + |
| + /** |
| * Update the status of a camera device. |
| */ |
| oneway void notifyCameraState(String cameraId, int facing, int newCameraState, |
| - String clientName); |
| + String clientName, int apiLevel); |
| } |
| diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp |
| index e409ddd..c59d0e7 100644 |
| --- a/camera/ndk/impl/ACameraManager.cpp |
| +++ b/camera/ndk/impl/ACameraManager.cpp |
| @@ -340,6 +340,9 @@ void CameraManagerGlobal::onStatusChangedLocked( |
| msg->setString(kCameraIdKey, AString(cameraId)); |
| msg->post(); |
| } |
| + if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT) { |
| + mDeviceStatusMap.erase(cameraId); |
| + } |
| } |
| |
| } // namespace android |
| diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp |
| index 9c45331..61b9acb 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 @@ 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; |
| @@ -118,19 +120,15 @@ status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) { |
| return res; |
| } |
| |
| -int CameraFlashlight::getNumberOfCameras() { |
| - return mProviderManager->getAPI1CompatibleCameraCount(); |
| -} |
| - |
| status_t CameraFlashlight::findFlashUnits() { |
| Mutex::Autolock l(mLock); |
| status_t res; |
| |
| std::vector<String8> cameraIds; |
| - int numberOfCameras = getNumberOfCameras(); |
| + std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds(); |
| + int numberOfCameras = static_cast<int>(ids.size()); |
| cameraIds.resize(numberOfCameras); |
| // No module, must be provider |
| - std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds(); |
| for (size_t i = 0; i < cameraIds.size(); i++) { |
| cameraIds[i] = String8(ids[i].c_str()); |
| } |
| @@ -184,7 +182,8 @@ bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) { |
| |
| ssize_t index = mHasFlashlightMap.indexOfKey(cameraId); |
| if (index == NAME_NOT_FOUND) { |
| - ALOGE("%s: camera %s not present when findFlashUnits() was called", |
| + // Might be external camera |
| + ALOGW("%s: camera %s not present when findFlashUnits() was called", |
| __FUNCTION__, cameraId.string()); |
| return false; |
| } |
| @@ -218,12 +217,13 @@ status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) { |
| |
| if (mOpenedCameraIds.size() == 0) { |
| // notify torch unavailable for all cameras with a flash |
| - int numCameras = getNumberOfCameras(); |
| + std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds(); |
| + int numCameras = static_cast<int>(ids.size()); |
| 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); |
| + String8 id8(ids[i].c_str()); |
| + if (hasFlashUnitLocked(id8)) { |
| + mCallbacks->onTorchStatusChanged( |
| + id8, TorchModeStatus::NOT_AVAILABLE); |
| } |
| } |
| } |
| @@ -263,12 +263,13 @@ status_t CameraFlashlight::deviceClosed(const String8& cameraId) { |
| |
| if (isBackwardCompatibleMode(cameraId)) { |
| // notify torch available for all cameras with a flash |
| - int numCameras = getNumberOfCameras(); |
| + std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds(); |
| + int numCameras = static_cast<int>(ids.size()); |
| 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); |
| + String8 id8(ids[i].c_str()); |
| + if (hasFlashUnitLocked(id8)) { |
| + mCallbacks->onTorchStatusChanged( |
| + id8, 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; |
| } |
| |
| diff --git a/services/camera/libcameraservice/CameraFlashlight.h b/services/camera/libcameraservice/CameraFlashlight.h |
| index c86ee85..1baaba2 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 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 |
| @@ -93,13 +92,11 @@ class CameraFlashlight : public virtual VirtualLightRefBase { |
| // opening cameras) |
| bool isBackwardCompatibleMode(const String8& cameraId); |
| |
| - int getNumberOfCameras(); |
| - |
| sp<FlashControlBase> mFlashControl; |
| |
| 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 +131,7 @@ class CameraHardwareInterfaceFlashControl : public FlashControlBase { |
| public: |
| CameraHardwareInterfaceFlashControl( |
| sp<CameraProviderManager> manager, |
| - const camera_module_callbacks_t& callbacks); |
| + CameraProviderManager::StatusListener* callbacks); |
| virtual ~CameraHardwareInterfaceFlashControl(); |
| |
| // FlashControlBase |
| @@ -166,7 +163,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; |
| diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp |
| index 01220e3..de0fac5 100644 |
| --- a/services/camera/libcameraservice/CameraService.cpp |
| +++ b/services/camera/libcameraservice/CameraService.cpp |
| @@ -109,79 +109,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); |
| } |
| |
| @@ -211,72 +145,43 @@ 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); |
| |
| - mNumberOfCameras = mCameraProviderManager->getCameraCount(); |
| - mNumberOfNormalCameras = |
| - mCameraProviderManager->getAPI1CompatibleCameraCount(); |
| + 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; |
| + } |
| + } |
| |
| - // 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); |
| - } |
| + // 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(); |
| |
| - 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; |
| - { |
| + if (nullptr == mFlashlight.get()) { |
| + mFlashlight = new CameraFlashlight(mCameraProviderManager, this); |
| + } |
| |
| - Mutex::Autolock lock(mCameraStatesLock); |
| - auto iter = mCameraStates.find(id8); |
| - if (iter != mCameraStates.end()) { |
| - cameraFound = true; |
| - } |
| + res = mFlashlight->findFlashUnits(); |
| + if (res != OK) { |
| + ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res); |
| } |
| |
| - if (!cameraFound) { |
| - hardware::camera::common::V1_0::CameraResourceCost cost; |
| - res = mCameraProviderManager->getResourceCost(cameraId, &cost); |
| - if (res != OK) { |
| - ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res); |
| - continue; |
| - } |
| - std::set<String8> conflicting; |
| - for (size_t i = 0; i < cost.conflictingDevices.size(); i++) { |
| - conflicting.emplace(String8(cost.conflictingDevices[i].c_str())); |
| - } |
| + deviceIds = mCameraProviderManager->getCameraDeviceIds(); |
| + } |
| |
| - { |
| - Mutex::Autolock lock(mCameraStatesLock); |
| - mCameraStates.emplace(id8, |
| - std::make_shared<CameraState>(id8, cost.resourceCost, conflicting)); |
| - } |
| - } |
| |
| + for (auto& cameraId : deviceIds) { |
| + String8 id8 = String8(cameraId.c_str()); |
| onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT); |
| - |
| - if (mFlashlight->hasFlashUnit(id8)) { |
| - mTorchStatusMap.add(id8, TorchModeStatus::AVAILABLE_OFF); |
| - } |
| } |
| |
| return OK; |
| @@ -312,6 +217,54 @@ 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; |
| + status_t res = mCameraProviderManager->getResourceCost(cameraId, &cost); |
| + if (res != OK) { |
| + ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res); |
| + return; |
| + } |
| + std::set<String8> conflicting; |
| + for (size_t i = 0; i < cost.conflictingDevices.size(); i++) { |
| + conflicting.emplace(String8(cost.conflictingDevices[i].c_str())); |
| + } |
| + |
| + { |
| + Mutex::Autolock lock(mCameraStatesLock); |
| + mCameraStates.emplace(id, std::make_shared<CameraState>(id, cost.resourceCost, |
| + conflicting)); |
| + } |
| + |
| + if (mFlashlight->hasFlashUnit(id)) { |
| + Mutex::Autolock al(mTorchStatusMutex); |
| + mTorchStatusMap.add(id, TorchModeStatus::AVAILABLE_OFF); |
| + } |
| + |
| + updateCameraNumAndIds(); |
| + logDeviceAdded(id, "Device added"); |
| +} |
| + |
| +void CameraService::removeStates(const String8 id) { |
| + updateCameraNumAndIds(); |
| + if (mFlashlight->hasFlashUnit(id)) { |
| + Mutex::Autolock al(mTorchStatusMutex); |
| + mTorchStatusMap.removeItem(id); |
| + } |
| + |
| + { |
| + Mutex::Autolock lock(mCameraStatesLock); |
| + mCameraStates.erase(id); |
| + } |
| +} |
| + |
| void CameraService::onDeviceStatusChanged(const String8& id, |
| CameraDeviceStatus newHalStatus) { |
| ALOGI("%s: Status changed for cameraId=%s, newStatus=%d", __FUNCTION__, |
| @@ -323,8 +276,13 @@ void CameraService::onDeviceStatusChanged(const String8& id, |
| |
| if (state == nullptr) { |
| if (newStatus == StatusInternal::PRESENT) { |
| - ALOGW("%s: Unknown camera ID %s, probably newly registered?", |
| + ALOGI("%s: Unknown camera ID %s, a new camera is added", |
| __FUNCTION__, id.string()); |
| + |
| + // First add as absent to make sure clients are notified below |
| + addStates(id); |
| + |
| + updateStatus(newStatus, id); |
| } else { |
| ALOGE("%s: Bad camera ID %s", __FUNCTION__, id.string()); |
| } |
| @@ -341,15 +299,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()); |
| |
| @@ -371,6 +330,7 @@ void CameraService::onDeviceStatusChanged(const String8& id, |
| clientToDisconnect->disconnect(); |
| } |
| |
| + removeStates(id); |
| } else { |
| if (oldStatus == StatusInternal::NOT_PRESENT) { |
| logDeviceAdded(id, String8::format("Device status changed from %d to %d", oldStatus, |
| @@ -451,7 +411,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; |
| @@ -481,7 +441,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, |
| @@ -491,13 +452,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, |
| @@ -614,8 +581,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) { |
| @@ -625,8 +592,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, |
| @@ -641,8 +609,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()); |
| @@ -664,8 +634,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" |
| @@ -765,7 +736,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) |
| @@ -1222,7 +1194,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, |
| @@ -1231,9 +1203,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); |
| @@ -1250,18 +1223,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); |
| @@ -1289,6 +1262,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, |
| @@ -1306,8 +1280,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(); |
| |
| @@ -1390,8 +1364,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; |
| } |
| @@ -2102,7 +2078,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, |
| @@ -2111,7 +2088,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); |
| @@ -2279,9 +2256,13 @@ status_t CameraService::BasicClient::startCameraOps() { |
| // Transition device availability listeners from PRESENT -> NOT_AVAILABLE |
| sCameraService->updateStatus(StatusInternal::NOT_AVAILABLE, mCameraIdStr); |
| |
| + int apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1; |
| + if (canCastToApiClient(API_2)) { |
| + apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2; |
| + } |
| // Transition device state to OPEN |
| sCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_OPEN, |
| - mCameraIdStr, mCameraFacing, mClientPackageName); |
| + mCameraIdStr, mCameraFacing, mClientPackageName, apiLevel); |
| |
| return OK; |
| } |
| @@ -2296,16 +2277,23 @@ status_t CameraService::BasicClient::finishCameraOps() { |
| mClientPackageName); |
| mOpsActive = false; |
| |
| + // This function is called when a client disconnects. This should |
| + // release the camera, but actually only if it was in a proper |
| + // functional state, i.e. with status NOT_AVAILABLE |
| std::initializer_list<StatusInternal> rejected = {StatusInternal::PRESENT, |
| - StatusInternal::ENUMERATING}; |
| + StatusInternal::ENUMERATING, StatusInternal::NOT_PRESENT}; |
| |
| // Transition to PRESENT if the camera is not in either of the rejected states |
| sCameraService->updateStatus(StatusInternal::PRESENT, |
| mCameraIdStr, rejected); |
| |
| + int apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1; |
| + if (canCastToApiClient(API_2)) { |
| + apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2; |
| + } |
| // Transition device state to CLOSED |
| sCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_CLOSED, |
| - mCameraIdStr, mCameraFacing, mClientPackageName); |
| + mCameraIdStr, mCameraFacing, mClientPackageName, apiLevel); |
| } |
| // Always stop watching, even if no camera op is active |
| if (mOpsCallback != NULL) { |
| @@ -2548,7 +2536,7 @@ void CameraService::UidPolicy::updateOverrideUid(uid_t uid, String16 callingPack |
| |
| CameraService::CameraState::CameraState(const String8& id, int cost, |
| const std::set<String8>& conflicting) : mId(id), |
| - mStatus(StatusInternal::PRESENT), mCost(cost), mConflicting(conflicting) {} |
| + mStatus(StatusInternal::NOT_PRESENT), mCost(cost), mConflicting(conflicting) {} |
| |
| CameraService::CameraState::~CameraState() {} |
| |
| @@ -2724,7 +2712,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()); |
| @@ -2979,11 +2970,11 @@ void CameraService::CameraState::updateStatus(StatusInternal status, |
| } |
| |
| void CameraService::updateProxyDeviceState(int newState, |
| - const String8& cameraId, int facing, const String16& clientName) { |
| + const String8& cameraId, int facing, const String16& clientName, int apiLevel) { |
| sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy(); |
| if (proxyBinder == nullptr) return; |
| String16 id(cameraId); |
| - proxyBinder->notifyCameraState(id, newState, facing, clientName); |
| + proxyBinder->notifyCameraState(id, newState, facing, clientName, apiLevel); |
| } |
| |
| status_t CameraService::getTorchStatusLocked( |
| diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h |
| index 6724c49..8d4bcdb 100644 |
| --- a/services/camera/libcameraservice/CameraService.h |
| +++ b/services/camera/libcameraservice/CameraService.h |
| @@ -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>; |
| @@ -190,7 +189,8 @@ public: |
| int newState, |
| const String8& cameraId, |
| int facing, |
| - const String16& clientName); |
| + const String16& clientName, |
| + int apiLevel); |
| |
| ///////////////////////////////////////////////////////////////////// |
| // CameraDeviceFactory functionality |
| @@ -334,6 +334,7 @@ public: |
| const sp<hardware::ICameraClient>& cameraClient, |
| const String16& clientPackageName, |
| const String8& cameraIdStr, |
| + int api1CameraId, |
| int cameraFacing, |
| int clientPid, |
| uid_t clientUid, |
| @@ -555,6 +556,11 @@ private: |
| // Eumerate all camera providers in the system |
| status_t enumerateProviders(); |
| |
| + // 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); |
| + |
| // Check if we can connect, before we acquire the service lock. |
| // The returned originalClientPid is the PID of the original process that wants to connect to |
| // camera. |
| @@ -578,7 +584,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); |
| @@ -643,9 +649,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. |
| + */ |
| + 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. |
| */ |
| - static int cameraIdToInt(const String8& cameraId); |
| + std::string cameraIdIntToStrLocked(int cameraIdInt); |
| |
| /** |
| * Remove a single client corresponding to the given camera id from the list of active clients. |
| @@ -713,8 +726,14 @@ private: |
| */ |
| void dumpEventLog(int fd); |
| |
| + /** |
| + * This method will acquire mServiceLock |
| + */ |
| + void updateCameraNumAndIds(); |
| + |
| int mNumberOfCameras; |
| - int mNumberOfNormalCameras; |
| + |
| + std::vector<std::string> mNormalDeviceIds; |
| |
| // sounds |
| sp<MediaPlayer> newMediaPlayer(const char *file); |
| @@ -824,8 +843,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); |
| diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp |
| index dd1cf2c..65faac9 100644 |
| --- a/services/camera/libcameraservice/api1/Camera2Client.cpp |
| +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp |
| @@ -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(); |
| |
| diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h |
| index c17cbd4..44929c3 100644 |
| --- a/services/camera/libcameraservice/api1/Camera2Client.h |
| +++ b/services/camera/libcameraservice/api1/Camera2Client.h |
| @@ -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, |
| diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp |
| index e2c8b8b..2358c1e 100644 |
| --- a/services/camera/libcameraservice/api1/CameraClient.cpp |
| +++ b/services/camera/libcameraservice/api1/CameraClient.cpp |
| @@ -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(); |
| @@ -264,7 +264,8 @@ binder::Status CameraClient::disconnect() { |
| mHardware->stopPreview(); |
| sCameraService->updateProxyDeviceState( |
| hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, |
| - mCameraIdStr, mCameraFacing, mClientPackageName); |
| + mCameraIdStr, mCameraFacing, mClientPackageName, |
| + hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1); |
| mHardware->cancelPicture(); |
| // Release the hardware resources. |
| mHardware->release(); |
| @@ -427,7 +428,8 @@ status_t CameraClient::startPreviewMode() { |
| if (result == NO_ERROR) { |
| sCameraService->updateProxyDeviceState( |
| hardware::ICameraServiceProxy::CAMERA_STATE_ACTIVE, |
| - mCameraIdStr, mCameraFacing, mClientPackageName); |
| + mCameraIdStr, mCameraFacing, mClientPackageName, |
| + hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1); |
| } |
| return result; |
| } |
| @@ -470,7 +472,8 @@ void CameraClient::stopPreview() { |
| mHardware->stopPreview(); |
| sCameraService->updateProxyDeviceState( |
| hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, |
| - mCameraIdStr, mCameraFacing, mClientPackageName); |
| + mCameraIdStr, mCameraFacing, mClientPackageName, |
| + hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1); |
| mPreviewBuffer.clear(); |
| } |
| |
| @@ -981,7 +984,8 @@ void CameraClient::handleShutter(void) { |
| // idle now, until preview is restarted |
| sCameraService->updateProxyDeviceState( |
| hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, |
| - mCameraIdStr, mCameraFacing, mClientPackageName); |
| + mCameraIdStr, mCameraFacing, mClientPackageName, |
| + hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1); |
| |
| mLock.unlock(); |
| } |
| diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp |
| index 7373b81..d66dec4 100644 |
| --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp |
| +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp |
| @@ -761,12 +761,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); |
| @@ -1104,9 +1109,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; |
| @@ -1191,10 +1202,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]; |
| + } |
| } |
| } |
| |
| @@ -2921,8 +2936,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}); |
| } |
| } |
| |
| @@ -3132,6 +3152,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; |
| diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h |
| index f0bde5b..97f8ea7 100644 |
| --- a/services/camera/libcameraservice/api1/client2/Parameters.h |
| +++ b/services/camera/libcameraservice/api1/client2/Parameters.h |
| @@ -209,6 +209,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. |
| @@ -235,6 +240,7 @@ struct Parameters { |
| } |
| }; |
| DefaultKeyedVector<uint8_t, OverrideModes> sceneModeOverrides; |
| + bool isExternalCamera; |
| float minFocalLength; |
| bool useFlexibleYuv; |
| Size maxJpegSize; |
| @@ -383,6 +389,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); |
| diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp |
| index 2297ed3..98d0534 100644 |
| --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp |
| +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp |
| @@ -49,6 +49,7 @@ CameraDeviceClientBase::CameraDeviceClientBase( |
| const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback, |
| const String16& clientPackageName, |
| const String8& cameraId, |
| + int api1CameraId, |
| int cameraFacing, |
| int clientPid, |
| uid_t clientUid, |
| @@ -62,6 +63,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 |
| @@ -75,7 +78,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) { |
| @@ -620,11 +624,19 @@ binder::Status CameraDeviceClient::createStream( |
| return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive"); |
| } |
| |
| - if (!checkPhysicalCameraId(physicalCameraId)) { |
| - String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.", |
| + if (physicalCameraId.size() > 0) { |
| + std::vector<std::string> physicalCameraIds; |
| + std::string physicalId(physicalCameraId.string()); |
| + bool logicalCamera = |
| + CameraProviderManager::isLogicalCamera(mDevice->info(), &physicalCameraIds); |
| + if (!logicalCamera || |
| + std::find(physicalCameraIds.begin(), physicalCameraIds.end(), physicalId) == |
| + physicalCameraIds.end()) { |
| + String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.", |
| mCameraIdStr.string(), physicalCameraId.string()); |
| - ALOGE("%s: %s", __FUNCTION__, msg.string()); |
| - return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string()); |
| + ALOGE("%s: %s", __FUNCTION__, msg.string()); |
| + return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string()); |
| + } |
| } |
| std::vector<sp<Surface>> surfaces; |
| std::vector<sp<IBinder>> binders; |
| @@ -1140,43 +1152,6 @@ binder::Status CameraDeviceClient::createSurfaceFromGbp( |
| return binder::Status::ok(); |
| } |
| |
| -bool CameraDeviceClient::checkPhysicalCameraId(const String8& physicalCameraId) { |
| - if (0 == physicalCameraId.size()) { |
| - return true; |
| - } |
| - |
| - CameraMetadata staticInfo = mDevice->info(); |
| - camera_metadata_entry_t entryCap; |
| - bool isLogicalCam = false; |
| - |
| - entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES); |
| - for (size_t i = 0; i < entryCap.count; ++i) { |
| - uint8_t capability = entryCap.data.u8[i]; |
| - if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) { |
| - isLogicalCam = true; |
| - } |
| - } |
| - if (!isLogicalCam) { |
| - return false; |
| - } |
| - |
| - camera_metadata_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS); |
| - const uint8_t* ids = entryIds.data.u8; |
| - size_t start = 0; |
| - for (size_t i = 0; i < entryIds.count; ++i) { |
| - if (ids[i] == '\0') { |
| - if (start != i) { |
| - String8 currentId((const char*)ids+start); |
| - if (currentId == physicalCameraId) { |
| - return true; |
| - } |
| - } |
| - start = i+1; |
| - } |
| - } |
| - return false; |
| -} |
| - |
| bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height, |
| int32_t format, android_dataspace dataSpace, const CameraMetadata& info, |
| /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) { |
| diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h |
| index 5bec39c..5aaf5aa 100644 |
| --- a/services/camera/libcameraservice/api2/CameraDeviceClient.h |
| +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h |
| @@ -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, |
| diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp |
| index 5c6711a..ce006a7 100644 |
| --- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp |
| +++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp |
| @@ -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); |
| @@ -252,7 +253,9 @@ void Camera2ClientBase<TClientBase>::notifyIdle() { |
| if (mDeviceActive) { |
| getCameraService()->updateProxyDeviceState( |
| hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, TClientBase::mCameraIdStr, |
| - TClientBase::mCameraFacing, TClientBase::mClientPackageName); |
| + TClientBase::mCameraFacing, TClientBase::mClientPackageName, |
| + ((mApi1CameraId < 0) ? hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2 : |
| + hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1)); |
| } |
| mDeviceActive = false; |
| |
| @@ -268,7 +271,9 @@ void Camera2ClientBase<TClientBase>::notifyShutter(const CaptureResultExtras& re |
| if (!mDeviceActive) { |
| getCameraService()->updateProxyDeviceState( |
| hardware::ICameraServiceProxy::CAMERA_STATE_ACTIVE, TClientBase::mCameraIdStr, |
| - TClientBase::mCameraFacing, TClientBase::mClientPackageName); |
| + TClientBase::mCameraFacing, TClientBase::mClientPackageName, |
| + ((mApi1CameraId < 0) ? hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2 : |
| + hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1)); |
| } |
| mDeviceActive = true; |
| |
| @@ -331,7 +336,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> |
| diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h |
| index 4da422a..e74fbdf 100644 |
| --- a/services/camera/libcameraservice/common/Camera2ClientBase.h |
| +++ b/services/camera/libcameraservice/common/Camera2ClientBase.h |
| @@ -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, const String8& monitorTags); |
| diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp |
| index 4bc78dd..21cfd44 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 { |
| |
| @@ -39,9 +41,6 @@ const std::string kLegacyProviderName("legacy/0"); |
| const std::string kExternalProviderName("external/0"); |
| #endif |
| |
| -// Slash-separated list of provider types to consider for use via the old camera API |
| -const std::string kStandardProviderTypes("internal/legacy"); |
| - |
| } // anonymous namespace |
| |
| CameraProviderManager::HardwareServiceInteractionProxy |
| @@ -83,18 +82,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; |
| } |
| @@ -114,12 +102,33 @@ std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds |
| std::lock_guard<std::mutex> lock(mInterfaceMutex); |
| std::vector<std::string> deviceIds; |
| for (auto& provider : mProviders) { |
| - if (kStandardProviderTypes.find(provider->getType()) != std::string::npos) { |
| - for (auto& id : provider->mUniqueAPI1CompatibleCameraIds) { |
| - deviceIds.push_back(id); |
| - } |
| - } |
| + std::vector<std::string> providerDeviceIds = provider->mUniqueAPI1CompatibleCameraIds; |
| + |
| + // API1 app doesn't handle logical and physical camera devices well. So |
| + // for each [logical, physical1, physical2, ...] id combo, only take the |
| + // first id advertised by HAL, and filter out the rest. |
| + filterLogicalCameraIdsLocked(providerDeviceIds); |
| + |
| + deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end()); |
| } |
| + |
| + 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; |
| } |
| |
| @@ -172,11 +181,7 @@ status_t CameraProviderManager::getCameraInfo(const std::string &id, |
| status_t CameraProviderManager::getCameraCharacteristics(const std::string &id, |
| CameraMetadata* characteristics) const { |
| std::lock_guard<std::mutex> lock(mInterfaceMutex); |
| - |
| - auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {4,0}); |
| - if (deviceInfo == nullptr) return NAME_NOT_FOUND; |
| - |
| - return deviceInfo->getCameraCharacteristics(characteristics); |
| + return getCameraCharacteristicsLocked(id, characteristics); |
| } |
| |
| status_t CameraProviderManager::getHighestSupportedVersion(const std::string &id, |
| @@ -391,6 +396,37 @@ metadata_vendor_id_t CameraProviderManager::getProviderTagIdLocked( |
| return ret; |
| } |
| |
| +bool CameraProviderManager::isLogicalCamera(const CameraMetadata& staticInfo, |
| + std::vector<std::string>* physicalCameraIds) { |
| + bool isLogicalCam = false; |
| + camera_metadata_ro_entry_t entryCap; |
| + |
| + entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES); |
| + for (size_t i = 0; i < entryCap.count; ++i) { |
| + uint8_t capability = entryCap.data.u8[i]; |
| + if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) { |
| + isLogicalCam = true; |
| + break; |
| + } |
| + } |
| + if (!isLogicalCam) { |
| + return false; |
| + } |
| + |
| + camera_metadata_ro_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS); |
| + const uint8_t* ids = entryIds.data.u8; |
| + size_t start = 0; |
| + for (size_t i = 0; i < entryIds.count; ++i) { |
| + if (ids[i] == '\0') { |
| + if (start != i) { |
| + physicalCameraIds->push_back((const char*)ids+start); |
| + } |
| + start = i+1; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) { |
| for (const auto& providerInfo : mProviders) { |
| if (providerInfo->mProviderName == newProvider) { |
| @@ -484,6 +520,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", |
| @@ -540,17 +578,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; |
| } |
| |
| @@ -598,15 +629,36 @@ 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.push_back(id); |
| + } |
| + |
| if (parsedId != nullptr) { |
| *parsedId = id; |
| } |
| return OK; |
| } |
| |
| +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(std::remove( |
| + mUniqueAPI1CompatibleCameraIds.begin(), |
| + mUniqueAPI1CompatibleCameraIds.end(), id)); |
| + } |
| + mDevices.erase(it); |
| + break; |
| + } |
| + } |
| +} |
| + |
| status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector<String16>&) const { |
| dprintf(fd, "== Camera Provider HAL %s (v2.4, %s) static info: %zu devices: ==\n", |
| mProviderName.c_str(), mInterface->isRemote() ? "remote" : "passthrough", |
| @@ -666,6 +718,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; |
| @@ -688,11 +741,17 @@ hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusCh |
| return hardware::Void(); |
| } |
| addDevice(cameraDeviceName, newStatus, &id); |
| + } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) { |
| + 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(); |
| @@ -1396,5 +1455,51 @@ status_t HidlVendorTagDescriptor::createDescriptorFromHidl( |
| return OK; |
| } |
| |
| +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; |
| + |
| + return deviceInfo->getCameraCharacteristics(characteristics); |
| +} |
| + |
| +void CameraProviderManager::filterLogicalCameraIdsLocked( |
| + std::vector<std::string>& deviceIds) const |
| +{ |
| + std::unordered_set<std::string> removedIds; |
| + |
| + for (auto& deviceId : deviceIds) { |
| + CameraMetadata info; |
| + status_t res = getCameraCharacteristicsLocked(deviceId, &info); |
| + if (res != OK) { |
| + ALOGE("%s: Failed to getCameraCharacteristics for id %s", __FUNCTION__, |
| + deviceId.c_str()); |
| + return; |
| + } |
| + |
| + // idCombo contains the ids of a logical camera and its physical cameras |
| + std::vector<std::string> idCombo; |
| + bool logicalCamera = CameraProviderManager::isLogicalCamera(info, &idCombo); |
| + if (!logicalCamera) { |
| + continue; |
| + } |
| + idCombo.push_back(deviceId); |
| + |
| + for (auto& id : deviceIds) { |
| + auto foundId = std::find(idCombo.begin(), idCombo.end(), id); |
| + if (foundId == idCombo.end()) { |
| + continue; |
| + } |
| + |
| + idCombo.erase(foundId); |
| + removedIds.insert(idCombo.begin(), idCombo.end()); |
| + break; |
| + } |
| + } |
| + |
| + deviceIds.erase(std::remove_if(deviceIds.begin(), deviceIds.end(), |
| + [&removedIds](const std::string& s) {return removedIds.find(s) != removedIds.end();}), |
| + deviceIds.end()); |
| +} |
| |
| } // namespace android |
| diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h |
| index 0f1f07b..b8b8b8c 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 @@ 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; |
| |
| /** |
| @@ -232,6 +230,13 @@ public: |
| hardware::hidl_version minVersion = hardware::hidl_version{0,0}, |
| hardware::hidl_version maxVersion = hardware::hidl_version{1000,0}) const; |
| |
| + /* |
| + * Check if a camera with staticInfo is a logical camera. And if yes, return |
| + * the physical camera ids. |
| + */ |
| + static bool isLogicalCamera(const CameraMetadata& staticInfo, |
| + std::vector<std::string>* physicalCameraIds); |
| + |
| private: |
| // All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use |
| mutable std::mutex mInterfaceMutex; |
| @@ -314,9 +319,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::vector<std::string> mUniqueAPI1CompatibleCameraIds; |
| |
| // HALv1-specific camera fields, including the actual device interface |
| struct DeviceInfo1 : public DeviceInfo { |
| @@ -366,6 +371,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> |
| @@ -387,6 +394,8 @@ private: |
| |
| // Generate vendor tag id |
| static metadata_vendor_id_t generateVendorTagId(const std::string &name); |
| + |
| + void removeDevice(std::string id); |
| }; |
| |
| // Utility to find a DeviceInfo by ID; pointer is only valid while mInterfaceMutex is held |
| @@ -412,6 +421,9 @@ private: |
| static const char* torchStatusToString( |
| const hardware::camera::common::V1_0::TorchModeStatus&); |
| |
| + status_t getCameraCharacteristicsLocked(const std::string &id, |
| + CameraMetadata* characteristics) const; |
| + void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const; |
| }; |
| |
| } // namespace android |
| -- |
| 2.7.4 |
| |