diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp index 569acfd510..61b892124d 100644 --- a/camera/device/3.4/default/ExternalCameraDevice.cpp +++ b/camera/device/3.4/default/ExternalCameraDevice.cpp @@ -44,9 +44,10 @@ const std::array kSupportedFourCCs {{ } // 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 51bfe3602b..74fd7f4cb1 100644 --- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp +++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp @@ -55,7 +55,7 @@ HandleImporter ExternalCameraDeviceSession::sHandleImporter; ExternalCameraDeviceSession::ExternalCameraDeviceSession( const sp& callback, - const ExternalCameraDeviceConfig& cfg, + const ExternalCameraConfig& cfg, const std::vector& 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 212573aa4f..80f296c6ad 100644 --- a/camera/device/3.4/default/ExternalCameraUtils.cpp +++ b/camera/device/3.4/default/ExternalCameraUtils.cpp @@ -30,14 +30,6 @@ namespace device { 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 @@ int AllocatedFrame::getCroppedLayout(const IMapper::Rect& rect, YCbCrLayout* out 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 @@ ExternalCameraDeviceConfig ExternalCameraDeviceConfig::loadFromCfg(const char* c 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 @@ ExternalCameraDeviceConfig ExternalCameraDeviceConfig::loadFromCfg(const char* c 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 @@ ExternalCameraDeviceConfig ExternalCameraDeviceConfig::loadFromCfg(const char* c return ret; } -ExternalCameraDeviceConfig::ExternalCameraDeviceConfig() : +ExternalCameraConfig::ExternalCameraConfig() : maxJpegBufSize(kDefaultJpegBufSize), numVideoBuffers(kDefaultNumVideoBuffer), numStillBuffers(kDefaultNumStillBuffer) { @@ -247,16 +284,9 @@ ExternalCameraDeviceConfig::ExternalCameraDeviceConfig() : 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 fabf26a3af..cced3f7628 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::device::V3_4::ICameraDeviceSession; 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 @@ using ::android::base::unique_fd; struct ExternalCameraDeviceSession : public virtual RefBase { ExternalCameraDeviceSession(const sp&, - const ExternalCameraDeviceConfig& cfg, + const ExternalCameraConfig& cfg, const std::vector& sortedFormats, const CroppingType& croppingType, const common::V1_0::helper::CameraMetadata& chars, @@ -277,7 +280,7 @@ protected: mutable Mutex mLock; // Protect all private members except otherwise noted const sp mCallback; - const ExternalCameraDeviceConfig mCfg; + const ExternalCameraConfig& mCfg; const common::V1_0::helper::CameraMetadata mCameraCharacteristics; const std::vector mSupportedFormats; const CroppingType mCroppingType; @@ -293,7 +296,7 @@ protected: 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 ef4b41c218..5880469d37 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::device::V3_2::ICameraDeviceCallback; 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 @@ struct ExternalCameraDevice : public ICameraDevice { // 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 @@ protected: Mutex mLock; bool mInitFailed = false; std::string mCameraId; - const ExternalCameraDeviceConfig mCfg; + const ExternalCameraConfig& mCfg; std::vector 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 849f947143..e56160a8d8 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 #include +#include #include using android::hardware::graphics::mapper::V2_0::IMapper; @@ -29,6 +30,60 @@ using android::hardware::graphics::mapper::V2_0::YCbCrLayout; 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 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 fpsLimits; + +private: + ExternalCameraConfig(); +}; + +} // common +} // external + namespace device { namespace V3_4 { namespace implementation { @@ -85,50 +140,6 @@ enum CroppingType { 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 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((sz).width) / (sz).height) diff --git a/camera/provider/2.4/default/ExternalCameraProvider.cpp b/camera/provider/2.4/default/ExternalCameraProvider.cpp index 7657fa3477..faa4e3a0a9 100644 --- a/camera/provider/2.4/default/ExternalCameraProvider.cpp +++ b/camera/provider/2.4/default/ExternalCameraProvider.cpp @@ -24,7 +24,6 @@ #include #include "ExternalCameraProvider.h" #include "ExternalCameraDevice_3_4.h" -#include "tinyxml2.h" // XML parsing namespace android { namespace hardware { @@ -38,6 +37,8 @@ namespace { 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 @@ bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion, } // anonymous namespace ExternalCameraProvider::ExternalCameraProvider() : + mCfg(ExternalCameraConfig::loadFromCfg()), mHotPlugThread(this) { mHotPlugThread.run("ExtCamHotPlug", PRIORITY_BACKGROUND); } @@ -69,8 +71,17 @@ ExternalCameraProvider::~ExternalCameraProvider() { Return ExternalCameraProvider::setCallback( const sp& 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 ExternalCameraProvider::getVendorTags(getVendorTags_cb _hidl_cb) { } Return ExternalCameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) { - std::vector deviceNameList; - for (auto const& kvPair : mCameraStatusMap) { - if (kvPair.second == CameraDeviceStatus::PRESENT) { - deviceNameList.push_back(kvPair.first); - } - } - hidl_vec 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 hidlDeviceNameList; _hidl_cb(Status::OK, hidlDeviceNameList); return Void(); } @@ -130,7 +136,7 @@ Return ExternalCameraProvider::getCameraDeviceInterface_V3_x( sp device; sp 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 @@ void ExternalCameraProvider::deviceRemoved(const char* devName) { } } -std::unordered_set -ExternalCameraProvider::HotplugThread::initInternalDevices() { - std::unordered_set 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 @@ bool ExternalCameraProvider::HotplugThread::threadLoop() { 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 @@ bool ExternalCameraProvider::HotplugThread::threadLoop() { 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 64a8878b55..c83cc708bf 100644 --- a/camera/provider/2.4/default/ExternalCameraProvider.h +++ b/camera/provider/2.4/default/ExternalCameraProvider.h @@ -25,6 +25,7 @@ #include #include #include +#include "ExternalCameraUtils.h" namespace android { namespace hardware { @@ -36,6 +37,7 @@ namespace implementation { 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 @@ private: virtual bool threadLoop() override; private: - static std::unordered_set initInternalDevices(); - ExternalCameraProvider* mParent = nullptr; const std::unordered_set mInternalDevices; @@ -93,6 +93,7 @@ private: Mutex mLock; sp mCallbacks = nullptr; std::unordered_map mCameraStatusMap; // camera id -> status + const ExternalCameraConfig mCfg; HotplugThread mHotPlugThread; };