Camera: plumb external camera API1 support
And also some refactoring to unify external camera
config file logics.
Bug: 72261912
Change-Id: If83d779c57540809bdaa58a5a32cf4ade734fafe
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index 569acfd..61b8921 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -44,9 +44,10 @@
} // anonymous namespace
-ExternalCameraDevice::ExternalCameraDevice(const std::string& cameraId) :
+ExternalCameraDevice::ExternalCameraDevice(
+ const std::string& cameraId, const ExternalCameraConfig& cfg) :
mCameraId(cameraId),
- mCfg(ExternalCameraDeviceConfig::loadFromCfg()) {
+ mCfg(cfg) {
status_t ret = initCameraCharacteristics();
if (ret != OK) {
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 51bfe36..74fd7f4 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -55,7 +55,7 @@
ExternalCameraDeviceSession::ExternalCameraDeviceSession(
const sp<ICameraDeviceCallback>& callback,
- const ExternalCameraDeviceConfig& cfg,
+ const ExternalCameraConfig& cfg,
const std::vector<SupportedV4L2Format>& sortedFormats,
const CroppingType& croppingType,
const common::V1_0::helper::CameraMetadata& chars,
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 212573a..80f296c 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -30,14 +30,6 @@
namespace V3_4 {
namespace implementation {
-namespace {
- const int kDefaultJpegBufSize = 5 << 20; // 5MB
- const int kDefaultNumVideoBuffer = 4;
- const int kDefaultNumStillBuffer = 2;
-} // anonymous namespace
-
-const char* ExternalCameraDeviceConfig::kDefaultCfgPath = "/vendor/etc/external_camera_config.xml";
-
V4L2Frame::V4L2Frame(
uint32_t w, uint32_t h, uint32_t fourcc,
int bufIdx, int fd, uint32_t dataSize, uint64_t offset) :
@@ -148,10 +140,32 @@
return 0;
}
+bool isAspectRatioClose(float ar1, float ar2) {
+ const float kAspectRatioMatchThres = 0.025f; // This threshold is good enough to distinguish
+ // 4:3/16:9/20:9
+ // 1.33 / 1.78 / 2
+ return (std::abs(ar1 - ar2) < kAspectRatioMatchThres);
+}
-ExternalCameraDeviceConfig ExternalCameraDeviceConfig::loadFromCfg(const char* cfgPath) {
+} // namespace implementation
+} // namespace V3_4
+} // namespace device
+
+
+namespace external {
+namespace common {
+
+namespace {
+ const int kDefaultJpegBufSize = 5 << 20; // 5MB
+ const int kDefaultNumVideoBuffer = 4;
+ const int kDefaultNumStillBuffer = 2;
+} // anonymous namespace
+
+const char* ExternalCameraConfig::kDefaultCfgPath = "/vendor/etc/external_camera_config.xml";
+
+ExternalCameraConfig ExternalCameraConfig::loadFromCfg(const char* cfgPath) {
using namespace tinyxml2;
- ExternalCameraDeviceConfig ret;
+ ExternalCameraConfig ret;
XMLDocument configXml;
XMLError err = configXml.LoadFile(cfgPath);
@@ -169,6 +183,29 @@
return ret;
}
+ XMLElement *providerCfg = extCam->FirstChildElement("Provider");
+ if (providerCfg == nullptr) {
+ ALOGI("%s: no external camera provider config specified", __FUNCTION__);
+ return ret;
+ }
+
+ XMLElement *ignore = providerCfg->FirstChildElement("ignore");
+ if (ignore == nullptr) {
+ ALOGI("%s: no internal ignored device specified", __FUNCTION__);
+ return ret;
+ }
+
+ XMLElement *id = ignore->FirstChildElement("id");
+ while (id != nullptr) {
+ const char* text = id->GetText();
+ if (text != nullptr) {
+ ret.mInternalDevices.insert(text);
+ ALOGI("%s: device %s will be ignored by external camera provider",
+ __FUNCTION__, text);
+ }
+ id = id->NextSiblingElement("id");
+ }
+
XMLElement *deviceCfg = extCam->FirstChildElement("Device");
if (deviceCfg == nullptr) {
ALOGI("%s: no external camera device config specified", __FUNCTION__);
@@ -226,7 +263,7 @@
ret.fpsLimits = limits;
}
- ALOGI("%s: external camera cfd loaded: maxJpgBufSize %d,"
+ ALOGI("%s: external camera cfg loaded: maxJpgBufSize %d,"
" num video buffers %d, num still buffers %d",
__FUNCTION__, ret.maxJpegBufSize,
ret.numVideoBuffers, ret.numStillBuffers);
@@ -237,7 +274,7 @@
return ret;
}
-ExternalCameraDeviceConfig::ExternalCameraDeviceConfig() :
+ExternalCameraConfig::ExternalCameraConfig() :
maxJpegBufSize(kDefaultJpegBufSize),
numVideoBuffers(kDefaultNumVideoBuffer),
numStillBuffers(kDefaultNumStillBuffer) {
@@ -247,16 +284,9 @@
fpsLimits.push_back({/*Size*/{4096, 3072}, /*FPS upper bound*/5.0});
}
-bool isAspectRatioClose(float ar1, float ar2) {
- const float kAspectRatioMatchThres = 0.025f; // This threshold is good enough to distinguish
- // 4:3/16:9/20:9
- // 1.33 / 1.78 / 2
- return (std::abs(ar1 - ar2) < kAspectRatioMatchThres);
-}
-} // namespace implementation
-} // namespace V3_4
-} // namespace device
+} // namespace common
+} // namespace external
} // namespace camera
} // namespace hardware
} // namespace android
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index fabf26a..cced3f7 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -67,6 +67,9 @@
using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
using ::android::hardware::camera::common::V1_0::helper::ExifUtils;
+using ::android::hardware::camera::external::common::ExternalCameraConfig;
+using ::android::hardware::camera::external::common::Size;
+using ::android::hardware::camera::external::common::SizeHasher;
using ::android::hardware::graphics::common::V1_0::BufferUsage;
using ::android::hardware::graphics::common::V1_0::Dataspace;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
@@ -84,7 +87,7 @@
struct ExternalCameraDeviceSession : public virtual RefBase {
ExternalCameraDeviceSession(const sp<ICameraDeviceCallback>&,
- const ExternalCameraDeviceConfig& cfg,
+ const ExternalCameraConfig& cfg,
const std::vector<SupportedV4L2Format>& sortedFormats,
const CroppingType& croppingType,
const common::V1_0::helper::CameraMetadata& chars,
@@ -277,7 +280,7 @@
mutable Mutex mLock; // Protect all private members except otherwise noted
const sp<ICameraDeviceCallback> mCallback;
- const ExternalCameraDeviceConfig mCfg;
+ const ExternalCameraConfig& mCfg;
const common::V1_0::helper::CameraMetadata mCameraCharacteristics;
const std::vector<SupportedV4L2Format> mSupportedFormats;
const CroppingType mCroppingType;
@@ -293,7 +296,7 @@
bool mV4l2Streaming = false;
SupportedV4L2Format mV4l2StreamingFmt;
- size_t mV4L2BufferCount;
+ size_t mV4L2BufferCount = 0;
static const int kBufferWaitTimeoutSec = 3; // TODO: handle long exposure (or not allowing)
std::mutex mV4l2BufferLock; // protect the buffer count and condition below
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
index ef4b41c..5880469 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
@@ -38,6 +38,8 @@
using ::android::hardware::camera::common::V1_0::CameraResourceCost;
using ::android::hardware::camera::common::V1_0::TorchMode;
using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::external::common::ExternalCameraConfig;
+using ::android::hardware::camera::external::common::Size;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
@@ -54,7 +56,7 @@
// be multiple CameraDevice trying to access the same physical camera. Also, provider will have
// to keep track of all CameraDevice objects in order to notify CameraDevice when the underlying
// camera is detached.
- ExternalCameraDevice(const std::string& cameraId);
+ ExternalCameraDevice(const std::string& cameraId, const ExternalCameraConfig& cfg);
~ExternalCameraDevice();
// Caller must use this method to check if CameraDevice ctor failed
@@ -95,7 +97,7 @@
Mutex mLock;
bool mInitFailed = false;
std::string mCameraId;
- const ExternalCameraDeviceConfig mCfg;
+ const ExternalCameraConfig& mCfg;
std::vector<SupportedV4L2Format> mSupportedFormats;
CroppingType mCroppingType;
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
index 849f947..e56160a 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
@@ -21,6 +21,7 @@
#include "utils/LightRefBase.h"
#include <mutex>
#include <vector>
+#include <unordered_set>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
using android::hardware::graphics::mapper::V2_0::IMapper;
@@ -29,6 +30,60 @@
namespace android {
namespace hardware {
namespace camera {
+
+namespace external {
+namespace common {
+
+struct Size {
+ uint32_t width;
+ uint32_t height;
+
+ bool operator==(const Size& other) const {
+ return (width == other.width && height == other.height);
+ }
+};
+
+struct SizeHasher {
+ size_t operator()(const Size& sz) const {
+ size_t result = 1;
+ result = 31 * result + sz.width;
+ result = 31 * result + sz.height;
+ return result;
+ }
+};
+
+struct ExternalCameraConfig {
+ static const char* kDefaultCfgPath;
+ static ExternalCameraConfig loadFromCfg(const char* cfgPath = kDefaultCfgPath);
+
+ // List of internal V4L2 video nodes external camera HAL must ignore.
+ std::unordered_set<std::string> mInternalDevices;
+
+ // Maximal size of a JPEG buffer, in bytes
+ uint32_t maxJpegBufSize;
+
+ // Maximum Size that can sustain 30fps streaming
+ Size maxVideoSize;
+
+ // Size of v4l2 buffer queue when streaming <= kMaxVideoSize
+ uint32_t numVideoBuffers;
+
+ // Size of v4l2 buffer queue when streaming > kMaxVideoSize
+ uint32_t numStillBuffers;
+
+ struct FpsLimitation {
+ Size size;
+ float fpsUpperBound;
+ };
+ std::vector<FpsLimitation> fpsLimits;
+
+private:
+ ExternalCameraConfig();
+};
+
+} // common
+} // external
+
namespace device {
namespace V3_4 {
namespace implementation {
@@ -85,50 +140,6 @@
VERTICAL = 1
};
-struct Size {
- uint32_t width;
- uint32_t height;
-
- bool operator==(const Size& other) const {
- return (width == other.width && height == other.height);
- }
-};
-
-struct SizeHasher {
- size_t operator()(const Size& sz) const {
- size_t result = 1;
- result = 31 * result + sz.width;
- result = 31 * result + sz.height;
- return result;
- }
-};
-
-struct ExternalCameraDeviceConfig {
- static const char* kDefaultCfgPath;
- static ExternalCameraDeviceConfig loadFromCfg(const char* cfgPath = kDefaultCfgPath);
-
- // Maximal size of a JPEG buffer, in bytes
- uint32_t maxJpegBufSize;
-
- // Maximum Size that can sustain 30fps streaming
- Size maxVideoSize;
-
- // Size of v4l2 buffer queue when streaming <= kMaxVideoSize
- uint32_t numVideoBuffers;
-
- // Size of v4l2 buffer queue when streaming > kMaxVideoSize
- uint32_t numStillBuffers;
-
- struct FpsLimitation {
- Size size;
- float fpsUpperBound;
- };
- std::vector<FpsLimitation> fpsLimits;
-
-private:
- ExternalCameraDeviceConfig();
-};
-
// Aspect ratio is defined as width/height here and ExternalCameraDevice
// will guarantee all supported sizes has width >= height (so aspect ratio >= 1.0)
#define ASPECT_RATIO(sz) (static_cast<float>((sz).width) / (sz).height)
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.cpp b/camera/provider/2.4/default/ExternalCameraProvider.cpp
index 7657fa3..faa4e3a 100644
--- a/camera/provider/2.4/default/ExternalCameraProvider.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProvider.cpp
@@ -24,7 +24,6 @@
#include <linux/videodev2.h>
#include "ExternalCameraProvider.h"
#include "ExternalCameraDevice_3_4.h"
-#include "tinyxml2.h" // XML parsing
namespace android {
namespace hardware {
@@ -38,6 +37,8 @@
const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
const int kMaxDevicePathLen = 256;
const char* kDevicePath = "/dev/";
+constexpr char kPrefix[] = "video";
+constexpr int kPrefixLen = sizeof(kPrefix) - 1;
bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion,
std::string* cameraId) {
@@ -58,6 +59,7 @@
} // anonymous namespace
ExternalCameraProvider::ExternalCameraProvider() :
+ mCfg(ExternalCameraConfig::loadFromCfg()),
mHotPlugThread(this) {
mHotPlugThread.run("ExtCamHotPlug", PRIORITY_BACKGROUND);
}
@@ -69,8 +71,17 @@
Return<Status> ExternalCameraProvider::setCallback(
const sp<ICameraProviderCallback>& callback) {
- Mutex::Autolock _l(mLock);
- mCallbacks = callback;
+ {
+ Mutex::Autolock _l(mLock);
+ mCallbacks = callback;
+ }
+ // Send a callback for all devices to initialize
+ {
+ for (const auto& pair : mCameraStatusMap) {
+ mCallbacks->cameraDeviceStatusChange(pair.first, pair.second);
+ }
+ }
+
return Status::OK;
}
@@ -82,14 +93,9 @@
}
Return<void> ExternalCameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) {
- std::vector<hidl_string> deviceNameList;
- for (auto const& kvPair : mCameraStatusMap) {
- if (kvPair.second == CameraDeviceStatus::PRESENT) {
- deviceNameList.push_back(kvPair.first);
- }
- }
- hidl_vec<hidl_string> hidlDeviceNameList(deviceNameList);
- ALOGV("ExtCam: number of cameras is %zu", deviceNameList.size());
+ // External camera HAL always report 0 camera, and extra cameras
+ // are just reported via cameraDeviceStatusChange callbacks
+ hidl_vec<hidl_string> hidlDeviceNameList;
_hidl_cb(Status::OK, hidlDeviceNameList);
return Void();
}
@@ -130,7 +136,7 @@
sp<device::V3_2::ICameraDevice> device;
sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl =
new device::V3_4::implementation::ExternalCameraDevice(
- cameraId);
+ cameraId, mCfg);
if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
device = nullptr;
@@ -194,59 +200,10 @@
}
}
-std::unordered_set<std::string>
-ExternalCameraProvider::HotplugThread::initInternalDevices() {
- std::unordered_set<std::string> ret;
- using device::V3_4::implementation::ExternalCameraDeviceConfig;
- const char* configPath = ExternalCameraDeviceConfig::kDefaultCfgPath;
-
- using namespace tinyxml2;
-
- XMLDocument configXml;
- XMLError err = configXml.LoadFile(configPath);
- if (err != XML_SUCCESS) {
- ALOGE("%s: Unable to load external camera config file '%s'. Error: %s",
- __FUNCTION__, configPath, XMLDocument::ErrorIDToName(err));
- } else {
- ALOGI("%s: load external camera config succeed!", __FUNCTION__);
- }
-
- XMLElement *extCam = configXml.FirstChildElement("ExternalCamera");
- if (extCam == nullptr) {
- ALOGI("%s: no external camera config specified", __FUNCTION__);
- return ret;
- }
-
- XMLElement *providerCfg = extCam->FirstChildElement("Provider");
- if (providerCfg == nullptr) {
- ALOGI("%s: no external camera provider config specified", __FUNCTION__);
- return ret;
- }
-
- XMLElement *ignore = providerCfg->FirstChildElement("ignore");
- if (ignore == nullptr) {
- ALOGI("%s: no internal ignored device specified", __FUNCTION__);
- return ret;
- }
-
- XMLElement *id = ignore->FirstChildElement("id");
- while (id != nullptr) {
- const char* text = id->GetText();
- if (text != nullptr) {
- ret.insert(text);
- ALOGI("%s: device %s will be ignored by external camera provider",
- __FUNCTION__, text);
- }
- id = id->NextSiblingElement("id");
- }
-
- return ret;
-}
-
ExternalCameraProvider::HotplugThread::HotplugThread(ExternalCameraProvider* parent) :
Thread(/*canCallJava*/false),
mParent(parent),
- mInternalDevices(initInternalDevices()) {}
+ mInternalDevices(parent->mCfg.mInternalDevices) {}
ExternalCameraProvider::HotplugThread::~HotplugThread() {}
@@ -261,10 +218,10 @@
struct dirent* de;
while ((de = readdir(devdir)) != 0) {
// Find external v4l devices that's existing before we start watching and add them
- if (!strncmp("video", de->d_name, 5)) {
+ if (!strncmp(kPrefix, de->d_name, kPrefixLen)) {
// TODO: This might reject some valid devices. Ex: internal is 33 and a device named 3
// is added.
- std::string deviceId(de->d_name + 5);
+ std::string deviceId(de->d_name + kPrefixLen);
if (mInternalDevices.count(deviceId) == 0) {
ALOGV("Non-internal v4l device %s found", de->d_name);
char v4l2DevicePath[kMaxDevicePathLen];
@@ -300,8 +257,8 @@
while (offset < ret) {
struct inotify_event* event = (struct inotify_event*)&eventBuf[offset];
if (event->wd == mWd) {
- if (!strncmp("video", event->name, 5)) {
- std::string deviceId(event->name + 5);
+ if (!strncmp(kPrefix, event->name, kPrefixLen)) {
+ std::string deviceId(event->name + kPrefixLen);
if (mInternalDevices.count(deviceId) == 0) {
char v4l2DevicePath[kMaxDevicePathLen];
snprintf(v4l2DevicePath, kMaxDevicePathLen,
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.h b/camera/provider/2.4/default/ExternalCameraProvider.h
index 64a8878..c83cc70 100644
--- a/camera/provider/2.4/default/ExternalCameraProvider.h
+++ b/camera/provider/2.4/default/ExternalCameraProvider.h
@@ -25,6 +25,7 @@
#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
+#include "ExternalCameraUtils.h"
namespace android {
namespace hardware {
@@ -36,6 +37,7 @@
using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::VendorTagSection;
+using ::android::hardware::camera::external::common::ExternalCameraConfig;
using ::android::hardware::camera::provider::V2_4::ICameraProvider;
using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
using ::android::hardware::Return;
@@ -81,8 +83,6 @@
virtual bool threadLoop() override;
private:
- static std::unordered_set<std::string> initInternalDevices();
-
ExternalCameraProvider* mParent = nullptr;
const std::unordered_set<std::string> mInternalDevices;
@@ -93,6 +93,7 @@
Mutex mLock;
sp<ICameraProviderCallback> mCallbacks = nullptr;
std::unordered_map<std::string, CameraDeviceStatus> mCameraStatusMap; // camera id -> status
+ const ExternalCameraConfig mCfg;
HotplugThread mHotPlugThread;
};