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

Commit 3b4b8661 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Use AidlMessageQueue for tuner service"

parents f12daa4e 6d266261
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);
}