From 7b7ede7ebde2698472276e2962a0f77c9d07f3e7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 28 Nov 2017 09:28:56 +0100 Subject: [PATCH] Camera: Fix hotplug According to the camera_module_t::get_number_of_cameras() description in camera_common.h, it should only return the number of "fixed" cameras, i.e. cameras, facing to the front and to the back. Any cameras, with the facing value of "external," i.e. externally connected cameras, should not be reported by it, instead they should later be reported, using the camera_module_callbacks_t::camera_device_status_change() callback. However, this doesn't work. When a camera is reported this way, it is ignored as unknown. Fix this by adding a new camera, when its status change is reported. Change-Id: I18874ed005f477e32fb723c00c16b67a81cde6ce Signed-off-by: Guennadi Liakhovetski --- camera/device/3.2/default/CameraDevice.cpp | 4 +- .../provider/2.4/default/CameraProvider.cpp | 72 ++++++++++++------- camera/provider/2.4/default/CameraProvider.h | 3 + 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp index 295ee32865..dfbb9768a4 100644 --- a/camera/device/3.2/default/CameraDevice.cpp +++ b/camera/device/3.2/default/CameraDevice.cpp @@ -40,9 +40,11 @@ CameraDevice::CameraDevice( mCameraDeviceNames(cameraDeviceNames) { mCameraIdInt = atoi(mCameraId.c_str()); // Should not reach here as provider also validate ID - if (mCameraIdInt < 0 || mCameraIdInt >= module->getNumberOfCameras()) { + if (mCameraIdInt < 0) { ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str()); mInitFail = true; + } else if (mCameraIdInt >= mModule->getNumberOfCameras()) { + ALOGI("%s: Adding a new camera id: %s", __FUNCTION__, mCameraId.c_str()); } mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt); diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp index d50168a20b..3a113def25 100644 --- a/camera/provider/2.4/default/CameraProvider.cpp +++ b/camera/provider/2.4/default/CameraProvider.cpp @@ -64,6 +64,46 @@ bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion, using ::android::hardware::camera::common::V1_0::CameraMetadataType; using ::android::hardware::camera::common::V1_0::Status; +void CameraProvider::addDeviceNames(int camera_id, CameraDeviceStatus status, bool cam_new) +{ + char cameraId[kMaxCameraIdLen]; + snprintf(cameraId, sizeof(cameraId), "%d", camera_id); + std::string cameraIdStr(cameraId); + + mCameraIds.add(cameraIdStr); + + // initialize mCameraDeviceNames and mOpenLegacySupported + mOpenLegacySupported[cameraIdStr] = false; + int deviceVersion = mModule->getDeviceVersion(camera_id); + auto deviceNamePair = std::make_pair(cameraIdStr, + getHidlDeviceName(cameraIdStr, deviceVersion)); + mCameraDeviceNames.add(deviceNamePair); + if (cam_new) { + mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status); + } + if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 && + mModule->isOpenLegacyDefined()) { + // try open_legacy to see if it actually works + struct hw_device_t* halDev = nullptr; + int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev); + if (ret == 0) { + mOpenLegacySupported[cameraIdStr] = true; + halDev->close(halDev); + deviceNamePair = std::make_pair(cameraIdStr, + getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0)); + mCameraDeviceNames.add(deviceNamePair); + if (cam_new) { + mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status); + } + } else if (ret == -EBUSY || ret == -EUSERS) { + // Looks like this provider instance is not initialized during + // system startup and there are other camera users already. + // Not a good sign but not fatal. + ALOGW("%s: open_legacy try failed!", __FUNCTION__); + } + } +} + /** * static callback forwarding methods from HAL to instance */ @@ -73,6 +113,7 @@ void CameraProvider::sCameraDeviceStatusChange( int new_status) { CameraProvider* cp = const_cast( static_cast(callbacks)); + bool found = false; if (cp == nullptr) { ALOGE("%s: callback ops is null", __FUNCTION__); @@ -90,8 +131,13 @@ void CameraProvider::sCameraDeviceStatusChange( if (cameraIdStr.compare(deviceNamePair.first) == 0) { cp->mCallbacks->cameraDeviceStatusChange( deviceNamePair.second, status); + found = true; } } + + if (!found) { + cp->addDeviceNames(camera_id, status, true); + } } } @@ -244,32 +290,8 @@ bool CameraProvider::initialize() { snprintf(cameraId, sizeof(cameraId), "%d", i); std::string cameraIdStr(cameraId); mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT; - mCameraIds.add(cameraIdStr); - // initialize mCameraDeviceNames and mOpenLegacySupported - mOpenLegacySupported[cameraIdStr] = false; - int deviceVersion = mModule->getDeviceVersion(i); - mCameraDeviceNames.add( - std::make_pair(cameraIdStr, - getHidlDeviceName(cameraIdStr, deviceVersion))); - if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 && - mModule->isOpenLegacyDefined()) { - // try open_legacy to see if it actually works - struct hw_device_t* halDev = nullptr; - int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev); - if (ret == 0) { - mOpenLegacySupported[cameraIdStr] = true; - halDev->close(halDev); - mCameraDeviceNames.add( - std::make_pair(cameraIdStr, - getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0))); - } else if (ret == -EBUSY || ret == -EUSERS) { - // Looks like this provider instance is not initialized during - // system startup and there are other camera users already. - // Not a good sign but not fatal. - ALOGW("%s: open_legacy try failed!", __FUNCTION__); - } - } + addDeviceNames(i); } return false; // mInitFailed diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h index 4980711bcf..2cf251ec4b 100644 --- a/camera/provider/2.4/default/CameraProvider.h +++ b/camera/provider/2.4/default/CameraProvider.h @@ -112,6 +112,9 @@ private: const struct camera_module_callbacks* callbacks, const char* camera_id, int new_status); + + void addDeviceNames(int camera_id, CameraDeviceStatus status = CameraDeviceStatus::PRESENT, + bool cam_new = false); }; extern "C" ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name);