Camera: Fill out vndk implementation for physical camera callbacks

Also fixed missing implementation of Camera availability callbacks for
ExtendedAvailabilityCallback.

Test: Camera CTS, and vndk test
Bug: 148146086
Change-Id: I557d6db3900b2346b7bc7e12cd946bc4c2dc4076
gugelfrei
Shuzhen Wang 5 years ago
parent de8e67bc32
commit 4fa28d2e0a

@ -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",
],
}

@ -2,7 +2,7 @@
<hal>
<name>android.frameworks.cameraservice.service</name>
<transport>hwbinder</transport>
<version>2.0</version>
<version>2.1</version>
<interface>
<name>ICameraService</name>
<instance>default</instance>

@ -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",

@ -130,6 +130,11 @@ sp<hardware::ICameraService> 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<IBinder>&)
void CameraManagerGlobal::registerExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
Callback cb(callback);
mCallbacks.insert(cb);
return registerAvailCallback<ACameraManager_ExtendedAvailabilityCallbacks>(callback);
}
void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
@ -214,6 +217,18 @@ void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
void CameraManagerGlobal::registerAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback) {
return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(callback);
}
void CameraManagerGlobal::unregisterAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
Callback cb(callback);
mCallbacks.erase(cb);
}
template<class T>
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<AMessage> 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<String8> unavailablePhysicalCameras =
pair.second.getUnavailablePhysicalIds();
for (const auto& physicalCameraId : unavailablePhysicalCameras) {
sp<AMessage> 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<String8> CameraManagerGlobal::StatusAndHAL3Support::getUnavailablePhysicalIds() {
std::lock_guard<std::mutex> lock(mLock);
return unavailablePhysicalIds;
}
} // namespace acam
} // namespace android

@ -70,6 +70,9 @@ class CameraManagerGlobal final : public RefBase {
const char* kCameraServiceName = "media.camera";
Mutex mLock;
template<class T>
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<String8> getUnavailablePhysicalIds();
};
// Map camera_id -> status

@ -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<ICameraService> CameraManagerGlobal::getCameraService() {
if (mCameraServiceListener == nullptr) {
mCameraServiceListener = new CameraServiceListener(this);
}
hidl_vec<CameraStatusAndId> cameraStatuses{};
hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId> 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<ICameraService> 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 wp<I
for (auto& pair : cm->mDeviceStatusMap) {
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<I
void CameraManagerGlobal::registerAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback) {
return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(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<ACameraManager_ExtendedAvailabilityCallbacks>(callback);
}
void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
Callback cb(callback);
mCallbacks.erase(cb);
}
template <class T>
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<AMessage> 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<hidl_string> unavailPhysicalIds = pair.second.getUnavailablePhysicalIds();
for (const auto& physicalCameraId : unavailPhysicalIds) {
sp<AMessage> 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<hidl_string>* 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<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
@ -450,6 +519,98 @@ void CameraManagerGlobal::onStatusChangedLocked(
}
}
hardware::Return<void> CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
const PhysicalCameraStatusAndId &statusAndId) {
sp<CameraManagerGlobal> 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<AMessage> 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<std::mutex> lock(mLock);
return status;
}
void CameraManagerGlobal::CameraStatus::updateStatus(CameraDeviceStatus newStatus) {
std::lock_guard<std::mutex> lock(mLock);
status = newStatus;
}
bool CameraManagerGlobal::CameraStatus::addUnavailablePhysicalId(
const hidl_string& physicalCameraId) {
std::lock_guard<std::mutex> lock(mLock);
auto result = unavailablePhysicalIds.insert(physicalCameraId);
return result.second;
}
bool CameraManagerGlobal::CameraStatus::removeUnavailablePhysicalId(
const hidl_string& physicalCameraId) {
std::lock_guard<std::mutex> lock(mLock);
auto count = unavailablePhysicalIds.erase(physicalCameraId);
return count > 0;
}
std::set<hidl_string> CameraManagerGlobal::CameraStatus::getUnavailablePhysicalIds() {
std::lock_guard<std::mutex> lock(mLock);
return unavailablePhysicalIds;
}
} // namespace acam
} // namespace android

@ -21,6 +21,8 @@
#include <android-base/parseint.h>
#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
#include <android/frameworks/cameraservice/service/2.1/ICameraService.h>
#include <android/frameworks/cameraservice/service/2.1/ICameraServiceListener.h>
#include <CameraMetadata.h>
#include <utils/StrongPointer.h>
@ -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<void> onStatusChanged(
const CameraStatusAndId &statusAndId) override;
android::hardware::Return<void> onPhysicalCameraStatusChanged(
const PhysicalCameraStatusAndId &statusAndId) override;
private:
const wp<CameraManagerGlobal> 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<Callback> 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<hidl_string> 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<hidl_string> getUnavailablePhysicalIds();
};
template <class T>
void registerAvailCallback(const T *callback);
// Map camera_id -> status
std::map<hidl_string, CameraDeviceStatus, CameraIdComparator> mDeviceStatusMap;
std::map<hidl_string, CameraStatus, CameraIdComparator> mDeviceStatusMap;
// For the singleton instance
static Mutex sLock;

@ -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 <gtest/gtest.h>
#include <mutex>
#include <set>
#include <string>
#include <utils/Log.h>
#include <camera/NdkCameraError.h>
#include <camera/NdkCameraManager.h>
namespace {
class CameraServiceListener {
public:
typedef std::set<std::pair<std::string, std::string>> StringPairSet;
static void onAvailable(void* obj, const char* cameraId) {
ALOGV("Camera %s onAvailable", cameraId);
if (obj == nullptr) {
return;
}
CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
std::lock_guard<std::mutex> 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<CameraServiceListener*>(obj);
std::lock_guard<std::mutex> 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<CameraServiceListener*>(obj);
std::lock_guard<std::mutex> 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<CameraServiceListener*>(obj);
std::lock_guard<std::mutex> lock(thiz->mMutex);
thiz->mUnavailablePhysicalCameras.emplace(cameraId, physicalCameraId);
return;
}
void resetCount() {
std::lock_guard<std::mutex> lock(mMutex);
mOnAvailableCount = 0;
mOnUnavailableCount = 0;
mOnPhysicalCameraAvailableCount = 0;
mUnavailablePhysicalCameras.clear();
return;
}
int getAvailableCount() {
std::lock_guard<std::mutex> lock(mMutex);
return mOnAvailableCount;
}
int getUnavailableCount() {
std::lock_guard<std::mutex> lock(mMutex);
return mOnUnavailableCount;
}
int getPhysicalCameraAvailableCount() {
std::lock_guard<std::mutex> lock(mMutex);
return mOnPhysicalCameraAvailableCount;
}
StringPairSet getUnavailablePhysicalCameras() {
std::lock_guard<std::mutex> lock(mMutex);
return mUnavailablePhysicalCameras;
}
bool isAvailable(const char* cameraId) {
std::lock_guard<std::mutex> 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<std::string, bool> 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

@ -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",

@ -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);

@ -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<HCameraServiceListener2_1> 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

@ -19,6 +19,7 @@
#include <android/frameworks/cameraservice/common/2.0/types.h>
#include <android/frameworks/cameraservice/service/2.0/ICameraServiceListener.h>
#include <android/frameworks/cameraservice/service/2.1/ICameraServiceListener.h>
#include <android/frameworks/cameraservice/device/2.0/types.h>
#include <android/hardware/BnCameraServiceListener.h>
#include <android/hardware/BpCameraServiceListener.h>
@ -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();
}
};

@ -197,6 +197,23 @@ void convertToHidl(const std::vector<hardware::CameraStatus> &src,
return;
}
void convertToHidl(const std::vector<hardware::CameraStatus> &src,
hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId>* 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) {

@ -23,6 +23,7 @@
#include <android/frameworks/cameraservice/device/2.0/ICameraDeviceUser.h>
#include <android/frameworks/cameraservice/common/2.0/types.h>
#include <android/frameworks/cameraservice/service/2.0/types.h>
#include <android/frameworks/cameraservice/service/2.1/types.h>
#include <android/frameworks/cameraservice/device/2.0/types.h>
#include <android/hardware/camera/common/1.0/types.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
@ -79,6 +80,9 @@ HCameraDeviceStatus convertToHidlCameraDeviceStatus(int32_t status);
void convertToHidl(const std::vector<hardware::CameraStatus> &src,
hidl_vec<HCameraStatusAndId>* dst);
void convertToHidl(const std::vector<hardware::CameraStatus> &src,
hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId>* dst);
void convertToHidl(const hardware::camera2::utils::SubmitInfo &submitInfo,
HSubmitInfo *hSubmitInfo);

@ -154,15 +154,50 @@ HidlCameraService::searchListenerCacheLocked(sp<HCameraServiceListener> hListene
Return<void> HidlCameraService::addListener(const sp<HCameraServiceListener>& hCsListener,
addListener_cb _hidl_cb) {
if (mAidlICameraService == nullptr) {
_hidl_cb(HStatus::UNKNOWN_ERROR, {});
std::vector<hardware::CameraStatus> cameraStatusAndIds{};
HStatus status = addListenerInternal<HCameraServiceListener>(
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<HCameraStatusAndId> hCameraStatusAndIds;
//Convert cameraStatusAndIds to HIDL and call callback
convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds);
_hidl_cb(status, hCameraStatusAndIds);
return Void();
}
Return<void> HidlCameraService::addListener_2_1(const sp<HCameraServiceListener2_1>& hCsListener,
addListener_2_1_cb _hidl_cb) {
std::vector<hardware::CameraStatus> cameraStatusAndIds{};
HStatus status = addListenerInternal<HCameraServiceListener2_1>(
hCsListener, &cameraStatusAndIds);
if (status != HStatus::NO_ERROR) {
_hidl_cb(status, {});
return Void();
}
hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId> hCameraStatusAndIds;
//Convert cameraStatusAndIds to HIDL and call callback
convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds);
_hidl_cb(status, hCameraStatusAndIds);
return Void();
}
template<class T>
HStatus HidlCameraService::addListenerInternal(const sp<T>& hCsListener,
std::vector<hardware::CameraStatus>* 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<hardware::ICameraServiceListener> csListener = nullptr;
// Check the cache for previously registered callbacks
{
@ -177,33 +212,27 @@ Return<void> HidlCameraService::addListener(const sp<HCameraServiceListener>& 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<hardware::CameraStatus> 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<HCameraStatusAndId> 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<HStatus> HidlCameraService::removeListener(const sp<HCameraServiceListener>& hCsListener) {

@ -21,7 +21,7 @@
#include <thread>
#include <android/frameworks/cameraservice/common/2.0/types.h>
#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
#include <android/frameworks/cameraservice/service/2.1/ICameraService.h>
#include <android/frameworks/cameraservice/service/2.0/types.h>
#include <android/frameworks/cameraservice/device/2.0/types.h>
@ -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<void> getCameraVendorTagSections(getCameraVendorTagSections_cb _hidl_cb) override;
Return<void> addListener_2_1(const sp<HCameraServiceListener2_1>& 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<HidlCameraService> getInstance(android::CameraService *cs);
@ -76,6 +80,11 @@ private:
sp<hardware::ICameraServiceListener> searchListenerCacheLocked(
sp<HCameraServiceListener> listener, /*removeIfFound*/ bool shouldRemove = false);
template<class T>
HStatus addListenerInternal(const sp<T>& listener,
std::vector<hardware::CameraStatus>* cameraStatusAndIds);
void addToListenerCacheLocked(sp<HCameraServiceListener> hListener,
sp<hardware::ICameraServiceListener> csListener);

Loading…
Cancel
Save