diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp index ca275f4fe4..084dc62adb 100644 --- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp +++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp @@ -183,6 +183,7 @@ struct TestInteractionProxy : public CameraProviderManager::ServiceInteractionPr sp mTestCameraProvider; TestInteractionProxy() {} + void setProvider(sp provider) { mTestCameraProvider = provider; } @@ -201,16 +202,29 @@ struct TestInteractionProxy : public CameraProviderManager::ServiceInteractionPr virtual sp tryGetService( const std::string &serviceName) override { + // If no provider has been given, act like the HAL isn't available and return null. + if (mTestCameraProvider == nullptr) return nullptr; return getService(serviceName); } virtual sp getService( const std::string &serviceName) override { + // If no provider has been given, fail; in reality, getService would + // block for HALs that don't start correctly, so we should never use + // getService when we don't have a valid HAL running + if (mTestCameraProvider == nullptr) { + ADD_FAILURE() << "getService called with no valid provider; would block indefinitely"; + // Real getService would block, but that's bad in unit tests. So + // just record an error and return nullptr + return nullptr; + } mLastRequestedServiceNames.push_back(serviceName); return mTestCameraProvider; } virtual hardware::hidl_vec listServices() override { + // Always provide a list even if there's no actual provider yet, to + // simulate stuck HAL situations as well hardware::hidl_vec ret = {"test/0"}; return ret; } @@ -443,3 +457,52 @@ TEST(CameraProviderManagerTest, NotifyStateChangeTest) { << "Unable to change device state"; } + +// Test that CameraProviderManager doesn't get stuck when the camera HAL isn't really working +TEST(CameraProviderManagerTest, BadHalStartupTest) { + + 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); + + // Not setting up provider in the service proxy yet, to test cases where a + // HAL isn't starting right + res = providerManager->initialize(statusListener, &serviceProxy); + ASSERT_EQ(res, OK) << "Unable to initialize provider manager"; + + // Now set up provider and trigger a registration + serviceProxy.setProvider(provider); + int numProviders = static_cast(serviceProxy.listServices().size()); + + hardware::hidl_string testProviderFqInterfaceName = + "android.hardware.camera.provider@2.4::ICameraProvider"; + hardware::hidl_string testProviderInstanceName = "test/0"; + serviceProxy.mManagerNotificationInterface->onRegistration( + testProviderFqInterfaceName, + testProviderInstanceName, false); + + // Check that new provider is called once for all the init methods + EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::SET_CALLBACK], numProviders) << + "Only one call to setCallback per provider expected during register"; + EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::GET_VENDOR_TAGS], numProviders) << + "Only one call to getVendorTags per provider expected during register"; + EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::IS_SET_TORCH_MODE_SUPPORTED], + numProviders) << + "Only one call to isSetTorchModeSupported per provider expected during init"; + EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::GET_CAMERA_ID_LIST], numProviders) << + "Only one call to getCameraIdList per provider expected during init"; + EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::NOTIFY_DEVICE_STATE], numProviders) << + "Only one call to notifyDeviceState per provider expected during init"; + + ASSERT_EQ(serviceProxy.mLastRequestedServiceNames.back(), testProviderInstanceName) << + "Incorrect instance requested from service manager"; +}