External camera: add device config file

Also remove sizes cannot be cropped from maximal
size.

Bug: 72261897
Change-Id: Icb50cfa58a12e80be3cacc49569fac90be03c8e5
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 1f46b89..31c5fdd 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -27,6 +27,7 @@
         "liblog",
         "libhardware",
         "libcamera_metadata",
+        "libtinyxml2"
     ],
     header_libs: [
         "camera.device@3.4-impl_headers",
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.cpp b/camera/provider/2.4/default/ExternalCameraProvider.cpp
index bb5c336..7657fa3 100644
--- a/camera/provider/2.4/default/ExternalCameraProvider.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProvider.cpp
@@ -24,6 +24,7 @@
 #include <linux/videodev2.h>
 #include "ExternalCameraProvider.h"
 #include "ExternalCameraDevice_3_4.h"
+#include "tinyxml2.h" // XML parsing
 
 namespace android {
 namespace hardware {
@@ -56,7 +57,8 @@
 
 } // anonymous namespace
 
-ExternalCameraProvider::ExternalCameraProvider() : mHotPlugThread(this) {
+ExternalCameraProvider::ExternalCameraProvider() :
+        mHotPlugThread(this) {
     mHotPlugThread.run("ExtCamHotPlug", PRIORITY_BACKGROUND);
 }
 
@@ -143,7 +145,7 @@
 }
 
 void ExternalCameraProvider::addExternalCamera(const char* devName) {
-    ALOGE("ExtCam: adding %s to External Camera HAL!", devName);
+    ALOGI("ExtCam: adding %s to External Camera HAL!", devName);
     Mutex::Autolock _l(mLock);
     std::string deviceName = std::string("device@3.4/external/") + devName;
     mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
@@ -192,8 +194,59 @@
     }
 }
 
+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) {}
+        Thread(/*canCallJava*/false),
+        mParent(parent),
+        mInternalDevices(initInternalDevices()) {}
 
 ExternalCameraProvider::HotplugThread::~HotplugThread() {}
 
@@ -206,14 +259,13 @@
     }
 
     struct dirent* de;
-    // This list is device dependent. TODO: b/72261897 allow setting it from setprop/device boot
-    std::string internalDevices = "0,1";
     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)) {
             // TODO: This might reject some valid devices. Ex: internal is 33 and a device named 3
             //       is added.
-            if (internalDevices.find(de->d_name + 5) == std::string::npos) {
+            std::string deviceId(de->d_name + 5);
+            if (mInternalDevices.count(deviceId) == 0) {
                 ALOGV("Non-internal v4l device %s found", de->d_name);
                 char v4l2DevicePath[kMaxDevicePathLen];
                 snprintf(v4l2DevicePath, kMaxDevicePathLen,
@@ -249,14 +301,17 @@
                 struct inotify_event* event = (struct inotify_event*)&eventBuf[offset];
                 if (event->wd == mWd) {
                     if (!strncmp("video", event->name, 5)) {
-                        char v4l2DevicePath[kMaxDevicePathLen];
-                        snprintf(v4l2DevicePath, kMaxDevicePathLen,
-                                "%s%s", kDevicePath, event->name);
-                        if (event->mask & IN_CREATE) {
-                            mParent->deviceAdded(v4l2DevicePath);
-                        }
-                        if (event->mask & IN_DELETE) {
-                            mParent->deviceRemoved(v4l2DevicePath);
+                        std::string deviceId(event->name + 5);
+                        if (mInternalDevices.count(deviceId) == 0) {
+                            char v4l2DevicePath[kMaxDevicePathLen];
+                            snprintf(v4l2DevicePath, kMaxDevicePathLen,
+                                    "%s%s", kDevicePath, event->name);
+                            if (event->mask & IN_CREATE) {
+                                mParent->deviceAdded(v4l2DevicePath);
+                            }
+                            if (event->mask & IN_DELETE) {
+                                mParent->deviceRemoved(v4l2DevicePath);
+                            }
                         }
                     }
                 }
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.h b/camera/provider/2.4/default/ExternalCameraProvider.h
index c7ed99e..64a8878 100644
--- a/camera/provider/2.4/default/ExternalCameraProvider.h
+++ b/camera/provider/2.4/default/ExternalCameraProvider.h
@@ -17,7 +17,9 @@
 #ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_EXTCAMERAPROVIDER_H
 #define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_EXTCAMERAPROVIDER_H
 
+#include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include "utils/Mutex.h"
 #include "utils/Thread.h"
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
@@ -79,15 +81,19 @@
         virtual bool threadLoop() override;
 
     private:
+        static std::unordered_set<std::string> initInternalDevices();
+
         ExternalCameraProvider* mParent = nullptr;
+        const std::unordered_set<std::string> mInternalDevices;
 
         int mINotifyFD = -1;
         int mWd = -1;
-    } mHotPlugThread;
+    };
 
     Mutex mLock;
     sp<ICameraProviderCallback> mCallbacks = nullptr;
     std::unordered_map<std::string, CameraDeviceStatus> mCameraStatusMap; // camera id -> status
+    HotplugThread mHotPlugThread;
 };