diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp index 22e9578da3..dc7f88a49c 100644 --- a/camera/cameraserver/Android.bp +++ b/camera/cameraserver/Android.bp @@ -48,6 +48,6 @@ cc_binary { init_rc: ["cameraserver.rc"], vintf_fragments: [ - "manifest_android.frameworks.cameraservice.service@2.0.xml", + "manifest_android.frameworks.cameraservice.service@2.1.xml", ], } diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.1.xml similarity index 90% rename from camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml rename to camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.1.xml index 601c7171b0..5a15b35b32 100644 --- a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml +++ b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.1.xml @@ -2,7 +2,7 @@ android.frameworks.cameraservice.service hwbinder - 2.0 + 2.1 ICameraService default diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp index 56f209c5a9..7ba82c1b5b 100644 --- a/camera/ndk/Android.bp +++ b/camera/ndk/Android.bp @@ -123,6 +123,7 @@ cc_library_shared { "android.frameworks.cameraservice.device@2.0", "android.frameworks.cameraservice.common@2.0", "android.frameworks.cameraservice.service@2.0", + "android.frameworks.cameraservice.service@2.1", ], static_libs: [ "android.hardware.camera.common@1.0-helper", @@ -140,9 +141,12 @@ cc_library_shared { } cc_test { - name: "AImageReaderVendorTest", + name: "ACameraNdkVendorTest", vendor: true, - srcs: ["ndk_vendor/tests/AImageReaderVendorTest.cpp"], + srcs: [ + "ndk_vendor/tests/AImageReaderVendorTest.cpp", + "ndk_vendor/tests/ACameraManagerTest.cpp", + ], shared_libs: [ "libcamera2ndk_vendor", "libcamera_metadata", diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp index 4870265770..f408b6a854 100644 --- a/camera/ndk/impl/ACameraManager.cpp +++ b/camera/ndk/impl/ACameraManager.cpp @@ -130,6 +130,11 @@ sp CameraManagerGlobal::getCameraServiceLocked() { mCameraService->addListener(mCameraServiceListener, &cameraStatuses); for (auto& c : cameraStatuses) { onStatusChangedLocked(c.status, c.cameraId); + + for (auto& unavailablePhysicalId : c.unavailablePhysicalIds) { + onStatusChangedLocked(hardware::ICameraServiceListener::STATUS_NOT_PRESENT, + c.cameraId, unavailablePhysicalId); + } } // setup vendor tags @@ -200,9 +205,7 @@ void CameraManagerGlobal::DeathNotifier::binderDied(const wp&) void CameraManagerGlobal::registerExtendedAvailabilityCallback( const ACameraManager_ExtendedAvailabilityCallbacks *callback) { - Mutex::Autolock _l(mLock); - Callback cb(callback); - mCallbacks.insert(cb); + return registerAvailCallback(callback); } void CameraManagerGlobal::unregisterExtendedAvailabilityCallback( @@ -214,6 +217,18 @@ void CameraManagerGlobal::unregisterExtendedAvailabilityCallback( void CameraManagerGlobal::registerAvailabilityCallback( const ACameraManager_AvailabilityCallbacks *callback) { + return registerAvailCallback(callback); +} + +void CameraManagerGlobal::unregisterAvailabilityCallback( + const ACameraManager_AvailabilityCallbacks *callback) { + Mutex::Autolock _l(mLock); + Callback cb(callback); + mCallbacks.erase(cb); +} + +template +void CameraManagerGlobal::registerAvailCallback(const T *callback) { Mutex::Autolock _l(mLock); Callback cb(callback); auto pair = mCallbacks.insert(cb); @@ -227,24 +242,33 @@ void CameraManagerGlobal::registerAvailabilityCallback( if (!pair.second.supportsHAL3) { continue; } + + // Camera available/unavailable callback sp msg = new AMessage(kWhatSendSingleCallback, mHandler); - ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ? - callback->onCameraAvailable : callback->onCameraUnavailable; - msg->setPointer(kCallbackFpKey, (void *) cb); - msg->setPointer(kContextKey, callback->context); + ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ? + cb.mAvailable : cb.mUnavailable; + msg->setPointer(kCallbackFpKey, (void *) cbFunc); + msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId)); msg->post(); + + // Physical camera unavailable callback + std::set unavailablePhysicalCameras = + pair.second.getUnavailablePhysicalIds(); + for (const auto& physicalCameraId : unavailablePhysicalCameras) { + sp msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler); + ACameraManager_PhysicalCameraAvailabilityCallback cbFunc = + cb.mPhysicalCamUnavailable; + msg->setPointer(kCallbackFpKey, (void *) cbFunc); + msg->setPointer(kContextKey, cb.mContext); + msg->setString(kCameraIdKey, AString(cameraId)); + msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId)); + msg->post(); + } } } } -void CameraManagerGlobal::unregisterAvailabilityCallback( - const ACameraManager_AvailabilityCallbacks *callback) { - Mutex::Autolock _l(mLock); - Callback cb(callback); - mCallbacks.erase(cb); -} - bool CameraManagerGlobal::supportsCamera2ApiLocked(const String8 &cameraId) { bool camera2Support = false; auto cs = getCameraServiceLocked(); @@ -550,6 +574,11 @@ bool CameraManagerGlobal::StatusAndHAL3Support::removeUnavailablePhysicalId( return count > 0; } +std::set CameraManagerGlobal::StatusAndHAL3Support::getUnavailablePhysicalIds() { + std::lock_guard lock(mLock); + return unavailablePhysicalIds; +} + } // namespace acam } // namespace android diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h index 98cd934865..836e037ecd 100644 --- a/camera/ndk/impl/ACameraManager.h +++ b/camera/ndk/impl/ACameraManager.h @@ -70,6 +70,9 @@ class CameraManagerGlobal final : public RefBase { const char* kCameraServiceName = "media.camera"; Mutex mLock; + template + void registerAvailCallback(const T *callback); + class DeathNotifier : public IBinder::DeathRecipient { public: explicit DeathNotifier(CameraManagerGlobal* cm) : mCameraManager(cm) {} @@ -222,6 +225,7 @@ class CameraManagerGlobal final : public RefBase { bool removeUnavailablePhysicalId(const String8& physicalCameraId); int32_t getStatus(); void updateStatus(int32_t newStatus); + std::set getUnavailablePhysicalIds(); }; // Map camera_id -> status diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp index 70c887acea..a95fe2a20c 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp +++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp @@ -36,13 +36,13 @@ using namespace android::acam; namespace android { namespace acam { -using frameworks::cameraservice::service::V2_0::CameraStatusAndId; using frameworks::cameraservice::common::V2_0::ProviderIdAndVendorTagSections; using android::hardware::camera::common::V1_0::helper::VendorTagDescriptor; using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache; // Static member definitions const char* CameraManagerGlobal::kCameraIdKey = "CameraId"; +const char* CameraManagerGlobal::kPhysicalCameraIdKey = "PhysicalCameraId"; const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp"; const char* CameraManagerGlobal::kContextKey = "CallbackContext"; Mutex CameraManagerGlobal::sLock; @@ -258,9 +258,9 @@ sp CameraManagerGlobal::getCameraService() { if (mCameraServiceListener == nullptr) { mCameraServiceListener = new CameraServiceListener(this); } - hidl_vec cameraStatuses{}; + hidl_vec cameraStatuses{}; Status status = Status::NO_ERROR; - auto remoteRet = mCameraService->addListener(mCameraServiceListener, + auto remoteRet = mCameraService->addListener_2_1(mCameraServiceListener, [&status, &cameraStatuses](Status s, auto &retStatuses) { status = s; @@ -277,7 +277,15 @@ sp CameraManagerGlobal::getCameraService() { } for (auto& c : cameraStatuses) { - onStatusChangedLocked(c); + onStatusChangedLocked(c.v2_0); + + for (auto& unavailablePhysicalId : c.unavailPhysicalCameraIds) { + PhysicalCameraStatusAndId statusAndId; + statusAndId.deviceStatus = CameraDeviceStatus::STATUS_NOT_PRESENT; + statusAndId.cameraId = c.v2_0.cameraId; + statusAndId.physicalCameraId = unavailablePhysicalId; + onStatusChangedLocked(statusAndId); + } } } return mCameraService; @@ -293,7 +301,7 @@ void CameraManagerGlobal::DeathNotifier::serviceDied(uint64_t cookie, const wpmDeviceStatusMap) { CameraStatusAndId cameraStatusAndId; cameraStatusAndId.cameraId = pair.first; - cameraStatusAndId.deviceStatus = pair.second; + cameraStatusAndId.deviceStatus = pair.second.getStatus(); cm->onStatusChangedLocked(cameraStatusAndId); } cm->mCameraService.clear(); @@ -303,6 +311,30 @@ void CameraManagerGlobal::DeathNotifier::serviceDied(uint64_t cookie, const wp(callback); +} + +void CameraManagerGlobal::unregisterAvailabilityCallback( + const ACameraManager_AvailabilityCallbacks *callback) { + Mutex::Autolock _l(mLock); + Callback cb(callback); + mCallbacks.erase(cb); +} + +void CameraManagerGlobal::registerExtendedAvailabilityCallback( + const ACameraManager_ExtendedAvailabilityCallbacks *callback) { + return registerAvailCallback(callback); +} + +void CameraManagerGlobal::unregisterExtendedAvailabilityCallback( + const ACameraManager_ExtendedAvailabilityCallbacks *callback) { + Mutex::Autolock _l(mLock); + Callback cb(callback); + mCallbacks.erase(cb); +} + +template +void CameraManagerGlobal::registerAvailCallback(const T *callback) { Mutex::Autolock _l(mLock); Callback cb(callback); auto pair = mCallbacks.insert(cb); @@ -310,34 +342,42 @@ void CameraManagerGlobal::registerAvailabilityCallback( if (pair.second) { for (auto& pair : mDeviceStatusMap) { const hidl_string& cameraId = pair.first; - CameraDeviceStatus status = pair.second; + CameraDeviceStatus status = pair.second.getStatus(); + // Camera available/unavailable callback sp msg = new AMessage(kWhatSendSingleCallback, mHandler); - ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ? - callback->onCameraAvailable : callback->onCameraUnavailable; - msg->setPointer(kCallbackFpKey, (void *) cb); - msg->setPointer(kContextKey, callback->context); + ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ? + cb.mAvailable : cb.mUnavailable; + msg->setPointer(kCallbackFpKey, (void *) cbFunc); + msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId.c_str())); msg->post(); + + // Physical camera unavailable callback + std::set unavailPhysicalIds = pair.second.getUnavailablePhysicalIds(); + for (const auto& physicalCameraId : unavailPhysicalIds) { + sp msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler); + ACameraManager_PhysicalCameraAvailabilityCallback cbFunc = + cb.mPhysicalCamUnavailable; + msg->setPointer(kCallbackFpKey, (void *) cbFunc); + msg->setPointer(kContextKey, cb.mContext); + msg->setString(kCameraIdKey, AString(cameraId.c_str())); + msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str())); + msg->post(); + } } } } -void CameraManagerGlobal::unregisterAvailabilityCallback( - const ACameraManager_AvailabilityCallbacks *callback) { - Mutex::Autolock _l(mLock); - Callback cb(callback); - mCallbacks.erase(cb); -} - void CameraManagerGlobal::getCameraIdList(std::vector* cameraIds) { // Ensure that we have initialized/refreshed the list of available devices auto cs = getCameraService(); Mutex::Autolock _l(mLock); for(auto& deviceStatus : mDeviceStatusMap) { - if (deviceStatus.second == CameraDeviceStatus::STATUS_NOT_PRESENT || - deviceStatus.second == CameraDeviceStatus::STATUS_ENUMERATING) { + CameraDeviceStatus status = deviceStatus.second.getStatus(); + if (status == CameraDeviceStatus::STATUS_NOT_PRESENT || + status == CameraDeviceStatus::STATUS_ENUMERATING) { continue; } cameraIds->push_back(deviceStatus.first); @@ -391,6 +431,35 @@ void CameraManagerGlobal::CallbackHandler::onMessageReceived( (*cb)(context, cameraId.c_str()); break; } + case kWhatSendSinglePhysicalCameraCallback: + { + ACameraManager_PhysicalCameraAvailabilityCallback cb; + void* context; + AString cameraId; + AString physicalCameraId; + bool found = msg->findPointer(kCallbackFpKey, (void**) &cb); + if (!found) { + ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__); + return; + } + found = msg->findPointer(kContextKey, &context); + if (!found) { + ALOGE("%s: Cannot find callback context!", __FUNCTION__); + return; + } + found = msg->findString(kCameraIdKey, &cameraId); + if (!found) { + ALOGE("%s: Cannot find camera ID!", __FUNCTION__); + return; + } + found = msg->findString(kPhysicalCameraIdKey, &physicalCameraId); + if (!found) { + ALOGE("%s: Cannot find physical camera ID!", __FUNCTION__); + return; + } + (*cb)(context, cameraId.c_str(), physicalCameraId.c_str()); + break; + } default: ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what()); break; @@ -426,7 +495,7 @@ void CameraManagerGlobal::onStatusChangedLocked( bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0); CameraDeviceStatus oldStatus = firstStatus ? status : // first status - mDeviceStatusMap[cameraId]; + mDeviceStatusMap[cameraId].getStatus(); if (!firstStatus && isStatusAvailable(status) == isStatusAvailable(oldStatus)) { @@ -435,7 +504,7 @@ void CameraManagerGlobal::onStatusChangedLocked( } // Iterate through all registered callbacks - mDeviceStatusMap[cameraId] = status; + mDeviceStatusMap[cameraId].updateStatus(status); for (auto cb : mCallbacks) { sp msg = new AMessage(kWhatSendSingleCallback, mHandler); ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ? @@ -450,6 +519,98 @@ void CameraManagerGlobal::onStatusChangedLocked( } } +hardware::Return CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged( + const PhysicalCameraStatusAndId &statusAndId) { + sp cm = mCameraManager.promote(); + if (cm != nullptr) { + cm->onStatusChanged(statusAndId); + } else { + ALOGE("Cannot deliver status change. Global camera manager died"); + } + return Void(); +} + +void CameraManagerGlobal::onStatusChanged( + const PhysicalCameraStatusAndId &statusAndId) { + Mutex::Autolock _l(mLock); + onStatusChangedLocked(statusAndId); +} + +void CameraManagerGlobal::onStatusChangedLocked( + const PhysicalCameraStatusAndId &statusAndId) { + hidl_string cameraId = statusAndId.cameraId; + hidl_string physicalCameraId = statusAndId.physicalCameraId; + CameraDeviceStatus status = statusAndId.deviceStatus; + if (!validStatus(status)) { + ALOGE("%s: Invalid status %d", __FUNCTION__, status); + return; + } + + auto logicalStatus = mDeviceStatusMap.find(cameraId); + if (logicalStatus == mDeviceStatusMap.end()) { + ALOGE("%s: Physical camera id %s status change on a non-present id %s", + __FUNCTION__, physicalCameraId.c_str(), cameraId.c_str()); + return; + } + CameraDeviceStatus logicalCamStatus = mDeviceStatusMap[cameraId].getStatus(); + if (logicalCamStatus != CameraDeviceStatus::STATUS_PRESENT && + logicalCamStatus != CameraDeviceStatus::STATUS_NOT_AVAILABLE) { + ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d", + __FUNCTION__, physicalCameraId.c_str(), status, logicalCamStatus); + return; + } + + bool updated = false; + if (status == CameraDeviceStatus::STATUS_PRESENT) { + updated = mDeviceStatusMap[cameraId].removeUnavailablePhysicalId(physicalCameraId); + } else { + updated = mDeviceStatusMap[cameraId].addUnavailablePhysicalId(physicalCameraId); + } + + // Iterate through all registered callbacks + if (updated) { + for (auto cb : mCallbacks) { + sp msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler); + ACameraManager_PhysicalCameraAvailabilityCallback cbFp = isStatusAvailable(status) ? + cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable; + msg->setPointer(kCallbackFpKey, (void *) cbFp); + msg->setPointer(kContextKey, cb.mContext); + msg->setString(kCameraIdKey, AString(cameraId.c_str())); + msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str())); + msg->post(); + } + } +} + +CameraDeviceStatus CameraManagerGlobal::CameraStatus::getStatus() { + std::lock_guard lock(mLock); + return status; +} + +void CameraManagerGlobal::CameraStatus::updateStatus(CameraDeviceStatus newStatus) { + std::lock_guard lock(mLock); + status = newStatus; +} + +bool CameraManagerGlobal::CameraStatus::addUnavailablePhysicalId( + const hidl_string& physicalCameraId) { + std::lock_guard lock(mLock); + auto result = unavailablePhysicalIds.insert(physicalCameraId); + return result.second; +} + +bool CameraManagerGlobal::CameraStatus::removeUnavailablePhysicalId( + const hidl_string& physicalCameraId) { + std::lock_guard lock(mLock); + auto count = unavailablePhysicalIds.erase(physicalCameraId); + return count > 0; +} + +std::set CameraManagerGlobal::CameraStatus::getUnavailablePhysicalIds() { + std::lock_guard lock(mLock); + return unavailablePhysicalIds; +} + } // namespace acam } // namespace android diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h index 2c62d44b0f..36c8e2bd8f 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraManager.h +++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include @@ -36,9 +38,10 @@ namespace android { namespace acam { -using ICameraService = frameworks::cameraservice::service::V2_0::ICameraService; +using ICameraService = frameworks::cameraservice::service::V2_1::ICameraService; using CameraDeviceStatus = frameworks::cameraservice::service::V2_0::CameraDeviceStatus; -using ICameraServiceListener = frameworks::cameraservice::service::V2_0::ICameraServiceListener; +using ICameraServiceListener = frameworks::cameraservice::service::V2_1::ICameraServiceListener; +using PhysicalCameraStatusAndId = frameworks::cameraservice::service::V2_1::PhysicalCameraStatusAndId; using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId; using Status = frameworks::cameraservice::common::V2_0::Status; using VendorTagSection = frameworks::cameraservice::common::V2_0::VendorTagSection; @@ -65,9 +68,9 @@ class CameraManagerGlobal final : public RefBase { const ACameraManager_AvailabilityCallbacks *callback); void registerExtendedAvailabilityCallback( - const ACameraManager_ExtendedAvailabilityCallbacks* /*callback*/) {} + const ACameraManager_ExtendedAvailabilityCallbacks* callback); void unregisterExtendedAvailabilityCallback( - const ACameraManager_ExtendedAvailabilityCallbacks* /*callback*/) {} + const ACameraManager_ExtendedAvailabilityCallbacks* callback); /** * Return camera IDs that support camera2 @@ -94,6 +97,8 @@ class CameraManagerGlobal final : public RefBase { explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {} android::hardware::Return onStatusChanged( const CameraStatusAndId &statusAndId) override; + android::hardware::Return onPhysicalCameraStatusChanged( + const PhysicalCameraStatusAndId &statusAndId) override; private: const wp mCameraManager; @@ -105,11 +110,25 @@ class CameraManagerGlobal final : public RefBase { explicit Callback(const ACameraManager_AvailabilityCallbacks *callback) : mAvailable(callback->onCameraAvailable), mUnavailable(callback->onCameraUnavailable), + mAccessPriorityChanged(nullptr), + mPhysicalCamAvailable(nullptr), + mPhysicalCamUnavailable(nullptr), mContext(callback->context) {} + explicit Callback(const ACameraManager_ExtendedAvailabilityCallbacks *callback) : + mAvailable(callback->availabilityCallbacks.onCameraAvailable), + mUnavailable(callback->availabilityCallbacks.onCameraUnavailable), + mAccessPriorityChanged(callback->onCameraAccessPrioritiesChanged), + mPhysicalCamAvailable(callback->onPhysicalCameraAvailable), + mPhysicalCamUnavailable(callback->onPhysicalCameraUnavailable), + mContext(callback->availabilityCallbacks.context) {} + bool operator == (const Callback& other) const { return (mAvailable == other.mAvailable && mUnavailable == other.mUnavailable && + mAccessPriorityChanged == other.mAccessPriorityChanged && + mPhysicalCamAvailable == other.mPhysicalCamAvailable && + mPhysicalCamUnavailable == other.mPhysicalCamUnavailable && mContext == other.mContext); } bool operator != (const Callback& other) const { @@ -119,6 +138,12 @@ class CameraManagerGlobal final : public RefBase { if (*this == other) return false; if (mContext != other.mContext) return mContext < other.mContext; if (mAvailable != other.mAvailable) return mAvailable < other.mAvailable; + if (mAccessPriorityChanged != other.mAccessPriorityChanged) + return mAccessPriorityChanged < other.mAccessPriorityChanged; + if (mPhysicalCamAvailable != other.mPhysicalCamAvailable) + return mPhysicalCamAvailable < other.mPhysicalCamAvailable; + if (mPhysicalCamUnavailable != other.mPhysicalCamUnavailable) + return mPhysicalCamUnavailable < other.mPhysicalCamUnavailable; return mUnavailable < other.mUnavailable; } bool operator > (const Callback& other) const { @@ -126,15 +151,20 @@ class CameraManagerGlobal final : public RefBase { } ACameraManager_AvailabilityCallback mAvailable; ACameraManager_AvailabilityCallback mUnavailable; + ACameraManager_AccessPrioritiesChangedCallback mAccessPriorityChanged; + ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamAvailable; + ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable; void* mContext; }; std::set mCallbacks; // definition of handler and message enum { - kWhatSendSingleCallback + kWhatSendSingleCallback, + kWhatSendSinglePhysicalCameraCallback, }; static const char* kCameraIdKey; + static const char* kPhysicalCameraIdKey; static const char* kCallbackFpKey; static const char* kContextKey; class CallbackHandler : public AHandler { @@ -147,6 +177,8 @@ class CameraManagerGlobal final : public RefBase { void onStatusChanged(const CameraStatusAndId &statusAndId); void onStatusChangedLocked(const CameraStatusAndId &statusAndId); + void onStatusChanged(const PhysicalCameraStatusAndId &statusAndId); + void onStatusChangedLocked(const PhysicalCameraStatusAndId &statusAndId); bool setupVendorTags(); // Utils for status @@ -174,8 +206,27 @@ class CameraManagerGlobal final : public RefBase { } }; + struct CameraStatus { + private: + CameraDeviceStatus status = CameraDeviceStatus::STATUS_NOT_PRESENT; + mutable std::mutex mLock; + std::set unavailablePhysicalIds; + public: + CameraStatus(CameraDeviceStatus st): status(st) { }; + CameraStatus() = default; + + bool addUnavailablePhysicalId(const hidl_string& physicalCameraId); + bool removeUnavailablePhysicalId(const hidl_string& physicalCameraId); + CameraDeviceStatus getStatus(); + void updateStatus(CameraDeviceStatus newStatus); + std::set getUnavailablePhysicalIds(); + }; + + template + void registerAvailCallback(const T *callback); + // Map camera_id -> status - std::map mDeviceStatusMap; + std::map mDeviceStatusMap; // For the singleton instance static Mutex sLock; diff --git a/camera/ndk/ndk_vendor/tests/ACameraManagerTest.cpp b/camera/ndk/ndk_vendor/tests/ACameraManagerTest.cpp new file mode 100644 index 0000000000..a20a29030c --- /dev/null +++ b/camera/ndk/ndk_vendor/tests/ACameraManagerTest.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ACameraManagerTest" +//#define LOG_NDEBUG 0 + +#include + +#include +#include +#include + +#include +#include +#include + +namespace { + +class CameraServiceListener { + public: + typedef std::set> StringPairSet; + + static void onAvailable(void* obj, const char* cameraId) { + ALOGV("Camera %s onAvailable", cameraId); + if (obj == nullptr) { + return; + } + CameraServiceListener* thiz = reinterpret_cast(obj); + std::lock_guard lock(thiz->mMutex); + thiz->mOnAvailableCount++; + thiz->mAvailableMap[cameraId] = true; + return; + } + + static void onUnavailable(void* obj, const char* cameraId) { + ALOGV("Camera %s onUnavailable", cameraId); + if (obj == nullptr) { + return; + } + CameraServiceListener* thiz = reinterpret_cast(obj); + std::lock_guard lock(thiz->mMutex); + thiz->mOnUnavailableCount++; + thiz->mAvailableMap[cameraId] = false; + return; + } + + static void onCameraAccessPrioritiesChanged(void* /*obj*/) { + return; + } + + static void onPhysicalCameraAvailable(void* obj, const char* cameraId, + const char* physicalCameraId) { + ALOGV("Camera %s : %s onAvailable", cameraId, physicalCameraId); + if (obj == nullptr) { + return; + } + CameraServiceListener* thiz = reinterpret_cast(obj); + std::lock_guard lock(thiz->mMutex); + thiz->mOnPhysicalCameraAvailableCount++; + return; + } + + static void onPhysicalCameraUnavailable(void* obj, const char* cameraId, + const char* physicalCameraId) { + ALOGV("Camera %s : %s onUnavailable", cameraId, physicalCameraId); + if (obj == nullptr) { + return; + } + CameraServiceListener* thiz = reinterpret_cast(obj); + std::lock_guard lock(thiz->mMutex); + thiz->mUnavailablePhysicalCameras.emplace(cameraId, physicalCameraId); + return; + } + + void resetCount() { + std::lock_guard lock(mMutex); + mOnAvailableCount = 0; + mOnUnavailableCount = 0; + mOnPhysicalCameraAvailableCount = 0; + mUnavailablePhysicalCameras.clear(); + return; + } + + int getAvailableCount() { + std::lock_guard lock(mMutex); + return mOnAvailableCount; + } + + int getUnavailableCount() { + std::lock_guard lock(mMutex); + return mOnUnavailableCount; + } + + int getPhysicalCameraAvailableCount() { + std::lock_guard lock(mMutex); + return mOnPhysicalCameraAvailableCount; + } + + StringPairSet getUnavailablePhysicalCameras() { + std::lock_guard lock(mMutex); + return mUnavailablePhysicalCameras; + } + + bool isAvailable(const char* cameraId) { + std::lock_guard lock(mMutex); + if (mAvailableMap.count(cameraId) == 0) { + return false; + } + return mAvailableMap[cameraId]; + } + + private: + std::mutex mMutex; + int mOnAvailableCount = 0; + int mOnUnavailableCount = 0; + int mOnPhysicalCameraAvailableCount = 0; + std::map mAvailableMap; + StringPairSet mUnavailablePhysicalCameras; +}; + +class ACameraManagerTest : public ::testing::Test { + public: + void SetUp() override { + mCameraManager = ACameraManager_create(); + if (mCameraManager == nullptr) { + ALOGE("Failed to create ACameraManager."); + return; + } + + camera_status_t ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList); + if (ret != ACAMERA_OK) { + ALOGE("Failed to get cameraIdList: ret=%d", ret); + return; + } + if (mCameraIdList->numCameras < 1) { + ALOGW("Device has no camera on board."); + return; + } + } + void TearDown() override { + // Destroy camera manager + if (mCameraIdList) { + ACameraManager_deleteCameraIdList(mCameraIdList); + mCameraIdList = nullptr; + } + if (mCameraManager) { + ACameraManager_delete(mCameraManager); + mCameraManager = nullptr; + } + } + + // Camera manager + ACameraManager* mCameraManager = nullptr; + ACameraIdList* mCameraIdList = nullptr; + CameraServiceListener mAvailabilityListener; + ACameraManager_ExtendedAvailabilityCallbacks mCbs = { + { + &mAvailabilityListener, + CameraServiceListener::onAvailable, + CameraServiceListener::onUnavailable + }, + CameraServiceListener::onCameraAccessPrioritiesChanged, + CameraServiceListener::onPhysicalCameraAvailable, + CameraServiceListener::onPhysicalCameraUnavailable, + {} + }; +}; + +TEST_F(ACameraManagerTest, testCameraManagerExtendedAvailabilityCallbacks) { + camera_status_t ret = ACameraManager_registerExtendedAvailabilityCallback(mCameraManager, + &mCbs); + ASSERT_EQ(ret, ACAMERA_OK); + + sleep(1); + + // Should at least get onAvailable for each camera once + ASSERT_EQ(mAvailabilityListener.getAvailableCount(), mCameraIdList->numCameras); + + // Expect no available callbacks for physical cameras + int availablePhysicalCamera = mAvailabilityListener.getPhysicalCameraAvailableCount(); + ASSERT_EQ(availablePhysicalCamera, 0); + + CameraServiceListener::StringPairSet unavailablePhysicalCameras; + CameraServiceListener::StringPairSet physicalCameraIdPairs; + + unavailablePhysicalCameras = mAvailabilityListener.getUnavailablePhysicalCameras(); + for (int i = 0; i < mCameraIdList->numCameras; i++) { + const char* cameraId = mCameraIdList->cameraIds[i]; + ASSERT_NE(cameraId, nullptr); + ASSERT_TRUE(mAvailabilityListener.isAvailable(cameraId)); + + ACameraMetadata* chars = nullptr; + ret = ACameraManager_getCameraCharacteristics(mCameraManager, cameraId, &chars); + ASSERT_EQ(ret, ACAMERA_OK); + ASSERT_NE(chars, nullptr); + + size_t physicalCameraCnt = 0; + const char *const* physicalCameraIds = nullptr; + if (!ACameraMetadata_isLogicalMultiCamera( + chars, &physicalCameraCnt, &physicalCameraIds)) { + ACameraMetadata_free(chars); + continue; + } + for (size_t j = 0; j < physicalCameraCnt; j++) { + physicalCameraIdPairs.emplace(cameraId, physicalCameraIds[j]); + } + ACameraMetadata_free(chars); + } + for (const auto& unavailIdPair : unavailablePhysicalCameras) { + bool validPair = false; + for (const auto& idPair : physicalCameraIdPairs) { + if (idPair.first == unavailIdPair.first && idPair.second == unavailIdPair.second) { + validPair = true; + break; + } + } + // Expect valid unavailable physical cameras + ASSERT_TRUE(validPair); + } + + ret = ACameraManager_unregisterExtendedAvailabilityCallback(mCameraManager, &mCbs); + ASSERT_EQ(ret, ACAMERA_OK); +} + +} // namespace diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index 98fee12634..788c051743 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -116,6 +116,7 @@ cc_library_shared { "libyuv", "android.frameworks.cameraservice.common@2.0", "android.frameworks.cameraservice.service@2.0", + "android.frameworks.cameraservice.service@2.1", "android.frameworks.cameraservice.device@2.0", "android.hardware.camera.common@1.0", "android.hardware.camera.provider@2.4", diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 5358307779..e9c941ef8e 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -456,10 +456,14 @@ void CameraService::onDeviceStatusChanged(const String8& id, } if (updated) { - logDeviceRemoved(id, String8::format("Device %s-%s availability changed from %d to %d", - id.string(), physicalId.string(), - newStatus != StatusInternal::PRESENT, - newStatus == StatusInternal::PRESENT)); + String8 idCombo = id + " : " + physicalId; + if (newStatus == StatusInternal::PRESENT) { + logDeviceAdded(idCombo, + String8::format("Device status changed to %d", newStatus)); + } else { + logDeviceRemoved(idCombo, + String8::format("Device status changed to %d", newStatus)); + } String16 id16(id), physicalId16(physicalId); Mutex::Autolock lock(mStatusListenerLock); diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp index 110ef8ea49..8e619e1feb 100644 --- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp +++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp @@ -25,6 +25,7 @@ namespace V2_0 { namespace implementation { using hardware::cameraservice::utils::conversion::convertToHidlCameraDeviceStatus; +typedef frameworks::cameraservice::service::V2_1::ICameraServiceListener HCameraServiceListener2_1; binder::Status H2BCameraServiceListener::onStatusChanged( int32_t status, const ::android::String16& cameraId) { @@ -40,6 +41,29 @@ binder::Status H2BCameraServiceListener::onStatusChanged( return binder::Status::ok(); } +binder::Status H2BCameraServiceListener::onPhysicalCameraStatusChanged( + int32_t status, const ::android::String16& cameraId, + const ::android::String16& physicalCameraId) { + auto cast2_1 = HCameraServiceListener2_1::castFrom(mBase); + sp interface2_1 = nullptr; + if (cast2_1.isOk()) { + interface2_1 = cast2_1; + if (interface2_1 != nullptr) { + HCameraDeviceStatus hCameraDeviceStatus = convertToHidlCameraDeviceStatus(status); + V2_1::PhysicalCameraStatusAndId cameraStatusAndId; + cameraStatusAndId.deviceStatus = hCameraDeviceStatus; + cameraStatusAndId.cameraId = String8(cameraId).string(); + cameraStatusAndId.physicalCameraId = String8(physicalCameraId).string(); + auto ret = interface2_1->onPhysicalCameraStatusChanged(cameraStatusAndId); + if (!ret.isOk()) { + ALOGE("%s OnPhysicalCameraStatusChanged callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + } + } + return binder::Status::ok(); +} + ::android::binder::Status H2BCameraServiceListener::onTorchStatusChanged( int32_t, const ::android::String16&) { // We don't implement onTorchStatusChanged diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h index 175eb8e941..95493a1cc2 100644 --- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h +++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -47,17 +48,14 @@ struct H2BCameraServiceListener : virtual ::android::binder::Status onStatusChanged(int32_t status, const ::android::String16& cameraId) override; - virtual ::android::binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/, - const ::android::String16& /*cameraId*/, - const ::android::String16& /*physicalCameraId*/) override { - // no implementation yet. - return binder::Status::ok(); - } + virtual ::android::binder::Status onPhysicalCameraStatusChanged(int32_t status, + const ::android::String16& cameraId, + const ::android::String16& physicalCameraId) override; virtual ::android::binder::Status onTorchStatusChanged( int32_t status, const ::android::String16& cameraId) override; virtual binder::Status onCameraAccessPrioritiesChanged() { - // TODO: no implementation yet. b/148146086 + // TODO: no implementation yet. return binder::Status::ok(); } }; diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp index 866c3b5780..597147bcac 100644 --- a/services/camera/libcameraservice/hidl/Convert.cpp +++ b/services/camera/libcameraservice/hidl/Convert.cpp @@ -197,6 +197,23 @@ void convertToHidl(const std::vector &src, return; } +void convertToHidl(const std::vector &src, + hidl_vec* dst) { + dst->resize(src.size()); + size_t i = 0; + for (const auto &statusAndId : src) { + auto &a = (*dst)[i++]; + a.v2_0.cameraId = statusAndId.cameraId.c_str(); + a.v2_0.deviceStatus = convertToHidlCameraDeviceStatus(statusAndId.status); + size_t numUnvailPhysicalCameras = statusAndId.unavailablePhysicalIds.size(); + a.unavailPhysicalCameraIds.resize(numUnvailPhysicalCameras); + for (size_t j = 0; j < numUnvailPhysicalCameras; j++) { + a.unavailPhysicalCameraIds[j] = statusAndId.unavailablePhysicalIds[j].c_str(); + } + } + return; +} + void convertToHidl( const hardware::camera2::utils::SubmitInfo &submitInfo, frameworks::cameraservice::device::V2_0::SubmitInfo *hSubmitInfo) { diff --git a/services/camera/libcameraservice/hidl/Convert.h b/services/camera/libcameraservice/hidl/Convert.h index 79683f6b00..82ffc48c21 100644 --- a/services/camera/libcameraservice/hidl/Convert.h +++ b/services/camera/libcameraservice/hidl/Convert.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,9 @@ HCameraDeviceStatus convertToHidlCameraDeviceStatus(int32_t status); void convertToHidl(const std::vector &src, hidl_vec* dst); +void convertToHidl(const std::vector &src, + hidl_vec* dst); + void convertToHidl(const hardware::camera2::utils::SubmitInfo &submitInfo, HSubmitInfo *hSubmitInfo); diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp index 97ba9c4176..a46133e620 100644 --- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp +++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp @@ -154,15 +154,50 @@ HidlCameraService::searchListenerCacheLocked(sp hListene Return HidlCameraService::addListener(const sp& hCsListener, addListener_cb _hidl_cb) { - if (mAidlICameraService == nullptr) { - _hidl_cb(HStatus::UNKNOWN_ERROR, {}); + std::vector cameraStatusAndIds{}; + HStatus status = addListenerInternal( + hCsListener, &cameraStatusAndIds); + if (status != HStatus::NO_ERROR) { + _hidl_cb(status, {}); return Void(); } - if (hCsListener == nullptr) { - ALOGE("%s listener must not be NULL", __FUNCTION__); - _hidl_cb(HStatus::ILLEGAL_ARGUMENT, {}); + + hidl_vec hCameraStatusAndIds; + //Convert cameraStatusAndIds to HIDL and call callback + convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds); + _hidl_cb(status, hCameraStatusAndIds); + + return Void(); +} + +Return HidlCameraService::addListener_2_1(const sp& hCsListener, + addListener_2_1_cb _hidl_cb) { + std::vector cameraStatusAndIds{}; + HStatus status = addListenerInternal( + hCsListener, &cameraStatusAndIds); + if (status != HStatus::NO_ERROR) { + _hidl_cb(status, {}); return Void(); } + + hidl_vec hCameraStatusAndIds; + //Convert cameraStatusAndIds to HIDL and call callback + convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds); + _hidl_cb(status, hCameraStatusAndIds); + + return Void(); +} + +template +HStatus HidlCameraService::addListenerInternal(const sp& hCsListener, + std::vector* cameraStatusAndIds) { + if (mAidlICameraService == nullptr) { + return HStatus::UNKNOWN_ERROR; + } + if (hCsListener == nullptr || cameraStatusAndIds == nullptr) { + ALOGE("%s listener and cameraStatusAndIds must not be NULL", __FUNCTION__); + return HStatus::ILLEGAL_ARGUMENT; + } sp csListener = nullptr; // Check the cache for previously registered callbacks { @@ -177,33 +212,27 @@ Return HidlCameraService::addListener(const sp& hC } else { ALOGE("%s: Trying to add a listener %p already registered", __FUNCTION__, hCsListener.get()); - _hidl_cb(HStatus::ILLEGAL_ARGUMENT, {}); - return Void(); + return HStatus::ILLEGAL_ARGUMENT; } } - std::vector cameraStatusAndIds{}; binder::Status serviceRet = - mAidlICameraService->addListenerHelper(csListener, &cameraStatusAndIds, true); + mAidlICameraService->addListenerHelper(csListener, cameraStatusAndIds, true); HStatus status = HStatus::NO_ERROR; if (!serviceRet.isOk()) { - ALOGE("%s: Unable to add camera device status listener", __FUNCTION__); - status = B2HStatus(serviceRet); - _hidl_cb(status, {}); - return Void(); + ALOGE("%s: Unable to add camera device status listener", __FUNCTION__); + status = B2HStatus(serviceRet); + return status; } - cameraStatusAndIds.erase(std::remove_if(cameraStatusAndIds.begin(), cameraStatusAndIds.end(), + cameraStatusAndIds->erase(std::remove_if(cameraStatusAndIds->begin(), cameraStatusAndIds->end(), [this](const hardware::CameraStatus& s) { - bool supportsHAL3 = false; - binder::Status sRet = + bool supportsHAL3 = false; + binder::Status sRet = mAidlICameraService->supportsCameraApi(String16(s.cameraId), hardware::ICameraService::API_VERSION_2, &supportsHAL3); - return !sRet.isOk() || !supportsHAL3; - }), cameraStatusAndIds.end()); - hidl_vec hCameraStatusAndIds; - //Convert cameraStatusAndIds to HIDL and call callback - convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds); - _hidl_cb(status, hCameraStatusAndIds); - return Void(); + return !sRet.isOk() || !supportsHAL3; + }), cameraStatusAndIds->end()); + + return HStatus::NO_ERROR; } Return HidlCameraService::removeListener(const sp& hCsListener) { diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.h b/services/camera/libcameraservice/hidl/HidlCameraService.h index eead0bc07b..097f4c5753 100644 --- a/services/camera/libcameraservice/hidl/HidlCameraService.h +++ b/services/camera/libcameraservice/hidl/HidlCameraService.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -42,8 +42,9 @@ using hardware::Return; using HCameraDeviceCallback = frameworks::cameraservice::device::V2_0::ICameraDeviceCallback; using HCameraMetadata = frameworks::cameraservice::service::V2_0::CameraMetadata; -using HCameraService = frameworks::cameraservice::service::V2_0::ICameraService; +using HCameraService = frameworks::cameraservice::service::V2_1::ICameraService; using HCameraServiceListener = frameworks::cameraservice::service::V2_0::ICameraServiceListener; +using HCameraServiceListener2_1 = frameworks::cameraservice::service::V2_1::ICameraServiceListener; using HStatus = frameworks::cameraservice::common::V2_0::Status; using HCameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId; @@ -66,6 +67,9 @@ struct HidlCameraService final : public HCameraService { Return getCameraVendorTagSections(getCameraVendorTagSections_cb _hidl_cb) override; + Return addListener_2_1(const sp& listener, + addListener_2_1_cb _hidl_cb) override; + // This method should only be called by the cameraservers main thread to // instantiate the hidl cameraserver. static sp getInstance(android::CameraService *cs); @@ -76,6 +80,11 @@ private: sp searchListenerCacheLocked( sp listener, /*removeIfFound*/ bool shouldRemove = false); + + template + HStatus addListenerInternal(const sp& listener, + std::vector* cameraStatusAndIds); + void addToListenerCacheLocked(sp hListener, sp csListener);