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

Commit 6d266261 authored by shubang's avatar shubang
Browse files

Use AidlMessageQueue for tuner service

Test: mmm
Change-Id: I002823d97400b8865edadfadc0293f304f93e0d8
parent 204fafe4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ cc_binary {
    shared_libs: [
        "android.hardware.media.omx@1.0",
        "libandroidicu",
        "libfmq",
        "libbinder",
        "libhidlbase",
        "liblog",
+26 −2
Original line number Diff line number Diff line
@@ -40,6 +40,21 @@ aidl_interface {
    srcs: [
        ":tv_tuner_aidl",
    ],
    imports: [
        "android.hardware.common.fmq",
    ],

    backend: {
        java: {
            enabled: false,
        },
        cpp: {
            enabled: false,
        },
        ndk: {
            enabled: true,
        },
    },
}

cc_library {
@@ -52,8 +67,10 @@ cc_library {

    shared_libs: [
        "android.hardware.tv.tuner@1.0",
        "libbinder",
        "libbase",
        "libbinder_ndk",
        "libcutils",
        "libfmq",
        "libhidlbase",
        "liblog",
        "libmedia",
@@ -61,7 +78,13 @@ cc_library {
        "tv_tuner_aidl_interface-ndk_platform",
    ],

    include_dirs: ["frameworks/av/include"],
    static_libs: [
        "android.hardware.common.fmq-unstable-ndk_platform",
    ],

    include_dirs: [
      "frameworks/av/include"
    ],

    cflags: [
        "-Werror",
@@ -83,6 +106,7 @@ cc_binary {
        "android.hardware.tv.tuner@1.0",
        "libbase",
        "libbinder",
        "libfmq",
        "liblog",
        "libtunerservice",
        "libutils",
+172 −6
Original line number Diff line number Diff line
@@ -32,14 +32,17 @@ using ::aidl::android::media::tv::tuner::TunerFrontendIsdbs3Capabilities;
using ::aidl::android::media::tv::tuner::TunerFrontendIsdbsCapabilities;
using ::aidl::android::media::tv::tuner::TunerFrontendIsdbtCapabilities;
using ::android::hardware::hidl_vec;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendType;
using ::android::hardware::tv::tuner::V1_0::Result;

namespace android {

sp<ITuner> TunerService::mTuner;

TunerService::TunerService() {}
TunerService::~TunerService() {}

@@ -47,17 +50,160 @@ void TunerService::instantiate() {
    std::shared_ptr<TunerService> service =
            ::ndk::SharedRefBase::make<TunerService>();
    AServiceManager_addService(service->asBinder().get(), getServiceName());
}

template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
bool TunerService::unsafeHidlToAidlMQDescriptor(
        const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidlDesc,
        MQDescriptor<AidlPayload, AidlFlavor>* aidlDesc) {
    // TODO: use the builtin coversion method when it's merged.
    ALOGD("unsafeHidlToAidlMQDescriptor");
    static_assert(sizeof(HidlPayload) == sizeof(AidlPayload), "Payload types are incompatible");
    static_assert(
            has_typedef_fixed_size<AidlPayload>::value == true ||
            std::is_fundamental<AidlPayload>::value ||
            std::is_enum<AidlPayload>::value,
            "Only fundamental types, enums, and AIDL parcelables annotated with @FixedSize "
            "and built for the NDK backend are supported as AIDL payload types.");
    aidlDesc->fileDescriptor = ndk::ScopedFileDescriptor(dup(hidlDesc.handle()->data[0]));
    for (const auto& grantor : hidlDesc.grantors()) {
        if (static_cast<int32_t>(grantor.offset) < 0 || static_cast<int64_t>(grantor.extent) < 0) {
            ALOGD("Unsafe static_cast of grantor fields. offset=%d, extend=%ld",
                    static_cast<int32_t>(grantor.offset), static_cast<long>(grantor.extent));
            logError(
                    "Unsafe static_cast of grantor fields. Either the hardware::MQDescriptor is "
                    "invalid, or the MessageQueue is too large to be described by AIDL.");
            return false;
        }
        aidlDesc->grantors.push_back(
                GrantorDescriptor {
                        .offset = static_cast<int32_t>(grantor.offset),
                        .extent = static_cast<int64_t>(grantor.extent)
                });
    }
    if (static_cast<int32_t>(hidlDesc.getQuantum()) < 0 ||
            static_cast<int32_t>(hidlDesc.getFlags()) < 0) {
        ALOGD("Unsafe static_cast of quantum or flags. Quantum=%d, flags=%d",
                static_cast<int32_t>(hidlDesc.getQuantum()),
                static_cast<int32_t>(hidlDesc.getFlags()));
        logError(
                "Unsafe static_cast of quantum or flags. Either the hardware::MQDescriptor is "
                "invalid, or the MessageQueue is too large to be described by AIDL.");
        return false;
    }
    aidlDesc->quantum = static_cast<int32_t>(hidlDesc.getQuantum());
    aidlDesc->flags = static_cast<int32_t>(hidlDesc.getFlags());
    return true;
}

bool TunerService::getITuner() {
    ALOGD("getITuner");
    if (mTuner != nullptr) {
        return true;
    }
    mTuner = ITuner::getService();
    if (mTuner == nullptr) {
        ALOGE("Failed to get ITuner service.");
        ALOGE("Failed to get ITuner service");
        return false;
    }
    return true;
}

Result TunerService::openDemux() {
    ALOGD("openDemux");
    if (!getITuner()) {
        return Result::NOT_INITIALIZED;
    }
    if (mDemux != nullptr) {
        return Result::SUCCESS;
    }
    Result res;
    uint32_t id;
    sp<IDemux> demuxSp;
    mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
        demuxSp = demux;
        id = demuxId;
        res = r;
        ALOGD("open demux, id = %d", demuxId);
    });
    if (res == Result::SUCCESS) {
        mDemux = demuxSp;
    } else {
        ALOGD("open demux failed, res = %d", res);
    }
    return res;
}

Result TunerService::openFilter() {
    ALOGD("openFilter");
    if (!getITuner()) {
        return Result::NOT_INITIALIZED;
    }
    DemuxFilterMainType mainType = DemuxFilterMainType::TS;
    DemuxFilterType filterType {
        .mainType = mainType,
    };
    filterType.subType.tsFilterType(DemuxTsFilterType::VIDEO);

    sp<FilterCallback> callback = new FilterCallback();
    Result res;
    mDemux->openFilter(filterType, 16000000, callback,
            [&](Result r, const sp<IFilter>& filter) {
                mFilter = filter;
                res = r;
            });
    if (res != Result::SUCCESS || mFilter == NULL) {
        ALOGD("Failed to open filter, type = %d", filterType.mainType);
        return res;
    }

    return Result::SUCCESS;
}

Result TunerService::configFilter() {
    ALOGD("configFilter");
    if (mFilter == NULL) {
        ALOGD("Failed to configure filter: filter not found");
        return Result::NOT_INITIALIZED;
    }
    DemuxFilterSettings filterSettings;
    DemuxTsFilterSettings tsFilterSettings {
        .tpid = 256,
    };
    DemuxFilterAvSettings filterAvSettings {
        .isPassthrough = false,
    };
    tsFilterSettings.filterSettings.av(filterAvSettings);
    filterSettings.ts(tsFilterSettings);
    Result res = mFilter->configure(filterSettings);

    if (res != Result::SUCCESS) {
        ALOGD("config filter failed, res = %d", res);
        return res;
    }

    Result getQueueDescResult = Result::UNKNOWN_ERROR;
    mFilter->getQueueDesc(
            [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
                mFilterMQDesc = desc;
                getQueueDescResult = r;
                ALOGD("getFilterQueueDesc");
            });
    if (getQueueDescResult == Result::SUCCESS) {
        unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
                mFilterMQDesc,  &mAidlMQDesc);
        mAidlMq = new (std::nothrow) AidlMessageQueue(mAidlMQDesc);
        EventFlag::createEventFlag(mAidlMq->getEventFlagWord(), &mEventFlag);
    } else {
        ALOGD("get MQDesc failed, res = %d", getQueueDescResult);
    }
    return getQueueDescResult;
}

Status TunerService::getFrontendIds(std::vector<int32_t>* ids, int32_t* /* _aidl_return */) {
    if (mTuner == nullptr) {
        ALOGE("ITuner service is not init.");
    if (!getITuner()) {
        return ::ndk::ScopedAStatus::fromServiceSpecificError(
                static_cast<int32_t>(Result::UNAVAILABLE));
                static_cast<int32_t>(Result::NOT_INITIALIZED));
    }
    hidl_vec<FrontendId> feIds;
    Result res;
@@ -221,4 +367,24 @@ TunerServiceFrontendInfo TunerService::convertToAidlFrontendInfo(int feId, Front
    info.caps = caps;
    return info;
}

Status TunerService::getFmqSyncReadWrite(
        MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) {
    ALOGD("getFmqSyncReadWrite");
    // TODO: put the following methods AIDL, and should be called from clients.
    openDemux();
    openFilter();
    configFilter();
    mFilter->start();
    if (mqDesc == nullptr) {
        ALOGD("getFmqSyncReadWrite null MQDescriptor.");
        *_aidl_return = false;
    } else {
        ALOGD("getFmqSyncReadWrite true");
        *_aidl_return = true;
        *mqDesc = std::move(mAidlMQDesc);
    }
    return ndk::ScopedAStatus::ok();
}

} // namespace android
+61 −2
Original line number Diff line number Diff line
@@ -20,17 +20,59 @@
#include <aidl/android/media/tv/tuner/BnTunerService.h>
#include <aidl/android/media/tv/tuner/TunerServiceFrontendInfo.h>
#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <fmq/AidlMessageQueue.h>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>

using Status = ::ndk::ScopedAStatus;
using ::aidl::android::hardware::common::fmq::GrantorDescriptor;
using ::aidl::android::hardware::common::fmq::MQDescriptor;
using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
using ::aidl::android::media::tv::tuner::BnTunerService;
using ::aidl::android::media::tv::tuner::ITunerFrontend;
using ::aidl::android::media::tv::tuner::TunerServiceFrontendInfo;

using ::android::hardware::details::logError;
using ::android::hardware::EventFlag;
using ::android::hardware::kSynchronizedReadWrite;
using ::android::hardware::MessageQueue;
using ::android::hardware::MQDescriptorSync;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendInfo;
using ::android::hardware::tv::tuner::V1_0::IDemux;
using ::android::hardware::tv::tuner::V1_0::IFilter;
using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
using ::android::hardware::tv::tuner::V1_0::ITuner;
using ::android::hardware::tv::tuner::V1_0::Result;

using Status = ::ndk::ScopedAStatus;

namespace android {


struct FilterCallback : public IFilterCallback {
    ~FilterCallback() {}
    Return<void> onFilterEvent(const DemuxFilterEvent&) {
        return Void();
    }
    Return<void> onFilterStatus(const DemuxFilterStatus) {
        return Void();
    }
};

class TunerService : public BnTunerService {
    typedef AidlMessageQueue<int8_t, SynchronizedReadWrite> AidlMessageQueue;
    typedef MessageQueue<uint8_t, kSynchronizedReadWrite> HidlMessageQueue;
    typedef MQDescriptor<int8_t, SynchronizedReadWrite> AidlMQDesc;

public:
    static char const *getServiceName() { return "media.tuner"; }
@@ -46,10 +88,27 @@ public:
    Status getFrontendInfo(int32_t frontendHandle, TunerServiceFrontendInfo* _aidl_return) override;
    Status openFrontend(
            int32_t frontendHandle, std::shared_ptr<ITunerFrontend>* _aidl_return) override;
    Status getFmqSyncReadWrite(
            MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) override;

private:
    static sp<ITuner> mTuner;
    template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
    bool unsafeHidlToAidlMQDescriptor(
            const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidl,
            MQDescriptor<AidlPayload, AidlFlavor>* aidl);

    bool getITuner();
    Result openFilter();
    Result openDemux();
    Result configFilter();

    sp<ITuner> mTuner;
    sp<IDemux> mDemux;
    sp<IFilter> mFilter;
    AidlMessageQueue* mAidlMq;
    MQDescriptorSync<uint8_t> mFilterMQDesc;
    AidlMQDesc mAidlMQDesc;
    EventFlag* mEventFlag;
    TunerServiceFrontendInfo convertToAidlFrontendInfo(int feId, FrontendInfo halInfo);
};

+11 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.media.tv.tuner;

import android.hardware.common.fmq.MQDescriptor;
import android.hardware.common.fmq.SynchronizedReadWrite;
import android.hardware.common.fmq.UnsynchronizedWrite;
import android.media.tv.tuner.ITunerFrontend;
import android.media.tv.tuner.TunerServiceFrontendInfo;

@@ -24,6 +27,7 @@ import android.media.tv.tuner.TunerServiceFrontendInfo;
 *
 * {@hide}
 */
//@VintfStability
interface ITunerService {

    /**
@@ -48,4 +52,11 @@ interface ITunerService {
     * @return the aidl interface of the frontend.
     */
    ITunerFrontend openFrontend(in int frontendHandle);

    /*
     * Gets synchronized fast message queue.
     *
     * @return true if succeeds, false otherwise.
     */
    boolean getFmqSyncReadWrite(out MQDescriptor<byte, SynchronizedReadWrite> mqDesc);
}