/* * Copyright (C) 2016 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_NDEBUG 0 #define LOG_TAG "CameraProviderManagerTest" #include "../common/CameraProviderManager.h" #include #include #include #include #include #include using namespace android; using namespace android::hardware::camera; using android::hardware::camera::common::V1_0::Status; using android::hardware::camera::common::V1_0::VendorTag; using android::hardware::camera::common::V1_0::VendorTagSection; using android::hardware::camera::common::V1_0::CameraMetadataType; using android::hardware::camera::device::V3_2::ICameraDeviceCallback; using android::hardware::camera::device::V3_2::ICameraDeviceSession; using android::hardware::camera::provider::V2_5::DeviceState; /** * Basic test implementation of a camera ver. 3.2 device interface */ struct TestDeviceInterface : public device::V3_2::ICameraDevice { std::vector mDeviceNames; TestDeviceInterface(std::vector deviceNames) : mDeviceNames(deviceNames) {} using getResourceCost_cb = std::function; virtual ::android::hardware::Return getResourceCost( getResourceCost_cb _hidl_cb) override { hardware::camera::common::V1_0::CameraResourceCost resourceCost = {100, mDeviceNames}; _hidl_cb(Status::OK, resourceCost); return hardware::Void(); } using getCameraCharacteristics_cb = std::function& cameraCharacteristics)>; hardware::Return getCameraCharacteristics( getCameraCharacteristics_cb _hidl_cb) override { hardware::hidl_vec cameraCharacteristics; _hidl_cb(Status::OK, cameraCharacteristics); return hardware::Void(); } hardware::Return setTorchMode( ::android::hardware::camera::common::V1_0::TorchMode) override { return Status::OK; } using open_cb = std::function& session)>; hardware::Return open( const ::android::sp&, open_cb _hidl_cb) override { sp deviceSession = nullptr; _hidl_cb(Status::OK, deviceSession); return hardware::Void(); } hardware::Return dumpState( const ::android::hardware::hidl_handle&) override { return hardware::Void(); } }; /** * Basic test implementation of a camera provider */ struct TestICameraProvider : virtual public provider::V2_5::ICameraProvider { sp mCallbacks; std::vector mDeviceNames; sp mDeviceInterface; hardware::hidl_vec mVendorTagSections; TestICameraProvider(const std::vector &devices, const hardware::hidl_vec &vendorSection) : mDeviceNames(devices), mDeviceInterface(new TestDeviceInterface(devices)), mVendorTagSections (vendorSection) {} virtual hardware::Return setCallback( const sp& callbacks) override { mCalledCounter[SET_CALLBACK]++; mCallbacks = callbacks; return hardware::Return(Status::OK); } using getVendorTags_cb = std::function& sections)>; hardware::Return getVendorTags(getVendorTags_cb _hidl_cb) override { mCalledCounter[GET_VENDOR_TAGS]++; _hidl_cb(Status::OK, mVendorTagSections); return hardware::Void(); } using isSetTorchModeSupported_cb = std::function; virtual ::hardware::Return isSetTorchModeSupported( isSetTorchModeSupported_cb _hidl_cb) override { mCalledCounter[IS_SET_TORCH_MODE_SUPPORTED]++; _hidl_cb(Status::OK, false); return hardware::Void(); } using getCameraIdList_cb = std::function& cameraDeviceNames)>; virtual hardware::Return getCameraIdList(getCameraIdList_cb _hidl_cb) override { mCalledCounter[GET_CAMERA_ID_LIST]++; _hidl_cb(Status::OK, mDeviceNames); return hardware::Void(); } using getCameraDeviceInterface_V1_x_cb = std::function& device)>; virtual hardware::Return getCameraDeviceInterface_V1_x( const hardware::hidl_string& cameraDeviceName, getCameraDeviceInterface_V1_x_cb _hidl_cb) override { (void) cameraDeviceName; _hidl_cb(Status::OK, nullptr); //TODO: impl. of ver. 1.0 device interface // otherwise enumeration will fail. return hardware::Void(); } using getCameraDeviceInterface_V3_x_cb = std::function& device)>; virtual hardware::Return getCameraDeviceInterface_V3_x( const hardware::hidl_string&, getCameraDeviceInterface_V3_x_cb _hidl_cb) override { _hidl_cb(Status::OK, mDeviceInterface); return hardware::Void(); } virtual hardware::Return notifyDeviceStateChange( hardware::hidl_bitfield newState) override { mCalledCounter[NOTIFY_DEVICE_STATE]++; mCurrentState = newState; return hardware::Void(); } enum MethodNames { SET_CALLBACK, GET_VENDOR_TAGS, IS_SET_TORCH_MODE_SUPPORTED, NOTIFY_DEVICE_STATE, GET_CAMERA_ID_LIST, METHOD_NAME_COUNT }; int mCalledCounter[METHOD_NAME_COUNT] {0}; hardware::hidl_bitfield mCurrentState = 0xFFFFFFFF; // Unlikely to be a real state }; /** * Simple test version of the interaction proxy, to use to inject onRegistered calls to the * CameraProviderManager */ struct TestInteractionProxy : public CameraProviderManager::ServiceInteractionProxy { sp mManagerNotificationInterface; sp mTestCameraProvider; TestInteractionProxy() {} void setProvider(sp provider) { mTestCameraProvider = provider; } std::vector mLastRequestedServiceNames; virtual ~TestInteractionProxy() {} virtual bool registerForNotifications( const std::string &serviceName, const sp ¬ification) override { (void) serviceName; mManagerNotificationInterface = notification; return true; } virtual sp getService( const std::string &serviceName) override { mLastRequestedServiceNames.push_back(serviceName); return mTestCameraProvider; } }; struct TestStatusListener : public CameraProviderManager::StatusListener { ~TestStatusListener() {} void onDeviceStatusChanged(const String8 &, hardware::camera::common::V1_0::CameraDeviceStatus) override {} void onTorchStatusChanged(const String8 &, hardware::camera::common::V1_0::TorchModeStatus) override {} void onNewProviderRegistered() override {} }; TEST(CameraProviderManagerTest, InitializeTest) { std::vector deviceNames; deviceNames.push_back("device@3.2/test/0"); deviceNames.push_back("device@1.0/test/0"); deviceNames.push_back("device@3.2/test/1"); hardware::hidl_vec vendorSection; status_t res; sp providerManager = new CameraProviderManager(); sp statusListener = new TestStatusListener(); TestInteractionProxy serviceProxy; sp provider = new TestICameraProvider(deviceNames, vendorSection); serviceProxy.setProvider(provider); res = providerManager->initialize(statusListener, &serviceProxy); ASSERT_EQ(res, OK) << "Unable to initialize provider manager"; // Check that both "legacy" and "external" providers (really the same object) are called // once for all the init methods EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::SET_CALLBACK], 2) << "Only one call to setCallback per provider expected during init"; EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::GET_VENDOR_TAGS], 2) << "Only one call to getVendorTags per provider expected during init"; EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::IS_SET_TORCH_MODE_SUPPORTED], 2) << "Only one call to isSetTorchModeSupported per provider expected during init"; EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::GET_CAMERA_ID_LIST], 2) << "Only one call to getCameraIdList per provider expected during init"; EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::NOTIFY_DEVICE_STATE], 2) << "Only one call to notifyDeviceState per provider expected during init"; std::string legacyInstanceName = "legacy/0"; std::string externalInstanceName = "external/0"; bool gotLegacy = false; bool gotExternal = false; EXPECT_EQ(2u, serviceProxy.mLastRequestedServiceNames.size()) << "Only two service queries expected to be seen by hardware service manager"; for (auto& serviceName : serviceProxy.mLastRequestedServiceNames) { if (serviceName == legacyInstanceName) gotLegacy = true; if (serviceName == externalInstanceName) gotExternal = true; } ASSERT_TRUE(gotLegacy) << "Legacy instance not requested from service manager"; ASSERT_TRUE(gotExternal) << "External instance not requested from service manager"; hardware::hidl_string testProviderFqInterfaceName = "android.hardware.camera.provider@2.4::ICameraProvider"; hardware::hidl_string testProviderInstanceName = "test/0"; serviceProxy.mManagerNotificationInterface->onRegistration( testProviderFqInterfaceName, testProviderInstanceName, false); ASSERT_EQ(serviceProxy.mLastRequestedServiceNames.back(), testProviderInstanceName) << "Incorrect instance requested from service manager"; } TEST(CameraProviderManagerTest, MultipleVendorTagTest) { hardware::hidl_string sectionName = "VendorTestSection"; hardware::hidl_string tagName = "VendorTestTag"; uint32_t tagId = VENDOR_SECTION << 16; hardware::hidl_vec vendorSection; CameraMetadataType tagType = CameraMetadataType::BYTE; vendorSection.resize(1); vendorSection[0].sectionName = sectionName; vendorSection[0].tags.resize(1); vendorSection[0].tags[0].tagId = tagId; vendorSection[0].tags[0].tagName = tagName; vendorSection[0].tags[0].tagType = tagType; std::vector deviceNames = {"device@3.2/test/0"}; sp providerManager = new CameraProviderManager(); sp statusListener = new TestStatusListener(); TestInteractionProxy serviceProxy; sp provider = new TestICameraProvider(deviceNames, vendorSection); serviceProxy.setProvider(provider); auto res = providerManager->initialize(statusListener, &serviceProxy); ASSERT_EQ(res, OK) << "Unable to initialize provider manager"; hardware::hidl_string testProviderInstanceName = "test/0"; hardware::hidl_string testProviderFqInterfaceName = "android.hardware.camera.provider@2.4::ICameraProvider"; serviceProxy.mManagerNotificationInterface->onRegistration( testProviderFqInterfaceName, testProviderInstanceName, false); ASSERT_EQ(serviceProxy.mLastRequestedServiceNames.back(), testProviderInstanceName) << "Incorrect instance requested from service manager"; hardware::hidl_string sectionNameSecond = "SecondVendorTestSection"; hardware::hidl_string secondTagName = "SecondVendorTestTag"; CameraMetadataType secondTagType = CameraMetadataType::DOUBLE; vendorSection[0].sectionName = sectionNameSecond; vendorSection[0].tags[0].tagId = tagId; vendorSection[0].tags[0].tagName = secondTagName; vendorSection[0].tags[0].tagType = secondTagType; deviceNames = {"device@3.2/test2/1"}; sp secondProvider = new TestICameraProvider( deviceNames, vendorSection); serviceProxy.setProvider(secondProvider); hardware::hidl_string testProviderSecondInstanceName = "test2/0"; serviceProxy.mManagerNotificationInterface->onRegistration( testProviderFqInterfaceName, testProviderSecondInstanceName, false); ASSERT_EQ(serviceProxy.mLastRequestedServiceNames.back(), testProviderSecondInstanceName) << "Incorrect instance requested from service manager"; ASSERT_EQ(NO_ERROR , providerManager->setUpVendorTags()); sp vendorCache = VendorTagDescriptorCache::getGlobalVendorTagCache(); ASSERT_NE(nullptr, vendorCache.get()); metadata_vendor_id_t vendorId = std::hash {} ( testProviderInstanceName.c_str()); metadata_vendor_id_t vendorIdSecond = std::hash {} ( testProviderSecondInstanceName.c_str()); hardware::hidl_string resultTag = vendorCache->getTagName(tagId, vendorId); ASSERT_EQ(resultTag, tagName); resultTag = vendorCache->getTagName(tagId, vendorIdSecond); ASSERT_EQ(resultTag, secondTagName); // Check whether we can create two separate CameraMetadata instances // using different tag vendor vendors. camera_metadata *metaBuffer = allocate_camera_metadata(10, 20); ASSERT_NE(nullptr, metaBuffer); set_camera_metadata_vendor_id(metaBuffer, vendorId); CameraMetadata metadata(metaBuffer); uint8_t byteVal = 10; ASSERT_TRUE(metadata.isEmpty()); ASSERT_EQ(OK, metadata.update(tagId, &byteVal, 1)); ASSERT_FALSE(metadata.isEmpty()); ASSERT_TRUE(metadata.exists(tagId)); metaBuffer = allocate_camera_metadata(10, 20); ASSERT_NE(nullptr, metaBuffer); set_camera_metadata_vendor_id(metaBuffer, vendorIdSecond); CameraMetadata secondMetadata(metaBuffer); ASSERT_TRUE(secondMetadata.isEmpty()); double doubleVal = 1.0f; ASSERT_EQ(OK, secondMetadata.update(tagId, &doubleVal, 1)); ASSERT_FALSE(secondMetadata.isEmpty()); ASSERT_TRUE(secondMetadata.exists(tagId)); // Check whether CameraMetadata copying works as expected CameraMetadata metadataCopy(metadata); ASSERT_FALSE(metadataCopy.isEmpty()); ASSERT_TRUE(metadataCopy.exists(tagId)); ASSERT_EQ(OK, metadataCopy.update(tagId, &byteVal, 1)); ASSERT_TRUE(metadataCopy.exists(tagId)); // Check whether values are as expected camera_metadata_entry_t entry = metadata.find(tagId); ASSERT_EQ(1u, entry.count); ASSERT_EQ(byteVal, entry.data.u8[0]); entry = secondMetadata.find(tagId); ASSERT_EQ(1u, entry.count); ASSERT_EQ(doubleVal, entry.data.d[0]); // Swap and erase secondMetadata.swap(metadataCopy); ASSERT_TRUE(metadataCopy.exists(tagId)); ASSERT_TRUE(secondMetadata.exists(tagId)); ASSERT_EQ(OK, secondMetadata.erase(tagId)); ASSERT_TRUE(secondMetadata.isEmpty()); doubleVal = 0.0f; ASSERT_EQ(OK, metadataCopy.update(tagId, &doubleVal, 1)); entry = metadataCopy.find(tagId); ASSERT_EQ(1u, entry.count); ASSERT_EQ(doubleVal, entry.data.d[0]); // Append uint8_t sceneMode = ANDROID_CONTROL_SCENE_MODE_ACTION; secondMetadata.update(ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1); // Append from two different vendor tag providers is not supported! ASSERT_NE(OK, metadataCopy.append(secondMetadata)); ASSERT_EQ(OK, metadataCopy.erase(tagId)); metadataCopy.update(ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1); // However appending from same vendor tag provider should be fine ASSERT_EQ(OK, metadata.append(secondMetadata)); // Append from a metadata without vendor tag provider should be supported CameraMetadata regularMetadata(10, 20); uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO; regularMetadata.update(ANDROID_CONTROL_MODE, &controlMode, 1); ASSERT_EQ(OK, secondMetadata.append(regularMetadata)); ASSERT_EQ(2u, secondMetadata.entryCount()); ASSERT_EQ(2u, metadata.entryCount()); // Dump metadata.dump(1, 2); metadataCopy.dump(1, 2); secondMetadata.dump(1, 2); } TEST(CameraProviderManagerTest, NotifyStateChangeTest) { std::vector deviceNames { "device@3.2/test/0", "device@1.0/test/0", "device@3.2/test/1"}; hardware::hidl_vec vendorSection; status_t res; sp providerManager = new CameraProviderManager(); sp statusListener = new TestStatusListener(); TestInteractionProxy serviceProxy; sp provider = new TestICameraProvider(deviceNames, vendorSection); serviceProxy.setProvider(provider); res = providerManager->initialize(statusListener, &serviceProxy); ASSERT_EQ(res, OK) << "Unable to initialize provider manager"; ASSERT_EQ(provider->mCurrentState, static_cast>(DeviceState::NORMAL)) << "Initial device state not set"; res = providerManager->notifyDeviceStateChange( static_cast>(DeviceState::FOLDED)); ASSERT_EQ(res, OK) << "Unable to call notifyDeviceStateChange"; ASSERT_EQ(provider->mCurrentState, static_cast>(DeviceState::FOLDED)) << "Unable to change device state"; }