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

Commit 14929832 authored by Iavor-Valentin Iftime's avatar Iavor-Valentin Iftime Committed by Android (Google) Code Review
Browse files

Merge "Add support for external lazy camera HALs"

parents a5d76cd8 29e2e151
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -187,6 +187,8 @@ interface ICameraService
     */
    const int EVENT_NONE = 0;
    const int EVENT_USER_SWITCHED = 1; // The argument is the set of new foreground user IDs.
    const int EVENT_USB_DEVICE_ATTACHED = 2; // The argument is the deviceId and vendorId
    const int EVENT_USB_DEVICE_DETACHED = 3; // The argument is the deviceId and vendorId
    oneway void notifySystemEvent(int eventId, in int[] args);

    /**
+7 −0
Original line number Diff line number Diff line
@@ -2335,6 +2335,13 @@ Status CameraService::notifySystemEvent(int32_t eventId,
            doUserSwitch(/*newUserIds*/ args);
            break;
        }
        case ICameraService::EVENT_USB_DEVICE_ATTACHED:
        case ICameraService::EVENT_USB_DEVICE_DETACHED: {
            // Notify CameraProviderManager for lazy HALs
            mCameraProviderManager->notifyUsbDeviceEvent(eventId,
                                                        std::to_string(args[0]));
            break;
        }
        case ICameraService::EVENT_NONE:
        default: {
            ALOGW("%s: Received invalid system event from system_server: %d", __FUNCTION__,
+174 −25
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ using hardware::camera::provider::V2_7::CameraIdAndStreamCombination;

namespace {
const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
const std::string kExternalProviderName = "external/0";
} // anonymous namespace

const float CameraProviderManager::kDepthARTolerance = .1f;
@@ -395,6 +396,73 @@ status_t CameraProviderManager::setUpVendorTags() {
    return OK;
}

sp<CameraProviderManager::ProviderInfo> CameraProviderManager::startExternalLazyProvider() const {
    std::lock_guard<std::mutex> providerLock(mProviderLifecycleLock);
    std::lock_guard<std::mutex> lock(mInterfaceMutex);

    for (const auto& providerInfo : mProviders) {
        if (providerInfo->isExternalLazyHAL()) {
            const sp<provider::V2_4::ICameraProvider>
                  interface = providerInfo->startProviderInterface();
            if (interface == nullptr) {
                return nullptr;
            } else {
                return providerInfo;
            }
        }
    }
    return nullptr;
}

status_t CameraProviderManager::notifyUsbDeviceEvent(int32_t eventId,
                                                     const std::string& usbDeviceId) {
    if (!kEnableLazyHal) {
        return OK;
    }

    ALOGV("notifySystemEvent: %d usbDeviceId : %s", eventId, usbDeviceId.c_str());

    if (eventId == android::hardware::ICameraService::EVENT_USB_DEVICE_ATTACHED) {
        sp<ProviderInfo> externalProvider = startExternalLazyProvider();
        if (externalProvider != nullptr) {
            auto usbDevices = mExternalUsbDevicesForProvider.first;
            usbDevices.push_back(usbDeviceId);
            mExternalUsbDevicesForProvider = {usbDevices, externalProvider};
        }
    } else if (eventId
          == android::hardware::ICameraService::EVENT_USB_DEVICE_DETACHED) {
        usbDeviceDetached(usbDeviceId);
    }

    return OK;
}

status_t CameraProviderManager::usbDeviceDetached(const std::string &usbDeviceId) {
    std::lock_guard<std::mutex> providerLock(mProviderLifecycleLock);
    std::lock_guard<std::mutex> interfaceLock(mInterfaceMutex);

    auto usbDevices = mExternalUsbDevicesForProvider.first;
    auto foundId = std::find(usbDevices.begin(), usbDevices.end(), usbDeviceId);
    if (foundId != usbDevices.end()) {
        sp<ProviderInfo> providerInfo = mExternalUsbDevicesForProvider.second;
        if (providerInfo == nullptr) {
              ALOGE("%s No valid external provider for USB device: %s",
                    __FUNCTION__,
                    usbDeviceId.c_str());
              mExternalUsbDevicesForProvider = {std::vector<std::string>(), nullptr};
              return DEAD_OBJECT;
        } else {
            mInterfaceMutex.unlock();
            providerInfo->removeAllDevices();
            mInterfaceMutex.lock();
            mExternalUsbDevicesForProvider = {std::vector<std::string>(), nullptr};
        }
    } else {
        return DEAD_OBJECT;
    }
    return OK;
}

status_t CameraProviderManager::notifyDeviceStateChange(
        hardware::hidl_bitfield<provider::V2_5::DeviceState> newState) {
    std::lock_guard<std::mutex> lock(mInterfaceMutex);
@@ -1314,7 +1382,8 @@ status_t CameraProviderManager::addProviderLocked(const std::string& newProvider
        if (providerInfo->mProviderName == newProvider) {
            ALOGW("%s: Camera provider HAL with name '%s' already registered",
                    __FUNCTION__, newProvider.c_str());
            if (preexisting) {
            // Do not add new instances for lazy HAL external provider
            if (preexisting || providerInfo->isExternalLazyHAL()) {
                return ALREADY_EXISTS;
            } else {
                ALOGW("%s: The new provider instance will get initialized immediately after the"
@@ -1606,13 +1675,30 @@ CameraProviderManager::ProviderInfo::startProviderInterface() {

    auto interface = mActiveInterface.promote();
    if (interface == nullptr) {
        ALOGI("Camera HAL provider needs restart, calling getService(%s)", mProviderName.c_str());
        // Try to get service without starting
        interface = mManager->mServiceProxy->tryGetService(mProviderName);
        if (interface == nullptr) {
            ALOGV("Camera provider actually needs restart, calling getService(%s)",
                  mProviderName.c_str());
            interface = mManager->mServiceProxy->getService(mProviderName);

            // Set all devices as ENUMERATING, provider should update status
            // to PRESENT after initializing.
            // This avoids failing getCameraDeviceInterface_V3_x before devices
            // are ready.
            for (auto& device : mDevices) {
              device->mIsDeviceAvailable = false;
            }

            interface->setCallback(this);
        hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
            hardware::Return<bool>
                linked = interface->linkToDeath(this, /*cookie*/ mId);
            if (!linked.isOk()) {
            ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
                    __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
              ALOGE(
                  "%s: Transaction error in linking to camera provider '%s' death: %s",
                  __FUNCTION__,
                  mProviderName.c_str(),
                  linked.description().c_str());
              mManager->removeProvider(mProviderName);
              return nullptr;
            } else if (!linked) {
@@ -1621,7 +1707,8 @@ CameraProviderManager::ProviderInfo::startProviderInterface() {
            }
            // Send current device state
            if (mMinorVersion >= 5) {
            auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
              auto castResult =
                  provider::V2_5::ICameraProvider::castFrom(interface);
              if (castResult.isOk()) {
                sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
                if (interface_2_5 != nullptr) {
@@ -1631,11 +1718,13 @@ CameraProviderManager::ProviderInfo::startProviderInterface() {
                }
              }
            }

        }
        mActiveInterface = interface;
    } else {
        ALOGV("Camera provider (%s) already in use. Re-using instance.", mProviderName.c_str());
        ALOGV("Camera provider (%s) already in use. Re-using instance.",
              mProviderName.c_str());
    }

    return interface;
}

@@ -1713,12 +1802,47 @@ void CameraProviderManager::ProviderInfo::removeDevice(std::string id) {
                    mUniqueAPI1CompatibleCameraIds.begin(),
                    mUniqueAPI1CompatibleCameraIds.end(), id));
            }

            // Remove reference to camera provider to avoid pointer leak when
            // unplugging external camera while in use with lazy HALs
            mManager->removeRef(DeviceMode::CAMERA, id);
            mManager->removeRef(DeviceMode::TORCH, id);

            mDevices.erase(it);
            break;
        }
    }
}

void CameraProviderManager::ProviderInfo::removeAllDevices() {
    std::lock_guard<std::mutex> lock(mLock);

    auto itDevices = mDevices.begin();
    while (itDevices != mDevices.end()) {
        std::string id = (*itDevices)->mId;
        std::string deviceName = (*itDevices)->mName;
        removeDevice(id);
        // device was removed, reset iterator
        itDevices = mDevices.begin();

        //notify CameraService of status change
        sp<StatusListener> listener = mManager->getStatusListener();
        if (listener != nullptr) {
            mLock.unlock();
            ALOGV("%s: notify device not_present: %s",
                  __FUNCTION__,
                  deviceName.c_str());
            listener->onDeviceStatusChanged(String8(id.c_str()),
                                            CameraDeviceStatus::NOT_PRESENT);
            mLock.lock();
        }
    }
}

bool CameraProviderManager::ProviderInfo::isExternalLazyHAL() const {
    return kEnableLazyHal && (mProviderName == kExternalProviderName);
}

status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector<String16>&) const {
    dprintf(fd, "== Camera Provider HAL %s (v2.%d, %s) static info: %zu devices: ==\n",
            mProviderInstance.c_str(),
@@ -1898,12 +2022,16 @@ status_t CameraProviderManager::ProviderInfo::cameraDeviceStatusChangeLocked(
    std::string cameraId;
    for (auto& deviceInfo : mDevices) {
        if (deviceInfo->mName == cameraDeviceName) {
            Mutex::Autolock l(deviceInfo->mDeviceAvailableLock);
            ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
                    deviceStatusToString(newStatus), deviceStatusToString(deviceInfo->mStatus));
            deviceInfo->mStatus = newStatus;
            // TODO: Handle device removal (NOT_PRESENT)
            cameraId = deviceInfo->mId;
            known = true;
            deviceInfo->mIsDeviceAvailable =
                (newStatus == CameraDeviceStatus::PRESENT);
            deviceInfo->mDeviceAvailableSignal.signal();
            break;
        }
    }
@@ -1917,6 +2045,11 @@ status_t CameraProviderManager::ProviderInfo::cameraDeviceStatusChangeLocked(
        addDevice(cameraDeviceName, newStatus, &cameraId);
    } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
        removeDevice(cameraId);
    } else if (isExternalLazyHAL()) {
        // Do not notify CameraService for PRESENT->PRESENT (lazy HAL restart)
        // because NOT_AVAILABLE is set on CameraService::connect and a PRESENT
        // notif. would overwrite it
        return BAD_VALUE;
    }
    if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
        ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
@@ -2297,11 +2430,27 @@ CameraProviderManager::ProviderInfo::DeviceInfo::~DeviceInfo() {}

template<class InterfaceT>
sp<InterfaceT> CameraProviderManager::ProviderInfo::DeviceInfo::startDeviceInterface() {
    Mutex::Autolock l(mDeviceAvailableLock);
    sp<InterfaceT> device;
    ATRACE_CALL();
    if (mSavedInterface == nullptr) {
        sp<ProviderInfo> parentProvider = mParentProvider.promote();
        if (parentProvider != nullptr) {
            // Wait for lazy HALs to confirm device availability
            if (parentProvider->isExternalLazyHAL() && !mIsDeviceAvailable) {
                ALOGV("%s: Wait for external device to become available %s",
                      __FUNCTION__,
                      mId.c_str());

                auto res = mDeviceAvailableSignal.waitRelative(mDeviceAvailableLock,
                                                         kDeviceAvailableTimeout);
                if (res != OK) {
                    ALOGE("%s: Failed waiting for device to become available",
                          __FUNCTION__);
                    return nullptr;
                }
            }

            device = parentProvider->startDeviceInterface<InterfaceT>(mName);
        }
    } else {
+29 −0
Original line number Diff line number Diff line
@@ -29,7 +29,9 @@
#include <camera/CameraParameters2.h>
#include <camera/CameraMetadata.h>
#include <camera/CameraBase.h>
#include <utils/Condition.h>
#include <utils/Errors.h>
#include <android/hardware/ICameraService.h>
#include <android/hardware/camera/common/1.0/types.h>
#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
@@ -358,6 +360,8 @@ public:

    status_t filterSmallJpegSizes(const std::string& cameraId);

    status_t notifyUsbDeviceEvent(int32_t eventId, const std::string &usbDeviceId);

    static const float kDepthARTolerance;
private:
    // All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use
@@ -488,6 +492,17 @@ private:
                                &halCameraIdsAndStreamCombinations,
                bool *isSupported);

        /**
         * Remove all devices associated with this provider and notify listeners
         * with NOT_PRESENT state.
         */
        void removeAllDevices();

        /**
         * Provider is an external lazy HAL
         */
        bool isExternalLazyHAL() const;

        // Basic device information, common to all camera devices
        struct DeviceInfo {
            const std::string mName;  // Full instance name
@@ -511,6 +526,12 @@ private:
            int32_t mTorchMaximumStrengthLevel;
            int32_t mTorchDefaultStrengthLevel;

            // Wait for lazy HALs to confirm device availability
            static const nsecs_t kDeviceAvailableTimeout = 2000e6; // 2000 ms
            Mutex     mDeviceAvailableLock;
            Condition mDeviceAvailableSignal;
            bool mIsDeviceAvailable = true;

            bool hasFlashUnit() const { return mHasFlashUnit; }
            bool supportNativeZoomRatio() const { return mSupportNativeZoomRatio; }
            virtual status_t setTorchMode(bool enabled) = 0;
@@ -735,6 +756,12 @@ private:
            hardware::hidl_version minVersion = hardware::hidl_version{0,0},
            hardware::hidl_version maxVersion = hardware::hidl_version{1000,0}) const;

    // Map external providers to USB devices in order to handle USB hotplug
    // events for lazy HALs
    std::pair<std::vector<std::string>, sp<ProviderInfo>>
        mExternalUsbDevicesForProvider;
    sp<ProviderInfo> startExternalLazyProvider() const;

    status_t addProviderLocked(const std::string& newProvider, bool preexisting = false);

    status_t tryToInitializeProviderLocked(const std::string& providerName,
@@ -782,6 +809,8 @@ private:
              hardware::hidl_vec<hardware::camera::provider::V2_7::CameraIdAndStreamCombination>
                      *halCameraIdsAndStreamCombinations,
              bool *earlyExit);

    status_t usbDeviceDetached(const std::string &usbDeviceId);
};

} // namespace android