Merge "Start uevent handling thread early" into qt-dev
diff --git a/evs/sampleDriver/EvsEnumerator.cpp b/evs/sampleDriver/EvsEnumerator.cpp
index 071aeaa..76d7b88 100644
--- a/evs/sampleDriver/EvsEnumerator.cpp
+++ b/evs/sampleDriver/EvsEnumerator.cpp
@@ -35,10 +35,10 @@
 // NOTE:  All members values are static so that all clients operate on the same state
 //        That is to say, this is effectively a singleton despite the fact that HIDL
 //        constructs a new instance for each client.
-std::list<EvsEnumerator::CameraRecord>   EvsEnumerator::sCameraList;
-wp<EvsGlDisplay>                         EvsEnumerator::sActiveDisplay;
-std::mutex                               EvsEnumerator::sLock;
-std::condition_variable                  EvsEnumerator::sCameraSignal;
+std::unordered_map<std::string, EvsEnumerator::CameraRecord> EvsEnumerator::sCameraList;
+wp<EvsGlDisplay>                                             EvsEnumerator::sActiveDisplay;
+std::mutex                                                   EvsEnumerator::sLock;
+std::condition_variable                                      EvsEnumerator::sCameraSignal;
 
 // Constants
 const auto kEnumerationTimeout = 10s;
@@ -90,17 +90,13 @@
 
             std::lock_guard<std::mutex> lock(sLock);
             if (cmd_removal) {
-                for (auto it = sCameraList.begin(); it != sCameraList.end(); ++it) {
-                    if (!devpath.compare(it->desc.cameraId)) {
-                        // There must be no entry with duplicated name.
-                        sCameraList.erase(it);
-                        break;
-                    }
-                }
+                sCameraList.erase(devpath);
+                ALOGI("%s is removed", devpath.c_str());
             } else if (cmd_addition) {
                 // NOTE: we are here adding new device without a validation
                 // because it always fails to open, b/132164956.
-                sCameraList.emplace_back(devpath.c_str());
+                sCameraList.emplace(devpath, devpath.c_str());
+                ALOGI("%s is added", devpath.c_str());
             } else {
                 // Ignore all other actions including "change".
             }
@@ -126,8 +122,8 @@
     //           information.  Platform implementers should consider hard coding this list of
     //           known good devices to speed up the startup time of their EVS implementation.
     //           For example, this code might be replaced with nothing more than:
-    //                   sCameraList.emplace_back("/dev/video0");
-    //                   sCameraList.emplace_back("/dev/video1");
+    //                   sCameraList.emplace("/dev/video0");
+    //                   sCameraList.emplace("/dev/video1");
     ALOGI("%s: Starting dev/video* enumeration", __FUNCTION__);
     unsigned videoCount   = 0;
     unsigned captureCount = 0;
@@ -145,8 +141,11 @@
                 std::string deviceName("/dev/");
                 deviceName += entry->d_name;
                 videoCount++;
-                if (qualifyCaptureDevice(deviceName.c_str())) {
-                    sCameraList.emplace_back(deviceName.c_str());
+                if (sCameraList.find(deviceName) != sCameraList.end()) {
+                    ALOGI("%s has been added already.", deviceName.c_str());
+                    captureCount++;
+                } else if(qualifyCaptureDevice(deviceName.c_str())) {
+                    sCameraList.emplace(deviceName, deviceName.c_str());
                     captureCount++;
                 }
             }
@@ -178,7 +177,7 @@
     hidl_vec<CameraDesc> hidlCameras;
     hidlCameras.resize(numCameras);
     unsigned i = 0;
-    for (const auto& cam : sCameraList) {
+    for (const auto& [key, cam] : sCameraList) {
         hidlCameras[i++] = cam.desc;
     }
 
@@ -370,11 +369,10 @@
 
 EvsEnumerator::CameraRecord* EvsEnumerator::findCameraById(const std::string& cameraId) {
     // Find the named camera
-    for (auto &&cam : sCameraList) {
-        if (cam.desc.cameraId == cameraId) {
-            // Found a match!
-            return &cam;
-        }
+    auto found = sCameraList.find(cameraId);
+    if (sCameraList.end() != found) {
+        // Found a match!
+        return &found->second;
     }
 
     // We didn't find a match
diff --git a/evs/sampleDriver/EvsEnumerator.h b/evs/sampleDriver/EvsEnumerator.h
index 01a57bd..f4d64d3 100644
--- a/evs/sampleDriver/EvsEnumerator.h
+++ b/evs/sampleDriver/EvsEnumerator.h
@@ -20,11 +20,10 @@
 #include <android/hardware/automotive/evs/1.0/IEvsEnumerator.h>
 #include <android/hardware/automotive/evs/1.0/IEvsCamera.h>
 
-#include <list>
+#include <unordered_map>
 #include <thread>
 #include <atomic>
 
-
 namespace android {
 namespace hardware {
 namespace automotive {
@@ -36,7 +35,6 @@
 class EvsV4lCamera;    // from EvsCamera.h
 class EvsGlDisplay;    // from EvsGlDisplay.h
 
-
 class EvsEnumerator : public IEvsEnumerator {
 public:
     // Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow.
@@ -61,7 +59,6 @@
         CameraRecord(const char *cameraId) : desc() { desc.cameraId = cameraId; }
     };
 
-
     static bool qualifyCaptureDevice(const char* deviceName);
     static CameraRecord* findCameraById(const std::string& cameraId);
     static void enumerateDevices();
@@ -72,12 +69,14 @@
     //        Because our server has a single thread in the thread pool, these values are
     //        never accessed concurrently despite potentially having multiple instance objects
     //        using them.
-    static std::list<CameraRecord> sCameraList;
+    static std::unordered_map<std::string,
+                              CameraRecord> sCameraList;
 
-    static wp<EvsGlDisplay>        sActiveDisplay; // Weak pointer. Object destructs if client dies.
+    static wp<EvsGlDisplay>                 sActiveDisplay; // Weak pointer.
+                                                            // Object destructs if client dies.
 
-    static std::mutex              sLock;          // Mutex on shared camera device list.
-    static std::condition_variable sCameraSignal;  // Signal on camera device addition.
+    static std::mutex                       sLock;          // Mutex on shared camera device list.
+    static std::condition_variable          sCameraSignal;  // Signal on camera device addition.
 };
 
 } // namespace implementation
diff --git a/evs/sampleDriver/service.cpp b/evs/sampleDriver/service.cpp
index a444686..d8fb316 100644
--- a/evs/sampleDriver/service.cpp
+++ b/evs/sampleDriver/service.cpp
@@ -42,13 +42,15 @@
 
 int main() {
     ALOGI("EVS Hardware Enumerator service is starting");
+
+    // Start a thread to listen video device addition events.
+    std::atomic<bool> running { true };
+    std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running));
+
     android::sp<IEvsEnumerator> service = new EvsEnumerator();
 
     configureRpcThreadpool(1, true /* callerWillJoin */);
 
-    std::atomic<bool> running { true };
-    std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running));
-
     // Register our service -- if somebody is already registered by our name,
     // they will be killed (their thread pool will throw an exception).
     status_t status = service->registerAsService(kEnumeratorServiceName);