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

Commit b97cceb4 authored by Tanmay Patil's avatar Tanmay Patil
Browse files

Adds default implementation for ultrasonics HAL

- Replicates logic from camera for default impl.

Bug: 148619310
Fixes: b/148608401
Test: Builds, VTS passes.

Change-Id: I5c1b4c615f98cb7405a9a233a7853daba09cc63d
parent 496b86cc
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ cc_binary {
        "EvsDisplay.cpp",
        "ConfigManager.cpp",
        "ConfigManagerUtil.cpp",
        "EvsUltrasonicsArray.cpp",
    ],
    init_rc: ["android.hardware.automotive.evs@1.1-service.rc"],

@@ -17,11 +18,14 @@ cc_binary {
        "android.hardware.automotive.evs@1.0",
        "android.hardware.automotive.evs@1.1",
        "android.hardware.camera.device@3.3",
        "android.hidl.allocator@1.0",
        "android.hidl.memory@1.0",
        "libbase",
        "libbinder",
        "liblog",
        "libhardware",
        "libhidlbase",
        "libhidlmemory",
        "liblog",
        "libui",
        "libutils",
+95 −16
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include "EvsEnumerator.h"
#include "EvsCamera.h"
#include "EvsDisplay.h"
#include "EvsUltrasonicsArray.h"

namespace android {
namespace hardware {
@@ -36,7 +37,7 @@ wp<EvsDisplay> EvsEnumerator::sActiveDisplay;
unique_ptr<ConfigManager>                           EvsEnumerator::sConfigManager;
sp<IAutomotiveDisplayProxyService>                  EvsEnumerator::sDisplayProxyService;
std::unordered_map<uint8_t, uint64_t>               EvsEnumerator::sDisplayPortList;

std::list<EvsEnumerator::UltrasonicsArrayRecord>    EvsEnumerator::sUltrasonicsArrayRecordList;

EvsEnumerator::EvsEnumerator(sp<IAutomotiveDisplayProxyService> windowService) {
    ALOGD("EvsEnumerator created");
@@ -66,6 +67,10 @@ EvsEnumerator::EvsEnumerator(sp<IAutomotiveDisplayProxyService> windowService) {
            }
        });
    }

    // Add ultrasonics array desc.
    sUltrasonicsArrayRecordList.emplace_back(
            EvsUltrasonicsArray::GetDummyArrayDesc("front_array"));
}


@@ -355,25 +360,99 @@ EvsEnumerator::CameraRecord* EvsEnumerator::findCameraById(const std::string& ca
    return pRecord;
}

// TODO(b/148608401): Add default implementation with dummy data.
EvsEnumerator::UltrasonicsArrayRecord* EvsEnumerator::findUltrasonicsArrayById(
        const std::string& ultrasonicsArrayId) {
    auto recordIt = std::find_if(
            sUltrasonicsArrayRecordList.begin(), sUltrasonicsArrayRecordList.end(),
                    [&ultrasonicsArrayId](const UltrasonicsArrayRecord& record) {
                            return ultrasonicsArrayId == record.desc.ultrasonicsArrayId;});

    return (recordIt != sUltrasonicsArrayRecordList.end()) ? &*recordIt : nullptr;
}

Return<void> EvsEnumerator::getUltrasonicsArrayList(getUltrasonicsArrayList_cb _hidl_cb) {
    hidl_vec<UltrasonicsArrayDesc> ultrasonicsArrayDesc;
    _hidl_cb(ultrasonicsArrayDesc);
    hidl_vec<UltrasonicsArrayDesc> desc;
    desc.resize(sUltrasonicsArrayRecordList.size());

    // Copy over desc from sUltrasonicsArrayRecordList.
    for (auto p = std::make_pair(sUltrasonicsArrayRecordList.begin(), desc.begin());
            p.first != sUltrasonicsArrayRecordList.end(); p.first++, p.second++) {
        *p.second = p.first->desc;
    }

    // Send back the results
    ALOGD("reporting %zu ultrasonics arrays available", desc.size());
    _hidl_cb(desc);

    // HIDL convention says we return Void if we sent our result back via callback
    return Void();
}

// TODO(b/148608401): Add default implementation with dummy data.
Return<sp<IEvsUltrasonicsArray>> EvsEnumerator::openUltrasonicsArray(
        const hidl_string& ultrasonicsArrayId) {
    (void)ultrasonicsArrayId;
    sp<IEvsUltrasonicsArray> pEvsUltrasonicsArray;
    return pEvsUltrasonicsArray;
    // Find the named ultrasonic array.
    UltrasonicsArrayRecord* pRecord = findUltrasonicsArrayById(ultrasonicsArrayId);

    // Is this a recognized ultrasonic array id?
    if (!pRecord) {
        ALOGE("Requested ultrasonics array %s not found", ultrasonicsArrayId.c_str());
        return nullptr;
    }

    // Has this ultrasonic array already been instantiated by another caller?
    sp<EvsUltrasonicsArray> pActiveUltrasonicsArray = pRecord->activeInstance.promote();
    if (pActiveUltrasonicsArray != nullptr) {
        ALOGW("Killing previous ultrasonics array because of new caller");
        closeUltrasonicsArray(pActiveUltrasonicsArray);
    }

    // Construct a ultrasonic array instance for the caller
    pActiveUltrasonicsArray = EvsUltrasonicsArray::Create(ultrasonicsArrayId.c_str());
    pRecord->activeInstance = pActiveUltrasonicsArray;
    if (pActiveUltrasonicsArray == nullptr) {
        ALOGE("Failed to allocate new EvsUltrasonicsArray object for %s\n",
              ultrasonicsArrayId.c_str());
    }

    return pActiveUltrasonicsArray;
}

// TODO(b/148608401): Add default implementation with dummy data.
Return<void> EvsEnumerator::closeUltrasonicsArray(
        const ::android::sp<IEvsUltrasonicsArray>& evsUltrasonicsArray)  {
    (void)evsUltrasonicsArray;
        const sp<IEvsUltrasonicsArray>& pEvsUltrasonicsArray) {

    if (pEvsUltrasonicsArray.get() == nullptr) {
        ALOGE("Ignoring call to closeUltrasonicsArray with null ultrasonics array");
        return Void();
    }

    // Get the ultrasonics array id so we can find it in our list.
    std::string ultrasonicsArrayId;
    pEvsUltrasonicsArray->getUltrasonicArrayInfo([&ultrasonicsArrayId](UltrasonicsArrayDesc desc) {
        ultrasonicsArrayId.assign(desc.ultrasonicsArrayId);
    });

    // Find the named ultrasonics array
    UltrasonicsArrayRecord* pRecord = findUltrasonicsArrayById(ultrasonicsArrayId);
    if (!pRecord) {
        ALOGE("Asked to close a ultrasonics array whose name isnt not found");
        return Void();
    }

    sp<EvsUltrasonicsArray> pActiveUltrasonicsArray = pRecord->activeInstance.promote();

    if (pActiveUltrasonicsArray.get() == nullptr) {
        ALOGE("Somehow a ultrasonics array is being destroyed when the enumerator didn't know "
              "one existed");
    } else if (pActiveUltrasonicsArray != pEvsUltrasonicsArray) {
        // This can happen if the ultrasonics array was aggressively reopened,
        // orphaning this previous instance
        ALOGW("Ignoring close of previously orphaned ultrasonics array - why did a client steal?");
    } else {
        // Drop the active ultrasonics array
        pActiveUltrasonicsArray->forceShutdown();
        pRecord->activeInstance = nullptr;
    }

    return Void();
}

+13 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <android/hardware/automotive/evs/1.1/IEvsCamera.h>
#include <android/hardware/automotive/evs/1.1/IEvsDisplay.h>
#include <android/frameworks/automotive/display/1.0/IAutomotiveDisplayProxyService.h>
#include <android/hardware/automotive/evs/1.1/IEvsUltrasonicsArray.h>

#include <list>

@@ -46,6 +47,7 @@ namespace implementation {

class EvsCamera;    // from EvsCamera.h
class EvsDisplay;   // from EvsDisplay.h
class EvsUltrasonicsArray;  // from EvsUltrasonicsArray.h


class EvsEnumerator : public IEvsEnumerator {
@@ -85,10 +87,21 @@ private:
        CameraRecord(const char *cameraId) : desc() { desc.v1.cameraId = cameraId; }
    };

    struct UltrasonicsArrayRecord {
        UltrasonicsArrayDesc desc;
        wp<EvsUltrasonicsArray> activeInstance;

        UltrasonicsArrayRecord(const UltrasonicsArrayDesc& arrayDesc) : desc(arrayDesc) {};
    };

    static CameraRecord* findCameraById(const std::string& cameraId);

    static std::list<CameraRecord>   sCameraList;

    static UltrasonicsArrayRecord* findUltrasonicsArrayById(const std::string& ultrasonicsArrayId);

    static std::list<UltrasonicsArrayRecord> sUltrasonicsArrayRecordList;

    // Weak pointer. Object destructs if client dies.
    static wp<EvsDisplay>            sActiveDisplay;

+551 −0

File added.

Preview size limit exceeded, changes collapsed.

+134 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSULTRASONICSARRAY_H
#define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSULTRASONICSARRAY_H

#include <thread>
#include <utility>

#include <android-base/macros.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <utils/threads.h>

#include <android/hardware/automotive/evs/1.1/IEvsUltrasonicsArray.h>
#include <android/hardware/automotive/evs/1.1/IEvsUltrasonicsArrayStream.h>
#include <android/hardware/automotive/evs/1.1/types.h>

using ::android::hardware::hidl_memory;
using ::android::hardware::automotive::evs::V1_0::EvsResult;
using ::android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArray;
using ::android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArrayStream;
using ::android::hardware::automotive::evs::V1_1::UltrasonicsArrayDesc;
using ::android::hardware::automotive::evs::V1_1::UltrasonicsDataFrameDesc;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;

namespace android {
namespace hardware {
namespace automotive {
namespace evs {
namespace V1_1 {
namespace implementation {

class EvsUltrasonicsArray : public IEvsUltrasonicsArray {
  public:
    // Methods from ::android::hardware::automotive::evs::V1_1::IEvsUltrasonicsArray follow.
    Return<void> getUltrasonicArrayInfo(getUltrasonicArrayInfo_cb _get_info_cb) override;
    Return<EvsResult> setMaxFramesInFlight(uint32_t bufferCount) override;
    Return<void> doneWithDataFrame(const UltrasonicsDataFrameDesc& dataFrameDesc) override;
    Return<EvsResult> startStream(const ::android::sp<IEvsUltrasonicsArrayStream>& stream) override;
    Return<void> stopStream() override;

    // Factory function to create a array.
    static sp<EvsUltrasonicsArray> Create(const char* deviceName);

    // Returns a ultrasonics array descriptor filled with sample data.
    static UltrasonicsArrayDesc GetDummyArrayDesc(const char* id);

    DISALLOW_COPY_AND_ASSIGN(EvsUltrasonicsArray);
    virtual ~EvsUltrasonicsArray() override;
    void forceShutdown();  // This gets called if another caller "steals" ownership

  private:
    // Structure holding the hidl memory struct and the interface to a shared memory.
    struct SharedMemory {
        hidl_memory hidlMemory;
        sp<IMemory> pIMemory;

        SharedMemory() : hidlMemory(hidl_memory()), pIMemory(nullptr){};

        SharedMemory(hidl_memory hidlMem, sp<IMemory> pIMem)
            : hidlMemory(hidlMem), pIMemory(pIMem) {}

        bool IsValid() { return (pIMemory.get() != nullptr && hidlMemory.valid()); }

        void clear() {
            hidlMemory = hidl_memory();
            pIMemory.clear();
        }
    };

    // Struct for a data frame record.
    struct DataFrameRecord {
        SharedMemory sharedMemory;
        bool inUse;
        explicit DataFrameRecord(SharedMemory shMem) : sharedMemory(shMem), inUse(false){};
    };

    enum StreamStateValues {
        STOPPED,
        RUNNING,
        STOPPING,
        DEAD,
    };

    EvsUltrasonicsArray(const char* deviceName);

    // These three functions are expected to be called while mAccessLock is held
    bool setAvailableFrames_Locked(unsigned bufferCount);
    unsigned increaseAvailableFrames_Locked(unsigned numToAdd);
    unsigned decreaseAvailableFrames_Locked(unsigned numToRemove);

    void generateDataFrames();

    SharedMemory allocateAndMapSharedMemory();

    UltrasonicsArrayDesc mArrayDesc = {};  // The properties of this ultrasonic array.

    std::thread mCaptureThread;  // The thread we'll use to synthesize frames

    sp<IEvsUltrasonicsArrayStream> mStream = nullptr;  // The callback used to deliver each frame

    sp<IAllocator> mShmemAllocator = nullptr;  // Shared memory allocator.

    std::mutex mAccessLock;
    std::vector<DataFrameRecord> mDataFrames GUARDED_BY(mAccessLock);  // Shared memory buffers.
    unsigned mFramesAllowed GUARDED_BY(mAccessLock);  // How many buffers are we currently using.
    unsigned mFramesInUse GUARDED_BY(mAccessLock);  // How many buffers are currently outstanding.

    StreamStateValues mStreamState GUARDED_BY(mAccessLock);
};

}  // namespace implementation
}  // namespace V1_1
}  // namespace evs
}  // namespace automotive
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSULTRASONICSARRAY_H