Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 998d1fe2 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

CameraService: Add unit test for stuck HAL at startup

New test verifies that getService is not called during camera service
startup, to make sure it can't get stuck if the camera HAL isn't
initializing properly.

Test: New test passes with new tryGetService code; test fails with
older camera service code.
Change-Id: I67b3fe392e8cc6961c33abf25e961a8e2df7d7b5
parent ec96060c
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
@@ -183,6 +183,7 @@ struct TestInteractionProxy : public CameraProviderManager::ServiceInteractionPr
    sp<TestICameraProvider> mTestCameraProvider;

    TestInteractionProxy() {}

    void setProvider(sp<TestICameraProvider> provider) {
        mTestCameraProvider = provider;
    }
@@ -201,16 +202,29 @@ struct TestInteractionProxy : public CameraProviderManager::ServiceInteractionPr

    virtual sp<hardware::camera::provider::V2_4::ICameraProvider> 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<hardware::camera::provider::V2_4::ICameraProvider> 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<hardware::hidl_string> listServices() override {
        // Always provide a list even if there's no actual provider yet, to
        // simulate stuck HAL situations as well
        hardware::hidl_vec<hardware::hidl_string> 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<hardware::hidl_string> 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<common::V1_0::VendorTagSection> vendorSection;
    status_t res;

    sp<CameraProviderManager> providerManager = new CameraProviderManager();
    sp<TestStatusListener> statusListener = new TestStatusListener();
    TestInteractionProxy serviceProxy;
    sp<TestICameraProvider> 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<int>(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";
}