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

Commit d72f9aed authored by Scott Randolph's avatar Scott Randolph Committed by android-build-merger
Browse files

Merge "Simplify EVS HAL and move to "agressive opens"" into oc-dev

am: 9ee6abd7

Change-Id: I4cb679b8efe5292947d3a06631ca1acdbaf33943
parents 1431dc2f 9ee6abd7
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -28,10 +28,10 @@ interface IEvsCamera {
    /**
     * Returns the ID of this camera.
     *
     * Returns the string id of this camera. This must be the same value as reported in
     * the camera_id field of the CameraDesc structure by EvsEnumerator::getCamerList().
     * Returns the description of this camera. This must be the same value as reported
     * by EvsEnumerator::getCamerList().
     */
    getId() generates (string cameraId);
    getCameraInfo() generates (CameraDesc info);

    /**
     * Specifies the depth of the buffer chain the camera is asked to support.
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ interface IEvsDisplay {
    /**
     * Returns basic information about the EVS display provided by the system.
     *
     * See the description of the DisplayDesc structure below for details.
     * See the description of the DisplayDesc structure for details.
     */
     getDisplayInfo() generates (DisplayDesc info);

+8 −5
Original line number Diff line number Diff line
@@ -31,14 +31,14 @@ interface IEvsEnumerator {
     */
    getCameraList() generates (vec<CameraDesc> cameras);


    /**
     * Get the IEvsCamera associated with a cameraId from a CameraDesc
     *
     * Given a camera's unique cameraId from ca CameraDesc, returns
     * the ICamera interface assocaited with the specified camera.
     * When done using the camera, it must be returned by calling
     * closeCamera on the ICamera interface.
     * the ICamera interface associated with the specified camera.
     * When done using the camera, the caller may release it by calling closeCamera().
     * TODO(b/36122635) Reliance on the sp<> going out of scope is not recommended because the
     * resources may not be released right away due to asynchronos behavior in the hardware binder.
     */
    openCamera(string cameraId) generates (IEvsCamera carCamera);

@@ -57,6 +57,9 @@ interface IEvsEnumerator {
     * There can be at most one EVS display object for the system and this function
     * requests access to it. If the EVS display is not available or is already in use,
     * a null pointer is returned.
     * When done using the display, the caller may release it by calling closeDisplay().
     * TODO(b/36122635) Reliance on the sp<> going out of scope is not recommended because the
     * resources may not be released right away due to asynchronos behavior in the hardware binder.
     */
    openDisplay() generates (IEvsDisplay display);

@@ -64,7 +67,7 @@ interface IEvsEnumerator {
     * Return the specified IEvsDisplay interface as no longer in use
     *
     * When the IEvsDisplay object is no longer required, it must be released.
     * NOTE: All buffer must have been returned to the display before making this call.
     * NOTE: All buffers must have been returned to the display before making this call.
     */
    closeDisplay(IEvsDisplay display);

+5 −0
Original line number Diff line number Diff line
@@ -23,4 +23,9 @@ cc_binary {
        "liblog",
        "libutils",
    ],

    cflags: [
        "-O0",
        "-g",
    ],
}
+67 −33
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#define LOG_TAG "android.hardware.automotive.evs@1.0-service"

#include "EvsCamera.h"
#include "EvsEnumerator.h"

#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
@@ -30,18 +31,15 @@ namespace V1_0 {
namespace implementation {


// These are the special camera names for which we'll initialize custom test data
// Special camera names for which we'll initialize alternate test data
const char EvsCamera::kCameraName_Backup[]    = "backup";
const char EvsCamera::kCameraName_RightTurn[] = "Right Turn";


// Arbitrary limit on number of graphics buffers allowed to be allocated
// Safeguards against unreasonable resource consumption and provides a testable limit
const unsigned MAX_BUFFERS_IN_FLIGHT = 100;


// TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
// As it stands, if the client dies suddenly, the buffer may be stranded.

EvsCamera::EvsCamera(const char *id) :
        mFramesAllowed(0),
        mFramesInUse(0),
@@ -53,22 +51,14 @@ EvsCamera::EvsCamera(const char *id) :

    // Set up dummy data for testing
    if (mDescription.cameraId == kCameraName_Backup) {
        mDescription.hints                  = static_cast<uint32_t>(UsageHint::USAGE_HINT_REVERSE);
        mWidth  = 640;          // full NTSC/VGA
        mHeight = 480;          // full NTSC/VGA
        mDescription.vendorFlags = 0xFFFFFFFF;   // Arbitrary value
        mDescription.defaultHorResolution   = 320;          // 1/2 NTSC/VGA
        mDescription.defaultVerResolution   = 240;          // 1/2 NTSC/VGA
    } else if (mDescription.cameraId == kCameraName_RightTurn) {
        // Nothing but the name and the usage hint
        mDescription.hints                  = static_cast<uint32_t>(UsageHint::USAGE_HINT_RIGHT_TURN);
    } else {
        // Leave empty for a minimalist camera description without even a hint
        mWidth  = 320;          // 1/2 NTSC/VGA
        mHeight = 240;          // 1/2 NTSC/VGA
    }


    // Set our buffer properties
    mWidth  = (mDescription.defaultHorResolution) ? mDescription.defaultHorResolution : 640;
    mHeight = (mDescription.defaultVerResolution) ? mDescription.defaultVerResolution : 480;

    mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
    mUsage  = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE |
              GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
@@ -77,13 +67,26 @@ EvsCamera::EvsCamera(const char *id) :

EvsCamera::~EvsCamera() {
    ALOGD("EvsCamera being destroyed");
    std::lock_guard<std::mutex> lock(mAccessLock);
    forceShutdown();
}


//
// This gets called if another caller "steals" ownership of the camera
//
void EvsCamera::forceShutdown()
{
    ALOGD("EvsCamera forceShutdown");

    // Make sure our output stream is cleaned up
    // (It really should be already)
    stopVideoStream();

    // Claim the lock while we work on internal state
    std::lock_guard <std::mutex> lock(mAccessLock);

    // Drop all the graphics buffers we've been using
    if (mBuffers.size() > 0) {
        GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
        for (auto&& rec : mBuffers) {
            if (rec.inUse) {
@@ -92,17 +95,21 @@ EvsCamera::~EvsCamera() {
            alloc.free(rec.handle);
            rec.handle = nullptr;
        }
        mBuffers.clear();
    }

    ALOGD("EvsCamera destroyed");
    // Put this object into an unrecoverable error state since somebody else
    // is going to own the underlying camera now
    mStreamState = DEAD;
}


// Methods from ::android::hardware::automotive::evs::V1_0::IEvsCamera follow.
Return<void> EvsCamera::getId(getId_cb id_cb) {
    ALOGD("getId");

    id_cb(mDescription.cameraId);
Return<void> EvsCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
    ALOGD("getCameraInfo");

    // Send back our self description
    _hidl_cb(mDescription);
    return Void();
}

@@ -111,6 +118,12 @@ Return<EvsResult> EvsCamera::setMaxFramesInFlight(uint32_t bufferCount) {
    ALOGD("setMaxFramesInFlight");
    std::lock_guard<std::mutex> lock(mAccessLock);

    // If we've been displaced by another owner of the camera, then we can't do anything else
    if (mStreamState == DEAD) {
        ALOGE("ignoring setMaxFramesInFlight call when camera has been lost.");
        return EvsResult::OWNERSHIP_LOST;
    }

    // We cannot function without at least one video buffer to send data
    if (bufferCount < 1) {
        ALOGE("Ignoring setMaxFramesInFlight with less than one buffer requested");
@@ -130,6 +143,11 @@ Return<EvsResult> EvsCamera::startVideoStream(const ::android::sp<IEvsCameraStre
    ALOGD("startVideoStream");
    std::lock_guard<std::mutex> lock(mAccessLock);

    // If we've been displaced by another owner of the camera, then we can't do anything else
    if (mStreamState == DEAD) {
        ALOGE("ignoring startVideoStream call when camera has been lost.");
        return EvsResult::OWNERSHIP_LOST;
    }
    if (mStreamState != STOPPED) {
        ALOGE("ignoring startVideoStream call when a stream is already running.");
        return EvsResult::STREAM_ALREADY_RUNNING;
@@ -207,6 +225,7 @@ Return<void> EvsCamera::stopVideoStream() {
        lock.lock();

        mStreamState = STOPPED;
        mStream = nullptr;
        ALOGD("Stream marked STOPPED.");
    }

@@ -232,6 +251,12 @@ Return<EvsResult> EvsCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/, int3
    ALOGD("setExtendedInfo");
    std::lock_guard<std::mutex> lock(mAccessLock);

    // If we've been displaced by another owner of the camera, then we can't do anything else
    if (mStreamState == DEAD) {
        ALOGE("ignoring setExtendedInfo call when camera has been lost.");
        return EvsResult::OWNERSHIP_LOST;
    }

    // We don't store any device specific information in this implementation
    return EvsResult::INVALID_ARG;
}
@@ -358,7 +383,9 @@ void EvsCamera::generateFrames() {

    while (true) {
        bool timeForFrame = false;
        // Lock scope
        nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);

        // Lock scope for updating shared state
        {
            std::lock_guard<std::mutex> lock(mAccessLock);

@@ -427,8 +454,15 @@ void EvsCamera::generateFrames() {
            }
        }

        // We arbitrarily choose to generate frames at 10 fps (1/10 * uSecPerSec)
        usleep(100000);
        // We arbitrarily choose to generate frames at 12 fps to ensure we pass the 10fps test requirement
        static const int kTargetFrameRate = 12;
        static const nsecs_t kTargetFrameTimeUs = 1000*1000 / kTargetFrameRate;
        const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        const nsecs_t workTimeUs = (now - startTime) / 1000;
        const nsecs_t sleepDurationUs = kTargetFrameTimeUs - workTimeUs;
        if (sleepDurationUs > 0) {
            usleep(sleepDurationUs);
        }
    }

    // If we've been asked to stop, send one last NULL frame to signal the actual end of stream
Loading