Camera: expose external camera to API1

- Cleanup legacy camera_module_t callbacks
- Order API1 compatible cameras by their ID: numeric strings first
- Dynamically updating number of cameras when device is
  added/removed
- Make sure the following methods are always called without holding
  mServiceLock
    - onDeviceStatusChange
    - updateStatus
    - addStates/removeStates
- Centralized all addState/removeState calls in onDeviceStatusChange
- Passing api1CameraId (number) and cameraDeviceId (string) to various
  client classes.
- Allow FOV information to not present for external camera
- Update API1 preview/video size logic to exclude < ~30fps sizes

Bug: 64874137
Change-Id: Ied6b7141fdad30e3d1c3fcacc5b69ca350fdeb24
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index e06a81f..394701a 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -32,13 +32,15 @@
 
 namespace android {
 
+using hardware::camera::common::V1_0::TorchModeStatus;
+
 /////////////////////////////////////////////////////////////////////
 // CameraFlashlight implementation begins
 // used by camera service to control flashflight.
 /////////////////////////////////////////////////////////////////////
 
 CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
-        camera_module_callbacks_t* callbacks) :
+        CameraProviderManager::StatusListener* callbacks) :
         mProviderManager(providerManager),
         mCallbacks(callbacks),
         mFlashlightMapInitialized(false) {
@@ -59,7 +61,7 @@
     } else {
         // Only HAL1 devices do not support setTorchMode
         mFlashControl =
-                new CameraHardwareInterfaceFlashControl(mProviderManager, *mCallbacks);
+                new CameraHardwareInterfaceFlashControl(mProviderManager, mCallbacks);
     }
 
     return OK;
@@ -119,7 +121,8 @@
 }
 
 int CameraFlashlight::getNumberOfCameras() {
-    return mProviderManager->getAPI1CompatibleCameraCount();
+    size_t len = mProviderManager->getAPI1CompatibleCameraDeviceIds().size();
+    return static_cast<int>(len);
 }
 
 status_t CameraFlashlight::findFlashUnits() {
@@ -221,9 +224,8 @@
             int numCameras = getNumberOfCameras();
             for (int i = 0; i < numCameras; i++) {
                 if (hasFlashUnitLocked(String8::format("%d", i))) {
-                    mCallbacks->torch_mode_status_change(mCallbacks,
-                            String8::format("%d", i).string(),
-                            TORCH_MODE_STATUS_NOT_AVAILABLE);
+                    mCallbacks->onTorchStatusChanged(
+                            String8::format("%d", i), TorchModeStatus::NOT_AVAILABLE);
                 }
             }
         }
@@ -266,9 +268,8 @@
         int numCameras = getNumberOfCameras();
         for (int i = 0; i < numCameras; i++) {
             if (hasFlashUnitLocked(String8::format("%d", i))) {
-                mCallbacks->torch_mode_status_change(mCallbacks,
-                        String8::format("%d", i).string(),
-                        TORCH_MODE_STATUS_AVAILABLE_OFF);
+                mCallbacks->onTorchStatusChanged(
+                        String8::format("%d", i), TorchModeStatus::AVAILABLE_OFF);
             }
         }
     }
@@ -315,9 +316,9 @@
 
 CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
         sp<CameraProviderManager> manager,
-        const camera_module_callbacks_t& callbacks) :
+        CameraProviderManager::StatusListener* callbacks) :
         mProviderManager(manager),
-        mCallbacks(&callbacks),
+        mCallbacks(callbacks),
         mTorchEnabled(false) {
 }
 
@@ -333,8 +334,7 @@
         if (mCallbacks) {
             ALOGV("%s: notify the framework that torch was turned off",
                     __FUNCTION__);
-            mCallbacks->torch_mode_status_change(mCallbacks,
-                    mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+            mCallbacks->onTorchStatusChanged(mCameraId, TorchModeStatus::AVAILABLE_OFF);
         }
     }
 }
@@ -368,8 +368,7 @@
         // disabling the torch mode of currently opened device
         disconnectCameraDevice();
         mTorchEnabled = false;
-        mCallbacks->torch_mode_status_change(mCallbacks,
-            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+        mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_OFF);
         return OK;
     }
 
@@ -379,8 +378,7 @@
     }
 
     mTorchEnabled = true;
-    mCallbacks->torch_mode_status_change(mCallbacks,
-            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
+    mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_ON);
     return OK;
 }
 
diff --git a/services/camera/libcameraservice/CameraFlashlight.h b/services/camera/libcameraservice/CameraFlashlight.h
index c86ee85..07ce829 100644
--- a/services/camera/libcameraservice/CameraFlashlight.h
+++ b/services/camera/libcameraservice/CameraFlashlight.h
@@ -19,7 +19,6 @@
 
 #include <gui/GLConsumer.h>
 #include <gui/Surface.h>
-#include <hardware/camera_common.h>
 #include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
 #include "common/CameraProviderManager.h"
@@ -55,7 +54,7 @@
 class CameraFlashlight : public virtual VirtualLightRefBase {
     public:
         CameraFlashlight(sp<CameraProviderManager> providerManager,
-                camera_module_callbacks_t* callbacks);
+                CameraProviderManager::StatusListener* callbacks);
         virtual ~CameraFlashlight();
 
         // Find all flash units. This must be called before other methods. All
@@ -99,7 +98,7 @@
 
         sp<CameraProviderManager> mProviderManager;
 
-        const camera_module_callbacks_t *mCallbacks;
+        CameraProviderManager::StatusListener* mCallbacks;
         SortedVector<String8> mOpenedCameraIds;
 
         // camera id -> if it has a flash unit
@@ -134,7 +133,7 @@
     public:
         CameraHardwareInterfaceFlashControl(
                 sp<CameraProviderManager> manager,
-                const camera_module_callbacks_t& callbacks);
+                CameraProviderManager::StatusListener* callbacks);
         virtual ~CameraHardwareInterfaceFlashControl();
 
         // FlashControlBase
@@ -166,7 +165,7 @@
         status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash, bool keepDeviceOpen);
 
         sp<CameraProviderManager> mProviderManager;
-        const camera_module_callbacks_t *mCallbacks;
+        CameraProviderManager::StatusListener* mCallbacks;
         sp<CameraHardwareInterface> mDevice;
         String8 mCameraId;
         CameraParameters mParameters;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index e7609ed..89ca6bb 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -107,79 +107,13 @@
 
 // ----------------------------------------------------------------------------
 
-extern "C" {
-static void camera_device_status_change(
-        const struct camera_module_callbacks* callbacks,
-        int camera_id,
-        int new_status) {
-    sp<CameraService> cs = const_cast<CameraService*>(
-            static_cast<const CameraService*>(callbacks));
-    String8 id = String8::format("%d", camera_id);
-
-    CameraDeviceStatus newStatus{CameraDeviceStatus::NOT_PRESENT};
-    switch (new_status) {
-        case CAMERA_DEVICE_STATUS_NOT_PRESENT:
-            newStatus = CameraDeviceStatus::NOT_PRESENT;
-            break;
-        case CAMERA_DEVICE_STATUS_PRESENT:
-            newStatus = CameraDeviceStatus::PRESENT;
-            break;
-        case CAMERA_DEVICE_STATUS_ENUMERATING:
-            newStatus = CameraDeviceStatus::ENUMERATING;
-            break;
-        default:
-            ALOGW("Unknown device status change to %d", new_status);
-            break;
-    }
-    cs->onDeviceStatusChanged(id, newStatus);
-}
-
-static void torch_mode_status_change(
-        const struct camera_module_callbacks* callbacks,
-        const char* camera_id,
-        int new_status) {
-    if (!callbacks || !camera_id) {
-        ALOGE("%s invalid parameters. callbacks %p, camera_id %p", __FUNCTION__,
-                callbacks, camera_id);
-    }
-    sp<CameraService> cs = const_cast<CameraService*>(
-                                static_cast<const CameraService*>(callbacks));
-
-    TorchModeStatus status;
-    switch (new_status) {
-        case TORCH_MODE_STATUS_NOT_AVAILABLE:
-            status = TorchModeStatus::NOT_AVAILABLE;
-            break;
-        case TORCH_MODE_STATUS_AVAILABLE_OFF:
-            status = TorchModeStatus::AVAILABLE_OFF;
-            break;
-        case TORCH_MODE_STATUS_AVAILABLE_ON:
-            status = TorchModeStatus::AVAILABLE_ON;
-            break;
-        default:
-            ALOGE("Unknown torch status %d", new_status);
-            return;
-    }
-
-    cs->onTorchStatusChanged(
-        String8(camera_id),
-        status);
-}
-} // extern "C"
-
-// ----------------------------------------------------------------------------
-
 static const String16 sManageCameraPermission("android.permission.MANAGE_CAMERA");
 
 CameraService::CameraService() :
         mEventLog(DEFAULT_EVENT_LOG_LENGTH),
-        mNumberOfCameras(0), mNumberOfNormalCameras(0),
+        mNumberOfCameras(0),
         mSoundRef(0), mInitialized(false) {
     ALOGI("CameraService started (pid=%d)", getpid());
-
-    this->camera_device_status_change = android::camera_device_status_change;
-    this->torch_mode_status_change = android::torch_mode_status_change;
-
     mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
 }
 
@@ -209,52 +143,42 @@
 
 status_t CameraService::enumerateProviders() {
     status_t res;
-    Mutex::Autolock l(mServiceLock);
 
-    if (nullptr == mCameraProviderManager.get()) {
-        mCameraProviderManager = new CameraProviderManager();
-        res = mCameraProviderManager->initialize(this);
-        if (res != OK) {
-            ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
-                    __FUNCTION__, strerror(-res), res);
-            return res;
-        }
-    }
+    std::vector<std::string> deviceIds;
+    {
+        Mutex::Autolock l(mServiceLock);
 
-    mNumberOfCameras = mCameraProviderManager->getCameraCount();
-    mNumberOfNormalCameras =
-            mCameraProviderManager->getAPI1CompatibleCameraCount();
-
-    // Setup vendor tags before we call get_camera_info the first time
-    // because HAL might need to setup static vendor keys in get_camera_info
-    // TODO: maybe put this into CameraProviderManager::initialize()?
-    mCameraProviderManager->setUpVendorTags();
-
-    if (nullptr == mFlashlight.get()) {
-        mFlashlight = new CameraFlashlight(mCameraProviderManager, this);
-    }
-
-    res = mFlashlight->findFlashUnits();
-    if (res != OK) {
-        ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
-    }
-
-    for (auto& cameraId : mCameraProviderManager->getCameraDeviceIds()) {
-        String8 id8 = String8(cameraId.c_str());
-        bool cameraFound = false;
-        {
-
-            Mutex::Autolock lock(mCameraStatesLock);
-            auto iter = mCameraStates.find(id8);
-            if (iter != mCameraStates.end()) {
-                cameraFound = true;
+        if (nullptr == mCameraProviderManager.get()) {
+            mCameraProviderManager = new CameraProviderManager();
+            res = mCameraProviderManager->initialize(this);
+            if (res != OK) {
+                ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
+                        __FUNCTION__, strerror(-res), res);
+                return res;
             }
         }
 
-        if (!cameraFound) {
-            addStates(id8);
+
+        // Setup vendor tags before we call get_camera_info the first time
+        // because HAL might need to setup static vendor keys in get_camera_info
+        // TODO: maybe put this into CameraProviderManager::initialize()?
+        mCameraProviderManager->setUpVendorTags();
+
+        if (nullptr == mFlashlight.get()) {
+            mFlashlight = new CameraFlashlight(mCameraProviderManager, this);
         }
 
+        res = mFlashlight->findFlashUnits();
+        if (res != OK) {
+            ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
+        }
+
+        deviceIds = mCameraProviderManager->getCameraDeviceIds();
+    }
+
+
+    for (auto& cameraId : deviceIds) {
+        String8 id8 = String8(cameraId.c_str());
         onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
     }
 
@@ -291,6 +215,13 @@
     enumerateProviders();
 }
 
+void CameraService::updateCameraNumAndIds() {
+    Mutex::Autolock l(mServiceLock);
+    mNumberOfCameras = mCameraProviderManager->getCameraCount();
+    mNormalDeviceIds =
+            mCameraProviderManager->getAPI1CompatibleCameraDeviceIds();
+}
+
 void CameraService::addStates(const String8 id) {
     std::string cameraId(id.c_str());
     hardware::camera::common::V1_0::CameraResourceCost cost;
@@ -313,10 +244,13 @@
     if (mFlashlight->hasFlashUnit(id)) {
         mTorchStatusMap.add(id, TorchModeStatus::AVAILABLE_OFF);
     }
+
+    updateCameraNumAndIds();
     logDeviceAdded(id, "Device added");
 }
 
 void CameraService::removeStates(const String8 id) {
+    updateCameraNumAndIds();
     if (mFlashlight->hasFlashUnit(id)) {
         mTorchStatusMap.removeItem(id);
     }
@@ -361,15 +295,16 @@
     if (newStatus == StatusInternal::NOT_PRESENT) {
         logDeviceRemoved(id, String8::format("Device status changed from %d to %d", oldStatus,
                 newStatus));
+
+        // Set the device status to NOT_PRESENT, clients will no longer be able to connect
+        // to this device until the status changes
+        updateStatus(StatusInternal::NOT_PRESENT, id);
+
         sp<BasicClient> clientToDisconnect;
         {
             // Don't do this in updateStatus to avoid deadlock over mServiceLock
             Mutex::Autolock lock(mServiceLock);
 
-            // Set the device status to NOT_PRESENT, clients will no longer be able to connect
-            // to this device until the status changes
-            updateStatus(StatusInternal::NOT_PRESENT, id);
-
             // Remove cached shim parameters
             state->setShimParams(CameraParameters());
 
@@ -472,7 +407,7 @@
     Mutex::Autolock l(mServiceLock);
     switch (type) {
         case CAMERA_TYPE_BACKWARD_COMPATIBLE:
-            *numCameras = mNumberOfNormalCameras;
+            *numCameras = static_cast<int>(mNormalDeviceIds.size());
             break;
         case CAMERA_TYPE_ALL:
             *numCameras = mNumberOfCameras;
@@ -502,7 +437,8 @@
     }
 
     Status ret = Status::ok();
-    status_t err = mCameraProviderManager->getCameraInfo(std::to_string(cameraId), cameraInfo);
+    status_t err = mCameraProviderManager->getCameraInfo(
+            cameraIdIntToStrLocked(cameraId), cameraInfo);
     if (err != OK) {
         ret = STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                 "Error retrieving camera info from device %d: %s (%d)", cameraId,
@@ -512,13 +448,19 @@
     return ret;
 }
 
-int CameraService::cameraIdToInt(const String8& cameraId) {
-    int id;
-    bool success = base::ParseInt(cameraId.string(), &id, 0);
-    if (!success) {
-        return -1;
+std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt) {
+    if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(mNormalDeviceIds.size())) {
+        ALOGE("%s: input id %d invalid: valid range  (0, %zu)",
+                __FUNCTION__, cameraIdInt, mNormalDeviceIds.size());
+        return std::string{};
     }
-    return id;
+
+    return mNormalDeviceIds[cameraIdInt];
+}
+
+String8 CameraService::cameraIdIntToStr(int cameraIdInt) {
+    Mutex::Autolock lock(mServiceLock);
+    return String8(cameraIdIntToStrLocked(cameraIdInt).c_str());
 }
 
 Status CameraService::getCameraCharacteristics(const String16& cameraId,
@@ -635,8 +577,8 @@
 
 Status CameraService::makeClient(const sp<CameraService>& cameraService,
         const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
-        int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
-        int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+        int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
+        bool legacyMode, int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
         /*out*/sp<BasicClient>* client) {
 
     if (halVersion < 0 || halVersion == deviceVersion) {
@@ -646,8 +588,9 @@
           case CAMERA_DEVICE_API_VERSION_1_0:
             if (effectiveApiLevel == API_1) {  // Camera1 API route
                 sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
-                *client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
-                        facing, clientPid, clientUid, getpid(), legacyMode);
+                *client = new CameraClient(cameraService, tmp, packageName,
+                        api1CameraId, facing, clientPid, clientUid,
+                        getpid(), legacyMode);
             } else { // Camera2 API route
                 ALOGW("Camera using old HAL version: %d", deviceVersion);
                 return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
@@ -662,8 +605,10 @@
           case CAMERA_DEVICE_API_VERSION_3_4:
             if (effectiveApiLevel == API_1) { // Camera1 API route
                 sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
-                *client = new Camera2Client(cameraService, tmp, packageName, cameraIdToInt(cameraId),
-                        facing, clientPid, clientUid, servicePid, legacyMode);
+                *client = new Camera2Client(cameraService, tmp, packageName,
+                        cameraId, api1CameraId,
+                        facing, clientPid, clientUid,
+                        servicePid, legacyMode);
             } else { // Camera2 API route
                 sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                         static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
@@ -685,8 +630,9 @@
             halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
             // Only support higher HAL version device opened as HAL1.0 device.
             sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
-            *client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
-                    facing, clientPid, clientUid, servicePid, legacyMode);
+            *client = new CameraClient(cameraService, tmp, packageName,
+                    api1CameraId, facing, clientPid, clientUid,
+                    servicePid, legacyMode);
         } else {
             // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
             ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
@@ -782,7 +728,8 @@
     Status ret = Status::ok();
     sp<Client> tmp = nullptr;
     if (!(ret = connectHelper<ICameraClient,Client>(
-            sp<ICameraClient>{nullptr}, id, static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED),
+            sp<ICameraClient>{nullptr}, id, cameraId,
+            static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED),
             internalPackageName, uid, USE_CALLING_PID,
             API_1, /*legacyMode*/ false, /*shimUpdateOnly*/ true,
             /*out*/ tmp)
@@ -1235,7 +1182,7 @@
 
 Status CameraService::connect(
         const sp<ICameraClient>& cameraClient,
-        int cameraId,
+        int api1CameraId,
         const String16& clientPackageName,
         int clientUid,
         int clientPid,
@@ -1244,9 +1191,10 @@
 
     ATRACE_CALL();
     Status ret = Status::ok();
-    String8 id = String8::format("%d", cameraId);
+
+    String8 id = cameraIdIntToStr(api1CameraId);
     sp<Client> client = nullptr;
-    ret = connectHelper<ICameraClient,Client>(cameraClient, id,
+    ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
             CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1,
             /*legacyMode*/ false, /*shimUpdateOnly*/ false,
             /*out*/client);
@@ -1263,18 +1211,18 @@
 
 Status CameraService::connectLegacy(
         const sp<ICameraClient>& cameraClient,
-        int cameraId, int halVersion,
+        int api1CameraId, int halVersion,
         const String16& clientPackageName,
         int clientUid,
         /*out*/
         sp<ICamera>* device) {
 
     ATRACE_CALL();
-    String8 id = String8::format("%d", cameraId);
+    String8 id = cameraIdIntToStr(api1CameraId);
 
     Status ret = Status::ok();
     sp<Client> client = nullptr;
-    ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion,
+    ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId, halVersion,
             clientPackageName, clientUid, USE_CALLING_PID, API_1,
             /*legacyMode*/ true, /*shimUpdateOnly*/ false,
             /*out*/client);
@@ -1302,6 +1250,7 @@
     String8 id = String8(cameraId);
     sp<CameraDeviceClient> client = nullptr;
     ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
+            /*api1CameraId*/-1,
             CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
             clientUid, USE_CALLING_PID, API_2,
             /*legacyMode*/ false, /*shimUpdateOnly*/ false,
@@ -1319,8 +1268,8 @@
 
 template<class CALLBACK, class CLIENT>
 Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
-        int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
-        apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
+        int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,
+        int clientPid, apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
         /*out*/sp<CLIENT>& device) {
     binder::Status ret = binder::Status::ok();
 
@@ -1403,8 +1352,10 @@
         }
 
         sp<BasicClient> tmp = nullptr;
-        if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
-                clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
+        if(!(ret = makeClient(this, cameraCb, clientPackageName,
+                cameraId, api1CameraId, facing,
+                clientPid, clientUid, getpid(), legacyMode,
+                halVersion, deviceVersion, effectiveApiLevel,
                 /*out*/&tmp)).isOk()) {
             return ret;
         }
@@ -2112,7 +2063,8 @@
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
         const String16& clientPackageName,
-        const String8& cameraIdStr, int cameraFacing,
+        const String8& cameraIdStr,
+        int api1CameraId, int cameraFacing,
         int clientPid, uid_t clientUid,
         int servicePid) :
         CameraService::BasicClient(cameraService,
@@ -2121,7 +2073,7 @@
                 cameraIdStr, cameraFacing,
                 clientPid, clientUid,
                 servicePid),
-        mCameraId(CameraService::cameraIdToInt(cameraIdStr))
+        mCameraId(api1CameraId)
 {
     int callingPid = getCallingPid();
     LOG1("Client::Client E (pid %d, id %d)", callingPid, mCameraId);
@@ -2676,7 +2628,10 @@
     }
     dprintf(fd, "\n== Service global info: ==\n\n");
     dprintf(fd, "Number of camera devices: %d\n", mNumberOfCameras);
-    dprintf(fd, "Number of normal camera devices: %d\n", mNumberOfNormalCameras);
+    dprintf(fd, "Number of normal camera devices: %zu\n", mNormalDeviceIds.size());
+    for (size_t i = 0; i < mNormalDeviceIds.size(); i++) {
+        dprintf(fd, "    Device %zu maps to \"%s\"\n", i, mNormalDeviceIds[i].c_str());
+    }
     String8 activeClientString = mActiveClientManager.toString();
     dprintf(fd, "Active Camera Clients:\n%s", activeClientString.string());
     dprintf(fd, "Allowed user IDs: %s\n", toString(mAllowedUsers).string());
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 67db7ec..81048e6 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -62,7 +62,6 @@
     public BinderService<CameraService>,
     public virtual ::android::hardware::BnCameraService,
     public virtual IBinder::DeathRecipient,
-    public camera_module_callbacks_t,
     public virtual CameraProviderManager::StatusListener
 {
     friend class BinderService<CameraService>;
@@ -333,6 +332,7 @@
                 const sp<hardware::ICameraClient>& cameraClient,
                 const String16& clientPackageName,
                 const String8& cameraIdStr,
+                int api1CameraId,
                 int cameraFacing,
                 int clientPid,
                 uid_t clientUid,
@@ -551,7 +551,8 @@
     // Eumerate all camera providers in the system
     status_t enumerateProviders();
 
-    // Add a new camera to camera and torch state lists or remove an unplugged one
+    // Add/remove a new camera to camera and torch state lists or remove an unplugged one
+    // Caller must not hold mServiceLock
     void addStates(const String8 id);
     void removeStates(const String8 id);
 
@@ -578,7 +579,7 @@
     // Single implementation shared between the various connect calls
     template<class CALLBACK, class CLIENT>
     binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
-            int halVersion, const String16& clientPackageName,
+            int api1CameraId, int halVersion, const String16& clientPackageName,
             int clientUid, int clientPid,
             apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
             /*out*/sp<CLIENT>& device);
@@ -640,9 +641,16 @@
     void finishConnectLocked(const sp<BasicClient>& client, const DescriptorPtr& desc);
 
     /**
-     * Returns the integer corresponding to the given camera ID string, or -1 on failure.
+     * Returns the underlying camera Id string mapped to a camera id int
+     * Empty string is returned when the cameraIdInt is invalid.
      */
-    static int cameraIdToInt(const String8& cameraId);
+    String8 cameraIdIntToStr(int cameraIdInt);
+
+    /**
+     * Returns the underlying camera Id string mapped to a camera id int
+     * Empty string is returned when the cameraIdInt is invalid.
+     */
+    std::string cameraIdIntToStrLocked(int cameraIdInt);
 
     /**
      * Remove a single client corresponding to the given camera id from the list of active clients.
@@ -710,8 +718,14 @@
      */
     void dumpEventLog(int fd);
 
+    /**
+     * This method will acquire mServiceLock
+     */
+    void updateCameraNumAndIds();
+
     int                 mNumberOfCameras;
-    int                 mNumberOfNormalCameras;
+
+    std::vector<std::string> mNormalDeviceIds;
 
     // sounds
     MediaPlayer*        newMediaPlayer(const char *file);
@@ -821,8 +835,8 @@
 
     static binder::Status makeClient(const sp<CameraService>& cameraService,
             const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
-            int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
-            int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+            int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
+            bool legacyMode, int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
             /*out*/sp<BasicClient>* client);
 
     status_t checkCameraAccess(const String16& opPackageName);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 585d2eb..0a82cb9 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -49,16 +49,17 @@
 Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
         const sp<hardware::ICameraClient>& cameraClient,
         const String16& clientPackageName,
-        int cameraId,
+        const String8& cameraDeviceId,
+        int api1CameraId,
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
         int servicePid,
         bool legacyMode):
         Camera2ClientBase(cameraService, cameraClient, clientPackageName,
-                String8::format("%d", cameraId), cameraFacing,
+                cameraDeviceId, api1CameraId, cameraFacing,
                 clientPid, clientUid, servicePid),
-        mParameters(cameraId, cameraFacing)
+        mParameters(api1CameraId, cameraFacing)
 {
     ATRACE_CALL();
 
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 5af74eb..1ebf4b0 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -91,7 +91,8 @@
     Camera2Client(const sp<CameraService>& cameraService,
             const sp<hardware::ICameraClient>& cameraClient,
             const String16& clientPackageName,
-            int cameraId,
+            const String8& cameraDeviceId,
+            int api1CameraId,
             int cameraFacing,
             int clientPid,
             uid_t clientUid,
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index e848a3f..8c6cd3d 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -42,7 +42,7 @@
         int clientPid, int clientUid,
         int servicePid, bool legacyMode):
         Client(cameraService, cameraClient, clientPackageName,
-                String8::format("%d", cameraId), cameraFacing, clientPid,
+                String8::format("%d", cameraId), cameraId, cameraFacing, clientPid,
                 clientUid, servicePid)
 {
     int callingPid = getCallingPid();
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 050c3f7..b4c7e9d 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -759,12 +759,17 @@
     focusingAreas.clear();
     focusingAreas.add(Parameters::Area(0,0,0,0,0));
 
-    camera_metadata_ro_entry_t availableFocalLengths =
-        staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, 0, 0, false);
-    if (!availableFocalLengths.count) return NO_INIT;
+    if (fastInfo.isExternalCamera) {
+        params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, -1.0);
+    } else {
+        camera_metadata_ro_entry_t availableFocalLengths =
+            staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, 0, 0, false);
+        if (!availableFocalLengths.count) return NO_INIT;
 
-    float minFocalLength = availableFocalLengths.data.f[0];
-    params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength);
+        float minFocalLength = availableFocalLengths.data.f[0];
+        params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength);
+    }
+
 
     float horizFov, vertFov;
     res = calculatePictureFovs(&horizFov, &vertFov);
@@ -1091,9 +1096,15 @@
             focusDistanceCalibration.data.u8[0] !=
             ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED);
 
+
+    camera_metadata_ro_entry_t hwLevel = staticInfo(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
+    if (!hwLevel.count) return NO_INIT;
+    fastInfo.isExternalCamera =
+            hwLevel.data.u8[0] == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
+
     camera_metadata_ro_entry_t availableFocalLengths =
-        staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
-    if (!availableFocalLengths.count) return NO_INIT;
+        staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, 0, 0, /*required*/false);
+    if (!availableFocalLengths.count && !fastInfo.isExternalCamera) return NO_INIT;
 
     SortedVector<int32_t> availableFormats = getAvailableOutputFormats();
     if (!availableFormats.size()) return NO_INIT;
@@ -1178,10 +1189,14 @@
 
     // Find smallest (widest-angle) focal length to use as basis of still
     // picture FOV reporting.
-    fastInfo.minFocalLength = availableFocalLengths.data.f[0];
-    for (size_t i = 1; i < availableFocalLengths.count; i++) {
-        if (fastInfo.minFocalLength > availableFocalLengths.data.f[i]) {
-            fastInfo.minFocalLength = availableFocalLengths.data.f[i];
+    if (fastInfo.isExternalCamera) {
+        fastInfo.minFocalLength = -1.0;
+    } else {
+        fastInfo.minFocalLength = availableFocalLengths.data.f[0];
+        for (size_t i = 1; i < availableFocalLengths.count; i++) {
+            if (fastInfo.minFocalLength > availableFocalLengths.data.f[i]) {
+                fastInfo.minFocalLength = availableFocalLengths.data.f[i];
+            }
         }
     }
 
@@ -2870,8 +2885,13 @@
         if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
                 sc.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
                 sc.width <= limit.width && sc.height <= limit.height) {
-            Size sz = {sc.width, sc.height};
-            sizes->push(sz);
+            int64_t minFrameDuration = getMinFrameDurationNs(
+                    {sc.width, sc.height}, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+            if (minFrameDuration > MAX_PREVIEW_RECORD_DURATION_NS) {
+                // Filter slow sizes from preview/record
+                continue;
+            }
+            sizes->push({sc.width, sc.height});
         }
     }
 
@@ -3081,6 +3101,16 @@
 
 status_t Parameters::calculatePictureFovs(float *horizFov, float *vertFov)
         const {
+    if (fastInfo.isExternalCamera) {
+        if (horizFov != NULL) {
+            *horizFov = -1.0;
+        }
+        if (vertFov != NULL) {
+            *vertFov = -1.0;
+        }
+        return OK;
+    }
+
     camera_metadata_ro_entry_t sensorSize =
             staticInfo(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, 2, 2);
     if (!sensorSize.count) return NO_INIT;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index 17e3d75..fe725fd 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -207,6 +207,11 @@
     static const int32_t FPS_MARGIN = 1;
     // Max FPS for default parameters
     static const int32_t MAX_DEFAULT_FPS = 30;
+    // Minimum FPS for a size to be listed in supported preview/video sizes
+    // Set to slightly less than 30.0 to have some tolerance margin
+    static constexpr double MIN_PREVIEW_RECORD_FPS = 29.97;
+    // Maximum frame duration for a size to be listed in supported preview/video sizes
+    static constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS = 1e9 / MIN_PREVIEW_RECORD_FPS;
 
     // Full static camera info, object owned by someone else, such as
     // Camera2Device.
@@ -233,6 +238,7 @@
             }
         };
         DefaultKeyedVector<uint8_t, OverrideModes> sceneModeOverrides;
+        bool isExternalCamera;
         float minFocalLength;
         bool useFlexibleYuv;
         Size maxJpegSize;
@@ -380,6 +386,7 @@
     Vector<Size> availablePreviewSizes;
     Vector<Size> availableVideoSizes;
     // Get size list (that are no larger than limit) from static metadata.
+    // This method filtered size with minFrameDuration < MAX_PREVIEW_RECORD_DURATION_NS
     status_t getFilteredSizes(Size limit, Vector<Size> *sizes);
     // Get max size (from the size array) that matches the given aspect ratio.
     Size getMaxSizeForRatio(float ratio, const int32_t* sizeArray, size_t count);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 8e112a1..8ff8ac5 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -47,6 +47,7 @@
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         const String16& clientPackageName,
         const String8& cameraId,
+        int api1CameraId,
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
@@ -60,6 +61,8 @@
             clientUid,
             servicePid),
     mRemoteCallback(remoteCallback) {
+    // We don't need it for API2 clients, but Camera2ClientBase requires it.
+    (void) api1CameraId;
 }
 
 // Interface used by CameraService
@@ -73,7 +76,8 @@
         uid_t clientUid,
         int servicePid) :
     Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
-                cameraId, cameraFacing, clientPid, clientUid, servicePid),
+                cameraId, /*API1 camera ID*/ -1,
+                cameraFacing, clientPid, clientUid, servicePid),
     mInputStream(),
     mStreamingRequestId(REQUEST_ID_NONE),
     mRequestIdCounter(0) {
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 435c99d..ca2d988 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -45,6 +45,7 @@
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
             const String8& cameraId,
+            int api1CameraId,
             int cameraFacing,
             int clientPid,
             uid_t clientUid,
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 4ce82dc..db26027 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -48,15 +48,16 @@
         const sp<TCamCallbacks>& remoteCallback,
         const String16& clientPackageName,
         const String8& cameraId,
+        int api1CameraId,
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
         int servicePid):
         TClientBase(cameraService, remoteCallback, clientPackageName,
-                cameraId, cameraFacing, clientPid, clientUid, servicePid),
+                cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
         mSharedCameraCallbacks(remoteCallback),
         mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
-        mDeviceActive(false)
+        mDeviceActive(false), mApi1CameraId(api1CameraId)
 {
     ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
             String8(clientPackageName).string(), clientPid, clientUid);
@@ -329,7 +330,7 @@
 
 template <typename TClientBase>
 int Camera2ClientBase<TClientBase>::getCameraId() const {
-    return std::stoi(TClientBase::mCameraIdStr.string());
+    return mApi1CameraId;
 }
 
 template <typename TClientBase>
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index e898d5d..edeae5b 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -49,6 +49,7 @@
                       const sp<TCamCallbacks>& remoteCallback,
                       const String16& clientPackageName,
                       const String8& cameraId,
+                      int api1CameraId,
                       int cameraFacing,
                       int clientPid,
                       uid_t clientUid,
@@ -140,6 +141,8 @@
 
     bool                  mDeviceActive;
 
+    const int             mApi1CameraId; // -1 if client is API2
+
 private:
     template<typename TProviderPtr>
     status_t              initializeImpl(TProviderPtr providerPtr);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 70e7761..b37f004 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -20,11 +20,13 @@
 
 #include "CameraProviderManager.h"
 
+#include <algorithm>
 #include <chrono>
 #include <inttypes.h>
 #include <hidl/ServiceManagement.h>
 #include <functional>
 #include <camera_metadata_hidden.h>
+#include <android-base/parseint.h>
 
 namespace android {
 
@@ -38,7 +40,7 @@
 const std::string kExternalProviderName("external/0");
 
 // Slash-separated list of provider types to consider for use via the old camera API
-const std::string kStandardProviderTypes("internal/legacy");
+const std::string kStandardProviderTypes("internal/legacy/external");
 
 } // anonymous namespace
 
@@ -79,18 +81,7 @@
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     int count = 0;
     for (auto& provider : mProviders) {
-        count += provider->mUniqueDeviceCount;
-    }
-    return count;
-}
-
-int CameraProviderManager::getAPI1CompatibleCameraCount() const {
-    std::lock_guard<std::mutex> lock(mInterfaceMutex);
-    int count = 0;
-    for (auto& provider : mProviders) {
-        if (kStandardProviderTypes.find(provider->getType()) != std::string::npos) {
-            count += provider->mUniqueAPI1CompatibleCameraIds.size();
-        }
+        count += provider->mUniqueCameraIds.size();
     }
     return count;
 }
@@ -116,6 +107,24 @@
             }
         }
     }
+
+    std::sort(deviceIds.begin(), deviceIds.end(),
+            [](const std::string& a, const std::string& b) -> bool {
+                uint32_t aUint = 0, bUint = 0;
+                bool aIsUint = base::ParseUint(a, &aUint);
+                bool bIsUint = base::ParseUint(b, &bUint);
+
+                // Uint device IDs first
+                if (aIsUint && bIsUint) {
+                    return aUint < bUint;
+                } else if (aIsUint) {
+                    return true;
+                } else if (bIsUint) {
+                    return false;
+                }
+                // Simple string compare if both id are not uint
+                return a < b;
+            });
     return deviceIds;
 }
 
@@ -480,6 +489,8 @@
     }
     ALOGI("Connecting to new camera provider: %s, isRemote? %d",
             mProviderName.c_str(), mInterface->isRemote());
+    // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
+    // before setCallback returns
     hardware::Return<Status> status = mInterface->setCallback(this);
     if (!status.isOk()) {
         ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
@@ -536,17 +547,10 @@
         }
     }
 
-    for (auto& device : mDevices) {
-        mUniqueCameraIds.insert(device->mId);
-        if (device->isAPI1Compatible()) {
-            mUniqueAPI1CompatibleCameraIds.insert(device->mId);
-        }
-    }
-    mUniqueDeviceCount = mUniqueCameraIds.size();
-
     ALOGI("Camera provider %s ready with %zu camera devices",
             mProviderName.c_str(), mDevices.size());
 
+    mInitialized = true;
     return OK;
 }
 
@@ -594,9 +598,15 @@
     }
     if (deviceInfo == nullptr) return BAD_VALUE;
     deviceInfo->mStatus = initialStatus;
+    bool isAPI1Compatible = deviceInfo->isAPI1Compatible();
 
     mDevices.push_back(std::move(deviceInfo));
 
+    mUniqueCameraIds.insert(id);
+    if (isAPI1Compatible) {
+        mUniqueAPI1CompatibleCameraIds.insert(id);
+    }
+
     if (parsedId != nullptr) {
         *parsedId = id;
     }
@@ -606,6 +616,10 @@
 void CameraProviderManager::ProviderInfo::removeDevice(std::string id) {
     for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
         if ((*it)->mId == id) {
+            mUniqueCameraIds.erase(id);
+            if ((*it)->isAPI1Compatible()) {
+                mUniqueAPI1CompatibleCameraIds.erase(id);
+            }
             mDevices.erase(it);
             break;
         }
@@ -671,6 +685,7 @@
         CameraDeviceStatus newStatus) {
     sp<StatusListener> listener;
     std::string id;
+    bool initialized = false;
     {
         std::lock_guard<std::mutex> lock(mLock);
         bool known = false;
@@ -697,9 +712,13 @@
             removeDevice(id);
         }
         listener = mManager->getStatusListener();
+        initialized = mInitialized;
     }
     // Call without lock held to allow reentrancy into provider manager
-    if (listener != nullptr) {
+    // Don't send the callback if providerInfo hasn't been initialized.
+    // CameraService will initialize device status after provider is
+    // initialized
+    if (listener != nullptr && initialized) {
         listener->onDeviceStatusChanged(String8(id.c_str()), newStatus);
     }
     return hardware::Void();
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index d02abb0..bbe6789 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -18,7 +18,7 @@
 #define ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_H
 
 #include <vector>
-#include <set>
+#include <unordered_set>
 #include <string>
 #include <mutex>
 
@@ -125,16 +125,14 @@
      */
     int getCameraCount() const;
 
+    std::vector<std::string> getCameraDeviceIds() const;
+
     /**
      * Retrieve the number of API1 compatible cameras; these are internal and
      * backwards-compatible. This is the set of cameras that will be
-     * accessible via the old camera API, with IDs in range of
-     * [0, getAPI1CompatibleCameraCount()-1]. This value is not expected to change dynamically.
+     * accessible via the old camera API.
+     * The return value may change dynamically due to external camera hotplug.
      */
-    int getAPI1CompatibleCameraCount() const;
-
-    std::vector<std::string> getCameraDeviceIds() const;
-
     std::vector<std::string> getAPI1CompatibleCameraDeviceIds() const;
 
     /**
@@ -314,9 +312,9 @@
             static status_t setTorchMode(InterfaceT& interface, bool enabled);
         };
         std::vector<std::unique_ptr<DeviceInfo>> mDevices;
-        std::set<std::string> mUniqueCameraIds;
+        std::unordered_set<std::string> mUniqueCameraIds;
         int mUniqueDeviceCount;
-        std::set<std::string> mUniqueAPI1CompatibleCameraIds;
+        std::unordered_set<std::string> mUniqueAPI1CompatibleCameraIds;
 
         // HALv1-specific camera fields, including the actual device interface
         struct DeviceInfo1 : public DeviceInfo {
@@ -366,6 +364,8 @@
 
         CameraProviderManager *mManager;
 
+        bool mInitialized = false;
+
         // Templated method to instantiate the right kind of DeviceInfo and call the
         // right CameraProvider getCameraDeviceInterface_* method.
         template<class DeviceInfoT>