summaryrefslogtreecommitdiff
path: root/camera/provider
diff options
context:
space:
mode:
Diffstat (limited to 'camera/provider')
-rw-r--r--camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp154
-rw-r--r--camera/provider/2.7/default/Android.bp111
-rw-r--r--camera/provider/2.7/default/CameraProvider_2_7.h122
-rw-r--r--camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp393
-rw-r--r--camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.h134
-rw-r--r--camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service-lazy.rc13
-rw-r--r--camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service.rc11
-rw-r--r--camera/provider/2.7/default/external-service.cpp66
8 files changed, 850 insertions, 154 deletions
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index dd45b0dca8..8c44010441 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -969,7 +969,6 @@ public:
void getPrivacyTestPatternModes(
const camera_metadata_t* staticMetadata,
std::unordered_set<int32_t>* privacyTestPatternModes/*out*/);
- static bool isColorCamera(const camera_metadata_t *metadata);
static V3_2::DataspaceFlags getDataspace(PixelFormat format);
@@ -6880,142 +6879,6 @@ TEST_P(CameraHidlTest, configureInjectionStreamsWithSessionParameters) {
}
}
-// Test the multi-camera API requirement for Google Requirement Freeze S
-// Note that this requirement can only be partially tested. If a vendor
-// device doesn't expose a physical camera in any shape or form, there is no way
-// the test can catch it.
-TEST_P(CameraHidlTest, grfSMultiCameraTest) {
- const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1);
- if (socGrfApi < 31 /*S*/) {
- // Non-GRF devices, or version < 31 Skip
- ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi);
- return;
- }
-
- // Test that if more than one rear-facing color camera is
- // supported, there must be at least one rear-facing logical camera.
- hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
- // Back facing non-logical color cameras
- std::set<std::string> rearColorCameras;
- // Back facing logical cameras' physical camera Id sets
- std::set<std::set<std::string>> rearPhysicalIds;
- for (const auto& name : cameraDeviceNames) {
- std::string cameraId;
- int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId);
- switch (deviceVersion) {
- case CAMERA_DEVICE_API_VERSION_3_8:
- case CAMERA_DEVICE_API_VERSION_3_7:
- case CAMERA_DEVICE_API_VERSION_3_6:
- case CAMERA_DEVICE_API_VERSION_3_5:
- case CAMERA_DEVICE_API_VERSION_3_4:
- case CAMERA_DEVICE_API_VERSION_3_3:
- case CAMERA_DEVICE_API_VERSION_3_2: {
- ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
- ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
- Return<void> ret;
- ret = mProvider->getCameraDeviceInterface_V3_x(
- name, [&](auto status, const auto& device) {
- ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
- ASSERT_EQ(Status::OK, status);
- ASSERT_NE(device, nullptr);
- device3_x = device;
- });
- ASSERT_TRUE(ret.isOk());
-
- ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
- ASSERT_EQ(Status::OK, status);
- const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
-
- // Skip if this is not a color camera.
- if (!CameraHidlTest::isColorCamera(metadata)) {
- return;
- }
-
- // Check camera facing. Skip if facing is not BACK.
- // If this is not a logical camera, only note down
- // the camera ID, and skip.
- camera_metadata_ro_entry entry;
- int retcode = find_camera_metadata_ro_entry(
- metadata, ANDROID_LENS_FACING, &entry);
- ASSERT_EQ(retcode, 0);
- ASSERT_GT(entry.count, 0);
- uint8_t facing = entry.data.u8[0];
- bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK);
- if (facing != ANDROID_LENS_FACING_BACK) {
- // Not BACK facing. Skip.
- return;
- }
- if (!isLogicalCamera) {
- rearColorCameras.insert(cameraId);
- return;
- }
-
- // Check logical camera's physical camera IDs for color
- // cameras.
- std::unordered_set<std::string> physicalCameraIds;
- Status s = getPhysicalCameraIds(metadata, &physicalCameraIds);
- ASSERT_EQ(Status::OK, s);
- rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
- for (const auto& physicalId : physicalCameraIds) {
- // Skip if the physicalId is publicly available
- for (auto& deviceName : cameraDeviceNames) {
- std::string publicVersion, publicId;
- ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType,
- &publicVersion, &publicId));
- if (physicalId == publicId) {
- // Skip because public Ids will be iterated in outer loop.
- return;
- }
- }
-
- auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x);
- ASSERT_TRUE(castResult.isOk());
- ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice>
- device3_5 = castResult;
- ASSERT_NE(device3_5, nullptr);
-
- // Check camera characteristics for hidden camera id
- Return<void> ret = device3_5->getPhysicalCameraCharacteristics(
- physicalId, [&](auto status, const auto& chars) {
- ASSERT_EQ(Status::OK, status);
- const camera_metadata_t* physicalMetadata =
- (camera_metadata_t*)chars.data();
-
- if (CameraHidlTest::isColorCamera(physicalMetadata)) {
- rearColorCameras.insert(physicalId);
- }
- });
- ASSERT_TRUE(ret.isOk());
- }
- });
- ASSERT_TRUE(ret.isOk());
- } break;
- case CAMERA_DEVICE_API_VERSION_1_0: {
- // Not applicable
- } break;
- default: {
- ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
- ADD_FAILURE();
- } break;
- }
- }
-
- // If there are more than one rear-facing color camera, a logical
- // multi-camera must be defined consisting of all rear-facing color
- // cameras.
- if (rearColorCameras.size() > 1) {
- bool hasRearLogical = false;
- for (const auto& physicalIds : rearPhysicalIds) {
- if (std::includes(physicalIds.begin(), physicalIds.end(),
- rearColorCameras.begin(), rearColorCameras.end())) {
- hasRearLogical = true;
- break;
- }
- }
- ASSERT_TRUE(hasRearLogical);
- }
-}
-
// Retrieve all valid output stream resolutions from the camera
// static characteristics.
Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
@@ -7523,23 +7386,6 @@ Status CameraHidlTest::isMonochromeCamera(const camera_metadata_t *staticMeta) {
return ret;
}
-bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) {
- camera_metadata_ro_entry entry;
- int retcode = find_camera_metadata_ro_entry(
- metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
- if ((0 == retcode) && (entry.count > 0)) {
- bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count,
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) !=
- entry.data.u8 + entry.count);
- bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count,
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) !=
- entry.data.u8 + entry.count);
- bool isColor = isBackwardCompatible && !isMonochrome;
- return isColor;
- }
- return false;
-}
-
// Retrieve the reprocess input-output format map from the static
// camera characteristics.
Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta,
diff --git a/camera/provider/2.7/default/Android.bp b/camera/provider/2.7/default/Android.bp
new file mode 100644
index 0000000000..bd5da2dbfa
--- /dev/null
+++ b/camera/provider/2.7/default/Android.bp
@@ -0,0 +1,111 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_shared {
+ name: "android.hardware.camera.provider@2.7-external",
+ proprietary: true,
+ srcs: ["ExternalCameraProviderImpl_2_7.cpp"],
+ shared_libs: [
+ "android.hardware.camera.common@1.0",
+ "android.hardware.camera.device@1.0",
+ "android.hardware.camera.device@3.2",
+ "android.hardware.camera.device@3.3",
+ "android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.5",
+ "android.hardware.camera.device@3.6",
+ "android.hardware.camera.provider@2.4",
+ "android.hardware.camera.provider@2.5",
+ "android.hardware.camera.provider@2.6",
+ "android.hardware.camera.provider@2.7",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.mapper@4.0",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ "camera.device@3.3-impl",
+ "camera.device@3.4-external-impl",
+ "camera.device@3.4-impl",
+ "camera.device@3.5-external-impl",
+ "camera.device@3.5-impl",
+ "camera.device@3.6-external-impl",
+ "libcamera_metadata",
+ "libcutils",
+ "libhardware",
+ "libhidlbase",
+ "liblog",
+ "libtinyxml2",
+ "libutils",
+ ],
+ static_libs: [
+ "android.hardware.camera.common@1.0-helper",
+ ],
+ header_libs: [
+ "camera.device@3.4-external-impl_headers",
+ "camera.device@3.5-external-impl_headers",
+ "camera.device@3.6-external-impl_headers",
+ ],
+ export_include_dirs: ["."],
+}
+
+cc_defaults {
+ name: "camera_external_service_2_7_defaults",
+ defaults: ["hidl_defaults"],
+ proprietary: true,
+ relative_install_path: "hw",
+ srcs: ["external-service.cpp"],
+ compile_multilib: "32",
+ shared_libs: [
+ "android.hardware.camera.common@1.0",
+ "android.hardware.camera.device@1.0",
+ "android.hardware.camera.device@3.2",
+ "android.hardware.camera.device@3.3",
+ "android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.5",
+ "android.hardware.camera.provider@2.4",
+ "android.hardware.camera.provider@2.4-external",
+ "android.hardware.camera.provider@2.5",
+ "android.hardware.camera.provider@2.5-external",
+ "android.hardware.camera.provider@2.6",
+ "android.hardware.camera.provider@2.7",
+ "android.hardware.camera.provider@2.7-external",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.mapper@4.0",
+ "libbinder",
+ "libcamera_metadata",
+ "libhidlbase",
+ "liblog",
+ "libtinyxml2",
+ "libutils",
+ ],
+ static_libs: [
+ "android.hardware.camera.common@1.0-helper",
+ ],
+ header_libs: [
+ "camera.device@3.4-external-impl_headers",
+ "camera.device@3.4-impl_headers",
+ "camera.device@3.5-external-impl_headers",
+ "camera.device@3.5-impl_headers",
+ "camera.device@3.6-external-impl_headers",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.camera.provider@2.7-external-service",
+ defaults: ["camera_external_service_2_7_defaults"],
+ init_rc: ["android.hardware.camera.provider@2.7-external-service.rc"],
+}
+
+cc_binary {
+ name: "android.hardware.camera.provider@2.7-external-service-lazy",
+ overrides: ["android.hardware.camera.provider@2.7-external-service"],
+ defaults: ["camera_external_service_2_7_defaults"],
+ init_rc: ["android.hardware.camera.provider@2.7-external-service-lazy.rc"],
+ cflags: ["-DLAZY_SERVICE"],
+}
diff --git a/camera/provider/2.7/default/CameraProvider_2_7.h b/camera/provider/2.7/default/CameraProvider_2_7.h
new file mode 100644
index 0000000000..c34905f3f3
--- /dev/null
+++ b/camera/provider/2.7/default/CameraProvider_2_7.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_CAMERAPROVIDER_H
+#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_CAMERAPROVIDER_H
+
+#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
+#include <android/hardware/camera/provider/2.7/ICameraProvider.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_7 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::TorchModeStatus;
+using ::android::hardware::camera::common::V1_0::VendorTag;
+using ::android::hardware::camera::common::V1_0::VendorTagSection;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::camera::provider::V2_5::DeviceState;
+using ::android::hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
+using ::android::hardware::camera::provider::V2_7::ICameraProvider;
+using ::android::hidl::base::V1_0::IBase;
+
+// Default recommended RPC thread count for camera provider implementations
+const int HWBINDER_THREAD_COUNT = 6;
+
+template <typename IMPL>
+struct CameraProvider : public ICameraProvider {
+ CameraProvider() : impl() {}
+ ~CameraProvider() {}
+
+ // Caller must use this method to check if CameraProvider ctor failed
+ bool isInitFailed() { return impl.isInitFailed(); }
+
+ // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
+ Return<Status> setCallback(const sp<ICameraProviderCallback>& callback) override {
+ return impl.setCallback(callback);
+ }
+
+ Return<void> getVendorTags(getVendorTags_cb _hidl_cb) override {
+ return impl.getVendorTags(_hidl_cb);
+ }
+
+ Return<void> getCameraIdList(getCameraIdList_cb _hidl_cb) override {
+ return impl.getCameraIdList(_hidl_cb);
+ }
+
+ Return<void> isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override {
+ return impl.isSetTorchModeSupported(_hidl_cb);
+ }
+
+ Return<void> getCameraDeviceInterface_V1_x(const hidl_string& cameraDeviceName,
+ getCameraDeviceInterface_V1_x_cb _hidl_cb) override {
+ return impl.getCameraDeviceInterface_V1_x(cameraDeviceName, _hidl_cb);
+ }
+
+ Return<void> getCameraDeviceInterface_V3_x(const hidl_string& cameraDeviceName,
+ getCameraDeviceInterface_V3_x_cb _hidl_cb) override {
+ return impl.getCameraDeviceInterface_V3_x(cameraDeviceName, _hidl_cb);
+ }
+
+ // Methods from ::android::hardware::camera::provider::V2_5::ICameraProvider follow.
+ Return<void> notifyDeviceStateChange(hardware::hidl_bitfield<DeviceState> newState) override {
+ return impl.notifyDeviceStateChange(newState);
+ }
+
+ // Methods from ::android::hardware::camera::provider::V2_7::ICameraProvider follow.
+ Return<void> getConcurrentStreamingCameraIds(
+ getConcurrentStreamingCameraIds_cb _hidl_cb) override {
+ return impl.getConcurrentStreamingCameraIds(_hidl_cb);
+ }
+
+ Return<void> isConcurrentStreamCombinationSupported(
+ const hidl_vec<
+ ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination>&
+ configs,
+ isConcurrentStreamCombinationSupported_cb _hidl_cb) override {
+ return impl.isConcurrentStreamCombinationSupported(configs, _hidl_cb);
+ }
+
+ Return<void> isConcurrentStreamCombinationSupported_2_7(
+ const hidl_vec<CameraIdAndStreamCombination>& configs,
+ isConcurrentStreamCombinationSupported_2_7_cb _hidl_cb) override {
+ return impl.isConcurrentStreamCombinationSupported_2_7(configs, _hidl_cb);
+ }
+
+ private:
+ IMPL impl;
+};
+
+} // namespace implementation
+} // namespace V2_7
+} // namespace provider
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H \ No newline at end of file
diff --git a/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
new file mode 100644
index 0000000000..b63e3bb88b
--- /dev/null
+++ b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CamPrvdr@2.7-external"
+//#define LOG_NDEBUG 0
+#include <log/log.h>
+
+#include <cutils/properties.h>
+#include <errno.h>
+#include <linux/videodev2.h>
+#include <sys/inotify.h>
+#include <regex>
+#include "ExternalCameraDevice_3_4.h"
+#include "ExternalCameraDevice_3_5.h"
+#include "ExternalCameraDevice_3_6.h"
+#include "ExternalCameraProviderImpl_2_7.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_7 {
+namespace implementation {
+
+namespace {
+// "device@<version>/external/<id>"
+const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
+const int kMaxDevicePathLen = 256;
+const char* kDevicePath = "/dev/";
+constexpr char kPrefix[] = "video";
+constexpr int kPrefixLen = sizeof(kPrefix) - 1;
+constexpr int kDevicePrefixLen = sizeof(kDevicePath) + kPrefixLen + 1;
+
+bool matchDeviceName(int cameraIdOffset, const hidl_string& deviceName, std::string* deviceVersion,
+ std::string* cameraDevicePath) {
+ std::string deviceNameStd(deviceName.c_str());
+ std::smatch sm;
+ if (std::regex_match(deviceNameStd, sm, kDeviceNameRE)) {
+ if (deviceVersion != nullptr) {
+ *deviceVersion = sm[1];
+ }
+ if (cameraDevicePath != nullptr) {
+ *cameraDevicePath = "/dev/video" + std::to_string(std::stoi(sm[2]) - cameraIdOffset);
+ }
+ return true;
+ }
+ return false;
+}
+
+} // anonymous namespace
+
+ExternalCameraProviderImpl_2_7::ExternalCameraProviderImpl_2_7()
+ : mCfg(ExternalCameraConfig::loadFromCfg()) {
+ mHotPlugThread = sp<HotplugThread>::make(this);
+ mHotPlugThread->run("ExtCamHotPlug", PRIORITY_BACKGROUND);
+
+ mPreferredHal3MinorVersion =
+ property_get_int32("ro.vendor.camera.external.hal3TrebleMinorVersion", 4);
+ ALOGV("Preferred HAL 3 minor version is %d", mPreferredHal3MinorVersion);
+ switch (mPreferredHal3MinorVersion) {
+ case 4:
+ case 5:
+ case 6:
+ // OK
+ break;
+ default:
+ ALOGW("Unknown minor camera device HAL version %d in property "
+ "'camera.external.hal3TrebleMinorVersion', defaulting to 4",
+ mPreferredHal3MinorVersion);
+ mPreferredHal3MinorVersion = 4;
+ }
+}
+
+ExternalCameraProviderImpl_2_7::~ExternalCameraProviderImpl_2_7() {
+ mHotPlugThread->requestExit();
+}
+
+Return<Status> ExternalCameraProviderImpl_2_7::setCallback(
+ const sp<ICameraProviderCallback>& callback) {
+ Mutex::Autolock _l(mLock);
+ mCallbacks = callback;
+ if (mCallbacks == nullptr) {
+ return Status::OK;
+ }
+ // Send a callback for all devices to initialize
+ {
+ for (const auto& pair : mCameraStatusMap) {
+ mCallbacks->cameraDeviceStatusChange(pair.first, pair.second);
+ }
+ }
+
+ return Status::OK;
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getVendorTags(
+ ICameraProvider::getVendorTags_cb _hidl_cb) {
+ // No vendor tag support for USB camera
+ hidl_vec<VendorTagSection> zeroSections;
+ _hidl_cb(Status::OK, zeroSections);
+ return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getCameraIdList(
+ ICameraProvider::getCameraIdList_cb _hidl_cb) {
+ // External camera HAL always report 0 camera, and extra cameras
+ // are just reported via cameraDeviceStatusChange callbacks
+ hidl_vec<hidl_string> hidlDeviceNameList;
+ _hidl_cb(Status::OK, hidlDeviceNameList);
+ return Void();
+}
+
+void ExternalCameraProviderImpl_2_7::updateAttachedCameras() {
+ ALOGV("%s start scaning for existing V4L2 devices", __FUNCTION__);
+ // Find existing /dev/video* devices
+ DIR* devdir = opendir(kDevicePath);
+ if (devdir == 0) {
+ ALOGE("%s: cannot open %s! Exiting threadloop", __FUNCTION__, kDevicePath);
+ return;
+ }
+
+ struct dirent* de;
+ while ((de = readdir(devdir)) != 0) {
+ // Find external v4l devices that's existing before we start watching and add them
+ if (!strncmp(kPrefix, de->d_name, kPrefixLen)) {
+ // TODO: This might reject some valid devices. Ex: internal is 33 and a device named 3
+ // is added.
+ std::string deviceId(de->d_name + kPrefixLen);
+ if (mCfg.mInternalDevices.count(deviceId) == 0) {
+ ALOGV("Non-internal v4l device %s found", de->d_name);
+ char v4l2DevicePath[kMaxDevicePathLen];
+ snprintf(v4l2DevicePath, kMaxDevicePathLen, "%s%s", kDevicePath, de->d_name);
+ deviceAdded(v4l2DevicePath);
+ }
+ }
+ }
+ closedir(devdir);
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::isSetTorchModeSupported(
+ ICameraProvider::isSetTorchModeSupported_cb _hidl_cb) {
+ // setTorchMode API is supported, though right now no external camera device
+ // has a flash unit.
+ _hidl_cb(Status::OK, true);
+ return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getCameraDeviceInterface_V1_x(
+ const hidl_string&, ICameraProvider::getCameraDeviceInterface_V1_x_cb _hidl_cb) {
+ // External Camera HAL does not support HAL1
+ _hidl_cb(Status::OPERATION_NOT_SUPPORTED, nullptr);
+ return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getCameraDeviceInterface_V3_x(
+ const hidl_string& cameraDeviceName,
+ ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb) {
+ std::string cameraDevicePath, deviceVersion;
+ bool match = matchDeviceName(mCfg.cameraIdOffset, cameraDeviceName, &deviceVersion,
+ &cameraDevicePath);
+ if (!match) {
+ _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+ return Void();
+ }
+
+ if (mCameraStatusMap.count(cameraDeviceName) == 0 ||
+ mCameraStatusMap[cameraDeviceName] != CameraDeviceStatus::PRESENT) {
+ _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+ return Void();
+ }
+
+ sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl;
+ switch (mPreferredHal3MinorVersion) {
+ case 4: {
+ ALOGV("Constructing v3.4 external camera device");
+ deviceImpl =
+ new device::V3_4::implementation::ExternalCameraDevice(cameraDevicePath, mCfg);
+ break;
+ }
+ case 5: {
+ ALOGV("Constructing v3.5 external camera device");
+ deviceImpl =
+ new device::V3_5::implementation::ExternalCameraDevice(cameraDevicePath, mCfg);
+ break;
+ }
+ case 6: {
+ ALOGV("Constructing v3.6 external camera device");
+ deviceImpl =
+ new device::V3_6::implementation::ExternalCameraDevice(cameraDevicePath, mCfg);
+ break;
+ }
+ default:
+ ALOGE("%s: Unknown HAL minor version %d!", __FUNCTION__, mPreferredHal3MinorVersion);
+ _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+ return Void();
+ }
+
+ if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
+ ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraDevicePath.c_str());
+ _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+ return Void();
+ }
+
+ IF_ALOGV() {
+ deviceImpl->getInterface()->interfaceChain(
+ [](::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+ ALOGV("Device interface chain:");
+ for (auto iface : interfaceChain) {
+ ALOGV(" %s", iface.c_str());
+ }
+ });
+ }
+
+ _hidl_cb(Status::OK, deviceImpl->getInterface());
+
+ return Void();
+}
+
+void ExternalCameraProviderImpl_2_7::addExternalCamera(const char* devName) {
+ ALOGV("ExtCam: adding %s to External Camera HAL!", devName);
+ Mutex::Autolock _l(mLock);
+ std::string deviceName;
+ std::string cameraId =
+ std::to_string(mCfg.cameraIdOffset + std::atoi(devName + kDevicePrefixLen));
+ if (mPreferredHal3MinorVersion == 6) {
+ deviceName = std::string("device@3.6/external/") + cameraId;
+ } else if (mPreferredHal3MinorVersion == 5) {
+ deviceName = std::string("device@3.5/external/") + cameraId;
+ } else {
+ deviceName = std::string("device@3.4/external/") + cameraId;
+ }
+ mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
+ if (mCallbacks != nullptr) {
+ mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::PRESENT);
+ }
+}
+
+void ExternalCameraProviderImpl_2_7::deviceAdded(const char* devName) {
+ {
+ base::unique_fd fd(::open(devName, O_RDWR));
+ if (fd.get() < 0) {
+ ALOGE("%s open v4l2 device %s failed:%s", __FUNCTION__, devName, strerror(errno));
+ return;
+ }
+
+ struct v4l2_capability capability;
+ int ret = ioctl(fd.get(), VIDIOC_QUERYCAP, &capability);
+ if (ret < 0) {
+ ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName);
+ return;
+ }
+
+ if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) {
+ ALOGW("%s device %s does not support VIDEO_CAPTURE", __FUNCTION__, devName);
+ return;
+ }
+ }
+ // See if we can initialize ExternalCameraDevice correctly
+ sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl =
+ new device::V3_4::implementation::ExternalCameraDevice(devName, mCfg);
+ if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
+ ALOGW("%s: Attempt to init camera device %s failed!", __FUNCTION__, devName);
+ return;
+ }
+ deviceImpl.clear();
+
+ addExternalCamera(devName);
+ return;
+}
+
+void ExternalCameraProviderImpl_2_7::deviceRemoved(const char* devName) {
+ Mutex::Autolock _l(mLock);
+ std::string deviceName;
+ std::string cameraId =
+ std::to_string(mCfg.cameraIdOffset + std::atoi(devName + kDevicePrefixLen));
+ if (mPreferredHal3MinorVersion == 6) {
+ deviceName = std::string("device@3.6/external/") + cameraId;
+ } else if (mPreferredHal3MinorVersion == 5) {
+ deviceName = std::string("device@3.5/external/") + cameraId;
+ } else {
+ deviceName = std::string("device@3.4/external/") + cameraId;
+ }
+ if (mCameraStatusMap.erase(deviceName) != 0) {
+ if (mCallbacks != nullptr) {
+ mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::NOT_PRESENT);
+ }
+ } else {
+ ALOGE("%s: cannot find camera device %s", __FUNCTION__, devName);
+ }
+}
+
+ExternalCameraProviderImpl_2_7::HotplugThread::HotplugThread(ExternalCameraProviderImpl_2_7* parent)
+ : Thread(/*canCallJava*/ false),
+ mParent(parent),
+ mInternalDevices(parent->mCfg.mInternalDevices) {}
+
+ExternalCameraProviderImpl_2_7::HotplugThread::~HotplugThread() {}
+
+bool ExternalCameraProviderImpl_2_7::HotplugThread::threadLoop() {
+ // Update existing cameras
+ mParent->updateAttachedCameras();
+
+ // Watch new video devices
+ mINotifyFD = inotify_init();
+ if (mINotifyFD < 0) {
+ ALOGE("%s: inotify init failed! Exiting threadloop", __FUNCTION__);
+ return true;
+ }
+
+ mWd = inotify_add_watch(mINotifyFD, kDevicePath, IN_CREATE | IN_DELETE);
+ if (mWd < 0) {
+ ALOGE("%s: inotify add watch failed! Exiting threadloop", __FUNCTION__);
+ return true;
+ }
+
+ bool done = false;
+ char eventBuf[512];
+ while (!done) {
+ int offset = 0;
+ int ret = read(mINotifyFD, eventBuf, sizeof(eventBuf));
+ if (ret >= (int)sizeof(struct inotify_event)) {
+ while (offset < ret) {
+ struct inotify_event* event = (struct inotify_event*)&eventBuf[offset];
+ if (event->wd == mWd) {
+ ALOGV("%s inotify_event %s", __FUNCTION__, event->name);
+ if (!strncmp(kPrefix, event->name, kPrefixLen)) {
+ std::string deviceId(event->name + kPrefixLen);
+ if (mInternalDevices.count(deviceId) == 0) {
+ char v4l2DevicePath[kMaxDevicePathLen];
+ snprintf(v4l2DevicePath, kMaxDevicePathLen, "%s%s", kDevicePath,
+ event->name);
+ if (event->mask & IN_CREATE) {
+ mParent->deviceAdded(v4l2DevicePath);
+ }
+ if (event->mask & IN_DELETE) {
+ mParent->deviceRemoved(v4l2DevicePath);
+ }
+ }
+ }
+ }
+ offset += sizeof(struct inotify_event) + event->len;
+ }
+ }
+ }
+
+ return true;
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::notifyDeviceStateChange(
+ hidl_bitfield<DeviceState> /*newState*/) {
+ return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getConcurrentStreamingCameraIds(
+ ICameraProvider::getConcurrentStreamingCameraIds_cb _hidl_cb) {
+ hidl_vec<hidl_vec<hidl_string>> hidl_camera_id_combinations;
+ _hidl_cb(Status::OK, hidl_camera_id_combinations);
+ return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::isConcurrentStreamCombinationSupported(
+ const hidl_vec<::android::hardware::camera::provider::V2_6::
+ CameraIdAndStreamCombination>& /* configs */,
+ ICameraProvider::isConcurrentStreamCombinationSupported_cb _hidl_cb) {
+ _hidl_cb(Status::OK, false);
+ return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::isConcurrentStreamCombinationSupported_2_7(
+ const hidl_vec<CameraIdAndStreamCombination>& /* configs */,
+ ICameraProvider::isConcurrentStreamCombinationSupported_2_7_cb _hidl_cb) {
+ _hidl_cb(Status::OK, false);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_7
+} // namespace provider
+} // namespace camera
+} // namespace hardware
+} // namespace android
diff --git a/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.h b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.h
new file mode 100644
index 0000000000..da9f6b3a91
--- /dev/null
+++ b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_EXTCAMERAPROVIDER_H
+#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_EXTCAMERAPROVIDER_H
+
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <utils/Mutex.h>
+#include <utils/Thread.h>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include "ExternalCameraUtils.h"
+
+#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
+#include <android/hardware/camera/provider/2.7/ICameraProvider.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_7 {
+namespace implementation {
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::VendorTagSection;
+using ::android::hardware::camera::external::common::ExternalCameraConfig;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::camera::provider::V2_5::DeviceState;
+using ::android::hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
+using ::android::hardware::camera::provider::V2_7::ICameraProvider;
+using ::android::hidl::base::V1_0::IBase;
+
+/**
+ * The implementation of external webcam CameraProvider 2.7, separated
+ * from the HIDL interface layer to allow for implementation reuse by later
+ * provider versions.
+ *
+ * This camera provider supports standard UVC webcameras via the Linux V4L2
+ * UVC driver.
+ */
+struct ExternalCameraProviderImpl_2_7 {
+ ExternalCameraProviderImpl_2_7();
+ ~ExternalCameraProviderImpl_2_7();
+
+ // Caller must use this method to check if CameraProvider ctor failed
+ bool isInitFailed() { return false; }
+
+ // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
+ Return<Status> setCallback(const sp<ICameraProviderCallback>& callback);
+ Return<void> getVendorTags(ICameraProvider::getVendorTags_cb _hidl_cb);
+ Return<void> getCameraIdList(ICameraProvider::getCameraIdList_cb _hidl_cb);
+ Return<void> isSetTorchModeSupported(ICameraProvider::isSetTorchModeSupported_cb _hidl_cb);
+ Return<void> getCameraDeviceInterface_V1_x(const hidl_string&,
+ ICameraProvider::getCameraDeviceInterface_V1_x_cb);
+ Return<void> getCameraDeviceInterface_V3_x(const hidl_string&,
+ ICameraProvider::getCameraDeviceInterface_V3_x_cb);
+
+ // Methods from ::android::hardware::camera::provider::V2_5::ICameraProvider follow.
+ Return<void> notifyDeviceStateChange(hidl_bitfield<DeviceState> newState);
+
+ // Methods from ::android::hardware::camera::provider::V2_7::ICameraProvider follow.
+ Return<void> getConcurrentStreamingCameraIds(
+ ICameraProvider::getConcurrentStreamingCameraIds_cb _hidl_cb);
+
+ Return<void> isConcurrentStreamCombinationSupported(
+ const hidl_vec<
+ ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination>&
+ configs,
+ ICameraProvider::isConcurrentStreamCombinationSupported_cb _hidl_cb);
+
+ Return<void> isConcurrentStreamCombinationSupported_2_7(
+ const hidl_vec<CameraIdAndStreamCombination>& configs,
+ ICameraProvider::isConcurrentStreamCombinationSupported_2_7_cb _hidl_cb);
+
+ private:
+ void addExternalCamera(const char* devName);
+
+ void deviceAdded(const char* devName);
+
+ void deviceRemoved(const char* devName);
+
+ void updateAttachedCameras();
+
+ class HotplugThread : public android::Thread {
+ public:
+ HotplugThread(ExternalCameraProviderImpl_2_7* parent);
+ ~HotplugThread();
+
+ virtual bool threadLoop() override;
+
+ private:
+ ExternalCameraProviderImpl_2_7* mParent = nullptr;
+ const std::unordered_set<std::string> mInternalDevices;
+
+ int mINotifyFD = -1;
+ int mWd = -1;
+ };
+
+ Mutex mLock;
+ sp<ICameraProviderCallback> mCallbacks = nullptr;
+ std::unordered_map<std::string, CameraDeviceStatus> mCameraStatusMap; // camera id -> status
+ const ExternalCameraConfig mCfg;
+ sp<HotplugThread> mHotPlugThread;
+ int mPreferredHal3MinorVersion;
+};
+
+} // namespace implementation
+} // namespace V2_7
+} // namespace provider
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_EXTCAMERAPROVIDER_H
diff --git a/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service-lazy.rc b/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service-lazy.rc
new file mode 100644
index 0000000000..9292c4f959
--- /dev/null
+++ b/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service-lazy.rc
@@ -0,0 +1,13 @@
+service vendor.camera-provider-2-7-ext /vendor/bin/hw/android.hardware.camera.provider@2.7-external-service-lazy
+ interface android.hardware.camera.provider@2.4::ICameraProvider external/0
+ interface android.hardware.camera.provider@2.5::ICameraProvider external/0
+ interface android.hardware.camera.provider@2.6::ICameraProvider external/0
+ interface android.hardware.camera.provider@2.7::ICameraProvider external/0
+ class hal
+ oneshot
+ disabled
+ user cameraserver
+ group audio camera input drmrpc usb
+ ioprio rt 4
+ capabilities SYS_NICE
+ task_profiles CameraServiceCapacity MaxPerformance \ No newline at end of file
diff --git a/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service.rc b/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service.rc
new file mode 100644
index 0000000000..2c9b782c1c
--- /dev/null
+++ b/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service.rc
@@ -0,0 +1,11 @@
+service vendor.camera-provider-2-7-ext /vendor/bin/hw/android.hardware.camera.provider@2.7-external-service
+ interface android.hardware.camera.provider@2.4::ICameraProvider external/0
+ interface android.hardware.camera.provider@2.5::ICameraProvider external/0
+ interface android.hardware.camera.provider@2.6::ICameraProvider external/0
+ interface android.hardware.camera.provider@2.7::ICameraProvider external/0
+ class hal
+ user cameraserver
+ group audio camera input drmrpc usb
+ ioprio rt 4
+ capabilities SYS_NICE
+ task_profiles CameraServiceCapacity MaxPerformance
diff --git a/camera/provider/2.7/default/external-service.cpp b/camera/provider/2.7/default/external-service.cpp
new file mode 100644
index 0000000000..90b823970f
--- /dev/null
+++ b/camera/provider/2.7/default/external-service.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef LAZY_SERVICE
+#define LOG_TAG "android.hardware.camera.provider@2.7-external-service-lazy"
+#else
+#define LOG_TAG "android.hardware.camera.provider@2.7-external-service"
+#endif
+
+#include <android/hardware/camera/provider/2.7/ICameraProvider.h>
+#include <binder/ProcessState.h>
+#include <hidl/HidlLazyUtils.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "CameraProvider_2_7.h"
+#include "ExternalCameraProviderImpl_2_7.h"
+
+using android::status_t;
+using android::hardware::camera::provider::V2_7::ICameraProvider;
+using android::hidl::base::V1_0::IBase;
+
+#ifdef LAZY_SERVICE
+const bool kLazyService = true;
+#else
+const bool kLazyService = false;
+#endif
+
+int main() {
+ using namespace android::hardware::camera::provider::V2_7::implementation;
+
+ ALOGI("CameraProvider@2.7 external webcam service is starting.");
+
+ ::android::hardware::configureRpcThreadpool(/*threads*/ HWBINDER_THREAD_COUNT,
+ /*willJoin*/ true);
+
+ ::android::sp<CameraProvider<ExternalCameraProviderImpl_2_7>> provider =
+ new CameraProvider<ExternalCameraProviderImpl_2_7>();
+
+ status_t status;
+ if (kLazyService) {
+ auto serviceRegistrar = ::android::hardware::LazyServiceRegistrar::getInstance();
+ status = serviceRegistrar.registerService(provider, "external/0");
+ } else {
+ status = provider->registerAsService("external/0");
+ }
+
+ LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering provider service: %d",
+ status);
+
+ ::android::hardware::joinRpcThreadpool();
+
+ return 0;
+} \ No newline at end of file