Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f6022ae authored by Anton D. Kachalov's avatar Anton D. Kachalov
Browse files

Camera: Advertise numbered string ID for external cameras

With current implementation cameraId is part of something like:

  device@3.5/external//dev/video0

This doesn't work well with Camera2 API based apps.

Adding CameraIdOffset tag to Provider as a base offset.

Change-Id: I6309d16be565616f048fb24a70e9be5b2f5ed480
parent e01472a3
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include <algorithm>
#include <array>
#include <regex>
#include <linux/videodev2.h>
#include "android-base/macros.h"
#include "CameraMetadata.h"
@@ -46,10 +47,20 @@ constexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds

} // anonymous namespace

const std::regex kDevicePathRE("/dev/video([0-9]+)");

ExternalCameraDevice::ExternalCameraDevice(
        const std::string& cameraId, const ExternalCameraConfig& cfg) :
        mCameraId(cameraId),
        mCfg(cfg) {}
        const std::string& devicePath, const ExternalCameraConfig& cfg) :
        mCameraId("-1"),
        mDevicePath(devicePath),
        mCfg(cfg) {
    std::smatch sm;
    if (std::regex_match(mDevicePath, sm, kDevicePathRE)) {
        mCameraId = std::to_string(mCfg.cameraIdOffset + std::stoi(sm[1]));
    } else {
        ALOGE("%s: device path match failed for %s", __FUNCTION__, mDevicePath.c_str());
    }
}

ExternalCameraDevice::~ExternalCameraDevice() {}

@@ -129,20 +140,20 @@ Return<void> ExternalCameraDevice::open(
        return Void();
    }

    unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
    unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
    if (fd.get() < 0) {
        int numAttempt = 0;
        do {
            ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again",
                    __FUNCTION__, mCameraId.c_str());
                    __FUNCTION__, mDevicePath.c_str());
            usleep(OPEN_RETRY_SLEEP_US); // sleep and try again
            fd.reset(::open(mCameraId.c_str(), O_RDWR));
            fd.reset(::open(mDevicePath.c_str(), O_RDWR));
            numAttempt++;
        } while (fd.get() < 0 && numAttempt <= MAX_RETRY);

        if (fd.get() < 0) {
            ALOGE("%s: v4l2 device open %s failed: %s",
                    __FUNCTION__, mCameraId.c_str(), strerror(errno));
                    __FUNCTION__, mDevicePath.c_str(), strerror(errno));
            mLock.unlock();
            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
            return Void();
@@ -203,9 +214,9 @@ Return<void> ExternalCameraDevice::dumpState(const ::android::hardware::hidl_han
status_t ExternalCameraDevice::initCameraCharacteristics() {
    if (mCameraCharacteristics.isEmpty()) {
        // init camera characteristics
        unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
        unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
        if (fd.get() < 0) {
            ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mCameraId.c_str());
            ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mDevicePath.c_str());
            return DEAD_OBJECT;
        }

+7 −0
Original line number Diff line number Diff line
@@ -703,6 +703,7 @@ namespace external {
namespace common {

namespace {
    const int kDefaultCameraIdOffset = 100;
    const int kDefaultJpegBufSize = 5 << 20; // 5MB
    const int kDefaultNumVideoBuffer = 4;
    const int kDefaultNumStillBuffer = 2;
@@ -738,6 +739,11 @@ ExternalCameraConfig ExternalCameraConfig::loadFromCfg(const char* cfgPath) {
        return ret;
    }

    XMLElement *cameraIdOffset = providerCfg->FirstChildElement("CameraIdOffset");
    if (cameraIdOffset != nullptr) {
        ret.cameraIdOffset = std::atoi(cameraIdOffset->GetText());
    }

    XMLElement *ignore = providerCfg->FirstChildElement("ignore");
    if (ignore == nullptr) {
        ALOGI("%s: no internal ignored device specified", __FUNCTION__);
@@ -874,6 +880,7 @@ bool ExternalCameraConfig::updateFpsList(tinyxml2::XMLElement* fpsList,
}

ExternalCameraConfig::ExternalCameraConfig() :
        cameraIdOffset(kDefaultCameraIdOffset),
        maxJpegBufSize(kDefaultJpegBufSize),
        numVideoBuffers(kDefaultNumVideoBuffer),
        numStillBuffers(kDefaultNumStillBuffer),
+1 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ protected:
    bool mInitialized = false;
    bool mInitFailed = false;
    std::string mCameraId;
    std::string mDevicePath;
    const ExternalCameraConfig& mCfg;
    std::vector<SupportedV4L2Format> mSupportedFormats;
    CroppingType mCroppingType;
+3 −0
Original line number Diff line number Diff line
@@ -68,6 +68,9 @@ struct ExternalCameraConfig {
    static const char* kDefaultCfgPath;
    static ExternalCameraConfig loadFromCfg(const char* cfgPath = kDefaultCfgPath);

    // CameraId base offset for numerical representation
    uint32_t cameraIdOffset;

    // List of internal V4L2 video nodes external camera HAL must ignore.
    std::unordered_set<std::string> mInternalDevices;

+23 −16
Original line number Diff line number Diff line
@@ -44,17 +44,19 @@ const int kMaxDevicePathLen = 256;
const char* kDevicePath = "/dev/";
constexpr char kPrefix[] = "video";
constexpr int kPrefixLen = sizeof(kPrefix) - 1;
constexpr int kDevicePrefixLen = sizeof(kDevicePath) + kPrefixLen + 1;

bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion,
                     std::string* cameraId) {
bool matchDeviceName(int cameraIdOffset,
                     const hidl_string& deviceName, std::string* deviceVersion,
                     std::string* cameraDevicePath) {
    std::string deviceNameStd(deviceName.c_str());
    std::smatch sm;
    if (std::regex_match(deviceNameStd, sm, kDeviceNameRE)) {
        if (deviceVersion != nullptr) {
            *deviceVersion = sm[1];
        }
        if (cameraId != nullptr) {
            *cameraId = sm[2];
        if (cameraDevicePath != nullptr) {
            *cameraDevicePath = "/dev/video" + std::to_string(std::stoi(sm[2]) - cameraIdOffset);
        }
        return true;
    }
@@ -146,8 +148,9 @@ Return<void> ExternalCameraProviderImpl_2_4::getCameraDeviceInterface_V3_x(
        const hidl_string& cameraDeviceName,
        ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb) {

    std::string cameraId, deviceVersion;
    bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
    std::string cameraDevicePath, deviceVersion;
    bool match = matchDeviceName(mCfg.cameraIdOffset, cameraDeviceName,
                                 &deviceVersion, &cameraDevicePath);
    if (!match) {
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
@@ -164,19 +167,19 @@ Return<void> ExternalCameraProviderImpl_2_4::getCameraDeviceInterface_V3_x(
        case 4: {
            ALOGV("Constructing v3.4 external camera device");
            deviceImpl = new device::V3_4::implementation::ExternalCameraDevice(
                    cameraId, mCfg);
                    cameraDevicePath, mCfg);
            break;
        }
        case 5: {
            ALOGV("Constructing v3.5 external camera device");
            deviceImpl = new device::V3_5::implementation::ExternalCameraDevice(
                    cameraId, mCfg);
                    cameraDevicePath, mCfg);
            break;
        }
        case 6: {
            ALOGV("Constructing v3.6 external camera device");
            deviceImpl = new device::V3_6::implementation::ExternalCameraDevice(
                    cameraId, mCfg);
                    cameraDevicePath, mCfg);
            break;
        }
        default:
@@ -186,7 +189,7 @@ Return<void> ExternalCameraProviderImpl_2_4::getCameraDeviceInterface_V3_x(
    }

    if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraDevicePath.c_str());
        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
        return Void();
    }
@@ -210,12 +213,14 @@ void ExternalCameraProviderImpl_2_4::addExternalCamera(const char* devName) {
    ALOGI("ExtCam: adding %s to External Camera HAL!", devName);
    Mutex::Autolock _l(mLock);
    std::string deviceName;
    std::string cameraId = std::to_string(mCfg.cameraIdOffset +
                                          std::atoi(devName + kDevicePrefixLen));
    if (mPreferredHal3MinorVersion == 6) {
        deviceName = std::string("device@3.6/external/") + devName;
        deviceName = std::string("device@3.6/external/") + cameraId;
    } else if (mPreferredHal3MinorVersion == 5) {
        deviceName = std::string("device@3.5/external/") + devName;
        deviceName = std::string("device@3.5/external/") + cameraId;
    } else {
        deviceName = std::string("device@3.4/external/") + devName;
        deviceName = std::string("device@3.4/external/") + cameraId;
    }
    mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
    if (mCallbacks != nullptr) {
@@ -259,12 +264,14 @@ void ExternalCameraProviderImpl_2_4::deviceAdded(const char* devName) {
void ExternalCameraProviderImpl_2_4::deviceRemoved(const char* devName) {
    Mutex::Autolock _l(mLock);
    std::string deviceName;
    std::string cameraId = std::to_string(mCfg.cameraIdOffset +
                                          std::atoi(devName + kDevicePrefixLen));
    if (mPreferredHal3MinorVersion == 6) {
        deviceName = std::string("device@3.6/external/") + devName;
        deviceName = std::string("device@3.6/external/") + cameraId;
    } else if (mPreferredHal3MinorVersion == 5) {
        deviceName = std::string("device@3.5/external/") + devName;
        deviceName = std::string("device@3.5/external/") + cameraId;
    } else {
        deviceName = std::string("device@3.4/external/") + devName;
        deviceName = std::string("device@3.4/external/") + cameraId;
    }
    if (mCameraStatusMap.find(deviceName) != mCameraStatusMap.end()) {
        mCameraStatusMap.erase(deviceName);