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/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;
 };