Merge "Use AidlMessageQueue for tuner service"
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 8d5c77f..ee7285d 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -17,6 +17,7 @@
shared_libs: [
"android.hardware.media.omx@1.0",
"libandroidicu",
+ "libfmq",
"libbinder",
"libhidlbase",
"liblog",
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index 65d8d41..5327289 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -40,6 +40,21 @@
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 @@
shared_libs: [
"android.hardware.tv.tuner@1.0",
- "libbinder",
+ "libbase",
"libbinder_ndk",
+ "libcutils",
+ "libfmq",
"libhidlbase",
"liblog",
"libmedia",
@@ -61,7 +78,13 @@
"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 @@
"android.hardware.tv.tuner@1.0",
"libbase",
"libbinder",
+ "libfmq",
"liblog",
"libtunerservice",
"libutils",
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 2b3de17..56cb34c 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -32,14 +32,17 @@
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 @@
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 @@
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
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index 36ccd3e..26591ab 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -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 @@
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);
};
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
index 5a0b47d..5c1bce7 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
@@ -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 @@
*
* {@hide}
*/
+//@VintfStability
interface ITunerService {
/**
@@ -48,4 +52,11 @@
* @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);
}