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

Commit 5ad93755 authored by Rucha Katakwar's avatar Rucha Katakwar
Browse files

Camera: Add 3.8 version of ICameraDevice.

The new version of ICameraDevice supports interfaces for torch
strength control feature. New VTS test has been added to test the
emulator HAL-side implementation of the newly added interfaces.

bug: 200174275

Test: Camera VTS test pass.
Change-Id: Ia5652a96e09bd716b5079fe9ed071dffc53b5b12
parent 7d4d3dac
Loading
Loading
Loading
Loading
+78 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.hardware.camera.device@3.8;

import android.hardware.camera.common@1.0::Status;
import @3.7::ICameraDevice;

/**
@@ -29,4 +30,81 @@ import @3.7::ICameraDevice;
 * @3.7::ICameraDeviceSession.
 */
interface ICameraDevice extends @3.7::ICameraDevice {
    /**
     * turnOnTorchWithStrengthLevel:
     *
     * Change the brightness level of the flash unit associated with this camera device
     * and set it to value in torchStrength. This function also turns ON the torch
     * with specified torchStrength if the torch is OFF.
     *
     * The torchStrength value must be within the valid range i.e. >=1 and
     * <= FLASH_INFO_STRENGTH_MAXIMUM_LEVEL. Whenever the torch is turned OFF,
     * the brightness level will reset to FLASH_INFO_STRENGTH_DEFAULT_LEVEL.
     * When the client calls setTorchMode(ON) after turnOnTorchWithStrengthLevel(N),
     * the flash unit will have brightness level equal to N. This level does not
     * represent the real brightness units. It is linear in nature i.e. flashlight
     * at level 10 is twice as bright as at level 5.
     *
     * @param torchStrength Brightness level to be set for the flashlight.
     *
     * @return status Status code for the operation, one of:
     *     OK:
     *         On a successful change to the torch strength level.
     *     INTERNAL_ERROR:
     *         The flash unit cannot be operated due to an unexpected internal
     *         error.
     *     CAMERA_IN_USE:
     *         This status code is returned when:
     *           - This camera device has been opened, so the torch cannot be
     *             controlled until it is closed.
     *           - Due to other camera devices being open, or due to other
     *             resource constraints, the torch cannot be controlled currently.
     *     ILLEGAL_ARGUMENT:
     *         If the torchStrength value is not within the range i.e. < 1 or
     *         > FLASH_INFO_STRENGTH_MAXIMUM_LEVEL.
     *     METHOD_NOT_SUPPORTED:
     *         This status code is returned when:
     *           - This camera device does not support direct operation of flashlight
     *             torch mode. The framework must open the camera device and turn
     *             the torch on through the device interface.
     *           - This camera device does not have a flash unit.
     *           - This camera device has flash unit but does not support torch
     *             strength control.
     *     CAMERA_DISCONNECTED:
     *         An external camera device has been disconnected, and is no longer
     *         available. This camera device interface is now stale, and a new
     *         instance must be acquired if the device is reconnected. All
     *         subsequent calls on this interface must return
     *         CAMERA_DISCONNECTED.
     *
     */
    turnOnTorchWithStrengthLevel(int32_t torchStrength) generates (Status status);

    /**
     * getTorchStrengthLevel:
     *
     * Get current torch strength level.
     * If the device supports torch strength control, when the torch is OFF the
     * strength level will reset to default level, so the return
     * value in this case will be equal to FLASH_INFO_STRENGTH_DEFAULT_LEVEL.
     *
     * @return status Status code for the operation, one of:
     *      OK:
     *           On success.
     *      INTERNAL_ERROR:
     *           An unexpected error occurred and the information is not
     *           available.
     *      METHOD_NOT_SUPPORTED:
     *          This status code is returned when:
     *            - This camera device does not support direct operation of flashlight
     *              torch mode. The framework must open the camera device and turn
     *              the torch on through the device interface.
     *            - This camera device does not have a flash unit.
     *            - This camera device has flash unit but does not support torch
     *              strength control.
     *
     * @return torchStrength Current torch strength level.
     *
     */
    getTorchStrengthLevel() generates (Status status, int32_t torchStrength);
};
+149 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <android/hardware/camera/device/3.6/ICameraDevice.h>
#include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.7/ICameraDevice.h>
#include <android/hardware/camera/device/3.8/ICameraDevice.h>
#include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera/device/3.8/ICameraDeviceCallback.h>
@@ -911,6 +912,7 @@ public:
            uint32_t* outBufSize);
    static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
    static Status isLogicalMultiCamera(const camera_metadata_t *staticMeta);
    static bool isTorchStrengthControlSupported(const camera_metadata_t *staticMeta);
    static Status isOfflineSessionSupported(const camera_metadata_t *staticMeta);
    static Status getPhysicalCameraIds(const camera_metadata_t *staticMeta,
            std::unordered_set<std::string> *physicalIds/*out*/);
@@ -2933,6 +2935,137 @@ TEST_P(CameraHidlTest, getCameraCharacteristics) {
    }
}

// Verify that the torch strength level can be set and retrieved successfully.
TEST_P(CameraHidlTest, turnOnTorchWithStrengthLevel) {
    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
    bool torchControlSupported = false;
    bool torchStrengthControlSupported = false;
    Return<void> ret;

    ret = mProvider->isSetTorchModeSupported([&](auto status, bool support) {
        ALOGI("isSetTorchModeSupported returns status:%d supported:%d", (int)status, support);
        ASSERT_EQ(Status::OK, status);
        torchControlSupported = support;
    });

    sp<TorchProviderCb> cb = new TorchProviderCb(this);
    Return<Status> returnStatus = mProvider->setCallback(cb);
    ASSERT_TRUE(returnStatus.isOk());
    ASSERT_EQ(Status::OK, returnStatus);

    for (const auto& name : cameraDeviceNames) {
        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
        int32_t defaultLevel;
        switch (deviceVersion) {
            case CAMERA_DEVICE_API_VERSION_3_8: {
                ::android::sp<::android::hardware::camera::device::V3_8::ICameraDevice> device3_8;
                ALOGI("%s: Testing camera device %s", __FUNCTION__, name.c_str());
                ret = mProvider->getCameraDeviceInterface_V3_x(
                        name, [&](auto status, const auto& device) {
                            ASSERT_EQ(Status::OK, status);
                            ASSERT_NE(device, nullptr);
                            auto castResult = device::V3_8::ICameraDevice::castFrom(device);
                            ASSERT_TRUE(castResult.isOk());
                            device3_8 = castResult;
                        });
                ASSERT_TRUE(ret.isOk());

                ret = device3_8->getCameraCharacteristics([&] (auto s, const auto& chars) {
                    ASSERT_EQ(Status::OK, s);
                    const camera_metadata_t* staticMeta =
                            reinterpret_cast<const camera_metadata_t*>(chars.data());
                    ASSERT_NE(nullptr, staticMeta);
                    torchStrengthControlSupported = isTorchStrengthControlSupported(staticMeta);
                    camera_metadata_ro_entry entry;
                    int rc = find_camera_metadata_ro_entry(staticMeta,
                            ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL, &entry);
                    if (torchStrengthControlSupported) {
                        ASSERT_EQ(rc, 0);
                        ASSERT_GT(entry.count, 0);
                        defaultLevel = *entry.data.i32;
                        ALOGI("Default level is:%d", defaultLevel);
                    }
                });
                ASSERT_TRUE(ret.isOk());
                // If torchStrengthControl is supported, torchControlSupported should be true.
                if (torchStrengthControlSupported) {
                    ASSERT_TRUE(torchControlSupported);
                }
                mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
                returnStatus = device3_8->turnOnTorchWithStrengthLevel(2);
                ASSERT_TRUE(returnStatus.isOk());
                // Method_not_supported check
                if (!torchStrengthControlSupported) {
                    ALOGI("Torch strength control not supported.");
                    ASSERT_EQ(Status::METHOD_NOT_SUPPORTED, returnStatus);
                } else {
                    ASSERT_EQ(Status::OK, returnStatus);
                    if (returnStatus == Status::OK) {
                        {
                            std::unique_lock<std::mutex> l(mTorchLock);
                            while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
                                auto timeout = std::chrono::system_clock::now() +
                                        std::chrono::seconds(kTorchTimeoutSec);
                                ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l,
                                        timeout));
                            }
                            ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
                            mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
                        }
                        ALOGI("getTorchStrengthLevel: Testing");
                        ret = device3_8->getTorchStrengthLevel([&]
                                (auto status, const auto& strengthLevel) {
                                    ASSERT_TRUE(ret.isOk());
                                    ASSERT_EQ(Status::OK, status);
                                    ALOGI("Torch strength level is : %d", strengthLevel);
                                    ASSERT_EQ(strengthLevel, 2);
                                });
                        // Turn OFF the torch and verify torch strength level is reset to default level.
                        ALOGI("Testing torch strength level reset after turning the torch OFF.");
                        returnStatus = device3_8->setTorchMode(TorchMode::OFF);
                        ASSERT_TRUE(returnStatus.isOk());
                        ASSERT_EQ(Status::OK, returnStatus);
                        {
                            std::unique_lock<std::mutex> l(mTorchLock);
                            while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
                                auto timeout = std::chrono::system_clock::now() +
                                        std::chrono::seconds(kTorchTimeoutSec);
                                ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l,
                                        timeout));
                            }
                            ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
                        }
                        ret = device3_8->getTorchStrengthLevel([&]
                                (auto status, const auto& strengthLevel) {
                                    ASSERT_TRUE(ret.isOk());
                                    ASSERT_EQ(Status::OK, status);
                                    ALOGI("Torch strength level after turning OFF torch is : %d",
                                            strengthLevel);
                                    ASSERT_EQ(strengthLevel, defaultLevel);
                                });
                    }
                }
            }
            break;
            case CAMERA_DEVICE_API_VERSION_3_7:
            case CAMERA_DEVICE_API_VERSION_3_6:
            case CAMERA_DEVICE_API_VERSION_3_5:
            case CAMERA_DEVICE_API_VERSION_3_4:
            case CAMERA_DEVICE_API_VERSION_3_3:
            case CAMERA_DEVICE_API_VERSION_3_2:
            case CAMERA_DEVICE_API_VERSION_1_0: {
                ALOGI("Torch strength control feature not supported.");
            }
            break;
            default: {
                ALOGI("Invalid device version.");
                ADD_FAILURE();
            }
            break;
        }
    }
}

//In case it is supported verify that torch can be enabled.
//Check for corresponding toch callbacks as well.
TEST_P(CameraHidlTest, setTorchMode) {
@@ -6600,6 +6733,22 @@ Status CameraHidlTest::isLogicalMultiCamera(const camera_metadata_t *staticMeta)
    return ret;
}

bool CameraHidlTest::isTorchStrengthControlSupported(const camera_metadata_t *staticMetadata) {
    int32_t maxLevel = 0;
    camera_metadata_ro_entry maxEntry;
    int rc = find_camera_metadata_ro_entry(staticMetadata,
            ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL, &maxEntry);
    if (rc != 0) {
        return false;
    }
    maxLevel = *maxEntry.data.i32;
    if (maxLevel > 1) {
        ALOGI("Torch strength control supported.");
        return true;
    }
    return false;
}

// Check if the camera device has logical multi-camera capability.
Status CameraHidlTest::isOfflineSessionSupported(const camera_metadata_t *staticMeta) {
    Status ret = Status::METHOD_NOT_SUPPORTED;