treble_patches: Update all patches per BlissRoms Source
Change-Id: I1371da94679a6c859e08f86b4a17b14281dfae81
Signed-off-by: Jackeagle <jackeagle102@gmail.com>
diff --git a/patches/platform_frameworks_av/0001-SQUASH-Revert-Camera-Specific-AOSP-Reverts.patch b/patches/platform_frameworks_av/0001-SQUASH-Revert-Camera-Specific-AOSP-Reverts.patch
new file mode 100644
index 0000000..0cde82c
--- /dev/null
+++ b/patches/platform_frameworks_av/0001-SQUASH-Revert-Camera-Specific-AOSP-Reverts.patch
@@ -0,0 +1,1716 @@
+From f584caaf5f6cd31cc6b8e30a4b62893d6d85818e Mon Sep 17 00:00:00 2001
+From: Jackeagle <jackeagle102@gmail.com>
+Date: Thu, 18 Oct 2018 04:21:22 -0400
+Subject: [PATCH 1/5] [SQUASH] Revert Camera Specific AOSP Reverts
+
+Revert "Revert "CameraService: fix camera removal paths""
+
+This reverts commit e1922854c4bf71d9170011b904b701d1b38e303e.
+
+Revert "Revert "CameraService: Update camera and torch state lists also at runtime""
+
+This reverts commit cb343b767cd41829bb994c9c0e671a9c3e5d7cfb.
+
+Revert "Revert "Camera: Add API level to service proxy notification""
+
+This reverts commit 48888c68523e50038e92b8d73fa4d471fe266972.
+
+Revert "Revert "Camera: expose external camera to API1""
+
+This reverts commit 92607517666eca78bb94817f780977c7024cdda4.
+
+Revert "Revert "Camera: fix camera ID in flashlight control""
+
+This reverts commit 2c7225b2fe3017d1fd146e55420c6b616f44d16b.
+
+Revert "Revert "Camera: Support all API1 compatible camera devices""
+
+This reverts commit 842255a5aff37bb06d43a06bb44be0a67c4570ac.
+
+Revert "Revert "Camera: Filter logical camera ids to API1 app""
+
+This reverts commit 4e10dacc6a5edc0b4382e570173e9f7ff89af9bd.
+---
+ .../aidl/android/hardware/ICameraServiceProxy.aidl | 8 +-
+ camera/ndk/impl/ACameraManager.cpp | 3 +
+ .../camera/libcameraservice/CameraFlashlight.cpp | 52 ++--
+ .../camera/libcameraservice/CameraFlashlight.h | 11 +-
+ services/camera/libcameraservice/CameraService.cpp | 317 ++++++++++-----------
+ services/camera/libcameraservice/CameraService.h | 35 ++-
+ .../camera/libcameraservice/api1/Camera2Client.cpp | 7 +-
+ .../camera/libcameraservice/api1/Camera2Client.h | 3 +-
+ .../camera/libcameraservice/api1/CameraClient.cpp | 14 +-
+ .../libcameraservice/api1/client2/Parameters.cpp | 56 +++-
+ .../libcameraservice/api1/client2/Parameters.h | 7 +
+ .../libcameraservice/api2/CameraDeviceClient.cpp | 59 ++--
+ .../libcameraservice/api2/CameraDeviceClient.h | 1 +
+ .../libcameraservice/common/Camera2ClientBase.cpp | 15 +-
+ .../libcameraservice/common/Camera2ClientBase.h | 3 +
+ .../common/CameraProviderManager.cpp | 173 ++++++++---
+ .../common/CameraProviderManager.h | 30 +-
+ 17 files changed, 476 insertions(+), 318 deletions(-)
+
+diff --git a/camera/aidl/android/hardware/ICameraServiceProxy.aidl b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
+index 5dc23eb..7575948 100644
+--- a/camera/aidl/android/hardware/ICameraServiceProxy.aidl
++++ b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
+@@ -46,8 +46,14 @@ interface ICameraServiceProxy
+ const int CAMERA_FACING_EXTERNAL = 2;
+
+ /**
++ * Values for notifyCameraState api level
++ */
++ const int CAMERA_API_LEVEL_1 = 1;
++ const int CAMERA_API_LEVEL_2 = 2;
++
++ /**
+ * Update the status of a camera device.
+ */
+ oneway void notifyCameraState(String cameraId, int facing, int newCameraState,
+- String clientName);
++ String clientName, int apiLevel);
+ }
+diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
+index e409ddd..c59d0e7 100644
+--- a/camera/ndk/impl/ACameraManager.cpp
++++ b/camera/ndk/impl/ACameraManager.cpp
+@@ -340,6 +340,9 @@ void CameraManagerGlobal::onStatusChangedLocked(
+ msg->setString(kCameraIdKey, AString(cameraId));
+ msg->post();
+ }
++ if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT) {
++ mDeviceStatusMap.erase(cameraId);
++ }
+ }
+
+ } // namespace android
+diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
+index 9c45331..61b9acb 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 @@ status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
+ } else {
+ // Only HAL1 devices do not support setTorchMode
+ mFlashControl =
+- new CameraHardwareInterfaceFlashControl(mProviderManager, *mCallbacks);
++ new CameraHardwareInterfaceFlashControl(mProviderManager, mCallbacks);
+ }
+
+ return OK;
+@@ -118,19 +120,15 @@ status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
+ return res;
+ }
+
+-int CameraFlashlight::getNumberOfCameras() {
+- return mProviderManager->getAPI1CompatibleCameraCount();
+-}
+-
+ status_t CameraFlashlight::findFlashUnits() {
+ Mutex::Autolock l(mLock);
+ status_t res;
+
+ std::vector<String8> cameraIds;
+- int numberOfCameras = getNumberOfCameras();
++ std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds();
++ int numberOfCameras = static_cast<int>(ids.size());
+ cameraIds.resize(numberOfCameras);
+ // No module, must be provider
+- std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds();
+ for (size_t i = 0; i < cameraIds.size(); i++) {
+ cameraIds[i] = String8(ids[i].c_str());
+ }
+@@ -184,7 +182,8 @@ bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
+
+ ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
+ if (index == NAME_NOT_FOUND) {
+- ALOGE("%s: camera %s not present when findFlashUnits() was called",
++ // Might be external camera
++ ALOGW("%s: camera %s not present when findFlashUnits() was called",
+ __FUNCTION__, cameraId.string());
+ return false;
+ }
+@@ -218,12 +217,13 @@ status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
+
+ if (mOpenedCameraIds.size() == 0) {
+ // notify torch unavailable for all cameras with a flash
+- int numCameras = getNumberOfCameras();
++ std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds();
++ int numCameras = static_cast<int>(ids.size());
+ 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);
++ String8 id8(ids[i].c_str());
++ if (hasFlashUnitLocked(id8)) {
++ mCallbacks->onTorchStatusChanged(
++ id8, TorchModeStatus::NOT_AVAILABLE);
+ }
+ }
+ }
+@@ -263,12 +263,13 @@ status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
+
+ if (isBackwardCompatibleMode(cameraId)) {
+ // notify torch available for all cameras with a flash
+- int numCameras = getNumberOfCameras();
++ std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds();
++ int numCameras = static_cast<int>(ids.size());
+ 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);
++ String8 id8(ids[i].c_str());
++ if (hasFlashUnitLocked(id8)) {
++ mCallbacks->onTorchStatusChanged(
++ id8, TorchModeStatus::AVAILABLE_OFF);
+ }
+ }
+ }
+@@ -315,9 +316,9 @@ status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enable
+
+ 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 @@ CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
+ 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 @@ status_t CameraHardwareInterfaceFlashControl::setTorchMode(
+ // 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 @@ status_t CameraHardwareInterfaceFlashControl::setTorchMode(
+ }
+
+ 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..1baaba2 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 FlashControlBase : public virtual VirtualLightRefBase {
+ 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
+@@ -93,13 +92,11 @@ class CameraFlashlight : public virtual VirtualLightRefBase {
+ // opening cameras)
+ bool isBackwardCompatibleMode(const String8& cameraId);
+
+- int getNumberOfCameras();
+-
+ sp<FlashControlBase> mFlashControl;
+
+ 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 +131,7 @@ class CameraHardwareInterfaceFlashControl : public FlashControlBase {
+ public:
+ CameraHardwareInterfaceFlashControl(
+ sp<CameraProviderManager> manager,
+- const camera_module_callbacks_t& callbacks);
++ CameraProviderManager::StatusListener* callbacks);
+ virtual ~CameraHardwareInterfaceFlashControl();
+
+ // FlashControlBase
+@@ -166,7 +163,7 @@ class CameraHardwareInterfaceFlashControl : public FlashControlBase {
+ 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 01220e3..de0fac5 100644
+--- a/services/camera/libcameraservice/CameraService.cpp
++++ b/services/camera/libcameraservice/CameraService.cpp
+@@ -109,79 +109,13 @@ static void setLogLevel(int level) {
+
+ // ----------------------------------------------------------------------------
+
+-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);
+ }
+
+@@ -211,72 +145,43 @@ void CameraService::onFirstRef()
+
+ 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();
++ 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;
++ }
++ }
+
+- // 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);
+- }
++ // 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();
+
+- 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;
+- {
++ if (nullptr == mFlashlight.get()) {
++ mFlashlight = new CameraFlashlight(mCameraProviderManager, this);
++ }
+
+- Mutex::Autolock lock(mCameraStatesLock);
+- auto iter = mCameraStates.find(id8);
+- if (iter != mCameraStates.end()) {
+- cameraFound = true;
+- }
++ res = mFlashlight->findFlashUnits();
++ if (res != OK) {
++ ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
+ }
+
+- if (!cameraFound) {
+- hardware::camera::common::V1_0::CameraResourceCost cost;
+- res = mCameraProviderManager->getResourceCost(cameraId, &cost);
+- if (res != OK) {
+- ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
+- continue;
+- }
+- std::set<String8> conflicting;
+- for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
+- conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
+- }
++ deviceIds = mCameraProviderManager->getCameraDeviceIds();
++ }
+
+- {
+- Mutex::Autolock lock(mCameraStatesLock);
+- mCameraStates.emplace(id8,
+- std::make_shared<CameraState>(id8, cost.resourceCost, conflicting));
+- }
+- }
+
++ for (auto& cameraId : deviceIds) {
++ String8 id8 = String8(cameraId.c_str());
+ onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
+-
+- if (mFlashlight->hasFlashUnit(id8)) {
+- mTorchStatusMap.add(id8, TorchModeStatus::AVAILABLE_OFF);
+- }
+ }
+
+ return OK;
+@@ -312,6 +217,54 @@ void CameraService::onNewProviderRegistered() {
+ 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;
++ status_t res = mCameraProviderManager->getResourceCost(cameraId, &cost);
++ if (res != OK) {
++ ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
++ return;
++ }
++ std::set<String8> conflicting;
++ for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
++ conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
++ }
++
++ {
++ Mutex::Autolock lock(mCameraStatesLock);
++ mCameraStates.emplace(id, std::make_shared<CameraState>(id, cost.resourceCost,
++ conflicting));
++ }
++
++ if (mFlashlight->hasFlashUnit(id)) {
++ Mutex::Autolock al(mTorchStatusMutex);
++ mTorchStatusMap.add(id, TorchModeStatus::AVAILABLE_OFF);
++ }
++
++ updateCameraNumAndIds();
++ logDeviceAdded(id, "Device added");
++}
++
++void CameraService::removeStates(const String8 id) {
++ updateCameraNumAndIds();
++ if (mFlashlight->hasFlashUnit(id)) {
++ Mutex::Autolock al(mTorchStatusMutex);
++ mTorchStatusMap.removeItem(id);
++ }
++
++ {
++ Mutex::Autolock lock(mCameraStatesLock);
++ mCameraStates.erase(id);
++ }
++}
++
+ void CameraService::onDeviceStatusChanged(const String8& id,
+ CameraDeviceStatus newHalStatus) {
+ ALOGI("%s: Status changed for cameraId=%s, newStatus=%d", __FUNCTION__,
+@@ -323,8 +276,13 @@ void CameraService::onDeviceStatusChanged(const String8& id,
+
+ if (state == nullptr) {
+ if (newStatus == StatusInternal::PRESENT) {
+- ALOGW("%s: Unknown camera ID %s, probably newly registered?",
++ ALOGI("%s: Unknown camera ID %s, a new camera is added",
+ __FUNCTION__, id.string());
++
++ // First add as absent to make sure clients are notified below
++ addStates(id);
++
++ updateStatus(newStatus, id);
+ } else {
+ ALOGE("%s: Bad camera ID %s", __FUNCTION__, id.string());
+ }
+@@ -341,15 +299,16 @@ void CameraService::onDeviceStatusChanged(const String8& id,
+ 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());
+
+@@ -371,6 +330,7 @@ void CameraService::onDeviceStatusChanged(const String8& id,
+ clientToDisconnect->disconnect();
+ }
+
++ removeStates(id);
+ } else {
+ if (oldStatus == StatusInternal::NOT_PRESENT) {
+ logDeviceAdded(id, String8::format("Device status changed from %d to %d", oldStatus,
+@@ -451,7 +411,7 @@ Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) {
+ 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;
+@@ -481,7 +441,8 @@ Status CameraService::getCameraInfo(int cameraId,
+ }
+
+ 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,
+@@ -491,13 +452,19 @@ Status CameraService::getCameraInfo(int cameraId,
+ 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,
+@@ -614,8 +581,8 @@ Status CameraService::filterGetInfoErrorCode(status_t err) {
+
+ 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) {
+@@ -625,8 +592,9 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService,
+ 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,
+@@ -641,8 +609,10 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService,
+ 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());
+@@ -664,8 +634,9 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService,
+ 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"
+@@ -765,7 +736,8 @@ Status CameraService::initializeShimMetadata(int cameraId) {
+ 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)
+@@ -1222,7 +1194,7 @@ status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clien
+
+ Status CameraService::connect(
+ const sp<ICameraClient>& cameraClient,
+- int cameraId,
++ int api1CameraId,
+ const String16& clientPackageName,
+ int clientUid,
+ int clientPid,
+@@ -1231,9 +1203,10 @@ Status CameraService::connect(
+
+ 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);
+@@ -1250,18 +1223,18 @@ Status CameraService::connect(
+
+ 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);
+@@ -1289,6 +1262,7 @@ Status CameraService::connectDevice(
+ 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,
+@@ -1306,8 +1280,8 @@ Status CameraService::connectDevice(
+
+ 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();
+
+@@ -1390,8 +1364,10 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8&
+ }
+
+ 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;
+ }
+@@ -2102,7 +2078,8 @@ void CameraService::playSound(sound_kind kind) {
+ 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,
+@@ -2111,7 +2088,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
+ cameraIdStr, cameraFacing,
+ clientPid, clientUid,
+ servicePid),
+- mCameraId(CameraService::cameraIdToInt(cameraIdStr))
++ mCameraId(api1CameraId)
+ {
+ int callingPid = getCallingPid();
+ LOG1("Client::Client E (pid %d, id %d)", callingPid, mCameraId);
+@@ -2279,9 +2256,13 @@ status_t CameraService::BasicClient::startCameraOps() {
+ // Transition device availability listeners from PRESENT -> NOT_AVAILABLE
+ sCameraService->updateStatus(StatusInternal::NOT_AVAILABLE, mCameraIdStr);
+
++ int apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1;
++ if (canCastToApiClient(API_2)) {
++ apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2;
++ }
+ // Transition device state to OPEN
+ sCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_OPEN,
+- mCameraIdStr, mCameraFacing, mClientPackageName);
++ mCameraIdStr, mCameraFacing, mClientPackageName, apiLevel);
+
+ return OK;
+ }
+@@ -2296,16 +2277,23 @@ status_t CameraService::BasicClient::finishCameraOps() {
+ mClientPackageName);
+ mOpsActive = false;
+
++ // This function is called when a client disconnects. This should
++ // release the camera, but actually only if it was in a proper
++ // functional state, i.e. with status NOT_AVAILABLE
+ std::initializer_list<StatusInternal> rejected = {StatusInternal::PRESENT,
+- StatusInternal::ENUMERATING};
++ StatusInternal::ENUMERATING, StatusInternal::NOT_PRESENT};
+
+ // Transition to PRESENT if the camera is not in either of the rejected states
+ sCameraService->updateStatus(StatusInternal::PRESENT,
+ mCameraIdStr, rejected);
+
++ int apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1;
++ if (canCastToApiClient(API_2)) {
++ apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2;
++ }
+ // Transition device state to CLOSED
+ sCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_CLOSED,
+- mCameraIdStr, mCameraFacing, mClientPackageName);
++ mCameraIdStr, mCameraFacing, mClientPackageName, apiLevel);
+ }
+ // Always stop watching, even if no camera op is active
+ if (mOpsCallback != NULL) {
+@@ -2548,7 +2536,7 @@ void CameraService::UidPolicy::updateOverrideUid(uid_t uid, String16 callingPack
+
+ CameraService::CameraState::CameraState(const String8& id, int cost,
+ const std::set<String8>& conflicting) : mId(id),
+- mStatus(StatusInternal::PRESENT), mCost(cost), mConflicting(conflicting) {}
++ mStatus(StatusInternal::NOT_PRESENT), mCost(cost), mConflicting(conflicting) {}
+
+ CameraService::CameraState::~CameraState() {}
+
+@@ -2724,7 +2712,10 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
+ }
+ 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());
+@@ -2979,11 +2970,11 @@ void CameraService::CameraState::updateStatus(StatusInternal status,
+ }
+
+ void CameraService::updateProxyDeviceState(int newState,
+- const String8& cameraId, int facing, const String16& clientName) {
++ const String8& cameraId, int facing, const String16& clientName, int apiLevel) {
+ sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
+ if (proxyBinder == nullptr) return;
+ String16 id(cameraId);
+- proxyBinder->notifyCameraState(id, newState, facing, clientName);
++ proxyBinder->notifyCameraState(id, newState, facing, clientName, apiLevel);
+ }
+
+ status_t CameraService::getTorchStatusLocked(
+diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
+index 6724c49..8d4bcdb 100644
+--- a/services/camera/libcameraservice/CameraService.h
++++ b/services/camera/libcameraservice/CameraService.h
+@@ -62,7 +62,6 @@ class CameraService :
+ 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>;
+@@ -190,7 +189,8 @@ public:
+ int newState,
+ const String8& cameraId,
+ int facing,
+- const String16& clientName);
++ const String16& clientName,
++ int apiLevel);
+
+ /////////////////////////////////////////////////////////////////////
+ // CameraDeviceFactory functionality
+@@ -334,6 +334,7 @@ public:
+ const sp<hardware::ICameraClient>& cameraClient,
+ const String16& clientPackageName,
+ const String8& cameraIdStr,
++ int api1CameraId,
+ int cameraFacing,
+ int clientPid,
+ uid_t clientUid,
+@@ -555,6 +556,11 @@ private:
+ // Eumerate all camera providers in the system
+ status_t enumerateProviders();
+
++ // 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);
++
+ // Check if we can connect, before we acquire the service lock.
+ // The returned originalClientPid is the PID of the original process that wants to connect to
+ // camera.
+@@ -578,7 +584,7 @@ private:
+ // 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);
+@@ -643,9 +649,16 @@ private:
+ 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.
++ */
++ 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.
+ */
+- static int cameraIdToInt(const String8& cameraId);
++ std::string cameraIdIntToStrLocked(int cameraIdInt);
+
+ /**
+ * Remove a single client corresponding to the given camera id from the list of active clients.
+@@ -713,8 +726,14 @@ private:
+ */
+ void dumpEventLog(int fd);
+
++ /**
++ * This method will acquire mServiceLock
++ */
++ void updateCameraNumAndIds();
++
+ int mNumberOfCameras;
+- int mNumberOfNormalCameras;
++
++ std::vector<std::string> mNormalDeviceIds;
+
+ // sounds
+ sp<MediaPlayer> newMediaPlayer(const char *file);
+@@ -824,8 +843,8 @@ private:
+
+ 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 dd1cf2c..65faac9 100644
+--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
++++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
+@@ -49,16 +49,17 @@ static int getCallingPid() {
+ 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 c17cbd4..44929c3 100644
+--- a/services/camera/libcameraservice/api1/Camera2Client.h
++++ b/services/camera/libcameraservice/api1/Camera2Client.h
+@@ -91,7 +91,8 @@ public:
+ 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 e2c8b8b..2358c1e 100644
+--- a/services/camera/libcameraservice/api1/CameraClient.cpp
++++ b/services/camera/libcameraservice/api1/CameraClient.cpp
+@@ -42,7 +42,7 @@ CameraClient::CameraClient(const sp<CameraService>& cameraService,
+ 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();
+@@ -264,7 +264,8 @@ binder::Status CameraClient::disconnect() {
+ mHardware->stopPreview();
+ sCameraService->updateProxyDeviceState(
+ hardware::ICameraServiceProxy::CAMERA_STATE_IDLE,
+- mCameraIdStr, mCameraFacing, mClientPackageName);
++ mCameraIdStr, mCameraFacing, mClientPackageName,
++ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
+ mHardware->cancelPicture();
+ // Release the hardware resources.
+ mHardware->release();
+@@ -427,7 +428,8 @@ status_t CameraClient::startPreviewMode() {
+ if (result == NO_ERROR) {
+ sCameraService->updateProxyDeviceState(
+ hardware::ICameraServiceProxy::CAMERA_STATE_ACTIVE,
+- mCameraIdStr, mCameraFacing, mClientPackageName);
++ mCameraIdStr, mCameraFacing, mClientPackageName,
++ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
+ }
+ return result;
+ }
+@@ -470,7 +472,8 @@ void CameraClient::stopPreview() {
+ mHardware->stopPreview();
+ sCameraService->updateProxyDeviceState(
+ hardware::ICameraServiceProxy::CAMERA_STATE_IDLE,
+- mCameraIdStr, mCameraFacing, mClientPackageName);
++ mCameraIdStr, mCameraFacing, mClientPackageName,
++ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
+ mPreviewBuffer.clear();
+ }
+
+@@ -981,7 +984,8 @@ void CameraClient::handleShutter(void) {
+ // idle now, until preview is restarted
+ sCameraService->updateProxyDeviceState(
+ hardware::ICameraServiceProxy::CAMERA_STATE_IDLE,
+- mCameraIdStr, mCameraFacing, mClientPackageName);
++ mCameraIdStr, mCameraFacing, mClientPackageName,
++ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
+
+ mLock.unlock();
+ }
+diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
+index 7373b81..d66dec4 100644
+--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
++++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
+@@ -761,12 +761,17 @@ status_t Parameters::initialize(const CameraMetadata *info, int deviceVersion) {
+ 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);
+@@ -1104,9 +1109,15 @@ status_t Parameters::buildFastInfo() {
+ 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;
+@@ -1191,10 +1202,14 @@ status_t Parameters::buildFastInfo() {
+
+ // 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];
++ }
+ }
+ }
+
+@@ -2921,8 +2936,13 @@ status_t Parameters::getFilteredSizes(Size limit, Vector<Size> *sizes) {
+ 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});
+ }
+ }
+
+@@ -3132,6 +3152,16 @@ Parameters::CropRegion Parameters::calculateCropRegion(bool previewOnly) const {
+
+ 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 f0bde5b..97f8ea7 100644
+--- a/services/camera/libcameraservice/api1/client2/Parameters.h
++++ b/services/camera/libcameraservice/api1/client2/Parameters.h
+@@ -209,6 +209,11 @@ struct Parameters {
+ 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.
+@@ -235,6 +240,7 @@ struct Parameters {
+ }
+ };
+ DefaultKeyedVector<uint8_t, OverrideModes> sceneModeOverrides;
++ bool isExternalCamera;
+ float minFocalLength;
+ bool useFlexibleYuv;
+ Size maxJpegSize;
+@@ -383,6 +389,7 @@ private:
+ 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 2297ed3..98d0534 100644
+--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
++++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+@@ -49,6 +49,7 @@ CameraDeviceClientBase::CameraDeviceClientBase(
+ const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
+ const String16& clientPackageName,
+ const String8& cameraId,
++ int api1CameraId,
+ int cameraFacing,
+ int clientPid,
+ uid_t clientUid,
+@@ -62,6 +63,8 @@ CameraDeviceClientBase::CameraDeviceClientBase(
+ clientUid,
+ servicePid),
+ mRemoteCallback(remoteCallback) {
++ // We don't need it for API2 clients, but Camera2ClientBase requires it.
++ (void) api1CameraId;
+ }
+
+ // Interface used by CameraService
+@@ -75,7 +78,8 @@ CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
+ 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) {
+@@ -620,11 +624,19 @@ binder::Status CameraDeviceClient::createStream(
+ return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+ }
+
+- if (!checkPhysicalCameraId(physicalCameraId)) {
+- String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
++ if (physicalCameraId.size() > 0) {
++ std::vector<std::string> physicalCameraIds;
++ std::string physicalId(physicalCameraId.string());
++ bool logicalCamera =
++ CameraProviderManager::isLogicalCamera(mDevice->info(), &physicalCameraIds);
++ if (!logicalCamera ||
++ std::find(physicalCameraIds.begin(), physicalCameraIds.end(), physicalId) ==
++ physicalCameraIds.end()) {
++ String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
+ mCameraIdStr.string(), physicalCameraId.string());
+- ALOGE("%s: %s", __FUNCTION__, msg.string());
+- return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
++ ALOGE("%s: %s", __FUNCTION__, msg.string());
++ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
++ }
+ }
+ std::vector<sp<Surface>> surfaces;
+ std::vector<sp<IBinder>> binders;
+@@ -1140,43 +1152,6 @@ binder::Status CameraDeviceClient::createSurfaceFromGbp(
+ return binder::Status::ok();
+ }
+
+-bool CameraDeviceClient::checkPhysicalCameraId(const String8& physicalCameraId) {
+- if (0 == physicalCameraId.size()) {
+- return true;
+- }
+-
+- CameraMetadata staticInfo = mDevice->info();
+- camera_metadata_entry_t entryCap;
+- bool isLogicalCam = false;
+-
+- entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+- for (size_t i = 0; i < entryCap.count; ++i) {
+- uint8_t capability = entryCap.data.u8[i];
+- if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+- isLogicalCam = true;
+- }
+- }
+- if (!isLogicalCam) {
+- return false;
+- }
+-
+- camera_metadata_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
+- const uint8_t* ids = entryIds.data.u8;
+- size_t start = 0;
+- for (size_t i = 0; i < entryIds.count; ++i) {
+- if (ids[i] == '\0') {
+- if (start != i) {
+- String8 currentId((const char*)ids+start);
+- if (currentId == physicalCameraId) {
+- return true;
+- }
+- }
+- start = i+1;
+- }
+- }
+- return false;
+-}
+-
+ bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
+ int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
+ /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
+diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
+index 5bec39c..5aaf5aa 100644
+--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
++++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
+@@ -45,6 +45,7 @@ protected:
+ 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 5c6711a..ce006a7 100644
+--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
++++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+@@ -48,15 +48,16 @@ Camera2ClientBase<TClientBase>::Camera2ClientBase(
+ 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);
+@@ -252,7 +253,9 @@ void Camera2ClientBase<TClientBase>::notifyIdle() {
+ if (mDeviceActive) {
+ getCameraService()->updateProxyDeviceState(
+ hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, TClientBase::mCameraIdStr,
+- TClientBase::mCameraFacing, TClientBase::mClientPackageName);
++ TClientBase::mCameraFacing, TClientBase::mClientPackageName,
++ ((mApi1CameraId < 0) ? hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2 :
++ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1));
+ }
+ mDeviceActive = false;
+
+@@ -268,7 +271,9 @@ void Camera2ClientBase<TClientBase>::notifyShutter(const CaptureResultExtras& re
+ if (!mDeviceActive) {
+ getCameraService()->updateProxyDeviceState(
+ hardware::ICameraServiceProxy::CAMERA_STATE_ACTIVE, TClientBase::mCameraIdStr,
+- TClientBase::mCameraFacing, TClientBase::mClientPackageName);
++ TClientBase::mCameraFacing, TClientBase::mClientPackageName,
++ ((mApi1CameraId < 0) ? hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2 :
++ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1));
+ }
+ mDeviceActive = true;
+
+@@ -331,7 +336,7 @@ void Camera2ClientBase<TClientBase>::notifyRepeatingRequestError(long lastFrameN
+
+ 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 4da422a..e74fbdf 100644
+--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
++++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
+@@ -49,6 +49,7 @@ public:
+ const sp<TCamCallbacks>& remoteCallback,
+ const String16& clientPackageName,
+ const String8& cameraId,
++ int api1CameraId,
+ int cameraFacing,
+ int clientPid,
+ uid_t clientUid,
+@@ -140,6 +141,8 @@ protected:
+
+ bool mDeviceActive;
+
++ const int mApi1CameraId; // -1 if client is API2
++
+ private:
+ template<typename TProviderPtr>
+ status_t initializeImpl(TProviderPtr providerPtr, const String8& monitorTags);
+diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
+index 4bc78dd..21cfd44 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 {
+
+@@ -39,9 +41,6 @@ const std::string kLegacyProviderName("legacy/0");
+ const std::string kExternalProviderName("external/0");
+ #endif
+
+-// Slash-separated list of provider types to consider for use via the old camera API
+-const std::string kStandardProviderTypes("internal/legacy");
+-
+ } // anonymous namespace
+
+ CameraProviderManager::HardwareServiceInteractionProxy
+@@ -83,18 +82,7 @@ int CameraProviderManager::getCameraCount() const {
+ 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;
+ }
+@@ -114,12 +102,33 @@ std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ std::vector<std::string> deviceIds;
+ for (auto& provider : mProviders) {
+- if (kStandardProviderTypes.find(provider->getType()) != std::string::npos) {
+- for (auto& id : provider->mUniqueAPI1CompatibleCameraIds) {
+- deviceIds.push_back(id);
+- }
+- }
++ std::vector<std::string> providerDeviceIds = provider->mUniqueAPI1CompatibleCameraIds;
++
++ // API1 app doesn't handle logical and physical camera devices well. So
++ // for each [logical, physical1, physical2, ...] id combo, only take the
++ // first id advertised by HAL, and filter out the rest.
++ filterLogicalCameraIdsLocked(providerDeviceIds);
++
++ deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end());
+ }
++
++ 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;
+ }
+
+@@ -172,11 +181,7 @@ status_t CameraProviderManager::getCameraInfo(const std::string &id,
+ status_t CameraProviderManager::getCameraCharacteristics(const std::string &id,
+ CameraMetadata* characteristics) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+-
+- auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
+- if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+-
+- return deviceInfo->getCameraCharacteristics(characteristics);
++ return getCameraCharacteristicsLocked(id, characteristics);
+ }
+
+ status_t CameraProviderManager::getHighestSupportedVersion(const std::string &id,
+@@ -391,6 +396,37 @@ metadata_vendor_id_t CameraProviderManager::getProviderTagIdLocked(
+ return ret;
+ }
+
++bool CameraProviderManager::isLogicalCamera(const CameraMetadata& staticInfo,
++ std::vector<std::string>* physicalCameraIds) {
++ bool isLogicalCam = false;
++ camera_metadata_ro_entry_t entryCap;
++
++ entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
++ for (size_t i = 0; i < entryCap.count; ++i) {
++ uint8_t capability = entryCap.data.u8[i];
++ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
++ isLogicalCam = true;
++ break;
++ }
++ }
++ if (!isLogicalCam) {
++ return false;
++ }
++
++ camera_metadata_ro_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
++ const uint8_t* ids = entryIds.data.u8;
++ size_t start = 0;
++ for (size_t i = 0; i < entryIds.count; ++i) {
++ if (ids[i] == '\0') {
++ if (start != i) {
++ physicalCameraIds->push_back((const char*)ids+start);
++ }
++ start = i+1;
++ }
++ }
++ return true;
++}
++
+ status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
+ for (const auto& providerInfo : mProviders) {
+ if (providerInfo->mProviderName == newProvider) {
+@@ -484,6 +520,8 @@ status_t CameraProviderManager::ProviderInfo::initialize() {
+ }
+ 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",
+@@ -540,17 +578,10 @@ status_t CameraProviderManager::ProviderInfo::initialize() {
+ }
+ }
+
+- 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;
+ }
+
+@@ -598,15 +629,36 @@ status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
+ }
+ 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.push_back(id);
++ }
++
+ if (parsedId != nullptr) {
+ *parsedId = id;
+ }
+ return OK;
+ }
+
++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(std::remove(
++ mUniqueAPI1CompatibleCameraIds.begin(),
++ mUniqueAPI1CompatibleCameraIds.end(), id));
++ }
++ mDevices.erase(it);
++ break;
++ }
++ }
++}
++
+ status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector<String16>&) const {
+ dprintf(fd, "== Camera Provider HAL %s (v2.4, %s) static info: %zu devices: ==\n",
+ mProviderName.c_str(), mInterface->isRemote() ? "remote" : "passthrough",
+@@ -666,6 +718,7 @@ hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusCh
+ CameraDeviceStatus newStatus) {
+ sp<StatusListener> listener;
+ std::string id;
++ bool initialized = false;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ bool known = false;
+@@ -688,11 +741,17 @@ hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusCh
+ return hardware::Void();
+ }
+ addDevice(cameraDeviceName, newStatus, &id);
++ } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
++ 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();
+@@ -1396,5 +1455,51 @@ status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
+ return OK;
+ }
+
++status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id,
++ CameraMetadata* characteristics) const {
++ auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
++ if (deviceInfo == nullptr) return NAME_NOT_FOUND;
++
++ return deviceInfo->getCameraCharacteristics(characteristics);
++}
++
++void CameraProviderManager::filterLogicalCameraIdsLocked(
++ std::vector<std::string>& deviceIds) const
++{
++ std::unordered_set<std::string> removedIds;
++
++ for (auto& deviceId : deviceIds) {
++ CameraMetadata info;
++ status_t res = getCameraCharacteristicsLocked(deviceId, &info);
++ if (res != OK) {
++ ALOGE("%s: Failed to getCameraCharacteristics for id %s", __FUNCTION__,
++ deviceId.c_str());
++ return;
++ }
++
++ // idCombo contains the ids of a logical camera and its physical cameras
++ std::vector<std::string> idCombo;
++ bool logicalCamera = CameraProviderManager::isLogicalCamera(info, &idCombo);
++ if (!logicalCamera) {
++ continue;
++ }
++ idCombo.push_back(deviceId);
++
++ for (auto& id : deviceIds) {
++ auto foundId = std::find(idCombo.begin(), idCombo.end(), id);
++ if (foundId == idCombo.end()) {
++ continue;
++ }
++
++ idCombo.erase(foundId);
++ removedIds.insert(idCombo.begin(), idCombo.end());
++ break;
++ }
++ }
++
++ deviceIds.erase(std::remove_if(deviceIds.begin(), deviceIds.end(),
++ [&removedIds](const std::string& s) {return removedIds.find(s) != removedIds.end();}),
++ deviceIds.end());
++}
+
+ } // namespace android
+diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
+index 0f1f07b..b8b8b8c 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 @@ public:
+ */
+ 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;
+
+ /**
+@@ -232,6 +230,13 @@ public:
+ hardware::hidl_version minVersion = hardware::hidl_version{0,0},
+ hardware::hidl_version maxVersion = hardware::hidl_version{1000,0}) const;
+
++ /*
++ * Check if a camera with staticInfo is a logical camera. And if yes, return
++ * the physical camera ids.
++ */
++ static bool isLogicalCamera(const CameraMetadata& staticInfo,
++ std::vector<std::string>* physicalCameraIds);
++
+ private:
+ // All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use
+ mutable std::mutex mInterfaceMutex;
+@@ -314,9 +319,9 @@ private:
+ 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::vector<std::string> mUniqueAPI1CompatibleCameraIds;
+
+ // HALv1-specific camera fields, including the actual device interface
+ struct DeviceInfo1 : public DeviceInfo {
+@@ -366,6 +371,8 @@ private:
+
+ CameraProviderManager *mManager;
+
++ bool mInitialized = false;
++
+ // Templated method to instantiate the right kind of DeviceInfo and call the
+ // right CameraProvider getCameraDeviceInterface_* method.
+ template<class DeviceInfoT>
+@@ -387,6 +394,8 @@ private:
+
+ // Generate vendor tag id
+ static metadata_vendor_id_t generateVendorTagId(const std::string &name);
++
++ void removeDevice(std::string id);
+ };
+
+ // Utility to find a DeviceInfo by ID; pointer is only valid while mInterfaceMutex is held
+@@ -412,6 +421,9 @@ private:
+ static const char* torchStatusToString(
+ const hardware::camera::common::V1_0::TorchModeStatus&);
+
++ status_t getCameraCharacteristicsLocked(const std::string &id,
++ CameraMetadata* characteristics) const;
++ void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
+ };
+
+ } // namespace android
+--
+2.7.4
+
diff --git a/patches/platform_frameworks_av/0001-FIH-devices-Fix-Earpiece-audio-output.patch b/patches/platform_frameworks_av/0002-FIH-devices-Fix-Earpiece-audio-output.patch
similarity index 96%
rename from patches/platform_frameworks_av/0001-FIH-devices-Fix-Earpiece-audio-output.patch
rename to patches/platform_frameworks_av/0002-FIH-devices-Fix-Earpiece-audio-output.patch
index 4a234aa..dbdbf37 100644
--- a/patches/platform_frameworks_av/0001-FIH-devices-Fix-Earpiece-audio-output.patch
+++ b/patches/platform_frameworks_av/0002-FIH-devices-Fix-Earpiece-audio-output.patch
@@ -1,7 +1,7 @@
-From 8d57e496a6e3252af1291a72113126270a8a87ec Mon Sep 17 00:00:00 2001
+From 7e9375da9c53bebe4e7390044b7c8cbd4d1f9d88 Mon Sep 17 00:00:00 2001
From: Pierre-Hugues Husson <phh@phh.me>
Date: Tue, 24 Apr 2018 00:14:28 +0200
-Subject: [PATCH 1/4] FIH devices: Fix "Earpiece" audio output
+Subject: [PATCH 2/5] FIH devices: Fix "Earpiece" audio output
On some FIH devices (confirmed on Razer, and probably on Aquos SS2),
Earpiece is not listed in attachedDevices, and devicePort's profile
diff --git a/patches/platform_frameworks_av/0002-Fix-WiFi-Display-on-Huawei-devices-EMUI-8.0.patch b/patches/platform_frameworks_av/0003-Fix-WiFi-Display-on-Huawei-devices-EMUI-8.0.patch
similarity index 86%
rename from patches/platform_frameworks_av/0002-Fix-WiFi-Display-on-Huawei-devices-EMUI-8.0.patch
rename to patches/platform_frameworks_av/0003-Fix-WiFi-Display-on-Huawei-devices-EMUI-8.0.patch
index 63114b4..321830f 100644
--- a/patches/platform_frameworks_av/0002-Fix-WiFi-Display-on-Huawei-devices-EMUI-8.0.patch
+++ b/patches/platform_frameworks_av/0003-Fix-WiFi-Display-on-Huawei-devices-EMUI-8.0.patch
@@ -1,7 +1,7 @@
-From 7d646a0485717ca51918de3869e4259e760e9b5e Mon Sep 17 00:00:00 2001
+From 7aa8d87cafe358617bfcb1999842c81dfbb6ae9d Mon Sep 17 00:00:00 2001
From: Alexander Pohl <pohl199885@gmail.com>
Date: Fri, 15 Jun 2018 19:58:07 +0200
-Subject: [PATCH 2/4] Fix WiFi-Display on Huawei devices (EMUI 8.0)
+Subject: [PATCH 3/5] Fix WiFi-Display on Huawei devices (EMUI 8.0)
Huaweis media stack doesn't handle intra-refresh-mode, so skip the error instead.
@@ -11,7 +11,7 @@
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
-index 7f39d10..ed54fb5 100644
+index 8949dae..fbee52b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -4279,9 +4279,8 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
diff --git a/patches/platform_frameworks_av/0003-Kirin-Remove-lock-to-prevent-self-lock.patch b/patches/platform_frameworks_av/0004-Kirin-Remove-lock-to-prevent-self-lock.patch
similarity index 88%
rename from patches/platform_frameworks_av/0003-Kirin-Remove-lock-to-prevent-self-lock.patch
rename to patches/platform_frameworks_av/0004-Kirin-Remove-lock-to-prevent-self-lock.patch
index 9ccaa41..0986aee 100644
--- a/patches/platform_frameworks_av/0003-Kirin-Remove-lock-to-prevent-self-lock.patch
+++ b/patches/platform_frameworks_av/0004-Kirin-Remove-lock-to-prevent-self-lock.patch
@@ -1,7 +1,7 @@
-From 50d1b8aad75fa641181a47da0fe14fafd6d5a7ed Mon Sep 17 00:00:00 2001
+From 05646ef62dfeb4286ce99ae50edd7c49510248ba Mon Sep 17 00:00:00 2001
From: Pierre-Hugues Husson <phh@phh.me>
Date: Sun, 19 Aug 2018 22:59:06 +0200
-Subject: [PATCH 3/4] ::Kirin:: Remove lock to prevent self-lock
+Subject: [PATCH 4/5] Kirin:: Remove lock to prevent self-lock
With Huawei Camera HAL, we get the following call order:
cameraserver CameraService::enumerateProviders (*)
@@ -17,7 +17,7 @@
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
-index c41de82..edbafbc 100644
+index de0fac5..e04b359 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -218,7 +218,7 @@ void CameraService::onNewProviderRegistered() {
diff --git a/patches/platform_frameworks_av/0004-We-might-not-have-a-mFlashlight-at-this-state-but-th.patch b/patches/platform_frameworks_av/0005-We-might-not-have-a-mFlashlight-at-this-state-but-th.patch
similarity index 84%
rename from patches/platform_frameworks_av/0004-We-might-not-have-a-mFlashlight-at-this-state-but-th.patch
rename to patches/platform_frameworks_av/0005-We-might-not-have-a-mFlashlight-at-this-state-but-th.patch
index 438f69a..7606db7 100644
--- a/patches/platform_frameworks_av/0004-We-might-not-have-a-mFlashlight-at-this-state-but-th.patch
+++ b/patches/platform_frameworks_av/0005-We-might-not-have-a-mFlashlight-at-this-state-but-th.patch
@@ -1,7 +1,7 @@
-From 817812fb440b18c27ae261cb06d7e4825ca92ae9 Mon Sep 17 00:00:00 2001
+From 962f7af622371eb8c0a170764facf92d9e1ddd74 Mon Sep 17 00:00:00 2001
From: Pierre-Hugues Husson <phh@phh.me>
Date: Sun, 19 Aug 2018 23:05:26 +0200
-Subject: [PATCH 4/4] We might not have a mFlashlight at this state, but that's
+Subject: [PATCH 5/5] We might not have a mFlashlight at this state, but that's
ok
---
@@ -9,7 +9,7 @@
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
-index edbafbc..222cfe4 100644
+index e04b359..178285d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -243,7 +243,7 @@ void CameraService::addStates(const String8 id) {