Manually discover virtual camera service

The virtual camera service is not declared in the VINTF manifest.
Currently libcameraservice only looks for declared AIDL ICameraProvider services

This CL checks if the virtual camera service is running and adds the
corresponding CameraProvider to the CameraProviderManager

Test: CameraProviderManagerTest.AidlVirtualCameraProviderDiscovered
Test: CameraProviderManagerTest.AidlVirtualCameraProviderDiscoveredOnInit

Bug: b/270352264
Change-Id: I15667ea18bc32c90f76c1e25faa5c42199495aab
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 3801470..54dc2bc 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -63,6 +63,7 @@
 namespace {
 const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
 const std::string kExternalProviderName = "external/0";
+const std::string kVirtualProviderName = "virtual/0";
 } // anonymous namespace
 
 const float CameraProviderManager::kDepthARTolerance = .1f;
@@ -71,6 +72,8 @@
 
 CameraProviderManager::HidlServiceInteractionProxyImpl
 CameraProviderManager::sHidlServiceInteractionProxy{};
+CameraProviderManager::AidlServiceInteractionProxyImpl
+CameraProviderManager::sAidlServiceInteractionProxy{};
 
 CameraProviderManager::~CameraProviderManager() {
 }
@@ -133,6 +136,29 @@
     return OK;
 }
 
+std::shared_ptr<aidl::android::hardware::camera::provider::ICameraProvider>
+CameraProviderManager::AidlServiceInteractionProxyImpl::getAidlService(
+        const std::string& serviceName) {
+    using aidl::android::hardware::camera::provider::ICameraProvider;
+
+    AIBinder* binder = nullptr;
+    if (flags::lazy_aidl_wait_for_service()) {
+        binder = AServiceManager_waitForService(serviceName.c_str());
+    } else {
+        binder = AServiceManager_getService(serviceName.c_str());
+    }
+
+    if (binder == nullptr) {
+        ALOGD("%s: AIDL Camera provider HAL '%s' is not actually available", __FUNCTION__,
+              serviceName.c_str());
+        return nullptr;
+    }
+    std::shared_ptr<ICameraProvider> interface =
+            ICameraProvider::fromBinder(ndk::SpAIBinder(binder));
+
+    return interface;
+};
+
 static std::string getFullAidlProviderName(const std::string instance) {
     std::string aidlHalServiceDescriptor =
             std::string(aidl::android::hardware::camera::provider::ICameraProvider::descriptor);
@@ -145,6 +171,13 @@
     auto sm = defaultServiceManager();
     auto aidlProviders = sm->getDeclaredInstances(
             String16(aidlHalServiceDescriptor));
+
+    if (isVirtualCameraHalEnabled()) {
+        // Virtual Camera provider is not declared in the VINTF manifest so we
+        // manually add it if the binary is present.
+        aidlProviders.push_back(String16(kVirtualProviderName.c_str()));
+    }
+
     for (const auto &aidlInstance : aidlProviders) {
         std::string aidlServiceName =
                 getFullAidlProviderName(toStdString(aidlInstance));
@@ -160,12 +193,19 @@
 }
 
 status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
-        HidlServiceInteractionProxy* hidlProxy) {
+        HidlServiceInteractionProxy* hidlProxy, AidlServiceInteractionProxy* aidlProxy) {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     if (hidlProxy == nullptr) {
-        ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
+        ALOGE("%s: No valid service Hidl interaction proxy provided", __FUNCTION__);
         return BAD_VALUE;
     }
+
+    if (aidlProxy == nullptr) {
+        ALOGE("%s: No valid service Aidl interaction proxy provided", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    mAidlServiceProxy = aidlProxy;
+
     mListener = listener;
     mDeviceState = 0;
     auto res = tryToInitAndAddHidlProvidersLocked(hidlProxy);
@@ -1974,14 +2014,8 @@
         const std::string& providerName, const sp<ProviderInfo>& providerInfo) {
     using aidl::android::hardware::camera::provider::ICameraProvider;
 
-    AIBinder *binder = nullptr;
-    if (flags::lazy_aidl_wait_for_service()) {
-        binder = AServiceManager_waitForService(providerName.c_str());
-    } else {
-        binder = AServiceManager_getService(providerName.c_str());
-    }
     std::shared_ptr<ICameraProvider> interface =
-            ICameraProvider::fromBinder(ndk::SpAIBinder(binder));
+            mAidlServiceProxy->getAidlService(providerName.c_str());
 
     if (interface == nullptr) {
         ALOGW("%s: AIDL Camera provider HAL '%s' is not actually available", __FUNCTION__,
@@ -3127,4 +3161,8 @@
     }
 }
 
+bool CameraProviderManager::isVirtualCameraHalEnabled() {
+    return flags::virtual_camera_service_discovery();
+}
+
 } // namespace android
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 2a5e73b..fd04854 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -174,6 +174,24 @@
         virtual hardware::hidl_vec<hardware::hidl_string> listServices() override;
     };
 
+    // Proxy to inject fake services in test.
+    class AidlServiceInteractionProxy {
+      public:
+        // Returns the Aidl service with the given serviceName
+        virtual std::shared_ptr<aidl::android::hardware::camera::provider::ICameraProvider>
+        getAidlService(const std::string& serviceName) = 0;
+
+        virtual ~AidlServiceInteractionProxy() = default;
+    };
+
+    // Standard use case - call into the normal static methods which invoke
+    // the real service manager
+    class AidlServiceInteractionProxyImpl : public AidlServiceInteractionProxy {
+      public:
+        virtual std::shared_ptr<aidl::android::hardware::camera::provider::ICameraProvider>
+        getAidlService(const std::string& serviceName) override;
+    };
+
     /**
      * Listener interface for device/torch status changes
      */
@@ -209,7 +227,8 @@
      * used for testing. The lifetime of the proxy must exceed the lifetime of the manager.
      */
     status_t initialize(wp<StatusListener> listener,
-            HidlServiceInteractionProxy *hidlProxy = &sHidlServiceInteractionProxy);
+                        HidlServiceInteractionProxy* hidlProxy = &sHidlServiceInteractionProxy,
+                        AidlServiceInteractionProxy* aidlProxy = &sAidlServiceInteractionProxy);
 
     status_t getCameraIdIPCTransport(const std::string &id,
             IPCTransport *providerTransport) const;
@@ -424,6 +443,7 @@
 
     wp<StatusListener> mListener;
     HidlServiceInteractionProxy* mHidlServiceProxy;
+    AidlServiceInteractionProxy* mAidlServiceProxy;
 
     // Current overall Android device physical status
     int64_t mDeviceState;
@@ -432,6 +452,7 @@
     mutable std::mutex mProviderLifecycleLock;
 
     static HidlServiceInteractionProxyImpl sHidlServiceInteractionProxy;
+    static AidlServiceInteractionProxyImpl sAidlServiceInteractionProxy;
 
     struct HalCameraProvider {
       // Empty parent struct for storing either aidl / hidl camera provider reference
@@ -868,6 +889,8 @@
     status_t usbDeviceDetached(const std::string &usbDeviceId);
     ndk::ScopedAStatus onAidlRegistration(const std::string& in_name,
             const ::ndk::SpAIBinder& in_binder);
+
+    static bool isVirtualCameraHalEnabled();
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 9f28b5f..257103f 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -130,11 +130,15 @@
     }
 
     mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(binderDied));
-    auto link = AIBinder_linkToDeath(interface->asBinder().get(), mDeathRecipient.get(), this);
-    if (link != STATUS_OK) {
-        ALOGW("%s: Unable to link to provider '%s' death notifications",
-                __FUNCTION__, mProviderName.c_str());
-        return DEAD_OBJECT;
+
+    if (!flags::virtual_camera_service_discovery() || interface->isRemote()) {
+        binder_status_t link =
+                AIBinder_linkToDeath(interface->asBinder().get(), mDeathRecipient.get(), this);
+        if (link != STATUS_OK) {
+            ALOGW("%s: Unable to link to provider '%s' death notifications (%d)", __FUNCTION__,
+                  mProviderName.c_str(), link);
+            return DEAD_OBJECT;
+        }
     }
 
     if (!kEnableLazyHal) {
@@ -284,13 +288,12 @@
         if (interface == nullptr) {
             ALOGV("Camera provider actually needs restart, calling getService(%s)",
                   mProviderName.c_str());
-            AIBinder * binder = nullptr;
-            if (flags::lazy_aidl_wait_for_service()) {
-                binder = AServiceManager_waitForService(mProviderName.c_str());
-            } else {
-                binder = AServiceManager_getService(mProviderName.c_str());
+            interface = mManager->mAidlServiceProxy->getAidlService(mProviderName.c_str());
+
+            if (interface == nullptr) {
+                ALOGD("%s: %s service not started", __FUNCTION__, mProviderName.c_str());
+                return nullptr;
             }
-            interface = ICameraProvider::fromBinder(ndk::SpAIBinder(binder));
 
             // Set all devices as ENUMERATING, provider should update status
             // to PRESENT after initializing.
diff --git a/services/camera/libcameraservice/tests/Android.bp b/services/camera/libcameraservice/tests/Android.bp
index b035edd..d600d42 100644
--- a/services/camera/libcameraservice/tests/Android.bp
+++ b/services/camera/libcameraservice/tests/Android.bp
@@ -53,6 +53,7 @@
         "android.hardware.camera.device@3.4",
         "android.hardware.camera.device@3.7",
         "android.hidl.token@1.0-utils",
+        "camera_platform_flags_c_lib",
     ],
 
     static_libs: [
@@ -63,6 +64,7 @@
         "android.hardware.camera.provider-V2-ndk",
         "libcameraservice",
         "libgmock",
+        "libflagtest",
     ],
 
     srcs: [
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index c0cd1a9..151c5ce 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -18,24 +18,40 @@
 #define LOG_TAG "CameraProviderManagerTest"
 
 #include "../common/CameraProviderManager.h"
-#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <android/hidl/manager/1.0/IServiceNotification.h>
+#include <aidl/android/hardware/camera/device/BnCameraDevice.h>
+#include <aidl/android/hardware/camera/provider/BnCameraProvider.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_libbinder.h>
+#include <android/binder_manager.h>
+#include <android/binder_parcel.h>
 #include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
 #include <android/hardware/camera/device/3.2/ICameraDeviceSession.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.0/IServiceNotification.h>
+#include <binder/IServiceManager.h>
 #include <camera_metadata_hidden.h>
-#include <hidl/HidlBinderSupport.h>
+#include <com_android_internal_camera_flags.h>
+#include <flag_macros.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
+#include <hidl/HidlBinderSupport.h>
 #include <utility>
 
 using namespace android;
 using namespace android::hardware::camera;
+using ::aidl::android::hardware::camera::provider::ICameraProviderCallback;
+using android::hardware::camera::common::V1_0::CameraMetadataType;
 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;
+using ::testing::ElementsAre;
+
+namespace flags = com::android::internal::camera::flags;
 
 /**
  * Basic test implementation of a camera ver. 3.2 device interface
@@ -241,13 +257,111 @@
     hardware::hidl_bitfield<DeviceState> mCurrentState = 0xFFFFFFFF; // Unlikely to be a real state
 };
 
+struct TestAidlCameraDevice : public aidl::android::hardware::camera::device::BnCameraDevice {
+    ::ndk::ScopedAStatus getCameraCharacteristics(
+            ::aidl::android::hardware::camera::device::CameraMetadata*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus getPhysicalCameraCharacteristics(
+            const std::string&,
+            ::aidl::android::hardware::camera::device::CameraMetadata*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus getResourceCost(
+            ::aidl::android::hardware::camera::common::CameraResourceCost* aidl_return) override {
+        auto cost = ::aidl::android::hardware::camera::common::CameraResourceCost();
+        aidl_return->resourceCost = 100;
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus isStreamCombinationSupported(
+            const ::aidl::android::hardware::camera::device::StreamConfiguration&, bool*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus
+    open(const std::shared_ptr<::aidl::android::hardware::camera::device::ICameraDeviceCallback>&,
+         std::shared_ptr<::aidl::android::hardware::camera::device::ICameraDeviceSession>*)
+            override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus openInjectionSession(
+            const std::shared_ptr<
+                    ::aidl::android::hardware::camera::device::ICameraDeviceCallback>&,
+            std::shared_ptr<::aidl::android::hardware::camera::device::ICameraInjectionSession>*)
+            override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus setTorchMode(bool) override { return ndk::ScopedAStatus::ok(); }
+    ::ndk::ScopedAStatus turnOnTorchWithStrengthLevel(int32_t) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus getTorchStrengthLevel(int32_t*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+/**
+ * Basic test implementation of a AIDL camera provider
+ */
+class TestAidlICameraProvider : public aidl::android::hardware::camera::provider::BnCameraProvider {
+  public:
+    std::shared_ptr<ICameraProviderCallback> mCallback;
+    std::vector<std::string> mDeviceNames;
+
+    TestAidlICameraProvider(const std::vector<std::string>& deviceNames) {
+        mDeviceNames = deviceNames;
+    }
+
+    ::ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<
+                    ::aidl::android::hardware::camera::provider::ICameraProviderCallback>& callback)
+            override {
+        mCallback = callback;
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus getVendorTags(
+            std::vector<::aidl::android::hardware::camera::common::VendorTagSection>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus getCameraIdList(std::vector<std::string>* camera_list) override {
+        ALOGW("getCameraIdList");
+        for (size_t i = 0; i < mDeviceNames.size(); i++) {
+            camera_list->push_back(mDeviceNames.at(i));
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus getCameraDeviceInterface(
+            const std::string&,
+            std::shared_ptr<::aidl::android::hardware::camera::device::ICameraDevice>* device)
+            override {
+        *device = ndk::SharedRefBase::make<TestAidlCameraDevice>();
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus notifyDeviceStateChange(int64_t) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus getConcurrentCameraIds(
+            std::vector<
+                    ::aidl::android::hardware::camera::provider::ConcurrentCameraIdCombination>*)
+            override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus isConcurrentStreamCombinationSupported(
+            const std::vector<
+                    ::aidl::android::hardware::camera::provider::CameraIdAndStreamCombination>&,
+            bool*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
 /**
  * Simple test version of the interaction proxy, to use to inject onRegistered calls to the
  * CameraProviderManager
  */
-struct TestInteractionProxy : public CameraProviderManager::HidlServiceInteractionProxy {
+struct TestInteractionProxy : public CameraProviderManager::HidlServiceInteractionProxy,
+                              public CameraProviderManager::AidlServiceInteractionProxy {
     sp<hidl::manager::V1_0::IServiceNotification> mManagerNotificationInterface;
     sp<TestICameraProvider> mTestCameraProvider;
+    std::shared_ptr<TestAidlICameraProvider> mTestAidlCameraProvider;
 
     TestInteractionProxy() {}
 
@@ -255,6 +369,10 @@
         mTestCameraProvider = provider;
     }
 
+    void setAidlProvider(std::shared_ptr<TestAidlICameraProvider> provider) {
+        mTestAidlCameraProvider = provider;
+    }
+
     std::vector<std::string> mLastRequestedServiceNames;
 
     virtual ~TestInteractionProxy() {}
@@ -295,6 +413,10 @@
         return ret;
     }
 
+    virtual std::shared_ptr<aidl::android::hardware::camera::provider::ICameraProvider>
+    getAidlService(const std::string&) {
+        return mTestAidlCameraProvider;
+    }
 };
 
 struct TestStatusListener : public CameraProviderManager::StatusListener {
@@ -713,3 +835,49 @@
     ASSERT_TRUE(unavailablePhysicalIds.count("0") > 0 && unavailablePhysicalIds["0"].count("2") > 0)
         << "Unavailable physical camera Ids not set properly.";
 }
+TEST_WITH_FLAGS(CameraProviderManagerTest, AidlVirtualCameraProviderDiscovered,
+                REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(flags, virtual_camera_service_discovery))) {
+    sp<CameraProviderManager> providerManager = new CameraProviderManager();
+    sp<TestStatusListener> statusListener = new TestStatusListener();
+    TestInteractionProxy serviceProxy;
+
+    status_t res = providerManager->initialize(statusListener, &serviceProxy, &serviceProxy);
+    ASSERT_EQ(res, OK) << "Unable to initialize provider manager";
+
+    std::vector<std::string> cameraList = {"device@1.1/virtual/123"};
+
+    std::shared_ptr<TestAidlICameraProvider> aidlProvider =
+            ndk::SharedRefBase::make<TestAidlICameraProvider>(cameraList);
+    ndk::SpAIBinder spBinder = aidlProvider->asBinder();
+    AIBinder* aiBinder = spBinder.get();
+    serviceProxy.setAidlProvider(aidlProvider);
+    providerManager->onServiceRegistration(
+            String16("android.hardware.camera.provider.ICameraProvider/virtual/0"),
+            AIBinder_toPlatformBinder(aiBinder));
+
+    std::unordered_map<std::string, std::set<std::string>> unavailableDeviceIds;
+    auto cameraIds = providerManager->getCameraDeviceIds(&unavailableDeviceIds);
+
+    EXPECT_THAT(cameraIds, ElementsAre("123"));
+}
+
+TEST_WITH_FLAGS(CameraProviderManagerTest, AidlVirtualCameraProviderDiscoveredOnInit,
+                REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(flags, virtual_camera_service_discovery))) {
+    sp<CameraProviderManager> providerManager = new CameraProviderManager();
+    sp<TestStatusListener> statusListener = new TestStatusListener();
+    TestInteractionProxy serviceProxy;
+
+    std::vector<std::string> cameraList = {"device@1.1/virtual/123"};
+
+    std::shared_ptr<TestAidlICameraProvider> aidlProvider =
+            ndk::SharedRefBase::make<TestAidlICameraProvider>(cameraList);
+    serviceProxy.setAidlProvider(aidlProvider);
+
+    status_t res = providerManager->initialize(statusListener, &serviceProxy, &serviceProxy);
+    ASSERT_EQ(res, OK) << "Unable to initialize provider manager";
+
+    std::unordered_map<std::string, std::set<std::string>> unavailableDeviceIds;
+    std::vector<std::string> cameraIds = providerManager->getCameraDeviceIds(&unavailableDeviceIds);
+
+    EXPECT_THAT(cameraIds, ElementsAre("123"));
+}