Merge "Add tuner legacy HIDL HAL support."
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index 8a1d45c..b2b1c3b 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -36,9 +36,12 @@
srcs: [
"Tuner*.cpp",
+ "hidl/Tuner*.cpp",
],
shared_libs: [
+ "android.hardware.tv.tuner@1.0",
+ "android.hardware.tv.tuner@1.1",
"android.hardware.tv.tuner-V1-ndk",
"libbase",
"libbinder",
@@ -79,6 +82,8 @@
],
shared_libs: [
+ "android.hardware.tv.tuner@1.0",
+ "android.hardware.tv.tuner@1.1",
"android.hardware.tv.tuner-V1-ndk",
"libbase",
"libbinder",
diff --git a/services/tuner/TunerFilter.h b/services/tuner/TunerFilter.h
index 86d178c..06c5b80 100644
--- a/services/tuner/TunerFilter.h
+++ b/services/tuner/TunerFilter.h
@@ -88,9 +88,6 @@
};
private:
- bool isAudioFilter();
- bool isVideoFilter();
-
shared_ptr<IFilter> mFilter;
int32_t mId;
int64_t mId64Bit;
diff --git a/services/tuner/TunerHelper.cpp b/services/tuner/TunerHelper.cpp
new file mode 100644
index 0000000..dc67110
--- /dev/null
+++ b/services/tuner/TunerHelper.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#include "TunerHelper.h"
+
+#include <aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.h>
+#include <android/binder_manager.h>
+#include <android/content/pm/IPackageManagerNative.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+using ::aidl::android::media::tv::tunerresourcemanager::ITunerResourceManager;
+using ::android::defaultServiceManager;
+using ::android::IBinder;
+using ::android::interface_cast;
+using ::android::IServiceManager;
+using ::android::sp;
+using ::android::binder::Status;
+using ::android::content::pm::IPackageManagerNative;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+// System Feature defined in PackageManager
+static const ::android::String16 FEATURE_TUNER(::android::String16("android.hardware.tv.tuner"));
+
+int32_t TunerHelper::sResourceRequestCount = 0;
+
+bool TunerHelper::checkTunerFeature() {
+ sp<IServiceManager> serviceMgr = defaultServiceManager();
+ sp<IPackageManagerNative> packageMgr;
+ if (serviceMgr.get() == nullptr) {
+ ALOGE("%s: Cannot find service manager", __func__);
+ return false;
+ }
+
+ sp<IBinder> binder = serviceMgr->waitForService(String16("package_native"));
+ packageMgr = interface_cast<IPackageManagerNative>(binder);
+ if (packageMgr != nullptr) {
+ bool hasFeature = false;
+ Status status = packageMgr->hasSystemFeature(FEATURE_TUNER, 0, &hasFeature);
+ if (!status.isOk()) {
+ ALOGE("%s: hasSystemFeature failed: %s", __func__, status.exceptionMessage().c_str());
+ return false;
+ }
+ if (!hasFeature) {
+ ALOGD("Current device does not support tuner feaure.");
+ return false;
+ }
+ } else {
+ ALOGD("%s: Cannot find package manager.", __func__);
+ return false;
+ }
+
+ return true;
+}
+
+// TODO: update Demux, Descrambler.
+void TunerHelper::updateTunerResources(const vector<TunerFrontendInfo>& feInfos,
+ const vector<int32_t>& lnbHandles) {
+ ::ndk::SpAIBinder binder(AServiceManager_waitForService("tv_tuner_resource_mgr"));
+ shared_ptr<ITunerResourceManager> tunerRM = ITunerResourceManager::fromBinder(binder);
+ if (tunerRM == nullptr) {
+ return;
+ }
+
+ tunerRM->setFrontendInfoList(feInfos);
+ tunerRM->setLnbInfoList(lnbHandles);
+}
+
+// TODO: create a map between resource id and handles.
+int TunerHelper::getResourceIdFromHandle(int resourceHandle, int /*type*/) {
+ return (resourceHandle & 0x00ff0000) >> 16;
+}
+
+int TunerHelper::getResourceHandleFromId(int id, int resourceType) {
+ // TODO: build up randomly generated id to handle mapping
+ return (resourceType & 0x000000ff) << 24 | (id << 16) | (sResourceRequestCount++ & 0xffff);
+}
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
diff --git a/services/tuner/TunerHelper.h b/services/tuner/TunerHelper.h
new file mode 100644
index 0000000..0d8d6a5
--- /dev/null
+++ b/services/tuner/TunerHelper.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2021 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_MEDIA_TUNERDVRHELPER_H
+#define ANDROID_MEDIA_TUNERDVRHELPER_H
+
+#include <aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.h>
+#include <utils/String16.h>
+
+using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
+using ::android::String16;
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+const static int TUNER_HAL_VERSION_UNKNOWN = 0;
+const static int TUNER_HAL_VERSION_1_0 = 1 << 16;
+const static int TUNER_HAL_VERSION_1_1 = (1 << 16) | 1;
+const static int TUNER_HAL_VERSION_2_0 = 2 << 16;
+
+typedef enum {
+ FRONTEND,
+ LNB,
+ DEMUX,
+ DESCRAMBLER,
+} TunerResourceType;
+
+class TunerHelper {
+public:
+ static bool checkTunerFeature();
+
+ // TODO: update Demux, Descrambler.
+ static void updateTunerResources(const vector<TunerFrontendInfo>& feInfos,
+ const vector<int32_t>& lnbHandles);
+ // TODO: create a map between resource id and handles.
+ static int getResourceIdFromHandle(int resourceHandle, int type);
+ static int getResourceHandleFromId(int id, int resourceType);
+
+private:
+ static int32_t sResourceRequestCount;
+};
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
+
+#endif // ANDROID_MEDIA_TUNERDVRHELPER_H
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 0703700..fe5d4ca 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -24,30 +24,20 @@
#include <aidl/android/hardware/tv/tuner/IFrontend.h>
#include <aidl/android/hardware/tv/tuner/ILnb.h>
#include <aidl/android/hardware/tv/tuner/Result.h>
-#include <aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.h>
#include <android/binder_manager.h>
-#include <android/content/pm/IPackageManagerNative.h>
-#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include "TunerDemux.h"
#include "TunerDescrambler.h"
#include "TunerFrontend.h"
+#include "TunerHelper.h"
#include "TunerLnb.h"
using ::aidl::android::hardware::tv::tuner::IDemux;
using ::aidl::android::hardware::tv::tuner::IDescrambler;
using ::aidl::android::hardware::tv::tuner::IFrontend;
using ::aidl::android::hardware::tv::tuner::Result;
-using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
-using ::android::defaultServiceManager;
-using ::android::IBinder;
-using ::android::interface_cast;
-using ::android::IServiceManager;
using ::android::sp;
-using ::android::String16;
-using ::android::binder::Status;
-using ::android::content::pm::IPackageManagerNative;
namespace aidl {
namespace android {
@@ -56,34 +46,11 @@
namespace tuner {
TunerService::TunerService() {
- sp<IServiceManager> serviceMgr = defaultServiceManager();
- sp<IPackageManagerNative> packageMgr;
- if (serviceMgr.get() == nullptr) {
- ALOGE("%s: Cannot find service manager", __func__);
- return;
- } else {
- sp<IBinder> binder = serviceMgr->waitForService(String16("package_native"));
- packageMgr = interface_cast<IPackageManagerNative>(binder);
- }
-
- if (packageMgr != nullptr) {
- bool hasFeature = false;
- Status status = packageMgr->hasSystemFeature(FEATURE_TUNER, 0, &hasFeature);
- if (!status.isOk()) {
- ALOGE("%s: hasSystemFeature failed: %s", __func__, status.exceptionMessage().c_str());
- return;
- }
- if (!hasFeature) {
- ALOGD("Current device does not support tuner feaure.");
- return;
- }
- } else {
- ALOGD("%s: Cannot find package manager.", __func__);
+ if (!TunerHelper::checkTunerFeature()) {
+ ALOGD("Device doesn't have tuner hardware.");
return;
}
- ::ndk::SpAIBinder binder(AServiceManager_waitForService("tv_tuner_resource_mgr"));
- mTunerResourceManager = ITunerResourceManager::fromBinder(binder);
updateTunerResources();
}
@@ -174,7 +141,7 @@
static_cast<int32_t>(Result::UNAVAILABLE));
}
- int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
+ int id = TunerHelper::getResourceIdFromHandle(frontendHandle, FRONTEND);
shared_ptr<IFrontend> frontend;
auto status = mTuner->openFrontendById(id, &frontend);
if (status.isOk()) {
@@ -192,7 +159,7 @@
}
shared_ptr<ILnb> lnb;
- int id = getResourceIdFromHandle(lnbHandle, LNB);
+ int id = TunerHelper::getResourceIdFromHandle(lnbHandle, LNB);
auto status = mTuner->openLnbById(id, &lnb);
if (status.isOk()) {
*_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, id);
@@ -228,7 +195,7 @@
}
shared_ptr<IDescrambler> descrambler;
- // int id = getResourceIdFromHandle(descramblerHandle, DESCRAMBLER);
+ // int id = TunerHelper::getResourceIdFromHandle(descramblerHandle, DESCRAMBLER);
auto status = mTuner->openDescrambler(&descrambler);
if (status.isOk()) {
*_aidl_return = ::ndk::SharedRefBase::make<TunerDescrambler>(descrambler);
@@ -237,31 +204,29 @@
return status;
}
-void TunerService::updateTunerResources() {
- if (!hasITuner() || mTunerResourceManager == nullptr) {
- ALOGE("Failed to updateTunerResources");
- return;
- }
-
- updateFrontendResources();
- updateLnbResources();
- // TODO: update Demux, Descrambler.
-}
-
::ndk::ScopedAStatus TunerService::getTunerHalVersion(int* _aidl_return) {
hasITuner();
*_aidl_return = mTunerVersion;
return ::ndk::ScopedAStatus::ok();
}
-void TunerService::updateFrontendResources() {
- vector<int32_t> ids;
- auto status = mTuner->getFrontendIds(&ids);
- if (!status.isOk()) {
+void TunerService::updateTunerResources() {
+ if (!hasITuner()) {
+ ALOGE("Failed to updateTunerResources");
return;
}
+ TunerHelper::updateTunerResources(getTRMFrontendInfos(), getTRMLnbHandles());
+}
+
+vector<TunerFrontendInfo> TunerService::getTRMFrontendInfos() {
vector<TunerFrontendInfo> infos;
+ vector<int32_t> ids;
+ auto status = mTuner->getFrontendIds(&ids);
+ if (!status.isOk()) {
+ return infos;
+ }
+
for (int i = 0; i < ids.size(); i++) {
FrontendInfo frontendInfo;
auto res = mTuner->getFrontendInfo(ids[i], &frontendInfo);
@@ -269,31 +234,24 @@
continue;
}
TunerFrontendInfo tunerFrontendInfo{
- .handle = getResourceHandleFromId((int)ids[i], FRONTEND),
+ .handle = TunerHelper::getResourceHandleFromId((int)ids[i], FRONTEND),
.type = static_cast<int>(frontendInfo.type),
.exclusiveGroupId = frontendInfo.exclusiveGroupId,
};
infos.push_back(tunerFrontendInfo);
}
- mTunerResourceManager->setFrontendInfoList(infos);
+
+ return infos;
}
-void TunerService::updateLnbResources() {
- vector<int32_t> handles = getLnbHandles();
- if (handles.size() == 0) {
- return;
- }
- mTunerResourceManager->setLnbInfoList(handles);
-}
-
-vector<int32_t> TunerService::getLnbHandles() {
+vector<int32_t> TunerService::getTRMLnbHandles() {
vector<int32_t> lnbHandles;
if (mTuner != nullptr) {
vector<int32_t> lnbIds;
auto res = mTuner->getLnbIds(&lnbIds);
if (res.isOk()) {
for (int i = 0; i < lnbIds.size(); i++) {
- lnbHandles.push_back(getResourceHandleFromId(lnbIds[i], LNB));
+ lnbHandles.push_back(TunerHelper::getResourceHandleFromId(lnbIds[i], LNB));
}
}
}
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index 164bef8..159e53e 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -17,20 +17,24 @@
#ifndef ANDROID_MEDIA_TUNERSERVICE_H
#define ANDROID_MEDIA_TUNERSERVICE_H
-#include <aidl/android/hardware/tv/tuner/BnFilterCallback.h>
#include <aidl/android/hardware/tv/tuner/DemuxFilterEvent.h>
#include <aidl/android/hardware/tv/tuner/DemuxFilterStatus.h>
#include <aidl/android/hardware/tv/tuner/ITuner.h>
#include <aidl/android/media/tv/tuner/BnTunerService.h>
-#include <aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.h>
+#include <aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.h>
-using ::aidl::android::hardware::tv::tuner::BnFilterCallback;
+#include "TunerHelper.h"
+
using ::aidl::android::hardware::tv::tuner::DemuxCapabilities;
using ::aidl::android::hardware::tv::tuner::DemuxFilterEvent;
using ::aidl::android::hardware::tv::tuner::DemuxFilterStatus;
using ::aidl::android::hardware::tv::tuner::FrontendInfo;
using ::aidl::android::hardware::tv::tuner::ITuner;
-using ::aidl::android::media::tv::tunerresourcemanager::ITunerResourceManager;
+using ::aidl::android::media::tv::tuner::BnTunerService;
+using ::aidl::android::media::tv::tuner::ITunerDemux;
+using ::aidl::android::media::tv::tuner::ITunerFrontend;
+using ::aidl::android::media::tv::tuner::ITunerLnb;
+using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
using namespace std;
@@ -40,32 +44,6 @@
namespace tv {
namespace tuner {
-const static int TUNER_HAL_VERSION_UNKNOWN = 0;
-const static int TUNER_HAL_VERSION_1_0 = 1 << 16;
-const static int TUNER_HAL_VERSION_1_1 = (1 << 16) | 1;
-const static int TUNER_HAL_VERSION_2_0 = 2 << 16;
-// System Feature defined in PackageManager
-static const ::android::String16 FEATURE_TUNER(::android::String16("android.hardware.tv.tuner"));
-
-typedef enum {
- FRONTEND,
- LNB,
- DEMUX,
- DESCRAMBLER,
-} TunerResourceType;
-
-struct FilterCallback : public BnFilterCallback {
- ~FilterCallback() {}
- virtual ::ndk::ScopedAStatus onFilterEvent(
- const vector<DemuxFilterEvent>& /* events */) override {
- return ::ndk::ScopedAStatus::ok();
- }
-
- virtual ::ndk::ScopedAStatus onFilterStatus(const DemuxFilterStatus /*status*/) override {
- return ::ndk::ScopedAStatus::ok();
- }
-};
-
class TunerService : public BnTunerService {
public:
static char const *getServiceName() { return "media.tuner"; }
@@ -89,28 +67,13 @@
shared_ptr<ITunerDescrambler>* _aidl_return) override;
::ndk::ScopedAStatus getTunerHalVersion(int32_t* _aidl_return) override;
- // TODO: create a map between resource id and handles.
- static int getResourceIdFromHandle(int resourceHandle, int /*type*/) {
- return (resourceHandle & 0x00ff0000) >> 16;
- }
-
- int getResourceHandleFromId(int id, int resourceType) {
- // TODO: build up randomly generated id to handle mapping
- return (resourceType & 0x000000ff) << 24
- | (id << 16)
- | (mResourceRequestCount++ & 0xffff);
- }
-
private:
bool hasITuner();
void updateTunerResources();
- void updateFrontendResources();
- void updateLnbResources();
- vector<int32_t> getLnbHandles();
+ vector<TunerFrontendInfo> getTRMFrontendInfos();
+ vector<int32_t> getTRMLnbHandles();
shared_ptr<ITuner> mTuner;
- shared_ptr<ITunerResourceManager> mTunerResourceManager;
- int mResourceRequestCount = 0;
int mTunerVersion = TUNER_HAL_VERSION_UNKNOWN;
};
diff --git a/services/tuner/hidl/TunerHidlDemux.cpp b/services/tuner/hidl/TunerHidlDemux.cpp
new file mode 100644
index 0000000..5a921b9
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlDemux.cpp
@@ -0,0 +1,278 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#define LOG_TAG "TunerHidlDemux"
+
+#include "TunerHidlDemux.h"
+
+#include "TunerHidlDvr.h"
+#include "TunerHidlFilter.h"
+#include "TunerHidlTimeFilter.h"
+
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSubType;
+
+using HidlDemuxAlpFilterType = ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
+using HidlDemuxFilterMainType = ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using HidlDemuxFilterType = ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using HidlDemuxIpFilterType = ::android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
+using HidlDemuxMmtpFilterType = ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using HidlDemuxTlvFilterType = ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
+using HidlDemuxTsFilterType = ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using HidlDvrType = ::android::hardware::tv::tuner::V1_0::DvrType;
+using HidlResult = ::android::hardware::tv::tuner::V1_0::Result;
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+TunerHidlDemux::TunerHidlDemux(sp<IDemux> demux, int id) {
+ mDemux = demux;
+ mDemuxId = id;
+}
+
+TunerHidlDemux::~TunerHidlDemux() {
+ mDemux = nullptr;
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::setFrontendDataSource(
+ const shared_ptr<ITunerFrontend>& in_frontend) {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ int frontendId;
+ in_frontend->getFrontendId(&frontendId);
+ HidlResult res = mDemux->setFrontendDataSource(frontendId);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::setFrontendDataSourceById(int frontendId) {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ HidlResult res = mDemux->setFrontendDataSource(frontendId);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::openFilter(const DemuxFilterType& in_type,
+ int32_t in_bufferSize,
+ const shared_ptr<ITunerFilterCallback>& in_cb,
+ shared_ptr<ITunerFilter>* _aidl_return) {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ HidlDemuxFilterMainType mainType = static_cast<HidlDemuxFilterMainType>(in_type.mainType);
+ HidlDemuxFilterType filterType{
+ .mainType = mainType,
+ };
+
+ switch (mainType) {
+ case HidlDemuxFilterMainType::TS:
+ filterType.subType.tsFilterType(static_cast<HidlDemuxTsFilterType>(
+ in_type.subType.get<DemuxFilterSubType::Tag::tsFilterType>()));
+ break;
+ case HidlDemuxFilterMainType::MMTP:
+ filterType.subType.mmtpFilterType(static_cast<HidlDemuxMmtpFilterType>(
+ in_type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>()));
+ break;
+ case HidlDemuxFilterMainType::IP:
+ filterType.subType.ipFilterType(static_cast<HidlDemuxIpFilterType>(
+ in_type.subType.get<DemuxFilterSubType::Tag::ipFilterType>()));
+ break;
+ case HidlDemuxFilterMainType::TLV:
+ filterType.subType.tlvFilterType(static_cast<HidlDemuxTlvFilterType>(
+ in_type.subType.get<DemuxFilterSubType::Tag::tlvFilterType>()));
+ break;
+ case HidlDemuxFilterMainType::ALP:
+ filterType.subType.alpFilterType(static_cast<HidlDemuxAlpFilterType>(
+ in_type.subType.get<DemuxFilterSubType::Tag::alpFilterType>()));
+ break;
+ }
+ HidlResult status;
+ sp<HidlIFilter> filterSp;
+ sp<::android::hardware::tv::tuner::V1_0::IFilterCallback> cbSp =
+ new TunerHidlFilter::FilterCallback(in_cb);
+ mDemux->openFilter(filterType, static_cast<uint32_t>(in_bufferSize), cbSp,
+ [&](HidlResult r, const sp<HidlIFilter>& filter) {
+ filterSp = filter;
+ status = r;
+ });
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlFilter>(filterSp, in_type);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::openTimeFilter(shared_ptr<ITunerTimeFilter>* _aidl_return) {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ HidlResult status;
+ sp<HidlITimeFilter> filterSp;
+ mDemux->openTimeFilter([&](HidlResult r, const sp<HidlITimeFilter>& filter) {
+ filterSp = filter;
+ status = r;
+ });
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlTimeFilter>(filterSp);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::getAvSyncHwId(const shared_ptr<ITunerFilter>& tunerFilter,
+ int32_t* _aidl_return) {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ uint32_t avSyncHwId;
+ HidlResult res;
+ sp<HidlIFilter> halFilter = static_cast<TunerHidlFilter*>(tunerFilter.get())->getHalFilter();
+ mDemux->getAvSyncHwId(halFilter, [&](HidlResult r, uint32_t id) {
+ res = r;
+ avSyncHwId = id;
+ });
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ *_aidl_return = (int)avSyncHwId;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::getAvSyncTime(int32_t avSyncHwId, int64_t* _aidl_return) {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ uint64_t time;
+ HidlResult res;
+ mDemux->getAvSyncTime(static_cast<uint32_t>(avSyncHwId), [&](HidlResult r, uint64_t ts) {
+ res = r;
+ time = ts;
+ });
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ *_aidl_return = (int64_t)time;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::openDvr(DvrType in_dvbType, int32_t in_bufferSize,
+ const shared_ptr<ITunerDvrCallback>& in_cb,
+ shared_ptr<ITunerDvr>* _aidl_return) {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ HidlResult res;
+ sp<HidlIDvrCallback> callback = new TunerHidlDvr::DvrCallback(in_cb);
+ sp<HidlIDvr> hidlDvr;
+ mDemux->openDvr(static_cast<HidlDvrType>(in_dvbType), in_bufferSize, callback,
+ [&](HidlResult r, const sp<HidlIDvr>& dvr) {
+ hidlDvr = dvr;
+ res = r;
+ });
+ if (res != HidlResult::SUCCESS) {
+ *_aidl_return = nullptr;
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlDvr>(hidlDvr, in_dvbType);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::connectCiCam(int32_t ciCamId) {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ HidlResult res = mDemux->connectCiCam(static_cast<uint32_t>(ciCamId));
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::disconnectCiCam() {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ HidlResult res = mDemux->disconnectCiCam();
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDemux::close() {
+ if (mDemux == nullptr) {
+ ALOGE("IDemux is not initialized.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(HidlResult::UNAVAILABLE));
+ }
+
+ HidlResult res = mDemux->close();
+ mDemux = nullptr;
+
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
diff --git a/services/tuner/hidl/TunerHidlDemux.h b/services/tuner/hidl/TunerHidlDemux.h
new file mode 100644
index 0000000..d535da6
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlDemux.h
@@ -0,0 +1,75 @@
+/**
+ * Copyright 2021, 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_MEDIA_TUNERHIDLDEMUX_H
+#define ANDROID_MEDIA_TUNERHIDLDEMUX_H
+
+#include <aidl/android/media/tv/tuner/BnTunerDemux.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+
+using ::aidl::android::hardware::tv::tuner::DemuxFilterType;
+using ::aidl::android::hardware::tv::tuner::DvrType;
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::std::shared_ptr;
+using ::std::vector;
+
+using HidlIDemux = ::android::hardware::tv::tuner::V1_0::IDemux;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+class TunerHidlDemux : public BnTunerDemux {
+public:
+ TunerHidlDemux(sp<HidlIDemux> demux, int demuxId);
+ virtual ~TunerHidlDemux();
+
+ ::ndk::ScopedAStatus setFrontendDataSource(
+ const shared_ptr<ITunerFrontend>& in_frontend) override;
+ ::ndk::ScopedAStatus setFrontendDataSourceById(int frontendId) override;
+ ::ndk::ScopedAStatus openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize,
+ const shared_ptr<ITunerFilterCallback>& in_cb,
+ shared_ptr<ITunerFilter>* _aidl_return) override;
+ ::ndk::ScopedAStatus openTimeFilter(shared_ptr<ITunerTimeFilter>* _aidl_return) override;
+ ::ndk::ScopedAStatus getAvSyncHwId(const shared_ptr<ITunerFilter>& in_tunerFilter,
+ int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) override;
+ ::ndk::ScopedAStatus openDvr(DvrType in_dvbType, int32_t in_bufferSize,
+ const shared_ptr<ITunerDvrCallback>& in_cb,
+ shared_ptr<ITunerDvr>* _aidl_return) override;
+ ::ndk::ScopedAStatus connectCiCam(int32_t in_ciCamId) override;
+ ::ndk::ScopedAStatus disconnectCiCam() override;
+ ::ndk::ScopedAStatus close() override;
+
+ int getId() { return mDemuxId; }
+
+private:
+ sp<HidlIDemux> mDemux;
+ int mDemuxId;
+};
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
+
+#endif // ANDROID_MEDIA_TUNERHIDLDEMUX_H
diff --git a/services/tuner/hidl/TunerHidlDescrambler.cpp b/services/tuner/hidl/TunerHidlDescrambler.cpp
new file mode 100644
index 0000000..dd8cd9c
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlDescrambler.cpp
@@ -0,0 +1,149 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#define LOG_TAG "TunerHidlDescrambler"
+
+#include "TunerHidlDescrambler.h"
+
+#include <aidl/android/hardware/tv/tuner/Result.h>
+
+#include "TunerHidlDemux.h"
+#include "TunerHidlFilter.h"
+
+using ::aidl::android::hardware::tv::tuner::Result;
+
+using HidlResult = ::android::hardware::tv::tuner::V1_0::Result;
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+TunerHidlDescrambler::TunerHidlDescrambler(sp<HidlIDescrambler> descrambler) {
+ mDescrambler = descrambler;
+}
+
+TunerHidlDescrambler::~TunerHidlDescrambler() {
+ mDescrambler = nullptr;
+}
+
+::ndk::ScopedAStatus TunerHidlDescrambler::setDemuxSource(
+ const shared_ptr<ITunerDemux>& in_tunerDemux) {
+ if (mDescrambler == nullptr) {
+ ALOGE("IDescrambler is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mDescrambler->setDemuxSource(
+ static_cast<TunerHidlDemux*>(in_tunerDemux.get())->getId());
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDescrambler::setKeyToken(const vector<uint8_t>& in_keyToken) {
+ if (mDescrambler == nullptr) {
+ ALOGE("IDescrambler is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mDescrambler->setKeyToken(in_keyToken);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDescrambler::addPid(
+ const DemuxPid& in_pid, const shared_ptr<ITunerFilter>& in_optionalSourceFilter) {
+ if (mDescrambler == nullptr) {
+ ALOGE("IDescrambler is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ sp<HidlIFilter> halFilter =
+ (in_optionalSourceFilter == nullptr)
+ ? nullptr
+ : static_cast<TunerHidlFilter*>(in_optionalSourceFilter.get())->getHalFilter();
+ HidlResult res = mDescrambler->addPid(getHidlDemuxPid(in_pid), halFilter);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDescrambler::removePid(
+ const DemuxPid& in_pid, const shared_ptr<ITunerFilter>& in_optionalSourceFilter) {
+ if (mDescrambler == nullptr) {
+ ALOGE("IDescrambler is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ sp<HidlIFilter> halFilter =
+ (in_optionalSourceFilter == nullptr)
+ ? nullptr
+ : static_cast<TunerHidlFilter*>(in_optionalSourceFilter.get())->getHalFilter();
+ HidlResult res = mDescrambler->removePid(getHidlDemuxPid(in_pid), halFilter);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDescrambler::close() {
+ if (mDescrambler == nullptr) {
+ ALOGE("IDescrambler is not initialized.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mDescrambler->close();
+ mDescrambler = nullptr;
+
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+HidlDemuxPid TunerHidlDescrambler::getHidlDemuxPid(const DemuxPid& pid) {
+ HidlDemuxPid hidlPid;
+ switch (pid.getTag()) {
+ case DemuxPid::tPid: {
+ hidlPid.tPid((uint16_t)pid.get<DemuxPid::Tag::tPid>());
+ break;
+ }
+ case DemuxPid::mmtpPid: {
+ hidlPid.mmtpPid((uint16_t)pid.get<DemuxPid::Tag::mmtpPid>());
+ break;
+ }
+ }
+ return hidlPid;
+}
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
diff --git a/services/tuner/hidl/TunerHidlDescrambler.h b/services/tuner/hidl/TunerHidlDescrambler.h
new file mode 100644
index 0000000..9494968
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlDescrambler.h
@@ -0,0 +1,66 @@
+/**
+ * Copyright 2021, 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_MEDIA_TUNERHIDLDESCRAMBLER_H
+#define ANDROID_MEDIA_TUNERHIDLDESCRAMBLER_H
+
+#include <aidl/android/hardware/tv/tuner/IDescrambler.h>
+#include <aidl/android/media/tv/tuner/BnTunerDescrambler.h>
+#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+
+using ::aidl::android::hardware::tv::tuner::DemuxPid;
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using HidlDemuxPid = ::android::hardware::tv::tuner::V1_0::DemuxPid;
+using HidlIDescrambler = ::android::hardware::tv::tuner::V1_0::IDescrambler;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+class TunerHidlDescrambler : public BnTunerDescrambler {
+public:
+ TunerHidlDescrambler(sp<HidlIDescrambler> descrambler);
+ virtual ~TunerHidlDescrambler();
+
+ ::ndk::ScopedAStatus setDemuxSource(const std::shared_ptr<ITunerDemux>& in_tunerDemux) override;
+ ::ndk::ScopedAStatus setKeyToken(const std::vector<uint8_t>& in_keyToken) override;
+ ::ndk::ScopedAStatus addPid(
+ const DemuxPid& in_pid,
+ const std::shared_ptr<ITunerFilter>& in_optionalSourceFilter) override;
+ ::ndk::ScopedAStatus removePid(
+ const DemuxPid& in_pid,
+ const std::shared_ptr<ITunerFilter>& in_optionalSourceFilter) override;
+ ::ndk::ScopedAStatus close() override;
+
+private:
+ HidlDemuxPid getHidlDemuxPid(const DemuxPid& pid);
+
+ sp<HidlIDescrambler> mDescrambler;
+};
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
+
+#endif // ANDROID_MEDIA_TUNERHIDLDESCRAMBLER_H
diff --git a/services/tuner/hidl/TunerHidlDvr.cpp b/services/tuner/hidl/TunerHidlDvr.cpp
new file mode 100644
index 0000000..1a619d5
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlDvr.cpp
@@ -0,0 +1,257 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#define LOG_TAG "TunerHidlDvr"
+
+#include "TunerHidlDvr.h"
+
+#include <aidl/android/hardware/tv/tuner/DataFormat.h>
+#include <aidl/android/hardware/tv/tuner/PlaybackStatus.h>
+#include <aidl/android/hardware/tv/tuner/RecordStatus.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <fmq/ConvertMQDescriptors.h>
+
+using ::aidl::android::hardware::tv::tuner::DataFormat;
+using ::aidl::android::hardware::tv::tuner::PlaybackStatus;
+using ::aidl::android::hardware::tv::tuner::RecordStatus;
+using ::aidl::android::hardware::tv::tuner::Result;
+using ::android::unsafeHidlToAidlMQDescriptor;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+
+using HidlDataFormat = ::android::hardware::tv::tuner::V1_0::DataFormat;
+using HidlResult = ::android::hardware::tv::tuner::V1_0::Result;
+using MQDesc = MQDescriptorSync<uint8_t>;
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+TunerHidlDvr::TunerHidlDvr(sp<HidlIDvr> dvr, DvrType type) {
+ mDvr = dvr;
+ mType = type;
+}
+
+TunerHidlDvr::~TunerHidlDvr() {
+ mDvr = nullptr;
+}
+
+::ndk::ScopedAStatus TunerHidlDvr::getQueueDesc(AidlMQDesc* _aidl_return) {
+ if (mDvr == nullptr) {
+ ALOGE("IDvr is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ MQDesc dvrMQDesc;
+ HidlResult res;
+ mDvr->getQueueDesc([&](HidlResult r, const MQDesc& desc) {
+ dvrMQDesc = desc;
+ res = r;
+ });
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ AidlMQDesc aidlMQDesc;
+ unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(dvrMQDesc, &aidlMQDesc);
+ *_aidl_return = move(aidlMQDesc);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDvr::configure(const DvrSettings& in_settings) {
+ if (mDvr == nullptr) {
+ ALOGE("IDvr is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mDvr->configure(getHidlDvrSettings(in_settings));
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDvr::attachFilter(const shared_ptr<ITunerFilter>& in_filter) {
+ if (mDvr == nullptr) {
+ ALOGE("IDvr is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (in_filter == nullptr) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+
+ sp<HidlIFilter> hidlFilter = static_cast<TunerHidlFilter*>(in_filter.get())->getHalFilter();
+ if (hidlFilter == nullptr) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+
+ HidlResult res = mDvr->attachFilter(hidlFilter);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDvr::detachFilter(const shared_ptr<ITunerFilter>& in_filter) {
+ if (mDvr == nullptr) {
+ ALOGE("IDvr is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (in_filter == nullptr) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+
+ sp<HidlIFilter> halFilter = (static_cast<TunerHidlFilter*>(in_filter.get()))->getHalFilter();
+ if (halFilter == nullptr) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+
+ HidlResult res = mDvr->detachFilter(halFilter);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDvr::start() {
+ if (mDvr == nullptr) {
+ ALOGE("IDvr is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mDvr->start();
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDvr::stop() {
+ if (mDvr == nullptr) {
+ ALOGE("IDvr is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mDvr->stop();
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDvr::flush() {
+ if (mDvr == nullptr) {
+ ALOGE("IDvr is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mDvr->flush();
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlDvr::close() {
+ if (mDvr == nullptr) {
+ ALOGE("IDvr is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mDvr->close();
+ mDvr = nullptr;
+
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+HidlDvrSettings TunerHidlDvr::getHidlDvrSettings(const DvrSettings& settings) {
+ HidlDvrSettings s;
+ switch (mType) {
+ case DvrType::PLAYBACK: {
+ s.playback({
+ .statusMask =
+ static_cast<uint8_t>(settings.get<DvrSettings::playback>().statusMask),
+ .lowThreshold =
+ static_cast<uint32_t>(settings.get<DvrSettings::playback>().lowThreshold),
+ .highThreshold =
+ static_cast<uint32_t>(settings.get<DvrSettings::playback>().highThreshold),
+ .dataFormat = static_cast<HidlDataFormat>(
+ settings.get<DvrSettings::playback>().dataFormat),
+ .packetSize =
+ static_cast<uint8_t>(settings.get<DvrSettings::playback>().packetSize),
+ });
+ return s;
+ }
+ case DvrType::RECORD: {
+ s.record({
+ .statusMask = static_cast<uint8_t>(settings.get<DvrSettings::record>().statusMask),
+ .lowThreshold =
+ static_cast<uint32_t>(settings.get<DvrSettings::record>().lowThreshold),
+ .highThreshold =
+ static_cast<uint32_t>(settings.get<DvrSettings::record>().highThreshold),
+ .dataFormat =
+ static_cast<HidlDataFormat>(settings.get<DvrSettings::record>().dataFormat),
+ .packetSize = static_cast<uint8_t>(settings.get<DvrSettings::record>().packetSize),
+ });
+ return s;
+ }
+ default:
+ break;
+ }
+ return s;
+}
+
+/////////////// IDvrCallback ///////////////////////
+Return<void> TunerHidlDvr::DvrCallback::onRecordStatus(const HidlRecordStatus status) {
+ if (mTunerDvrCallback != nullptr) {
+ mTunerDvrCallback->onRecordStatus(static_cast<RecordStatus>(status));
+ }
+ return Void();
+}
+
+Return<void> TunerHidlDvr::DvrCallback::onPlaybackStatus(const HidlPlaybackStatus status) {
+ if (mTunerDvrCallback != nullptr) {
+ mTunerDvrCallback->onPlaybackStatus(static_cast<PlaybackStatus>(status));
+ }
+ return Void();
+}
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
diff --git a/services/tuner/hidl/TunerHidlDvr.h b/services/tuner/hidl/TunerHidlDvr.h
new file mode 100644
index 0000000..a280ff7
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlDvr.h
@@ -0,0 +1,91 @@
+/**
+ * Copyright 2021, 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_MEDIA_TUNERHIDLDVR_H
+#define ANDROID_MEDIA_TUNERHIDLDVR_H
+
+#include <aidl/android/hardware/tv/tuner/DvrSettings.h>
+#include <aidl/android/hardware/tv/tuner/DvrType.h>
+#include <aidl/android/media/tv/tuner/BnTunerDvr.h>
+#include <aidl/android/media/tv/tuner/ITunerDvrCallback.h>
+#include <android/hardware/tv/tuner/1.0/IDvr.h>
+#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
+
+#include "TunerHidlFilter.h"
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::aidl::android::hardware::tv::tuner::DvrSettings;
+using ::aidl::android::hardware::tv::tuner::DvrType;
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::std::shared_ptr;
+using ::std::vector;
+
+using HidlDvrSettings = ::android::hardware::tv::tuner::V1_0::DvrSettings;
+using HidlIDvr = ::android::hardware::tv::tuner::V1_0::IDvr;
+using HidlIDvrCallback = ::android::hardware::tv::tuner::V1_0::IDvrCallback;
+using HidlPlaybackStatus = ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
+using HidlRecordStatus = ::android::hardware::tv::tuner::V1_0::RecordStatus;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+using AidlMQDesc = MQDescriptor<int8_t, SynchronizedReadWrite>;
+
+class TunerHidlDvr : public BnTunerDvr {
+public:
+ TunerHidlDvr(sp<HidlIDvr> dvr, DvrType type);
+ ~TunerHidlDvr();
+
+ ::ndk::ScopedAStatus getQueueDesc(AidlMQDesc* _aidl_return) override;
+ ::ndk::ScopedAStatus configure(const DvrSettings& in_settings) override;
+ ::ndk::ScopedAStatus attachFilter(const shared_ptr<ITunerFilter>& in_filter) override;
+ ::ndk::ScopedAStatus detachFilter(const shared_ptr<ITunerFilter>& in_filter) override;
+ ::ndk::ScopedAStatus start() override;
+ ::ndk::ScopedAStatus stop() override;
+ ::ndk::ScopedAStatus flush() override;
+ ::ndk::ScopedAStatus close() override;
+
+ struct DvrCallback : public HidlIDvrCallback {
+ DvrCallback(const shared_ptr<ITunerDvrCallback> tunerDvrCallback)
+ : mTunerDvrCallback(tunerDvrCallback){};
+
+ virtual Return<void> onRecordStatus(const HidlRecordStatus status);
+ virtual Return<void> onPlaybackStatus(const HidlPlaybackStatus status);
+
+ private:
+ shared_ptr<ITunerDvrCallback> mTunerDvrCallback;
+ };
+
+private:
+ HidlDvrSettings getHidlDvrSettings(const DvrSettings& settings);
+
+ sp<HidlIDvr> mDvr;
+ DvrType mType;
+};
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
+
+#endif // ANDROID_MEDIA_TUNERHIDLDVR_H
diff --git a/services/tuner/hidl/TunerHidlFilter.cpp b/services/tuner/hidl/TunerHidlFilter.cpp
new file mode 100644
index 0000000..1573c8e
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlFilter.cpp
@@ -0,0 +1,1002 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#define LOG_TAG "TunerHidlFilter"
+
+#include "TunerHidlFilter.h"
+
+#include <aidl/android/hardware/tv/tuner/Constant.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <fmq/ConvertMQDescriptors.h>
+
+using ::aidl::android::hardware::tv::tuner::AudioExtraMetaData;
+using ::aidl::android::hardware::tv::tuner::Constant;
+using ::aidl::android::hardware::tv::tuner::DemuxAlpFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxAlpFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterDownloadEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterIpPayloadEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMainType;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMediaEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMediaEventExtraMetaData;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMmtpRecordEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMonitorEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterPesEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterScIndexMask;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionBits;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionSettingsCondition;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionSettingsConditionTableInfo;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSubType;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterTemiEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterTsRecordEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxIpAddress;
+using ::aidl::android::hardware::tv::tuner::DemuxIpAddressIpAddress;
+using ::aidl::android::hardware::tv::tuner::DemuxIpFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxIpFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterType;
+using ::aidl::android::hardware::tv::tuner::DemuxPid;
+using ::aidl::android::hardware::tv::tuner::DemuxTlvFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxTlvFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxTsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxTsFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxTsFilterType;
+using ::aidl::android::hardware::tv::tuner::Result;
+using ::aidl::android::hardware::tv::tuner::ScramblingStatus;
+using ::android::dupToAidl;
+using ::android::makeFromAidl;
+using ::android::unsafeHidlToAidlMQDescriptor;
+using ::android::hardware::hidl_handle;
+
+using HidlDemuxAlpLengthType = ::android::hardware::tv::tuner::V1_0::DemuxAlpLengthType;
+using HidlDemuxFilterMainType = ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using HidlDemuxIpAddress = ::android::hardware::tv::tuner::V1_0::DemuxIpAddress;
+using HidlDemuxMmtpFilterType = ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using HidlDemuxMmtpPid = ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid;
+using HidlDemuxRecordScIndexType = ::android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
+using HidlDemuxStreamId = ::android::hardware::tv::tuner::V1_0::DemuxStreamId;
+using HidlDemuxTsFilterType = ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using HidlResult = ::android::hardware::tv::tuner::V1_0::Result;
+using HidlAudioStreamType = ::android::hardware::tv::tuner::V1_1::AudioStreamType;
+using HidlConstant = ::android::hardware::tv::tuner::V1_1::Constant;
+using HidlVideoStreamType = ::android::hardware::tv::tuner::V1_1::VideoStreamType;
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+TunerHidlFilter::TunerHidlFilter(sp<HidlIFilter> filter, DemuxFilterType type)
+ : mFilter(filter), mType(type) {
+ mFilter_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(filter);
+}
+
+TunerHidlFilter::~TunerHidlFilter() {
+ mFilter = nullptr;
+ mFilter_1_1 = nullptr;
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::getQueueDesc(AidlMQDesc* _aidl_return) {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ MQDesc filterMQDesc;
+ HidlResult res;
+ mFilter->getQueueDesc([&](HidlResult r, const MQDesc& desc) {
+ filterMQDesc = desc;
+ res = r;
+ });
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ AidlMQDesc aidlMQDesc;
+ unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(filterMQDesc, &aidlMQDesc);
+ *_aidl_return = move(aidlMQDesc);
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::getId(int32_t* _aidl_return) {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res;
+ mFilter->getId([&](HidlResult r, uint32_t filterId) {
+ res = r;
+ mId = filterId;
+ });
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ *_aidl_return = mId;
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::getId64Bit(int64_t* _aidl_return) {
+ if (mFilter_1_1 == nullptr) {
+ ALOGE("IFilter_1_1 is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res;
+ mFilter_1_1->getId64Bit([&](HidlResult r, uint64_t filterId) {
+ res = r;
+ mId64Bit = filterId;
+ });
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ *_aidl_return = mId64Bit;
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::configure(const DemuxFilterSettings& in_settings) {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlDemuxFilterSettings settings;
+ switch (in_settings.getTag()) {
+ case DemuxFilterSettings::ts: {
+ getHidlTsSettings(in_settings, settings);
+ break;
+ }
+ case DemuxFilterSettings::mmtp: {
+ getHidlMmtpSettings(in_settings, settings);
+ break;
+ }
+ case DemuxFilterSettings::ip: {
+ getHidlIpSettings(in_settings, settings);
+ break;
+ }
+ case DemuxFilterSettings::tlv: {
+ getHidlTlvSettings(in_settings, settings);
+ break;
+ }
+ case DemuxFilterSettings::alp: {
+ getHidlAlpSettings(in_settings, settings);
+ break;
+ }
+ }
+
+ HidlResult res = mFilter->configure(settings);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::configureMonitorEvent(int32_t monitorEventType) {
+ if (mFilter_1_1 == nullptr) {
+ ALOGE("IFilter_1_1 is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mFilter_1_1->configureMonitorEvent(monitorEventType);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::configureIpFilterContextId(int32_t cid) {
+ if (mFilter_1_1 == nullptr) {
+ ALOGE("IFilter_1_1 is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mFilter_1_1->configureIpCid(cid);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::configureAvStreamType(const AvStreamType& in_avStreamType) {
+ if (mFilter_1_1 == nullptr) {
+ ALOGE("IFilter_1_1 is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlAvStreamType type;
+ if (!getHidlAvStreamType(in_avStreamType, type)) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
+ HidlResult res = mFilter_1_1->configureAvStreamType(type);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::setDataSource(const shared_ptr<ITunerFilter>& filter) {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (filter == nullptr) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+
+ sp<HidlIFilter> hidlFilter = static_cast<TunerHidlFilter*>(filter.get())->getHalFilter();
+ HidlResult res = mFilter->setDataSource(hidlFilter);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::getAvSharedHandle(NativeHandle* out_avMemory,
+ int64_t* _aidl_return) {
+ if (mFilter_1_1 == nullptr) {
+ ALOGE("IFilter_1_1 is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res;
+ mFilter_1_1->getAvSharedHandle([&](HidlResult r, hidl_handle avMemory, uint64_t avMemSize) {
+ res = r;
+ if (res == HidlResult::SUCCESS) {
+ *out_avMemory = dupToAidl(avMemory);
+ *_aidl_return = static_cast<int64_t>(avMemSize);
+ } else {
+ _aidl_return = nullptr;
+ }
+ });
+
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::releaseAvHandle(const NativeHandle& in_handle,
+ int64_t in_avDataId) {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mFilter->releaseAvHandle(hidl_handle(makeFromAidl(in_handle)), in_avDataId);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::start() {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mFilter->start();
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::stop() {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mFilter->stop();
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::flush() {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mFilter->flush();
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::close() {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mFilter->close();
+ mFilter = nullptr;
+ mFilter_1_1 = nullptr;
+
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+sp<HidlIFilter> TunerHidlFilter::getHalFilter() {
+ return mFilter;
+}
+
+bool TunerHidlFilter::getHidlAvStreamType(const AvStreamType avStreamType, HidlAvStreamType& type) {
+ if (isAudioFilter()) {
+ type.audio(static_cast<HidlAudioStreamType>(avStreamType.get<AvStreamType::audio>()));
+ return true;
+ }
+
+ if (isVideoFilter()) {
+ type.video(static_cast<HidlVideoStreamType>(avStreamType.get<AvStreamType::video>()));
+ return true;
+ }
+
+ return false;
+}
+
+bool TunerHidlFilter::isAudioFilter() {
+ return (mType.mainType == DemuxFilterMainType::TS &&
+ mType.subType.get<DemuxFilterSubType::tsFilterType>() == DemuxTsFilterType::AUDIO) ||
+ (mType.mainType == DemuxFilterMainType::MMTP &&
+ mType.subType.get<DemuxFilterSubType::mmtpFilterType>() == DemuxMmtpFilterType::AUDIO);
+}
+
+bool TunerHidlFilter::isVideoFilter() {
+ return (mType.mainType == DemuxFilterMainType::TS &&
+ mType.subType.get<DemuxFilterSubType::tsFilterType>() == DemuxTsFilterType::VIDEO) ||
+ (mType.mainType == DemuxFilterMainType::MMTP &&
+ mType.subType.get<DemuxFilterSubType::mmtpFilterType>() == DemuxMmtpFilterType::VIDEO);
+}
+
+void TunerHidlFilter::getHidlTsSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings) {
+ const DemuxTsFilterSettings& tsConf = settings.get<DemuxFilterSettings::ts>();
+ HidlDemuxTsFilterSettings ts{
+ .tpid = static_cast<uint16_t>(tsConf.tpid),
+ };
+
+ switch (tsConf.filterSettings.getTag()) {
+ case DemuxTsFilterSettingsFilterSettings::av: {
+ ts.filterSettings.av(getHidlAvSettings(
+ tsConf.filterSettings.get<DemuxTsFilterSettingsFilterSettings::av>()));
+ break;
+ }
+ case DemuxTsFilterSettingsFilterSettings::section: {
+ ts.filterSettings.section(getHidlSectionSettings(
+ tsConf.filterSettings.get<DemuxTsFilterSettingsFilterSettings::section>()));
+ break;
+ }
+ case DemuxTsFilterSettingsFilterSettings::pesData: {
+ ts.filterSettings.pesData(getHidlPesDataSettings(
+ tsConf.filterSettings.get<DemuxTsFilterSettingsFilterSettings::pesData>()));
+ break;
+ }
+ case DemuxTsFilterSettingsFilterSettings::record: {
+ ts.filterSettings.record(getHidlRecordSettings(
+ tsConf.filterSettings.get<DemuxTsFilterSettingsFilterSettings::record>()));
+ break;
+ }
+ default: {
+ ts.filterSettings.noinit();
+ break;
+ }
+ }
+ hidlSettings.ts(ts);
+}
+
+void TunerHidlFilter::getHidlMmtpSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings) {
+ const DemuxMmtpFilterSettings& mmtpConf = settings.get<DemuxFilterSettings::mmtp>();
+ HidlDemuxMmtpFilterSettings mmtp{
+ .mmtpPid = static_cast<HidlDemuxMmtpPid>(mmtpConf.mmtpPid),
+ };
+
+ switch (mmtpConf.filterSettings.getTag()) {
+ case DemuxMmtpFilterSettingsFilterSettings::av: {
+ mmtp.filterSettings.av(getHidlAvSettings(
+ mmtpConf.filterSettings.get<DemuxMmtpFilterSettingsFilterSettings::av>()));
+ break;
+ }
+ case DemuxMmtpFilterSettingsFilterSettings::section: {
+ mmtp.filterSettings.section(getHidlSectionSettings(
+ mmtpConf.filterSettings.get<DemuxMmtpFilterSettingsFilterSettings::section>()));
+ break;
+ }
+ case DemuxMmtpFilterSettingsFilterSettings::pesData: {
+ mmtp.filterSettings.pesData(getHidlPesDataSettings(
+ mmtpConf.filterSettings.get<DemuxMmtpFilterSettingsFilterSettings::pesData>()));
+ break;
+ }
+ case DemuxMmtpFilterSettingsFilterSettings::record: {
+ mmtp.filterSettings.record(getHidlRecordSettings(
+ mmtpConf.filterSettings.get<DemuxMmtpFilterSettingsFilterSettings::record>()));
+ break;
+ }
+ case DemuxMmtpFilterSettingsFilterSettings::download: {
+ mmtp.filterSettings.download(getHidlDownloadSettings(
+ mmtpConf.filterSettings.get<DemuxMmtpFilterSettingsFilterSettings::download>()));
+ break;
+ }
+ default: {
+ mmtp.filterSettings.noinit();
+ break;
+ }
+ }
+ hidlSettings.mmtp(mmtp);
+}
+
+void TunerHidlFilter::getHidlIpSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings) {
+ const DemuxIpFilterSettings& ipConf = settings.get<DemuxFilterSettings::ip>();
+ HidlDemuxIpAddress ipAddr{
+ .srcPort = static_cast<uint16_t>(ipConf.ipAddr.srcPort),
+ .dstPort = static_cast<uint16_t>(ipConf.ipAddr.dstPort),
+ };
+
+ ipConf.ipAddr.srcIpAddress.getTag() == DemuxIpAddressIpAddress::v6
+ ? ipAddr.srcIpAddress.v6(getIpV6Address(ipConf.ipAddr.srcIpAddress))
+ : ipAddr.srcIpAddress.v4(getIpV4Address(ipConf.ipAddr.srcIpAddress));
+ ipConf.ipAddr.dstIpAddress.getTag() == DemuxIpAddressIpAddress::v6
+ ? ipAddr.dstIpAddress.v6(getIpV6Address(ipConf.ipAddr.dstIpAddress))
+ : ipAddr.dstIpAddress.v4(getIpV4Address(ipConf.ipAddr.dstIpAddress));
+
+ HidlDemuxIpFilterSettings ip;
+ ip.ipAddr = ipAddr;
+
+ switch (ipConf.filterSettings.getTag()) {
+ case DemuxIpFilterSettingsFilterSettings::section: {
+ ip.filterSettings.section(getHidlSectionSettings(
+ ipConf.filterSettings.get<DemuxIpFilterSettingsFilterSettings::section>()));
+ break;
+ }
+ case DemuxIpFilterSettingsFilterSettings::bPassthrough: {
+ ip.filterSettings.bPassthrough(
+ ipConf.filterSettings.get<DemuxIpFilterSettingsFilterSettings::bPassthrough>());
+ break;
+ }
+ default: {
+ ip.filterSettings.noinit();
+ break;
+ }
+ }
+ hidlSettings.ip(ip);
+}
+
+hidl_array<uint8_t, IP_V6_LENGTH> TunerHidlFilter::getIpV6Address(
+ const DemuxIpAddressIpAddress& addr) {
+ hidl_array<uint8_t, IP_V6_LENGTH> ip;
+ if (addr.get<DemuxIpAddressIpAddress::v6>().size() != IP_V6_LENGTH) {
+ return ip;
+ }
+ copy(addr.get<DemuxIpAddressIpAddress::v6>().begin(),
+ addr.get<DemuxIpAddressIpAddress::v6>().end(), ip.data());
+ return ip;
+}
+
+hidl_array<uint8_t, IP_V4_LENGTH> TunerHidlFilter::getIpV4Address(
+ const DemuxIpAddressIpAddress& addr) {
+ hidl_array<uint8_t, IP_V4_LENGTH> ip;
+ if (addr.get<DemuxIpAddressIpAddress::v4>().size() != IP_V4_LENGTH) {
+ return ip;
+ }
+ copy(addr.get<DemuxIpAddressIpAddress::v4>().begin(),
+ addr.get<DemuxIpAddressIpAddress::v4>().end(), ip.data());
+ return ip;
+}
+
+void TunerHidlFilter::getHidlTlvSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings) {
+ const DemuxTlvFilterSettings& tlvConf = settings.get<DemuxFilterSettings::tlv>();
+ HidlDemuxTlvFilterSettings tlv{
+ .packetType = static_cast<uint8_t>(tlvConf.packetType),
+ .isCompressedIpPacket = tlvConf.isCompressedIpPacket,
+ };
+
+ switch (tlvConf.filterSettings.getTag()) {
+ case DemuxTlvFilterSettingsFilterSettings::section: {
+ tlv.filterSettings.section(getHidlSectionSettings(
+ tlvConf.filterSettings.get<DemuxTlvFilterSettingsFilterSettings::section>()));
+ break;
+ }
+ case DemuxTlvFilterSettingsFilterSettings::bPassthrough: {
+ tlv.filterSettings.bPassthrough(
+ tlvConf.filterSettings.get<DemuxTlvFilterSettingsFilterSettings::bPassthrough>());
+ break;
+ }
+ default: {
+ tlv.filterSettings.noinit();
+ break;
+ }
+ }
+ hidlSettings.tlv(tlv);
+}
+
+void TunerHidlFilter::getHidlAlpSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings) {
+ const DemuxAlpFilterSettings& alpConf = settings.get<DemuxFilterSettings::alp>();
+ HidlDemuxAlpFilterSettings alp{
+ .packetType = static_cast<uint8_t>(alpConf.packetType),
+ .lengthType = static_cast<HidlDemuxAlpLengthType>(alpConf.lengthType),
+ };
+
+ switch (alpConf.filterSettings.getTag()) {
+ case DemuxAlpFilterSettingsFilterSettings::section: {
+ alp.filterSettings.section(getHidlSectionSettings(
+ alpConf.filterSettings.get<DemuxAlpFilterSettingsFilterSettings::section>()));
+ break;
+ }
+ default: {
+ alp.filterSettings.noinit();
+ break;
+ }
+ }
+ hidlSettings.alp(alp);
+}
+
+HidlDemuxFilterAvSettings TunerHidlFilter::getHidlAvSettings(
+ const DemuxFilterAvSettings& settings) {
+ HidlDemuxFilterAvSettings av{
+ .isPassthrough = settings.isPassthrough,
+ };
+ return av;
+}
+
+HidlDemuxFilterSectionSettings TunerHidlFilter::getHidlSectionSettings(
+ const DemuxFilterSectionSettings& settings) {
+ HidlDemuxFilterSectionSettings section{
+ .isCheckCrc = settings.isCheckCrc,
+ .isRepeat = settings.isRepeat,
+ .isRaw = settings.isRaw,
+ };
+
+ switch (settings.condition.getTag()) {
+ case DemuxFilterSectionSettingsCondition::sectionBits: {
+ const DemuxFilterSectionBits& sectionBits =
+ settings.condition.get<DemuxFilterSectionSettingsCondition::sectionBits>();
+ vector<uint8_t> filter(sectionBits.filter.begin(), sectionBits.filter.end());
+ vector<uint8_t> mask(sectionBits.mask.begin(), sectionBits.mask.end());
+ vector<uint8_t> mode(sectionBits.mode.begin(), sectionBits.mode.end());
+ section.condition.sectionBits({
+ .filter = filter,
+ .mask = mask,
+ .mode = mode,
+ });
+ break;
+ }
+ case DemuxFilterSectionSettingsCondition::tableInfo: {
+ const DemuxFilterSectionSettingsConditionTableInfo& tableInfo =
+ settings.condition.get<DemuxFilterSectionSettingsCondition::tableInfo>();
+ section.condition.tableInfo({
+ .tableId = static_cast<uint16_t>(tableInfo.tableId),
+ .version = static_cast<uint16_t>(tableInfo.version),
+ });
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ return section;
+}
+
+HidlDemuxFilterPesDataSettings TunerHidlFilter::getHidlPesDataSettings(
+ const DemuxFilterPesDataSettings& settings) {
+ HidlDemuxFilterPesDataSettings pes{
+ .streamId = static_cast<HidlDemuxStreamId>(settings.streamId),
+ .isRaw = settings.isRaw,
+ };
+ return pes;
+}
+
+HidlDemuxFilterRecordSettings TunerHidlFilter::getHidlRecordSettings(
+ const DemuxFilterRecordSettings& settings) {
+ HidlDemuxFilterRecordSettings record{
+ .tsIndexMask = static_cast<uint32_t>(settings.tsIndexMask),
+ .scIndexType = static_cast<HidlDemuxRecordScIndexType>(settings.scIndexType),
+ };
+
+ switch (settings.scIndexMask.getTag()) {
+ case DemuxFilterScIndexMask::scIndex: {
+ record.scIndexMask.sc(
+ static_cast<uint32_t>(settings.scIndexMask.get<DemuxFilterScIndexMask::scIndex>()));
+ break;
+ }
+ case DemuxFilterScIndexMask::scHevc: {
+ record.scIndexMask.scHevc(
+ static_cast<uint32_t>(settings.scIndexMask.get<DemuxFilterScIndexMask::scHevc>()));
+ break;
+ }
+ }
+ return record;
+}
+
+HidlDemuxFilterDownloadSettings TunerHidlFilter::getHidlDownloadSettings(
+ const DemuxFilterDownloadSettings& settings) {
+ HidlDemuxFilterDownloadSettings download{
+ .downloadId = static_cast<uint32_t>(settings.downloadId),
+ };
+ return download;
+}
+
+/////////////// FilterCallback ///////////////////////
+Return<void> TunerHidlFilter::FilterCallback::onFilterStatus(HidlDemuxFilterStatus status) {
+ if (mTunerFilterCallback != NULL) {
+ mTunerFilterCallback->onFilterStatus(static_cast<DemuxFilterStatus>(status));
+ }
+ return Void();
+}
+
+Return<void> TunerHidlFilter::FilterCallback::onFilterEvent(
+ const HidlDemuxFilterEvent& filterEvent) {
+ vector<HidlDemuxFilterEventExt::Event> emptyEventsExt;
+ HidlDemuxFilterEventExt emptyFilterEventExt{
+ .events = emptyEventsExt,
+ };
+ onFilterEvent_1_1(filterEvent, emptyFilterEventExt);
+ return Void();
+}
+
+Return<void> TunerHidlFilter::FilterCallback::onFilterEvent_1_1(
+ const HidlDemuxFilterEvent& filterEvent, const HidlDemuxFilterEventExt& filterEventExt) {
+ if (mTunerFilterCallback != NULL) {
+ vector<HidlDemuxFilterEvent::Event> events = filterEvent.events;
+ vector<HidlDemuxFilterEventExt::Event> eventsExt = filterEventExt.events;
+ vector<DemuxFilterEvent> tunerEvents;
+
+ getAidlFilterEvent(events, eventsExt, tunerEvents);
+ mTunerFilterCallback->onFilterEvent(tunerEvents);
+ }
+ return Void();
+}
+
+/////////////// FilterCallback Helper Methods ///////////////////////
+void TunerHidlFilter::FilterCallback::getAidlFilterEvent(
+ const vector<HidlDemuxFilterEvent::Event>& events,
+ const vector<HidlDemuxFilterEventExt::Event>& eventsExt,
+ vector<DemuxFilterEvent>& aidlEvents) {
+ if (events.empty() && !eventsExt.empty()) {
+ switch (eventsExt[0].getDiscriminator()) {
+ case HidlDemuxFilterEventExt::Event::hidl_discriminator::monitorEvent: {
+ getMonitorEvent(eventsExt, aidlEvents);
+ break;
+ }
+ case HidlDemuxFilterEventExt::Event::hidl_discriminator::startId: {
+ getRestartEvent(eventsExt, aidlEvents);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+
+ if (!events.empty()) {
+ switch (events[0].getDiscriminator()) {
+ case HidlDemuxFilterEvent::Event::hidl_discriminator::media: {
+ getMediaEvent(events, aidlEvents);
+ break;
+ }
+ case HidlDemuxFilterEvent::Event::hidl_discriminator::section: {
+ getSectionEvent(events, aidlEvents);
+ break;
+ }
+ case HidlDemuxFilterEvent::Event::hidl_discriminator::pes: {
+ getPesEvent(events, aidlEvents);
+ break;
+ }
+ case HidlDemuxFilterEvent::Event::hidl_discriminator::tsRecord: {
+ getTsRecordEvent(events, eventsExt, aidlEvents);
+ break;
+ }
+ case HidlDemuxFilterEvent::Event::hidl_discriminator::mmtpRecord: {
+ getMmtpRecordEvent(events, eventsExt, aidlEvents);
+ break;
+ }
+ case HidlDemuxFilterEvent::Event::hidl_discriminator::download: {
+ getDownloadEvent(events, aidlEvents);
+ break;
+ }
+ case HidlDemuxFilterEvent::Event::hidl_discriminator::ipPayload: {
+ getIpPayloadEvent(events, aidlEvents);
+ break;
+ }
+ case HidlDemuxFilterEvent::Event::hidl_discriminator::temi: {
+ getTemiEvent(events, aidlEvents);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+}
+
+void TunerHidlFilter::FilterCallback::getMediaEvent(
+ const vector<HidlDemuxFilterEvent::Event>& events, vector<DemuxFilterEvent>& res) {
+ for (int i = 0; i < events.size(); i++) {
+ const HidlDemuxFilterMediaEvent& mediaEvent = events[i].media();
+ DemuxFilterMediaEvent media;
+
+ media.streamId = static_cast<int32_t>(mediaEvent.streamId);
+ media.isPtsPresent = mediaEvent.isPtsPresent;
+ media.pts = static_cast<int64_t>(mediaEvent.pts);
+ media.dataLength = static_cast<int64_t>(mediaEvent.dataLength);
+ media.offset = static_cast<int64_t>(mediaEvent.offset);
+ media.isSecureMemory = mediaEvent.isSecureMemory;
+ media.avDataId = static_cast<int64_t>(mediaEvent.avDataId);
+ media.mpuSequenceNumber = static_cast<int32_t>(mediaEvent.mpuSequenceNumber);
+ media.isPesPrivateData = mediaEvent.isPesPrivateData;
+
+ if (mediaEvent.extraMetaData.getDiscriminator() ==
+ HidlDemuxFilterMediaEvent::ExtraMetaData::hidl_discriminator::audio) {
+ AudioExtraMetaData audio;
+ audio.adFade = static_cast<int8_t>(mediaEvent.extraMetaData.audio().adFade);
+ audio.adPan = static_cast<int8_t>(mediaEvent.extraMetaData.audio().adPan);
+ audio.versionTextTag =
+ static_cast<int16_t>(mediaEvent.extraMetaData.audio().versionTextTag);
+ audio.adGainCenter = static_cast<int8_t>(mediaEvent.extraMetaData.audio().adGainCenter);
+ audio.adGainFront = static_cast<int8_t>(mediaEvent.extraMetaData.audio().adGainFront);
+ audio.adGainSurround =
+ static_cast<int8_t>(mediaEvent.extraMetaData.audio().adGainSurround);
+ media.extraMetaData.set<DemuxFilterMediaEventExtraMetaData::audio>(audio);
+ } else {
+ media.extraMetaData.set<DemuxFilterMediaEventExtraMetaData::noinit>(true);
+ }
+
+ if (mediaEvent.avMemory.getNativeHandle() != nullptr) {
+ media.avMemory = dupToAidl(mediaEvent.avMemory.getNativeHandle());
+ }
+
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::media>(move(media));
+ res.push_back(move(filterEvent));
+ }
+}
+
+void TunerHidlFilter::FilterCallback::getSectionEvent(
+ const vector<HidlDemuxFilterEvent::Event>& events, vector<DemuxFilterEvent>& res) {
+ for (int i = 0; i < events.size(); i++) {
+ const HidlDemuxFilterSectionEvent& sectionEvent = events[i].section();
+ DemuxFilterSectionEvent section;
+
+ section.tableId = static_cast<int32_t>(sectionEvent.tableId);
+ section.version = static_cast<int32_t>(sectionEvent.version);
+ section.sectionNum = static_cast<int32_t>(sectionEvent.sectionNum);
+ section.dataLength = static_cast<int32_t>(sectionEvent.dataLength);
+
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::section>(move(section));
+ res.push_back(move(filterEvent));
+ }
+}
+
+void TunerHidlFilter::FilterCallback::getPesEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ vector<DemuxFilterEvent>& res) {
+ for (int i = 0; i < events.size(); i++) {
+ const HidlDemuxFilterPesEvent& pesEvent = events[i].pes();
+ DemuxFilterPesEvent pes;
+
+ pes.streamId = static_cast<int32_t>(pesEvent.streamId);
+ pes.dataLength = static_cast<int32_t>(pesEvent.dataLength);
+ pes.mpuSequenceNumber = static_cast<int32_t>(pesEvent.mpuSequenceNumber);
+
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::pes>(move(pes));
+ res.push_back(move(filterEvent));
+ }
+}
+
+void TunerHidlFilter::FilterCallback::getTsRecordEvent(
+ const vector<HidlDemuxFilterEvent::Event>& events,
+ const vector<HidlDemuxFilterEventExt::Event>& eventsExt, vector<DemuxFilterEvent>& res) {
+ for (int i = 0; i < events.size(); i++) {
+ DemuxFilterTsRecordEvent tsRecord;
+ const HidlDemuxFilterTsRecordEvent& tsRecordEvent = events[i].tsRecord();
+
+ DemuxFilterScIndexMask scIndexMask;
+ if (tsRecordEvent.scIndexMask.getDiscriminator() ==
+ HidlDemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::sc) {
+ scIndexMask.set<DemuxFilterScIndexMask::scIndex>(
+ static_cast<int32_t>(tsRecordEvent.scIndexMask.sc()));
+ } else if (tsRecordEvent.scIndexMask.getDiscriminator() ==
+ HidlDemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::scHevc) {
+ scIndexMask.set<DemuxFilterScIndexMask::scHevc>(
+ static_cast<int32_t>(tsRecordEvent.scIndexMask.scHevc()));
+ }
+
+ if (tsRecordEvent.pid.getDiscriminator() == HidlDemuxPid::hidl_discriminator::tPid) {
+ DemuxPid pid;
+ pid.set<DemuxPid::tPid>(static_cast<int32_t>(tsRecordEvent.pid.tPid()));
+ tsRecord.pid = pid;
+ } else {
+ DemuxPid pid;
+ pid.set<DemuxPid::tPid>(static_cast<int32_t>(Constant::INVALID_TS_PID));
+ tsRecord.pid = pid;
+ }
+
+ tsRecord.scIndexMask = scIndexMask;
+ tsRecord.tsIndexMask = static_cast<int32_t>(tsRecordEvent.tsIndexMask);
+ tsRecord.byteNumber = static_cast<int64_t>(tsRecordEvent.byteNumber);
+
+ if (eventsExt.size() > i &&
+ eventsExt[i].getDiscriminator() ==
+ HidlDemuxFilterEventExt::Event::hidl_discriminator::tsRecord) {
+ tsRecord.pts = static_cast<int64_t>(eventsExt[i].tsRecord().pts);
+ tsRecord.firstMbInSlice = static_cast<int32_t>(eventsExt[i].tsRecord().firstMbInSlice);
+ }
+
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::tsRecord>(move(tsRecord));
+ res.push_back(move(filterEvent));
+ }
+}
+
+void TunerHidlFilter::FilterCallback::getMmtpRecordEvent(
+ const vector<HidlDemuxFilterEvent::Event>& events,
+ const vector<HidlDemuxFilterEventExt::Event>& eventsExt, vector<DemuxFilterEvent>& res) {
+ for (int i = 0; i < events.size(); i++) {
+ DemuxFilterMmtpRecordEvent mmtpRecord;
+ const HidlDemuxFilterMmtpRecordEvent& mmtpRecordEvent = events[i].mmtpRecord();
+
+ mmtpRecord.scHevcIndexMask = static_cast<int32_t>(mmtpRecordEvent.scHevcIndexMask);
+ mmtpRecord.byteNumber = static_cast<int64_t>(mmtpRecordEvent.byteNumber);
+
+ if (eventsExt.size() > i &&
+ eventsExt[i].getDiscriminator() ==
+ HidlDemuxFilterEventExt::Event::hidl_discriminator::mmtpRecord) {
+ mmtpRecord.pts = static_cast<int64_t>(eventsExt[i].mmtpRecord().pts);
+ mmtpRecord.mpuSequenceNumber =
+ static_cast<int32_t>(eventsExt[i].mmtpRecord().mpuSequenceNumber);
+ mmtpRecord.firstMbInSlice =
+ static_cast<int32_t>(eventsExt[i].mmtpRecord().firstMbInSlice);
+ mmtpRecord.tsIndexMask = static_cast<int32_t>(eventsExt[i].mmtpRecord().tsIndexMask);
+ }
+
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::mmtpRecord>(move(mmtpRecord));
+ res.push_back(move(filterEvent));
+ }
+}
+
+void TunerHidlFilter::FilterCallback::getDownloadEvent(
+ const vector<HidlDemuxFilterEvent::Event>& events, vector<DemuxFilterEvent>& res) {
+ for (int i = 0; i < events.size(); i++) {
+ const HidlDemuxFilterDownloadEvent& downloadEvent = events[i].download();
+ DemuxFilterDownloadEvent download;
+
+ download.itemId = static_cast<int32_t>(downloadEvent.itemId);
+ download.itemFragmentIndex = static_cast<int32_t>(downloadEvent.itemFragmentIndex);
+ download.mpuSequenceNumber = static_cast<int32_t>(downloadEvent.mpuSequenceNumber);
+ download.lastItemFragmentIndex = static_cast<int32_t>(downloadEvent.lastItemFragmentIndex);
+ download.dataLength = static_cast<int32_t>(downloadEvent.dataLength);
+
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::download>(move(download));
+ res.push_back(move(filterEvent));
+ }
+}
+
+void TunerHidlFilter::FilterCallback::getIpPayloadEvent(
+ const vector<HidlDemuxFilterEvent::Event>& events, vector<DemuxFilterEvent>& res) {
+ for (int i = 0; i < events.size(); i++) {
+ const HidlDemuxFilterIpPayloadEvent& ipPayloadEvent = events[i].ipPayload();
+ DemuxFilterIpPayloadEvent ipPayload;
+
+ ipPayload.dataLength = static_cast<int32_t>(ipPayloadEvent.dataLength);
+
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::ipPayload>(move(ipPayload));
+ res.push_back(move(filterEvent));
+ }
+}
+
+void TunerHidlFilter::FilterCallback::getTemiEvent(
+ const vector<HidlDemuxFilterEvent::Event>& events, vector<DemuxFilterEvent>& res) {
+ for (int i = 0; i < events.size(); i++) {
+ const HidlDemuxFilterTemiEvent& temiEvent = events[i].temi();
+ DemuxFilterTemiEvent temi;
+
+ temi.pts = static_cast<int64_t>(temiEvent.pts);
+ temi.descrTag = static_cast<int8_t>(temiEvent.descrTag);
+ vector<uint8_t> descrData = temiEvent.descrData;
+ temi.descrData.resize(descrData.size());
+ copy(descrData.begin(), descrData.end(), temi.descrData.begin());
+
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::temi>(move(temi));
+ res.push_back(move(filterEvent));
+ }
+}
+
+void TunerHidlFilter::FilterCallback::getMonitorEvent(
+ const vector<HidlDemuxFilterEventExt::Event>& eventsExt, vector<DemuxFilterEvent>& res) {
+ HidlDemuxFilterMonitorEvent monitorEvent = eventsExt[0].monitorEvent();
+ DemuxFilterMonitorEvent monitor;
+
+ switch (monitorEvent.getDiscriminator()) {
+ case HidlDemuxFilterMonitorEvent::hidl_discriminator::scramblingStatus: {
+ monitor.set<DemuxFilterMonitorEvent::scramblingStatus>(
+ static_cast<ScramblingStatus>(monitorEvent.scramblingStatus()));
+ break;
+ }
+ case HidlDemuxFilterMonitorEvent::hidl_discriminator::cid: {
+ monitor.set<DemuxFilterMonitorEvent::cid>(static_cast<int32_t>(monitorEvent.cid()));
+ break;
+ }
+ }
+
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::monitorEvent>(move(monitor));
+ res.push_back(move(filterEvent));
+}
+
+void TunerHidlFilter::FilterCallback::getRestartEvent(
+ const vector<HidlDemuxFilterEventExt::Event>& eventsExt, vector<DemuxFilterEvent>& res) {
+ DemuxFilterEvent filterEvent;
+ filterEvent.set<DemuxFilterEvent::startId>(static_cast<int32_t>(eventsExt[0].startId()));
+ res.push_back(move(filterEvent));
+}
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
diff --git a/services/tuner/hidl/TunerHidlFilter.h b/services/tuner/hidl/TunerHidlFilter.h
new file mode 100644
index 0000000..0111e00
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlFilter.h
@@ -0,0 +1,215 @@
+/**
+ * Copyright 2021, 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_MEDIA_TUNERHIDLFILTER_H
+#define ANDROID_MEDIA_TUNERHIDLFILTER_H
+
+#include <aidl/android/hardware/tv/tuner/AvStreamType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterAvSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterDownloadSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterPesDataSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterRecordSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSectionSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterStatus.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterType.h>
+#include <aidl/android/media/tv/tuner/BnTunerFilter.h>
+#include <aidl/android/media/tv/tuner/ITunerFilterCallback.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.1/IFilter.h>
+#include <android/hardware/tv/tuner/1.1/IFilterCallback.h>
+#include <android/hardware/tv/tuner/1.1/types.h>
+#include <fmq/MessageQueue.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+using ::aidl::android::hardware::common::NativeHandle;
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::aidl::android::hardware::tv::tuner::AvStreamType;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterAvSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterDownloadSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterPesDataSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterRecordSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterStatus;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterType;
+using ::aidl::android::hardware::tv::tuner::DemuxIpAddressIpAddress;
+using ::aidl::android::media::tv::tuner::BnTunerFilter;
+using ::aidl::android::media::tv::tuner::ITunerFilterCallback;
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::std::shared_ptr;
+using ::std::vector;
+
+using HidlAvStreamType = ::android::hardware::tv::tuner::V1_1::AvStreamType;
+using HidlDemuxAlpFilterSettings = ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterSettings;
+using HidlDemuxFilterAvSettings = ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
+using HidlDemuxFilterDownloadEvent = ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadEvent;
+using HidlDemuxFilterDownloadSettings =
+ ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadSettings;
+using HidlDemuxFilterIpPayloadEvent =
+ ::android::hardware::tv::tuner::V1_0::DemuxFilterIpPayloadEvent;
+using HidlDemuxFilterEvent = ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using HidlDemuxFilterMediaEvent = ::android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
+using HidlDemuxFilterMmtpRecordEvent =
+ ::android::hardware::tv::tuner::V1_0::DemuxFilterMmtpRecordEvent;
+using HidlDemuxFilterPesDataSettings =
+ ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
+using HidlDemuxFilterPesEvent = ::android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
+using HidlDemuxFilterRecordSettings =
+ ::android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
+using HidlDemuxFilterSectionEvent = ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
+using HidlDemuxFilterSectionSettings =
+ ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
+using HidlDemuxFilterSettings = ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using HidlDemuxFilterStatus = ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using HidlDemuxFilterTemiEvent = ::android::hardware::tv::tuner::V1_0::DemuxFilterTemiEvent;
+using HidlDemuxFilterTsRecordEvent = ::android::hardware::tv::tuner::V1_0::DemuxFilterTsRecordEvent;
+using HidlDemuxIpFilterSettings = ::android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings;
+using HidlDemuxMmtpFilterSettings = ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterSettings;
+using HidlDemuxTlvFilterSettings = ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterSettings;
+using HidlDemuxTsFilterSettings = ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
+using HidlDemuxPid = ::android::hardware::tv::tuner::V1_0::DemuxPid;
+using HidlIFilter = ::android::hardware::tv::tuner::V1_0::IFilter;
+using HidlDvStreamType = ::android::hardware::tv::tuner::V1_1::AvStreamType;
+using HidlDemuxFilterEventExt = ::android::hardware::tv::tuner::V1_1::DemuxFilterEventExt;
+using HidlDemuxFilterMonitorEvent = ::android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEvent;
+using HidlDemuxFilterTsRecordEventExt =
+ ::android::hardware::tv::tuner::V1_1::DemuxFilterTsRecordEventExt;
+using HidlIFilterCallback = ::android::hardware::tv::tuner::V1_1::IFilterCallback;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+using MQDesc = MQDescriptorSync<uint8_t>;
+using AidlMQDesc = MQDescriptor<int8_t, SynchronizedReadWrite>;
+
+const static int IP_V4_LENGTH = 4;
+const static int IP_V6_LENGTH = 16;
+
+class TunerHidlFilter : public BnTunerFilter {
+public:
+ TunerHidlFilter(sp<HidlIFilter> filter, DemuxFilterType type);
+ virtual ~TunerHidlFilter();
+
+ ::ndk::ScopedAStatus getId(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getId64Bit(int64_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getQueueDesc(AidlMQDesc* _aidl_return) override;
+ ::ndk::ScopedAStatus configure(const DemuxFilterSettings& in_settings) override;
+ ::ndk::ScopedAStatus configureMonitorEvent(int32_t in_monitorEventTypes) override;
+ ::ndk::ScopedAStatus configureIpFilterContextId(int32_t in_cid) override;
+ ::ndk::ScopedAStatus configureAvStreamType(const AvStreamType& in_avStreamType) override;
+ ::ndk::ScopedAStatus getAvSharedHandle(NativeHandle* out_avMemory,
+ int64_t* _aidl_return) override;
+ ::ndk::ScopedAStatus releaseAvHandle(const NativeHandle& in_handle,
+ int64_t in_avDataId) override;
+ ::ndk::ScopedAStatus setDataSource(const shared_ptr<ITunerFilter>& in_filter) override;
+ ::ndk::ScopedAStatus start() override;
+ ::ndk::ScopedAStatus stop() override;
+ ::ndk::ScopedAStatus flush() override;
+ ::ndk::ScopedAStatus close() override;
+
+ sp<HidlIFilter> getHalFilter();
+
+ struct FilterCallback : public HidlIFilterCallback {
+ FilterCallback(const shared_ptr<ITunerFilterCallback> tunerFilterCallback)
+ : mTunerFilterCallback(tunerFilterCallback){};
+
+ virtual Return<void> onFilterEvent(const HidlDemuxFilterEvent& filterEvent);
+ virtual Return<void> onFilterEvent_1_1(const HidlDemuxFilterEvent& filterEvent,
+ const HidlDemuxFilterEventExt& filterEventExt);
+ virtual Return<void> onFilterStatus(HidlDemuxFilterStatus status);
+
+ void getAidlFilterEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ const vector<HidlDemuxFilterEventExt::Event>& eventsExt,
+ vector<DemuxFilterEvent>& aidlEvents);
+
+ void getMediaEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ vector<DemuxFilterEvent>& res);
+ void getSectionEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ vector<DemuxFilterEvent>& res);
+ void getPesEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ vector<DemuxFilterEvent>& res);
+ void getTsRecordEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ const vector<HidlDemuxFilterEventExt::Event>& eventsExt,
+ vector<DemuxFilterEvent>& res);
+ void getMmtpRecordEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ const vector<HidlDemuxFilterEventExt::Event>& eventsExt,
+ vector<DemuxFilterEvent>& res);
+ void getDownloadEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ vector<DemuxFilterEvent>& res);
+ void getIpPayloadEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ vector<DemuxFilterEvent>& res);
+ void getTemiEvent(const vector<HidlDemuxFilterEvent::Event>& events,
+ vector<DemuxFilterEvent>& res);
+ void getMonitorEvent(const vector<HidlDemuxFilterEventExt::Event>& eventsExt,
+ vector<DemuxFilterEvent>& res);
+ void getRestartEvent(const vector<HidlDemuxFilterEventExt::Event>& eventsExt,
+ vector<DemuxFilterEvent>& res);
+
+ shared_ptr<ITunerFilterCallback> mTunerFilterCallback;
+ };
+
+private:
+ bool isAudioFilter();
+ bool isVideoFilter();
+
+ HidlDemuxFilterAvSettings getHidlAvSettings(const DemuxFilterAvSettings& settings);
+ HidlDemuxFilterSectionSettings getHidlSectionSettings(
+ const DemuxFilterSectionSettings& settings);
+ HidlDemuxFilterPesDataSettings getHidlPesDataSettings(
+ const DemuxFilterPesDataSettings& settings);
+ HidlDemuxFilterRecordSettings getHidlRecordSettings(const DemuxFilterRecordSettings& settings);
+ HidlDemuxFilterDownloadSettings getHidlDownloadSettings(
+ const DemuxFilterDownloadSettings& settings);
+ bool getHidlAvStreamType(const AvStreamType avStreamType, HidlAvStreamType& type);
+ void getHidlTsSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings);
+ void getHidlMmtpSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings);
+ void getHidlIpSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings);
+ void getHidlTlvSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings);
+ void getHidlAlpSettings(const DemuxFilterSettings& settings,
+ HidlDemuxFilterSettings& hidlSettings);
+
+ hidl_array<uint8_t, IP_V4_LENGTH> getIpV4Address(const DemuxIpAddressIpAddress& addr);
+ hidl_array<uint8_t, IP_V6_LENGTH> getIpV6Address(const DemuxIpAddressIpAddress& addr);
+
+ sp<HidlIFilter> mFilter;
+ sp<::android::hardware::tv::tuner::V1_1::IFilter> mFilter_1_1;
+ int32_t mId;
+ int64_t mId64Bit;
+ DemuxFilterType mType;
+};
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
+
+#endif // ANDROID_MEDIA_TUNERHIDLFILTER_H
diff --git a/services/tuner/hidl/TunerHidlFrontend.cpp b/services/tuner/hidl/TunerHidlFrontend.cpp
new file mode 100644
index 0000000..bbfc90f
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlFrontend.cpp
@@ -0,0 +1,1201 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "TunerHidlFrontend"
+
+#include "TunerHidlFrontend.h"
+
+#include <aidl/android/hardware/tv/tuner/Result.h>
+
+#include "TunerHidlLnb.h"
+
+using ::aidl::android::hardware::tv::tuner::FrontendAnalogSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendAnalogSifStandard;
+using ::aidl::android::hardware::tv::tuner::FrontendAnalogType;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Bandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3CodeRate;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Fec;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Modulation;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3PlpSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Settings;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3TimeInterleaveMode;
+using ::aidl::android::hardware::tv::tuner::FrontendAtscModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendAtscSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendCableTimeInterleaveMode;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbGuardInterval;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbTimeInterleaveMode;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbTransmissionMode;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcAnnex;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsRolloff;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsStandard;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtConstellation;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtGuardInterval;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtHierarchy;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtStandard;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtTransmissionMode;
+using ::aidl::android::hardware::tv::tuner::FrontendGuardInterval;
+using ::aidl::android::hardware::tv::tuner::FrontendInnerFec;
+using ::aidl::android::hardware::tv::tuner::FrontendInterleaveMode;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Modulation;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Rolloff;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Settings;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbsModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbsRolloff;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbsSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtCoderate;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtGuardInterval;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtMode;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendModulationStatus;
+using ::aidl::android::hardware::tv::tuner::FrontendRollOff;
+using ::aidl::android::hardware::tv::tuner::FrontendScanAtsc3PlpInfo;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessageStandard;
+using ::aidl::android::hardware::tv::tuner::FrontendSpectralInversion;
+using ::aidl::android::hardware::tv::tuner::FrontendStatusAtsc3PlpInfo;
+using ::aidl::android::hardware::tv::tuner::FrontendTransmissionMode;
+using ::aidl::android::hardware::tv::tuner::Result;
+
+using HidlFrontendStatusAtsc3PlpInfo =
+ ::aidl::android::hardware::tv::tuner::FrontendStatusAtsc3PlpInfo;
+using HidlFrontendAnalogSifStandard =
+ ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
+using HidlFrontendAnalogType = ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
+using HidlFrontendAtscModulation = ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
+using HidlFrontendAtsc3Bandwidth = ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Bandwidth;
+using HidlFrontendAtsc3CodeRate = ::android::hardware::tv::tuner::V1_0::FrontendAtsc3CodeRate;
+using HidlFrontendAtsc3DemodOutputFormat =
+ ::android::hardware::tv::tuner::V1_0::FrontendAtsc3DemodOutputFormat;
+using HidlFrontendAtsc3Fec = ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Fec;
+using HidlFrontendAtsc3Modulation = ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation;
+using HidlFrontendAtsc3TimeInterleaveMode =
+ ::android::hardware::tv::tuner::V1_0::FrontendAtsc3TimeInterleaveMode;
+using HidlFrontendDvbcAnnex = ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex;
+using HidlFrontendDvbcModulation = ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation;
+using HidlFrontendDvbcOuterFec = ::android::hardware::tv::tuner::V1_0::FrontendDvbcOuterFec;
+using HidlFrontendDvbcSpectralInversion =
+ ::android::hardware::tv::tuner::V1_0::FrontendDvbcSpectralInversion;
+using HidlFrontendDvbsModulation = ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation;
+using HidlFrontendDvbsPilot = ::android::hardware::tv::tuner::V1_0::FrontendDvbsPilot;
+using HidlFrontendDvbsRolloff = ::android::hardware::tv::tuner::V1_0::FrontendDvbsRolloff;
+using HidlFrontendDvbsSettings = ::android::hardware::tv::tuner::V1_0::FrontendDvbsSettings;
+using HidlFrontendDvbsStandard = ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard;
+using HidlFrontendDvbsVcmMode = ::android::hardware::tv::tuner::V1_0::FrontendDvbsVcmMode;
+using HidlFrontendDvbtBandwidth = ::android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
+using HidlFrontendDvbtCoderate = ::android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
+using HidlFrontendDvbtConstellation =
+ ::android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
+using HidlFrontendDvbtGuardInterval =
+ ::android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval;
+using HidlFrontendDvbtHierarchy = ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
+using HidlFrontendDvbtPlpMode = ::android::hardware::tv::tuner::V1_0::FrontendDvbtPlpMode;
+using HidlFrontendDvbtSettings = ::android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
+using HidlFrontendDvbtStandard = ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
+using HidlFrontendDvbtTransmissionMode =
+ ::android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
+using HidlFrontendInnerFec = ::android::hardware::tv::tuner::V1_0::FrontendInnerFec;
+using HidlFrontendIsdbs3Coderate = ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Coderate;
+using HidlFrontendIsdbs3Modulation = ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation;
+using HidlFrontendIsdbs3Rolloff = ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Rolloff;
+using HidlFrontendIsdbs3Settings = ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Settings;
+using HidlFrontendIsdbsCoderate = ::android::hardware::tv::tuner::V1_0::FrontendIsdbsCoderate;
+using HidlFrontendIsdbsModulation = ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation;
+using HidlFrontendIsdbsRolloff = ::android::hardware::tv::tuner::V1_0::FrontendIsdbsRolloff;
+using HidlFrontendIsdbsSettings = ::android::hardware::tv::tuner::V1_0::FrontendIsdbsSettings;
+using HidlFrontendIsdbsStreamIdType =
+ ::android::hardware::tv::tuner::V1_0::FrontendIsdbsStreamIdType;
+using HidlFrontendIsdbtBandwidth = ::android::hardware::tv::tuner::V1_0::FrontendIsdbtBandwidth;
+using HidlFrontendIsdbtCoderate = ::android::hardware::tv::tuner::V1_0::FrontendIsdbtCoderate;
+using HidlFrontendIsdbtGuardInterval =
+ ::android::hardware::tv::tuner::V1_0::FrontendIsdbtGuardInterval;
+using HidlFrontendIsdbtMode = ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode;
+using HidlFrontendIsdbtModulation = ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
+using HidlFrontendIsdbtSettings = ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings;
+using HidlFrontendModulationStatus = ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus;
+using HidlFrontendScanAtsc3PlpInfo = ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
+using HidlFrontendScanType = ::android::hardware::tv::tuner::V1_0::FrontendScanType;
+using HidlFrontendStatusType = ::android::hardware::tv::tuner::V1_0::FrontendStatusType;
+using HidlResult = ::android::hardware::tv::tuner::V1_0::Result;
+using HidlFrontendAnalogAftFlag = ::android::hardware::tv::tuner::V1_1::FrontendAnalogAftFlag;
+using HidlFrontendBandwidth = ::android::hardware::tv::tuner::V1_1::FrontendBandwidth;
+using HidlFrontendCableTimeInterleaveMode =
+ ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode;
+using HidlFrontendDvbcBandwidth = ::android::hardware::tv::tuner::V1_1::FrontendDvbcBandwidth;
+using HidlFrontendDtmbBandwidth = ::android::hardware::tv::tuner::V1_1::FrontendDtmbBandwidth;
+using HidlFrontendDtmbCodeRate = ::android::hardware::tv::tuner::V1_1::FrontendDtmbCodeRate;
+using HidlFrontendDtmbGuardInterval =
+ ::android::hardware::tv::tuner::V1_1::FrontendDtmbGuardInterval;
+using HidlFrontendDtmbModulation = ::android::hardware::tv::tuner::V1_1::FrontendDtmbModulation;
+using HidlFrontendDtmbTimeInterleaveMode =
+ ::android::hardware::tv::tuner::V1_1::FrontendDtmbTimeInterleaveMode;
+using HidlFrontendDtmbTransmissionMode =
+ ::android::hardware::tv::tuner::V1_1::FrontendDtmbTransmissionMode;
+using HidlFrontendDvbsScanType = ::android::hardware::tv::tuner::V1_1::FrontendDvbsScanType;
+using HidlFrontendGuardInterval = ::android::hardware::tv::tuner::V1_1::FrontendGuardInterval;
+using HidlFrontendInterleaveMode = ::android::hardware::tv::tuner::V1_1::FrontendInterleaveMode;
+using HidlFrontendModulation = ::android::hardware::tv::tuner::V1_1::FrontendModulation;
+using HidlFrontendRollOff = ::android::hardware::tv::tuner::V1_1::FrontendRollOff;
+using HidlFrontendTransmissionMode = ::android::hardware::tv::tuner::V1_1::FrontendTransmissionMode;
+using HidlFrontendSpectralInversion =
+ ::android::hardware::tv::tuner::V1_1::FrontendSpectralInversion;
+using HidlFrontendStatusTypeExt1_1 = ::android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1;
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+TunerHidlFrontend::TunerHidlFrontend(sp<HidlIFrontend> frontend, int id) {
+ mFrontend = frontend;
+ mFrontend_1_1 = ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
+ mId = id;
+}
+
+TunerHidlFrontend::~TunerHidlFrontend() {
+ mFrontend = nullptr;
+ mFrontend_1_1 = nullptr;
+ mId = -1;
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::setCallback(
+ const shared_ptr<ITunerFrontendCallback>& tunerFrontendCallback) {
+ if (mFrontend == nullptr) {
+ ALOGE("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (tunerFrontendCallback == nullptr) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+
+ sp<HidlIFrontendCallback> frontendCallback = new FrontendCallback(tunerFrontendCallback);
+ HidlResult status = mFrontend->setCallback(frontendCallback);
+ if (status == HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::tune(const FrontendSettings& settings) {
+ if (mFrontend == nullptr) {
+ ALOGE("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status;
+ HidlFrontendSettings frontendSettings;
+ HidlFrontendSettingsExt1_1 frontendSettingsExt;
+ getHidlFrontendSettings(settings, frontendSettings, frontendSettingsExt);
+ if (mFrontend_1_1 != nullptr) {
+ status = mFrontend_1_1->tune_1_1(frontendSettings, frontendSettingsExt);
+ } else {
+ status = mFrontend->tune(frontendSettings);
+ }
+ if (status == HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::stopTune() {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mFrontend->stopTune();
+ if (status == HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::scan(const FrontendSettings& settings,
+ FrontendScanType frontendScanType) {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status;
+ HidlFrontendSettings frontendSettings;
+ HidlFrontendSettingsExt1_1 frontendSettingsExt;
+ getHidlFrontendSettings(settings, frontendSettings, frontendSettingsExt);
+ if (mFrontend_1_1 != nullptr) {
+ status = mFrontend_1_1->scan_1_1(frontendSettings,
+ static_cast<HidlFrontendScanType>(frontendScanType),
+ frontendSettingsExt);
+ } else {
+ status = mFrontend->scan(frontendSettings,
+ static_cast<HidlFrontendScanType>(frontendScanType));
+ }
+ if (status == HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::stopScan() {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mFrontend->stopScan();
+ if (status == HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::setLnb(const shared_ptr<ITunerLnb>& lnb) {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (lnb == nullptr) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+
+ HidlResult status = mFrontend->setLnb(static_cast<TunerHidlLnb*>(lnb.get())->getId());
+ if (status == HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::setLna(bool bEnable) {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mFrontend->setLna(bEnable);
+ if (status == HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::linkCiCamToFrontend(int32_t ciCamId,
+ int32_t* _aidl_return) {
+ if (mFrontend_1_1 == nullptr) {
+ ALOGD("IFrontend_1_1 is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ int ltsId;
+ HidlResult status;
+ mFrontend_1_1->linkCiCam(static_cast<uint32_t>(ciCamId), [&](HidlResult r, uint32_t id) {
+ status = r;
+ ltsId = id;
+ });
+
+ if (status == HidlResult::SUCCESS) {
+ *_aidl_return = ltsId;
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::unlinkCiCamToFrontend(int32_t ciCamId) {
+ if (mFrontend_1_1 == nullptr) {
+ ALOGD("IFrontend_1_1 is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mFrontend_1_1->unlinkCiCam(ciCamId);
+ if (status == HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::close() {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mFrontend->close();
+ mFrontend = nullptr;
+ mFrontend_1_1 = nullptr;
+
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::getStatus(const vector<FrontendStatusType>& in_statusTypes,
+ vector<FrontendStatus>* _aidl_return) {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res;
+ vector<HidlFrontendStatus> status;
+ vector<HidlFrontendStatusExt1_1> statusExt;
+ vector<HidlFrontendStatusType> types;
+ vector<HidlFrontendStatusTypeExt1_1> typesExt;
+ for (auto s : in_statusTypes) {
+ if (static_cast<int32_t>(s) <=
+ static_cast<int32_t>(HidlFrontendStatusType::ATSC3_PLP_INFO)) {
+ types.push_back(static_cast<HidlFrontendStatusType>(s));
+ } else {
+ typesExt.push_back(static_cast<HidlFrontendStatusTypeExt1_1>(s));
+ }
+ }
+
+ mFrontend->getStatus(types, [&](HidlResult r, const hidl_vec<HidlFrontendStatus>& ss) {
+ res = r;
+ for (auto s : ss) {
+ status.push_back(s);
+ }
+ });
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ if (mFrontend_1_1 != nullptr) {
+ mFrontend_1_1->getStatusExt1_1(
+ typesExt, [&](HidlResult r, const hidl_vec<HidlFrontendStatusExt1_1>& ss) {
+ res = r;
+ for (auto s : ss) {
+ statusExt.push_back(s);
+ }
+ });
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ }
+
+ getAidlFrontendStatus(status, statusExt, *_aidl_return);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::getFrontendId(int32_t* _aidl_return) {
+ *_aidl_return = mId;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+/////////////// FrontendCallback ///////////////////////
+Return<void> TunerHidlFrontend::FrontendCallback::onEvent(HidlFrontendEventType frontendEventType) {
+ ALOGV("FrontendCallback::onEvent, type=%d", frontendEventType);
+ mTunerFrontendCallback->onEvent(static_cast<FrontendEventType>(frontendEventType));
+ return Void();
+}
+
+Return<void> TunerHidlFrontend::FrontendCallback::onScanMessage(
+ HidlFrontendScanMessageType type, const HidlFrontendScanMessage& message) {
+ ALOGV("FrontendCallback::onScanMessage, type=%d", type);
+ FrontendScanMessage scanMessage;
+ switch (type) {
+ case HidlFrontendScanMessageType::LOCKED: {
+ scanMessage.set<FrontendScanMessage::isLocked>(message.isLocked());
+ break;
+ }
+ case HidlFrontendScanMessageType::END: {
+ scanMessage.set<FrontendScanMessage::isEnd>(message.isEnd());
+ break;
+ }
+ case HidlFrontendScanMessageType::PROGRESS_PERCENT: {
+ scanMessage.set<FrontendScanMessage::progressPercent>(message.progressPercent());
+ break;
+ }
+ case HidlFrontendScanMessageType::FREQUENCY: {
+ const vector<uint32_t>& f = message.frequencies();
+ vector<int64_t> lf(begin(f), end(f));
+ scanMessage.set<FrontendScanMessage::frequencies>(lf);
+ break;
+ }
+ case HidlFrontendScanMessageType::SYMBOL_RATE: {
+ const vector<uint32_t>& s = message.symbolRates();
+ vector<int32_t> symbolRates(begin(s), end(s));
+ scanMessage.set<FrontendScanMessage::symbolRates>(symbolRates);
+ break;
+ }
+ case HidlFrontendScanMessageType::HIERARCHY: {
+ scanMessage.set<FrontendScanMessage::hierarchy>(
+ static_cast<FrontendDvbtHierarchy>(message.hierarchy()));
+ break;
+ }
+ case HidlFrontendScanMessageType::ANALOG_TYPE: {
+ scanMessage.set<FrontendScanMessage::analogType>(
+ static_cast<FrontendAnalogType>(message.analogType()));
+ break;
+ }
+ case HidlFrontendScanMessageType::PLP_IDS: {
+ const vector<uint8_t>& p = message.plpIds();
+ vector<int32_t> plpIds(begin(p), end(p));
+ scanMessage.set<FrontendScanMessage::plpIds>(plpIds);
+ break;
+ }
+ case HidlFrontendScanMessageType::GROUP_IDS: {
+ const vector<uint8_t>& g = message.groupIds();
+ vector<int32_t> groupIds(begin(g), end(g));
+ scanMessage.set<FrontendScanMessage::groupIds>(groupIds);
+ break;
+ }
+ case HidlFrontendScanMessageType::INPUT_STREAM_IDS: {
+ const vector<uint16_t>& i = message.inputStreamIds();
+ vector<int32_t> streamIds(begin(i), end(i));
+ scanMessage.set<FrontendScanMessage::inputStreamIds>(streamIds);
+ break;
+ }
+ case HidlFrontendScanMessageType::STANDARD: {
+ const HidlFrontendScanMessage::Standard& std = message.std();
+ FrontendScanMessageStandard standard;
+ if (std.getDiscriminator() == HidlFrontendScanMessage::Standard::hidl_discriminator::sStd) {
+ standard.set<FrontendScanMessageStandard::sStd>(
+ static_cast<FrontendDvbsStandard>(std.sStd()));
+ } else if (std.getDiscriminator() ==
+ HidlFrontendScanMessage::Standard::hidl_discriminator::tStd) {
+ standard.set<FrontendScanMessageStandard::tStd>(
+ static_cast<FrontendDvbtStandard>(std.tStd()));
+ } else if (std.getDiscriminator() ==
+ HidlFrontendScanMessage::Standard::hidl_discriminator::sifStd) {
+ standard.set<FrontendScanMessageStandard::sifStd>(
+ static_cast<FrontendAnalogSifStandard>(std.sifStd()));
+ }
+ scanMessage.set<FrontendScanMessage::std>(standard);
+ break;
+ }
+ case HidlFrontendScanMessageType::ATSC3_PLP_INFO: {
+ const vector<HidlFrontendScanAtsc3PlpInfo>& plpInfos = message.atsc3PlpInfos();
+ vector<FrontendScanAtsc3PlpInfo> tunerPlpInfos;
+ for (int i = 0; i < plpInfos.size(); i++) {
+ FrontendScanAtsc3PlpInfo plpInfo{
+ .plpId = static_cast<int32_t>(plpInfos[i].plpId),
+ .bLlsFlag = plpInfos[i].bLlsFlag,
+ };
+ tunerPlpInfos.push_back(plpInfo);
+ }
+ scanMessage.set<FrontendScanMessage::atsc3PlpInfos>(tunerPlpInfos);
+ break;
+ }
+ default:
+ break;
+ }
+ mTunerFrontendCallback->onScanMessage(static_cast<FrontendScanMessageType>(type), scanMessage);
+ return Void();
+}
+
+Return<void> TunerHidlFrontend::FrontendCallback::onScanMessageExt1_1(
+ HidlFrontendScanMessageTypeExt1_1 type, const HidlFrontendScanMessageExt1_1& message) {
+ ALOGV("onScanMessageExt1_1::onScanMessage, type=%d", type);
+ FrontendScanMessage scanMessage;
+ switch (type) {
+ case HidlFrontendScanMessageTypeExt1_1::MODULATION: {
+ HidlFrontendModulation m = message.modulation();
+ FrontendModulation modulation;
+ switch (m.getDiscriminator()) {
+ case HidlFrontendModulation::hidl_discriminator::dvbc: {
+ modulation.set<FrontendModulation::dvbc>(static_cast<FrontendDvbcModulation>(m.dvbc()));
+ break;
+ }
+ case HidlFrontendModulation::hidl_discriminator::dvbt: {
+ modulation.set<FrontendModulation::dvbt>(
+ static_cast<FrontendDvbtConstellation>(m.dvbt()));
+ break;
+ }
+ case HidlFrontendModulation::hidl_discriminator::dvbs: {
+ modulation.set<FrontendModulation::dvbs>(static_cast<FrontendDvbsModulation>(m.dvbs()));
+ break;
+ }
+ case HidlFrontendModulation::hidl_discriminator::isdbs: {
+ modulation.set<FrontendModulation::isdbs>(
+ static_cast<FrontendIsdbsModulation>(m.isdbs()));
+ break;
+ }
+ case HidlFrontendModulation::hidl_discriminator::isdbs3: {
+ modulation.set<FrontendModulation::isdbs3>(
+ static_cast<FrontendIsdbs3Modulation>(m.isdbs3()));
+ break;
+ }
+ case HidlFrontendModulation::hidl_discriminator::isdbt: {
+ modulation.set<FrontendModulation::isdbt>(
+ static_cast<FrontendIsdbtModulation>(m.isdbt()));
+ break;
+ }
+ case HidlFrontendModulation::hidl_discriminator::atsc: {
+ modulation.set<FrontendModulation::atsc>(static_cast<FrontendAtscModulation>(m.atsc()));
+ break;
+ }
+ case HidlFrontendModulation::hidl_discriminator::atsc3: {
+ modulation.set<FrontendModulation::atsc3>(
+ static_cast<FrontendAtsc3Modulation>(m.atsc3()));
+ break;
+ }
+ case HidlFrontendModulation::hidl_discriminator::dtmb: {
+ modulation.set<FrontendModulation::dtmb>(static_cast<FrontendDtmbModulation>(m.dtmb()));
+ break;
+ }
+ }
+ scanMessage.set<FrontendScanMessage::modulation>(modulation);
+ break;
+ }
+ case HidlFrontendScanMessageTypeExt1_1::DVBC_ANNEX: {
+ scanMessage.set<FrontendScanMessage::annex>(
+ static_cast<FrontendDvbcAnnex>(message.annex()));
+ break;
+ }
+ case HidlFrontendScanMessageTypeExt1_1::HIGH_PRIORITY: {
+ scanMessage.set<FrontendScanMessage::isHighPriority>(message.isHighPriority());
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ mTunerFrontendCallback->onScanMessage(static_cast<FrontendScanMessageType>(type), scanMessage);
+ return Void();
+}
+
+/////////////// TunerHidlFrontend Helper Methods ///////////////////////
+void TunerHidlFrontend::getAidlFrontendStatus(const vector<HidlFrontendStatus>& hidlStatus,
+ const vector<HidlFrontendStatusExt1_1>& hidlStatusExt,
+ vector<FrontendStatus>& aidlStatus) {
+ for (HidlFrontendStatus s : hidlStatus) {
+ FrontendStatus status;
+ switch (s.getDiscriminator()) {
+ case HidlFrontendStatus::hidl_discriminator::isDemodLocked: {
+ status.set<FrontendStatus::isDemodLocked>(s.isDemodLocked());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::snr: {
+ status.set<FrontendStatus::snr>((int)s.snr());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::ber: {
+ status.set<FrontendStatus::ber>((int)s.ber());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::per: {
+ status.set<FrontendStatus::per>((int)s.per());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::preBer: {
+ status.set<FrontendStatus::preBer>((int)s.preBer());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::signalQuality: {
+ status.set<FrontendStatus::signalQuality>((int)s.signalQuality());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::signalStrength: {
+ status.set<FrontendStatus::signalStrength>((int)s.signalStrength());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::symbolRate: {
+ status.set<FrontendStatus::symbolRate>((int)s.symbolRate());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::innerFec: {
+ status.set<FrontendStatus::innerFec>(static_cast<FrontendInnerFec>(s.innerFec()));
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::modulation: {
+ FrontendModulationStatus modulationStatus;
+ switch (s.modulation().getDiscriminator()) {
+ case HidlFrontendModulationStatus::hidl_discriminator::dvbc:
+ modulationStatus.set<FrontendModulationStatus::dvbc>(
+ static_cast<FrontendDvbcModulation>(s.modulation().dvbc()));
+ break;
+ case HidlFrontendModulationStatus::hidl_discriminator::dvbs:
+ modulationStatus.set<FrontendModulationStatus::dvbs>(
+ static_cast<FrontendDvbsModulation>(s.modulation().dvbs()));
+ break;
+ case HidlFrontendModulationStatus::hidl_discriminator::isdbs:
+ modulationStatus.set<FrontendModulationStatus::isdbs>(
+ static_cast<FrontendIsdbsModulation>(s.modulation().isdbs()));
+ break;
+ case HidlFrontendModulationStatus::hidl_discriminator::isdbs3:
+ modulationStatus.set<FrontendModulationStatus::isdbs3>(
+ static_cast<FrontendIsdbs3Modulation>(s.modulation().isdbs3()));
+ break;
+ case HidlFrontendModulationStatus::hidl_discriminator::isdbt:
+ modulationStatus.set<FrontendModulationStatus::isdbt>(
+ static_cast<FrontendIsdbtModulation>(s.modulation().isdbt()));
+ break;
+ }
+ status.set<FrontendStatus::modulationStatus>(modulationStatus);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::inversion: {
+ status.set<FrontendStatus::inversion>(
+ static_cast<FrontendSpectralInversion>(s.inversion()));
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::lnbVoltage: {
+ status.set<FrontendStatus::lnbVoltage>(static_cast<LnbVoltage>(s.lnbVoltage()));
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::plpId: {
+ status.set<FrontendStatus::plpId>((int32_t)s.plpId());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::isEWBS: {
+ status.set<FrontendStatus::isEWBS>(s.isEWBS());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::agc: {
+ status.set<FrontendStatus::agc>((int32_t)s.agc());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::isLnaOn: {
+ status.set<FrontendStatus::isLnaOn>(s.isLnaOn());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::isLayerError: {
+ vector<bool> e(s.isLayerError().begin(), s.isLayerError().end());
+ status.set<FrontendStatus::isLayerError>(e);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::mer: {
+ status.set<FrontendStatus::mer>(static_cast<int32_t>(s.mer()));
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::freqOffset: {
+ status.set<FrontendStatus::freqOffset>(static_cast<int64_t>(s.freqOffset()));
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::hierarchy: {
+ status.set<FrontendStatus::hierarchy>(
+ static_cast<FrontendDvbtHierarchy>(s.hierarchy()));
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::isRfLocked: {
+ status.set<FrontendStatus::isRfLocked>(s.isRfLocked());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatus::hidl_discriminator::plpInfo: {
+ vector<FrontendStatusAtsc3PlpInfo> info;
+ for (auto i : s.plpInfo()) {
+ info.push_back({
+ .plpId = static_cast<int32_t>(i.plpId),
+ .isLocked = i.isLocked,
+ .uec = static_cast<int32_t>(i.uec),
+ });
+ }
+ status.set<FrontendStatus::plpInfo>(info);
+ aidlStatus.push_back(status);
+ break;
+ }
+ }
+ }
+
+ for (HidlFrontendStatusExt1_1 s : hidlStatusExt) {
+ FrontendStatus status;
+ switch (s.getDiscriminator()) {
+ case HidlFrontendStatusExt1_1::hidl_discriminator::modulations: {
+ vector<FrontendModulation> aidlMod;
+ for (auto m : s.modulations()) {
+ switch (m.getDiscriminator()) {
+ case HidlFrontendModulation::hidl_discriminator::dvbc:
+ aidlMod.push_back(static_cast<FrontendDvbcModulation>(m.dvbc()));
+ break;
+ case HidlFrontendModulation::hidl_discriminator::dvbs:
+ aidlMod.push_back(static_cast<FrontendDvbsModulation>(m.dvbs()));
+ break;
+ case HidlFrontendModulation::hidl_discriminator::dvbt:
+ aidlMod.push_back(static_cast<FrontendDvbtConstellation>(m.dvbt()));
+ break;
+ case HidlFrontendModulation::hidl_discriminator::isdbs:
+ aidlMod.push_back(static_cast<FrontendIsdbsModulation>(m.isdbs()));
+ break;
+ case HidlFrontendModulation::hidl_discriminator::isdbs3:
+ aidlMod.push_back(static_cast<FrontendIsdbs3Modulation>(m.isdbs3()));
+ break;
+ case HidlFrontendModulation::hidl_discriminator::isdbt:
+ aidlMod.push_back(static_cast<FrontendIsdbtModulation>(m.isdbt()));
+ break;
+ case HidlFrontendModulation::hidl_discriminator::atsc:
+ aidlMod.push_back(static_cast<FrontendAtscModulation>(m.atsc()));
+ break;
+ case HidlFrontendModulation::hidl_discriminator::atsc3:
+ aidlMod.push_back(static_cast<FrontendAtsc3Modulation>(m.atsc3()));
+ break;
+ case HidlFrontendModulation::hidl_discriminator::dtmb:
+ aidlMod.push_back(static_cast<FrontendDtmbModulation>(m.dtmb()));
+ break;
+ }
+ }
+ status.set<FrontendStatus::modulations>(aidlMod);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::bers: {
+ vector<int> b(s.bers().begin(), s.bers().end());
+ status.set<FrontendStatus::bers>(b);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::codeRates: {
+ vector<FrontendInnerFec> codeRates;
+ for (auto c : s.codeRates()) {
+ codeRates.push_back(static_cast<FrontendInnerFec>(c));
+ }
+ status.set<FrontendStatus::codeRates>(codeRates);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::bandwidth: {
+ FrontendBandwidth bandwidth;
+ switch (s.bandwidth().getDiscriminator()) {
+ case HidlFrontendBandwidth::hidl_discriminator::atsc3:
+ bandwidth.set<FrontendBandwidth::atsc3>(
+ static_cast<FrontendAtsc3Bandwidth>(s.bandwidth().atsc3()));
+ break;
+ case HidlFrontendBandwidth::hidl_discriminator::dvbc:
+ bandwidth.set<FrontendBandwidth::dvbc>(
+ static_cast<FrontendDvbcBandwidth>(s.bandwidth().dvbc()));
+ break;
+ case HidlFrontendBandwidth::hidl_discriminator::dvbt:
+ bandwidth.set<FrontendBandwidth::dvbt>(
+ static_cast<FrontendDvbtBandwidth>(s.bandwidth().dvbt()));
+ break;
+ case HidlFrontendBandwidth::hidl_discriminator::isdbt:
+ bandwidth.set<FrontendBandwidth::isdbt>(
+ static_cast<FrontendIsdbtBandwidth>(s.bandwidth().isdbt()));
+ break;
+ case HidlFrontendBandwidth::hidl_discriminator::dtmb:
+ bandwidth.set<FrontendBandwidth::dtmb>(
+ static_cast<FrontendDtmbBandwidth>(s.bandwidth().dtmb()));
+ break;
+ }
+ status.set<FrontendStatus::bandwidth>(bandwidth);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::interval: {
+ FrontendGuardInterval interval;
+ switch (s.interval().getDiscriminator()) {
+ case HidlFrontendGuardInterval::hidl_discriminator::dvbt:
+ interval.set<FrontendGuardInterval::dvbt>(
+ static_cast<FrontendDvbtGuardInterval>(s.interval().dvbt()));
+ break;
+ case HidlFrontendGuardInterval::hidl_discriminator::isdbt:
+ interval.set<FrontendGuardInterval::isdbt>(
+ static_cast<FrontendIsdbtGuardInterval>(s.interval().isdbt()));
+ break;
+ case HidlFrontendGuardInterval::hidl_discriminator::dtmb:
+ interval.set<FrontendGuardInterval::dtmb>(
+ static_cast<FrontendDtmbGuardInterval>(s.interval().dtmb()));
+ break;
+ }
+ status.set<FrontendStatus::interval>(interval);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::transmissionMode: {
+ FrontendTransmissionMode transmissionMode;
+ switch (s.transmissionMode().getDiscriminator()) {
+ case HidlFrontendTransmissionMode::hidl_discriminator::dvbt:
+ transmissionMode.set<FrontendTransmissionMode::dvbt>(
+ static_cast<FrontendDvbtTransmissionMode>(s.transmissionMode().dvbt()));
+ break;
+ case HidlFrontendTransmissionMode::hidl_discriminator::isdbt:
+ transmissionMode.set<FrontendTransmissionMode::isdbt>(
+ static_cast<FrontendIsdbtMode>(s.transmissionMode().isdbt()));
+ break;
+ case HidlFrontendTransmissionMode::hidl_discriminator::dtmb:
+ transmissionMode.set<FrontendTransmissionMode::dtmb>(
+ static_cast<FrontendDtmbTransmissionMode>(s.transmissionMode().dtmb()));
+ break;
+ }
+ status.set<FrontendStatus::transmissionMode>(transmissionMode);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::uec: {
+ status.set<FrontendStatus::uec>(static_cast<int32_t>(s.uec()));
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::systemId: {
+ status.set<FrontendStatus::systemId>(static_cast<int32_t>(s.systemId()));
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::interleaving: {
+ vector<FrontendInterleaveMode> aidlInter;
+ for (auto i : s.interleaving()) {
+ FrontendInterleaveMode leaveMode;
+ switch (i.getDiscriminator()) {
+ case HidlFrontendInterleaveMode::hidl_discriminator::atsc3:
+ leaveMode.set<FrontendInterleaveMode::atsc3>(
+ static_cast<FrontendAtsc3TimeInterleaveMode>(i.atsc3()));
+ break;
+ case HidlFrontendInterleaveMode::hidl_discriminator::dvbc:
+ leaveMode.set<FrontendInterleaveMode::dvbc>(
+ static_cast<FrontendCableTimeInterleaveMode>(i.dvbc()));
+ break;
+ case HidlFrontendInterleaveMode::hidl_discriminator::dtmb:
+ leaveMode.set<FrontendInterleaveMode::dtmb>(
+ static_cast<FrontendDtmbTimeInterleaveMode>(i.dtmb()));
+ break;
+ }
+ aidlInter.push_back(leaveMode);
+ }
+ status.set<FrontendStatus::interleaving>(aidlInter);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::isdbtSegment: {
+ const vector<uint8_t>& seg = s.isdbtSegment();
+ vector<int32_t> i(seg.begin(), seg.end());
+ status.set<FrontendStatus::isdbtSegment>(i);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::tsDataRate: {
+ vector<int32_t> ts(s.tsDataRate().begin(), s.tsDataRate().end());
+ status.set<FrontendStatus::tsDataRate>(ts);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::rollOff: {
+ FrontendRollOff rollOff;
+ switch (s.rollOff().getDiscriminator()) {
+ case HidlFrontendRollOff::hidl_discriminator::dvbs:
+ rollOff.set<FrontendRollOff::dvbs>(
+ static_cast<FrontendDvbsRolloff>(s.rollOff().dvbs()));
+ break;
+ case HidlFrontendRollOff::hidl_discriminator::isdbs:
+ rollOff.set<FrontendRollOff::isdbs>(
+ static_cast<FrontendIsdbsRolloff>(s.rollOff().isdbs()));
+ break;
+ case HidlFrontendRollOff::hidl_discriminator::isdbs3:
+ rollOff.set<FrontendRollOff::isdbs3>(
+ static_cast<FrontendIsdbs3Rolloff>(s.rollOff().isdbs3()));
+ break;
+ }
+ status.set<FrontendStatus::rollOff>(rollOff);
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::isMiso: {
+ status.set<FrontendStatus::isMiso>(s.isMiso());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::isLinear: {
+ status.set<FrontendStatus::isLinear>(s.isLinear());
+ aidlStatus.push_back(status);
+ break;
+ }
+ case HidlFrontendStatusExt1_1::hidl_discriminator::isShortFrames: {
+ status.set<FrontendStatus::isShortFrames>(s.isShortFrames());
+ aidlStatus.push_back(status);
+ break;
+ }
+ }
+ }
+}
+
+hidl_vec<HidlFrontendAtsc3PlpSettings> TunerHidlFrontend::getAtsc3PlpSettings(
+ const FrontendAtsc3Settings& settings) {
+ int len = settings.plpSettings.size();
+ hidl_vec<HidlFrontendAtsc3PlpSettings> plps = hidl_vec<HidlFrontendAtsc3PlpSettings>(len);
+ // parse PLP settings
+ for (int i = 0; i < len; i++) {
+ uint8_t plpId = static_cast<uint8_t>(settings.plpSettings[i].plpId);
+ HidlFrontendAtsc3Modulation modulation =
+ static_cast<HidlFrontendAtsc3Modulation>(settings.plpSettings[i].modulation);
+ HidlFrontendAtsc3TimeInterleaveMode interleaveMode =
+ static_cast<HidlFrontendAtsc3TimeInterleaveMode>(
+ settings.plpSettings[i].interleaveMode);
+ HidlFrontendAtsc3CodeRate codeRate =
+ static_cast<HidlFrontendAtsc3CodeRate>(settings.plpSettings[i].codeRate);
+ HidlFrontendAtsc3Fec fec = static_cast<HidlFrontendAtsc3Fec>(settings.plpSettings[i].fec);
+ HidlFrontendAtsc3PlpSettings frontendAtsc3PlpSettings{
+ .plpId = plpId,
+ .modulation = modulation,
+ .interleaveMode = interleaveMode,
+ .codeRate = codeRate,
+ .fec = fec,
+ };
+ plps[i] = frontendAtsc3PlpSettings;
+ }
+ return plps;
+}
+
+HidlFrontendDvbsCodeRate TunerHidlFrontend::getDvbsCodeRate(const FrontendDvbsCodeRate& codeRate) {
+ HidlFrontendInnerFec innerFec = static_cast<HidlFrontendInnerFec>(codeRate.fec);
+ bool isLinear = codeRate.isLinear;
+ bool isShortFrames = codeRate.isShortFrames;
+ uint32_t bitsPer1000Symbol = static_cast<uint32_t>(codeRate.bitsPer1000Symbol);
+ HidlFrontendDvbsCodeRate coderate{
+ .fec = innerFec,
+ .isLinear = isLinear,
+ .isShortFrames = isShortFrames,
+ .bitsPer1000Symbol = bitsPer1000Symbol,
+ };
+ return coderate;
+}
+
+void TunerHidlFrontend::getHidlFrontendSettings(const FrontendSettings& aidlSettings,
+ HidlFrontendSettings& settings,
+ HidlFrontendSettingsExt1_1& settingsExt) {
+ switch (aidlSettings.getTag()) {
+ case FrontendSettings::analog: {
+ const FrontendAnalogSettings& analog = aidlSettings.get<FrontendSettings::analog>();
+ settings.analog({
+ .frequency = static_cast<uint32_t>(analog.frequency),
+ .type = static_cast<HidlFrontendAnalogType>(analog.type),
+ .sifStandard = static_cast<HidlFrontendAnalogSifStandard>(analog.sifStandard),
+ });
+ settingsExt.settingExt.analog({
+ .aftFlag = static_cast<HidlFrontendAnalogAftFlag>(analog.aftFlag),
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(analog.endFrequency);
+ settingsExt.inversion = static_cast<HidlFrontendSpectralInversion>(analog.inversion);
+ break;
+ }
+ case FrontendSettings::atsc: {
+ const FrontendAtscSettings& atsc = aidlSettings.get<FrontendSettings::atsc>();
+ settings.atsc({
+ .frequency = static_cast<uint32_t>(atsc.frequency),
+ .modulation = static_cast<HidlFrontendAtscModulation>(atsc.modulation),
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(atsc.endFrequency);
+ settingsExt.inversion = static_cast<HidlFrontendSpectralInversion>(atsc.inversion);
+ settingsExt.settingExt.noinit();
+ break;
+ }
+ case FrontendSettings::atsc3: {
+ const FrontendAtsc3Settings& atsc3 = aidlSettings.get<FrontendSettings::atsc3>();
+ settings.atsc3({
+ .frequency = static_cast<uint32_t>(atsc3.frequency),
+ .bandwidth = static_cast<HidlFrontendAtsc3Bandwidth>(atsc3.bandwidth),
+ .demodOutputFormat =
+ static_cast<HidlFrontendAtsc3DemodOutputFormat>(atsc3.demodOutputFormat),
+ .plpSettings = getAtsc3PlpSettings(atsc3),
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(atsc3.endFrequency);
+ settingsExt.inversion = static_cast<HidlFrontendSpectralInversion>(atsc3.inversion);
+ settingsExt.settingExt.noinit();
+ break;
+ }
+ case FrontendSettings::dvbc: {
+ const FrontendDvbcSettings& dvbc = aidlSettings.get<FrontendSettings::dvbc>();
+ settings.dvbc({
+ .frequency = static_cast<uint32_t>(dvbc.frequency),
+ .modulation = static_cast<HidlFrontendDvbcModulation>(dvbc.modulation),
+ .fec = static_cast<HidlFrontendInnerFec>(dvbc.fec),
+ .symbolRate = static_cast<uint32_t>(dvbc.symbolRate),
+ .outerFec = static_cast<HidlFrontendDvbcOuterFec>(dvbc.outerFec),
+ .annex = static_cast<HidlFrontendDvbcAnnex>(dvbc.annex),
+ .spectralInversion = static_cast<HidlFrontendDvbcSpectralInversion>(dvbc.inversion),
+ });
+ settingsExt.settingExt.dvbc({
+ .interleaveMode =
+ static_cast<HidlFrontendCableTimeInterleaveMode>(dvbc.interleaveMode),
+ .bandwidth = static_cast<HidlFrontendDvbcBandwidth>(dvbc.bandwidth),
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(dvbc.endFrequency);
+ settingsExt.inversion = static_cast<HidlFrontendSpectralInversion>(dvbc.inversion);
+ break;
+ }
+ case FrontendSettings::dvbs: {
+ const FrontendDvbsSettings& dvbs = aidlSettings.get<FrontendSettings::dvbs>();
+ settings.dvbs({
+ .frequency = static_cast<uint32_t>(dvbs.frequency),
+ .modulation = static_cast<HidlFrontendDvbsModulation>(dvbs.modulation),
+ .coderate = getDvbsCodeRate(dvbs.coderate),
+ .symbolRate = static_cast<uint32_t>(dvbs.symbolRate),
+ .rolloff = static_cast<HidlFrontendDvbsRolloff>(dvbs.rolloff),
+ .pilot = static_cast<HidlFrontendDvbsPilot>(dvbs.pilot),
+ .inputStreamId = static_cast<uint32_t>(dvbs.inputStreamId),
+ .standard = static_cast<HidlFrontendDvbsStandard>(dvbs.standard),
+ .vcmMode = static_cast<HidlFrontendDvbsVcmMode>(dvbs.vcmMode),
+ });
+ settingsExt.settingExt.dvbs({
+ .scanType = static_cast<HidlFrontendDvbsScanType>(dvbs.scanType),
+ .isDiseqcRxMessage = dvbs.isDiseqcRxMessage,
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(dvbs.endFrequency);
+ settingsExt.inversion = static_cast<HidlFrontendSpectralInversion>(dvbs.inversion);
+ break;
+ }
+ case FrontendSettings::dvbt: {
+ const FrontendDvbtSettings& dvbt = aidlSettings.get<FrontendSettings::dvbt>();
+ settings.dvbt({
+ .frequency = static_cast<uint32_t>(dvbt.frequency),
+ .transmissionMode =
+ static_cast<HidlFrontendDvbtTransmissionMode>(dvbt.transmissionMode),
+ .bandwidth = static_cast<HidlFrontendDvbtBandwidth>(dvbt.bandwidth),
+ .constellation = static_cast<HidlFrontendDvbtConstellation>(dvbt.constellation),
+ .hierarchy = static_cast<HidlFrontendDvbtHierarchy>(dvbt.hierarchy),
+ .hpCoderate = static_cast<HidlFrontendDvbtCoderate>(dvbt.hpCoderate),
+ .lpCoderate = static_cast<HidlFrontendDvbtCoderate>(dvbt.lpCoderate),
+ .guardInterval = static_cast<HidlFrontendDvbtGuardInterval>(dvbt.guardInterval),
+ .isHighPriority = dvbt.isHighPriority,
+ .standard = static_cast<HidlFrontendDvbtStandard>(dvbt.standard),
+ .isMiso = dvbt.isMiso,
+ .plpMode = static_cast<HidlFrontendDvbtPlpMode>(dvbt.plpMode),
+ .plpId = static_cast<uint8_t>(dvbt.plpId),
+ .plpGroupId = static_cast<uint8_t>(dvbt.plpGroupId),
+ });
+ settingsExt.settingExt.dvbt({
+ .constellation = static_cast<
+ ::android::hardware::tv::tuner::V1_1::FrontendDvbtConstellation>(
+ dvbt.constellation),
+ .transmissionMode = static_cast<
+ ::android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode>(
+ dvbt.transmissionMode),
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(dvbt.endFrequency);
+ settingsExt.inversion = static_cast<HidlFrontendSpectralInversion>(dvbt.inversion);
+ break;
+ }
+ case FrontendSettings::isdbs: {
+ const FrontendIsdbsSettings& isdbs = aidlSettings.get<FrontendSettings::isdbs>();
+ settings.isdbs({
+ .frequency = static_cast<uint32_t>(isdbs.frequency),
+ .streamId = static_cast<uint16_t>(isdbs.streamId),
+ .streamIdType = static_cast<HidlFrontendIsdbsStreamIdType>(isdbs.streamIdType),
+ .modulation = static_cast<HidlFrontendIsdbsModulation>(isdbs.modulation),
+ .coderate = static_cast<HidlFrontendIsdbsCoderate>(isdbs.coderate),
+ .symbolRate = static_cast<uint32_t>(isdbs.symbolRate),
+ .rolloff = static_cast<HidlFrontendIsdbsRolloff>(isdbs.rolloff),
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(isdbs.endFrequency);
+ settingsExt.settingExt.noinit();
+ break;
+ }
+ case FrontendSettings::isdbs3: {
+ const FrontendIsdbs3Settings& isdbs3 = aidlSettings.get<FrontendSettings::isdbs3>();
+ settings.isdbs3({
+ .frequency = static_cast<uint32_t>(isdbs3.frequency),
+ .streamId = static_cast<uint16_t>(isdbs3.streamId),
+ .streamIdType = static_cast<HidlFrontendIsdbsStreamIdType>(isdbs3.streamIdType),
+ .modulation = static_cast<HidlFrontendIsdbs3Modulation>(isdbs3.modulation),
+ .coderate = static_cast<HidlFrontendIsdbs3Coderate>(isdbs3.coderate),
+ .symbolRate = static_cast<uint32_t>(isdbs3.symbolRate),
+ .rolloff = static_cast<HidlFrontendIsdbs3Rolloff>(isdbs3.rolloff),
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(isdbs3.endFrequency);
+ settingsExt.settingExt.noinit();
+ break;
+ }
+ case FrontendSettings::isdbt: {
+ const FrontendIsdbtSettings& isdbt = aidlSettings.get<FrontendSettings::isdbt>();
+ settings.isdbt({
+ .frequency = static_cast<uint32_t>(isdbt.frequency),
+ .modulation = static_cast<HidlFrontendIsdbtModulation>(isdbt.modulation),
+ .bandwidth = static_cast<HidlFrontendIsdbtBandwidth>(isdbt.bandwidth),
+ .mode = static_cast<HidlFrontendIsdbtMode>(isdbt.mode),
+ .coderate = static_cast<HidlFrontendIsdbtCoderate>(isdbt.coderate),
+ .guardInterval = static_cast<HidlFrontendIsdbtGuardInterval>(isdbt.guardInterval),
+ .serviceAreaId = static_cast<uint32_t>(isdbt.serviceAreaId),
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(isdbt.endFrequency);
+ settingsExt.inversion = static_cast<HidlFrontendSpectralInversion>(isdbt.inversion);
+ settingsExt.settingExt.noinit();
+ break;
+ }
+ case FrontendSettings::dtmb: {
+ const FrontendDtmbSettings& dtmb = aidlSettings.get<FrontendSettings::dtmb>();
+ settingsExt.settingExt.dtmb({
+ .frequency = static_cast<uint32_t>(dtmb.frequency),
+ .transmissionMode =
+ static_cast<HidlFrontendDtmbTransmissionMode>(dtmb.transmissionMode),
+ .bandwidth = static_cast<HidlFrontendDtmbBandwidth>(dtmb.bandwidth),
+ .modulation = static_cast<HidlFrontendDtmbModulation>(dtmb.modulation),
+ .codeRate = static_cast<HidlFrontendDtmbCodeRate>(dtmb.codeRate),
+ .guardInterval = static_cast<HidlFrontendDtmbGuardInterval>(dtmb.guardInterval),
+ .interleaveMode =
+ static_cast<HidlFrontendDtmbTimeInterleaveMode>(dtmb.interleaveMode),
+ });
+ settingsExt.endFrequency = static_cast<uint32_t>(dtmb.endFrequency);
+ settingsExt.inversion = static_cast<HidlFrontendSpectralInversion>(dtmb.inversion);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
diff --git a/services/tuner/hidl/TunerHidlFrontend.h b/services/tuner/hidl/TunerHidlFrontend.h
new file mode 100644
index 0000000..0abd80b
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlFrontend.h
@@ -0,0 +1,123 @@
+/**
+ * Copyright 2021, 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_MEDIA_TUNERHIDLFRONTEND_H
+#define ANDROID_MEDIA_TUNERHIDLFRONTEND_H
+
+#include <aidl/android/hardware/tv/tuner/IFrontendCallback.h>
+#include <aidl/android/media/tv/tuner/BnTunerFrontend.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.1/IFrontend.h>
+#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <utils/Log.h>
+
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Settings;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsCodeRate;
+using ::aidl::android::hardware::tv::tuner::FrontendEventType;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessage;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessageType;
+using ::aidl::android::hardware::tv::tuner::FrontendScanType;
+using ::aidl::android::hardware::tv::tuner::FrontendSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendStatus;
+using ::aidl::android::hardware::tv::tuner::FrontendStatusType;
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::std::shared_ptr;
+using ::std::vector;
+
+using HidlFrontendAtsc3PlpSettings = ::android::hardware::tv::tuner::V1_0::FrontendAtsc3PlpSettings;
+using HidlFrontendDvbsCodeRate = ::android::hardware::tv::tuner::V1_0::FrontendDvbsCodeRate;
+using HidlFrontendEventType = ::android::hardware::tv::tuner::V1_0::FrontendEventType;
+using HidlFrontendId = ::android::hardware::tv::tuner::V1_0::FrontendId;
+using HidlFrontendScanMessage = ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
+using HidlFrontendScanMessageType = ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using HidlFrontendSettings = ::android::hardware::tv::tuner::V1_0::FrontendSettings;
+using HidlFrontendStatus = ::android::hardware::tv::tuner::V1_0::FrontendStatus;
+using HidlIFrontend = ::android::hardware::tv::tuner::V1_0::IFrontend;
+using HidlIFrontendCallback = ::android::hardware::tv::tuner::V1_1::IFrontendCallback;
+using HidlFrontendScanMessageExt1_1 =
+ ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
+using HidlFrontendScanMessageTypeExt1_1 =
+ ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
+using HidlFrontendSettingsExt1_1 = ::android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1;
+using HidlFrontendStatusExt1_1 = ::android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+class TunerHidlFrontend : public BnTunerFrontend {
+public:
+ TunerHidlFrontend(sp<HidlIFrontend> frontend, int id);
+ virtual ~TunerHidlFrontend();
+
+ ::ndk::ScopedAStatus setCallback(
+ const shared_ptr<ITunerFrontendCallback>& in_tunerFrontendCallback) override;
+ ::ndk::ScopedAStatus tune(const FrontendSettings& in_settings) override;
+ ::ndk::ScopedAStatus stopTune() override;
+ ::ndk::ScopedAStatus scan(const FrontendSettings& in_settings,
+ FrontendScanType in_frontendScanType) override;
+ ::ndk::ScopedAStatus stopScan() override;
+ ::ndk::ScopedAStatus setLnb(const shared_ptr<ITunerLnb>& in_lnb) override;
+ ::ndk::ScopedAStatus setLna(bool in_bEnable) override;
+ ::ndk::ScopedAStatus linkCiCamToFrontend(int32_t in_ciCamId, int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus unlinkCiCamToFrontend(int32_t in_ciCamId) override;
+ ::ndk::ScopedAStatus close() override;
+ ::ndk::ScopedAStatus getStatus(const vector<FrontendStatusType>& in_statusTypes,
+ vector<FrontendStatus>* _aidl_return) override;
+ ::ndk::ScopedAStatus getFrontendId(int32_t* _aidl_return) override;
+
+ struct FrontendCallback : public HidlIFrontendCallback {
+ FrontendCallback(const shared_ptr<ITunerFrontendCallback> tunerFrontendCallback)
+ : mTunerFrontendCallback(tunerFrontendCallback){};
+
+ virtual Return<void> onEvent(HidlFrontendEventType frontendEventType);
+ virtual Return<void> onScanMessage(HidlFrontendScanMessageType type,
+ const HidlFrontendScanMessage& message);
+ virtual Return<void> onScanMessageExt1_1(HidlFrontendScanMessageTypeExt1_1 type,
+ const HidlFrontendScanMessageExt1_1& message);
+
+ shared_ptr<ITunerFrontendCallback> mTunerFrontendCallback;
+ };
+
+private:
+ hidl_vec<HidlFrontendAtsc3PlpSettings> getAtsc3PlpSettings(
+ const FrontendAtsc3Settings& settings);
+ HidlFrontendDvbsCodeRate getDvbsCodeRate(const FrontendDvbsCodeRate& codeRate);
+ void getHidlFrontendSettings(const FrontendSettings& aidlSettings,
+ HidlFrontendSettings& settings,
+ HidlFrontendSettingsExt1_1& settingsExt);
+ void getAidlFrontendStatus(const vector<HidlFrontendStatus>& hidlStatus,
+ const vector<HidlFrontendStatusExt1_1>& hidlStatusExt,
+ vector<FrontendStatus>& aidlStatus);
+
+ int mId;
+ sp<HidlIFrontend> mFrontend;
+ sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFrontend_1_1;
+};
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
+
+#endif // ANDROID_MEDIA_TUNERHIDLFRONTEND_H
diff --git a/services/tuner/hidl/TunerHidlLnb.cpp b/services/tuner/hidl/TunerHidlLnb.cpp
new file mode 100644
index 0000000..a7e20bb
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlLnb.cpp
@@ -0,0 +1,160 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#define LOG_TAG "TunerHidlLnb"
+
+#include "TunerHidlLnb.h"
+
+#include <aidl/android/hardware/tv/tuner/Result.h>
+
+using ::aidl::android::hardware::tv::tuner::Result;
+using HidlLnbPosition = ::android::hardware::tv::tuner::V1_0::LnbPosition;
+using HidlLnbTone = ::android::hardware::tv::tuner::V1_0::LnbTone;
+using HidlLnbVoltage = ::android::hardware::tv::tuner::V1_0::LnbVoltage;
+using HidlResult = ::android::hardware::tv::tuner::V1_0::Result;
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+TunerHidlLnb::TunerHidlLnb(sp<HidlILnb> lnb, int id) {
+ mLnb = lnb;
+ mId = id;
+}
+
+TunerHidlLnb::~TunerHidlLnb() {
+ mLnb = nullptr;
+ mId = -1;
+}
+
+::ndk::ScopedAStatus TunerHidlLnb::setCallback(
+ const shared_ptr<ITunerLnbCallback>& in_tunerLnbCallback) {
+ if (mLnb == nullptr) {
+ ALOGE("ILnb is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (in_tunerLnbCallback == nullptr) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+
+ sp<HidlILnbCallback> lnbCallback = new LnbCallback(in_tunerLnbCallback);
+ HidlResult status = mLnb->setCallback(lnbCallback);
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlLnb::setVoltage(LnbVoltage in_voltage) {
+ if (mLnb == nullptr) {
+ ALOGE("ILnb is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mLnb->setVoltage(static_cast<HidlLnbVoltage>(in_voltage));
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlLnb::setTone(LnbTone in_tone) {
+ if (mLnb == nullptr) {
+ ALOGE("ILnb is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mLnb->setTone(static_cast<HidlLnbTone>(in_tone));
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlLnb::setSatellitePosition(LnbPosition in_position) {
+ if (mLnb == nullptr) {
+ ALOGE("ILnb is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mLnb->setSatellitePosition(static_cast<HidlLnbPosition>(in_position));
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlLnb::sendDiseqcMessage(const vector<uint8_t>& in_diseqcMessage) {
+ if (mLnb == nullptr) {
+ ALOGE("ILnb is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mLnb->sendDiseqcMessage(in_diseqcMessage);
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlLnb::close() {
+ if (mLnb == nullptr) {
+ ALOGE("ILnb is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mLnb->close();
+ mLnb = nullptr;
+
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+/////////////// ILnbCallback ///////////////////////
+Return<void> TunerHidlLnb::LnbCallback::onEvent(const HidlLnbEventType lnbEventType) {
+ if (mTunerLnbCallback != nullptr) {
+ mTunerLnbCallback->onEvent(static_cast<LnbEventType>(lnbEventType));
+ }
+ return Void();
+}
+
+Return<void> TunerHidlLnb::LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
+ if (mTunerLnbCallback != nullptr) {
+ vector<uint8_t> msg(begin(diseqcMessage), end(diseqcMessage));
+ mTunerLnbCallback->onDiseqcMessage(msg);
+ }
+ return Void();
+}
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
diff --git a/services/tuner/hidl/TunerHidlLnb.h b/services/tuner/hidl/TunerHidlLnb.h
new file mode 100644
index 0000000..c496f48
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlLnb.h
@@ -0,0 +1,84 @@
+/**
+ * Copyright 2021, 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_MEDIA_TUNERHIDLLNB_H
+#define ANDROID_MEDIA_TUNERHIDLLNB_H
+
+#include <aidl/android/hardware/tv/tuner/ILnb.h>
+#include <aidl/android/media/tv/tuner/BnTunerLnb.h>
+#include <android/hardware/tv/tuner/1.0/ILnb.h>
+#include <android/hardware/tv/tuner/1.0/ILnbCallback.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <utils/Log.h>
+
+using ::aidl::android::hardware::tv::tuner::LnbEventType;
+using ::aidl::android::hardware::tv::tuner::LnbPosition;
+using ::aidl::android::hardware::tv::tuner::LnbTone;
+using ::aidl::android::hardware::tv::tuner::LnbVoltage;
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::std::shared_ptr;
+using ::std::vector;
+
+using HidlILnb = ::android::hardware::tv::tuner::V1_0::ILnb;
+using HidlILnbCallback = ::android::hardware::tv::tuner::V1_0::ILnbCallback;
+using HidlLnbEventType = ::android::hardware::tv::tuner::V1_0::LnbEventType;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+class TunerHidlLnb : public BnTunerLnb {
+public:
+ TunerHidlLnb(sp<HidlILnb> lnb, int id);
+ virtual ~TunerHidlLnb();
+
+ ::ndk::ScopedAStatus setCallback(
+ const shared_ptr<ITunerLnbCallback>& in_tunerLnbCallback) override;
+ ::ndk::ScopedAStatus setVoltage(LnbVoltage in_voltage) override;
+ ::ndk::ScopedAStatus setTone(LnbTone in_tone) override;
+ ::ndk::ScopedAStatus setSatellitePosition(LnbPosition in_position) override;
+ ::ndk::ScopedAStatus sendDiseqcMessage(const vector<uint8_t>& in_diseqcMessage) override;
+ ::ndk::ScopedAStatus close() override;
+
+ int getId() { return mId; }
+
+ struct LnbCallback : public HidlILnbCallback {
+ LnbCallback(const shared_ptr<ITunerLnbCallback> tunerLnbCallback)
+ : mTunerLnbCallback(tunerLnbCallback){};
+
+ virtual Return<void> onEvent(const HidlLnbEventType lnbEventType);
+ virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
+
+ shared_ptr<ITunerLnbCallback> mTunerLnbCallback;
+ };
+
+private:
+ int mId;
+ sp<HidlILnb> mLnb;
+};
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
+
+#endif // ANDROID_MEDIA_TUNERHIDLLNB_H
diff --git a/services/tuner/hidl/TunerHidlService.cpp b/services/tuner/hidl/TunerHidlService.cpp
new file mode 100644
index 0000000..9d9bc7e
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlService.cpp
@@ -0,0 +1,584 @@
+/**
+ * Copyright (c) 2021, 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "TunerHidlService"
+
+#include "TunerHidlService.h"
+
+#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <android/binder_manager.h>
+#include <utils/Log.h>
+
+#include "TunerHelper.h"
+#include "TunerHidlDemux.h"
+#include "TunerHidlDescrambler.h"
+#include "TunerHidlFrontend.h"
+#include "TunerHidlLnb.h"
+
+using ::aidl::android::hardware::tv::tuner::FrontendAnalogCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Capabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendAtscCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Capabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbsCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendType;
+using ::aidl::android::hardware::tv::tuner::Result;
+using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
+using ::android::hardware::hidl_vec;
+
+using HidlFrontendId = ::android::hardware::tv::tuner::V1_0::FrontendId;
+using HidlLnbId = ::android::hardware::tv::tuner::V1_0::LnbId;
+using HidlFrontendType = ::android::hardware::tv::tuner::V1_1::FrontendType;
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+TunerHidlService::TunerHidlService() {
+ if (!TunerHelper::checkTunerFeature()) {
+ ALOGD("Device doesn't have tuner hardware.");
+ return;
+ }
+
+ updateTunerResources();
+}
+
+TunerHidlService::~TunerHidlService() {}
+
+binder_status_t TunerHidlService::instantiate() {
+ if (HidlITuner::getService() == nullptr) {
+ ALOGD("Failed to get ITuner HIDL HAL");
+ return STATUS_NAME_NOT_FOUND;
+ }
+
+ shared_ptr<TunerHidlService> service = ::ndk::SharedRefBase::make<TunerHidlService>();
+ return AServiceManager_addService(service->asBinder().get(), getServiceName());
+}
+
+bool TunerHidlService::hasITuner() {
+ ALOGV("hasITuner");
+ if (mTuner != nullptr) {
+ return true;
+ }
+
+ mTuner = HidlITuner::getService();
+ if (mTuner == nullptr) {
+ ALOGE("Failed to get ITuner service");
+ return false;
+ }
+ mTunerVersion = TUNER_HAL_VERSION_1_0;
+
+ mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::castFrom(mTuner);
+ if (mTuner_1_1 != nullptr) {
+ mTunerVersion = TUNER_HAL_VERSION_1_1;
+ } else {
+ ALOGD("Failed to get ITuner_1_1 service");
+ }
+
+ return true;
+}
+
+bool TunerHidlService::hasITuner_1_1() {
+ ALOGV("hasITuner_1_1");
+ hasITuner();
+ return (mTunerVersion == TUNER_HAL_VERSION_1_1);
+}
+
+::ndk::ScopedAStatus TunerHidlService::openDemux(int32_t /* in_demuxHandle */,
+ shared_ptr<ITunerDemux>* _aidl_return) {
+ ALOGV("openDemux");
+ if (!hasITuner()) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res;
+ uint32_t id;
+ sp<IDemux> demuxSp = nullptr;
+ mTuner->openDemux([&](HidlResult r, uint32_t demuxId, const sp<IDemux>& demux) {
+ demuxSp = demux;
+ id = demuxId;
+ res = r;
+ ALOGD("open demux, id = %d", demuxId);
+ });
+ if (res == HidlResult::SUCCESS) {
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlDemux>(demuxSp, id);
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ ALOGW("open demux failed, res = %d", res);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+}
+
+::ndk::ScopedAStatus TunerHidlService::getDemuxCaps(DemuxCapabilities* _aidl_return) {
+ ALOGV("getDemuxCaps");
+ if (!hasITuner()) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res;
+ HidlDemuxCapabilities caps;
+ mTuner->getDemuxCaps([&](HidlResult r, const HidlDemuxCapabilities& demuxCaps) {
+ caps = demuxCaps;
+ res = r;
+ });
+ if (res == HidlResult::SUCCESS) {
+ *_aidl_return = getAidlDemuxCaps(caps);
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ ALOGW("Get demux caps failed, res = %d", res);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+}
+
+::ndk::ScopedAStatus TunerHidlService::getFrontendIds(vector<int32_t>* ids) {
+ if (!hasITuner()) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ hidl_vec<HidlFrontendId> feIds;
+ HidlResult res = getHidlFrontendIds(feIds);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ ids->resize(feIds.size());
+ copy(feIds.begin(), feIds.end(), ids->begin());
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlService::getFrontendInfo(int32_t id, FrontendInfo* _aidl_return) {
+ if (!hasITuner()) {
+ ALOGE("ITuner service is not init.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlFrontendInfo info;
+ HidlResult res = getHidlFrontendInfo(id, info);
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+
+ HidlFrontendDtmbCapabilities dtmbCaps;
+ if (static_cast<HidlFrontendType>(info.type) == HidlFrontendType::DTMB) {
+ if (!hasITuner_1_1()) {
+ ALOGE("ITuner_1_1 service is not init.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ mTuner_1_1->getFrontendDtmbCapabilities(
+ id, [&](HidlResult r, const HidlFrontendDtmbCapabilities& caps) {
+ dtmbCaps = caps;
+ res = r;
+ });
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ }
+
+ *_aidl_return = getAidlFrontendInfo(info, dtmbCaps);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlService::openFrontend(int32_t frontendHandle,
+ shared_ptr<ITunerFrontend>* _aidl_return) {
+ if (!hasITuner()) {
+ ALOGE("ITuner service is not init.");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status;
+ sp<HidlIFrontend> frontend;
+ int id = TunerHelper::getResourceIdFromHandle(frontendHandle, FRONTEND);
+ mTuner->openFrontendById(id, [&](HidlResult result, const sp<HidlIFrontend>& fe) {
+ frontend = fe;
+ status = result;
+ });
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlFrontend>(frontend, id);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
+ if (!hasITuner()) {
+ ALOGD("get ITuner failed");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status;
+ sp<HidlILnb> lnb;
+ int id = TunerHelper::getResourceIdFromHandle(lnbHandle, LNB);
+ mTuner->openLnbById(id, [&](HidlResult result, const sp<HidlILnb>& lnbSp) {
+ lnb = lnbSp;
+ status = result;
+ });
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlLnb>(lnb, id);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlService::openLnbByName(const string& lnbName,
+ shared_ptr<ITunerLnb>* _aidl_return) {
+ if (!hasITuner()) {
+ ALOGE("get ITuner failed");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ int lnbId;
+ HidlResult status;
+ sp<HidlILnb> lnb;
+ mTuner->openLnbByName(lnbName, [&](HidlResult r, HidlLnbId id, const sp<HidlILnb>& lnbSp) {
+ status = r;
+ lnb = lnbSp;
+ lnbId = static_cast<int32_t>(id);
+ });
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlLnb>(lnb, lnbId);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlService::openDescrambler(
+ int32_t /*descramblerHandle*/, shared_ptr<ITunerDescrambler>* _aidl_return) {
+ if (!hasITuner()) {
+ ALOGD("get ITuner failed");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status;
+ sp<HidlIDescrambler> descrambler;
+ //int id = TunerHelper::getResourceIdFromHandle(descramblerHandle, DESCRAMBLER);
+ mTuner->openDescrambler([&](HidlResult r, const sp<HidlIDescrambler>& descramblerSp) {
+ status = r;
+ descrambler = descramblerSp;
+ });
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlDescrambler>(descrambler);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlService::getTunerHalVersion(int* _aidl_return) {
+ hasITuner();
+ *_aidl_return = mTunerVersion;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+void TunerHidlService::updateTunerResources() {
+ if (!hasITuner()) {
+ ALOGE("Failed to updateTunerResources");
+ return;
+ }
+
+ TunerHelper::updateTunerResources(getTRMFrontendInfos(), getTRMLnbHandles());
+}
+
+vector<TunerFrontendInfo> TunerHidlService::getTRMFrontendInfos() {
+ vector<TunerFrontendInfo> infos;
+ hidl_vec<HidlFrontendId> ids;
+ HidlResult res = getHidlFrontendIds(ids);
+ if (res != HidlResult::SUCCESS) {
+ return infos;
+ }
+
+ for (int i = 0; i < ids.size(); i++) {
+ HidlFrontendInfo frontendInfo;
+ HidlResult res = getHidlFrontendInfo(static_cast<int32_t>(ids[i]), frontendInfo);
+ if (res != HidlResult::SUCCESS) {
+ continue;
+ }
+ TunerFrontendInfo tunerFrontendInfo{
+ .handle = TunerHelper::getResourceHandleFromId(static_cast<int32_t>(ids[i]),
+ FRONTEND),
+ .type = static_cast<int32_t>(frontendInfo.type),
+ .exclusiveGroupId = static_cast<int32_t>(frontendInfo.exclusiveGroupId),
+ };
+ infos.push_back(tunerFrontendInfo);
+ }
+
+ return infos;
+}
+
+vector<int32_t> TunerHidlService::getTRMLnbHandles() {
+ vector<int32_t> lnbHandles;
+ if (mTuner != nullptr) {
+ HidlResult res;
+ vector<HidlLnbId> lnbIds;
+ mTuner->getLnbIds([&](HidlResult r, const hidl_vec<HidlLnbId>& ids) {
+ lnbIds = ids;
+ res = r;
+ });
+ if (res == HidlResult::SUCCESS && lnbIds.size() > 0) {
+ for (int i = 0; i < lnbIds.size(); i++) {
+ lnbHandles.push_back(
+ TunerHelper::getResourceHandleFromId(static_cast<int32_t>(lnbIds[i]), LNB));
+ }
+ }
+ }
+
+ return lnbHandles;
+}
+
+HidlResult TunerHidlService::getHidlFrontendIds(hidl_vec<HidlFrontendId>& ids) {
+ if (mTuner == nullptr) {
+ return HidlResult::NOT_INITIALIZED;
+ }
+ HidlResult res;
+ mTuner->getFrontendIds([&](HidlResult r, const hidl_vec<HidlFrontendId>& frontendIds) {
+ ids = frontendIds;
+ res = r;
+ });
+ return res;
+}
+
+HidlResult TunerHidlService::getHidlFrontendInfo(const int id, HidlFrontendInfo& info) {
+ if (mTuner == nullptr) {
+ return HidlResult::NOT_INITIALIZED;
+ }
+ HidlResult res;
+ mTuner->getFrontendInfo(id, [&](HidlResult r, const HidlFrontendInfo& feInfo) {
+ info = feInfo;
+ res = r;
+ });
+ return res;
+}
+
+DemuxCapabilities TunerHidlService::getAidlDemuxCaps(const HidlDemuxCapabilities& caps) {
+ DemuxCapabilities aidlCaps{
+ .numDemux = static_cast<int32_t>(caps.numDemux),
+ .numRecord = static_cast<int32_t>(caps.numRecord),
+ .numPlayback = static_cast<int32_t>(caps.numPlayback),
+ .numTsFilter = static_cast<int32_t>(caps.numTsFilter),
+ .numSectionFilter = static_cast<int32_t>(caps.numSectionFilter),
+ .numAudioFilter = static_cast<int32_t>(caps.numAudioFilter),
+ .numVideoFilter = static_cast<int32_t>(caps.numVideoFilter),
+ .numPesFilter = static_cast<int32_t>(caps.numPesFilter),
+ .numPcrFilter = static_cast<int32_t>(caps.numPcrFilter),
+ .numBytesInSectionFilter = static_cast<int64_t>(caps.numBytesInSectionFilter),
+ .filterCaps = static_cast<int32_t>(caps.filterCaps),
+ .bTimeFilter = caps.bTimeFilter,
+ };
+ aidlCaps.linkCaps.resize(caps.linkCaps.size());
+ copy(caps.linkCaps.begin(), caps.linkCaps.end(), aidlCaps.linkCaps.begin());
+ return aidlCaps;
+}
+
+FrontendInfo TunerHidlService::getAidlFrontendInfo(
+ const HidlFrontendInfo& halInfo, const HidlFrontendDtmbCapabilities& halDtmbCaps) {
+ FrontendInfo info{
+ .type = static_cast<FrontendType>(halInfo.type),
+ .minFrequency = static_cast<int64_t>(halInfo.minFrequency),
+ .maxFrequency = static_cast<int64_t>(halInfo.maxFrequency),
+ .minSymbolRate = static_cast<int32_t>(halInfo.minSymbolRate),
+ .maxSymbolRate = static_cast<int32_t>(halInfo.maxSymbolRate),
+ .acquireRange = static_cast<int64_t>(halInfo.acquireRange),
+ .exclusiveGroupId = static_cast<int32_t>(halInfo.exclusiveGroupId),
+ };
+ for (int i = 0; i < halInfo.statusCaps.size(); i++) {
+ info.statusCaps.push_back(static_cast<FrontendStatusType>(halInfo.statusCaps[i]));
+ }
+
+ FrontendCapabilities caps;
+ switch (halInfo.type) {
+ case ::android::hardware::tv::tuner::V1_0::FrontendType::ANALOG: {
+ if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps ==
+ halInfo.frontendCaps.getDiscriminator()) {
+ FrontendAnalogCapabilities analogCaps{
+ .typeCap = static_cast<int32_t>(halInfo.frontendCaps.analogCaps().typeCap),
+ .sifStandardCap =
+ static_cast<int32_t>(halInfo.frontendCaps.analogCaps().sifStandardCap),
+ };
+ caps.set<FrontendCapabilities::analogCaps>(analogCaps);
+ }
+ break;
+ }
+ case ::android::hardware::tv::tuner::V1_0::FrontendType::ATSC: {
+ if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps ==
+ halInfo.frontendCaps.getDiscriminator()) {
+ FrontendAtscCapabilities atscCaps{
+ .modulationCap =
+ static_cast<int32_t>(halInfo.frontendCaps.atscCaps().modulationCap),
+ };
+ caps.set<FrontendCapabilities::atscCaps>(atscCaps);
+ }
+ break;
+ }
+ case ::android::hardware::tv::tuner::V1_0::FrontendType::ATSC3: {
+ if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps ==
+ halInfo.frontendCaps.getDiscriminator()) {
+ FrontendAtsc3Capabilities atsc3Caps{
+ .bandwidthCap =
+ static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().bandwidthCap),
+ .modulationCap =
+ static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().modulationCap),
+ .timeInterleaveModeCap = static_cast<int32_t>(
+ halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap),
+ .codeRateCap =
+ static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().codeRateCap),
+ .demodOutputFormatCap = static_cast<int8_t>(
+ halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap),
+ .fecCap = static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().fecCap),
+ };
+ caps.set<FrontendCapabilities::atsc3Caps>(atsc3Caps);
+ }
+ break;
+ }
+ case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBC: {
+ if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps ==
+ halInfo.frontendCaps.getDiscriminator()) {
+ FrontendDvbcCapabilities dvbcCaps{
+ .modulationCap =
+ static_cast<int32_t>(halInfo.frontendCaps.dvbcCaps().modulationCap),
+ .fecCap = static_cast<int64_t>(halInfo.frontendCaps.dvbcCaps().fecCap),
+ .annexCap = static_cast<int8_t>(halInfo.frontendCaps.dvbcCaps().annexCap),
+ };
+ caps.set<FrontendCapabilities::dvbcCaps>(dvbcCaps);
+ }
+ break;
+ }
+ case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBS: {
+ if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps ==
+ halInfo.frontendCaps.getDiscriminator()) {
+ FrontendDvbsCapabilities dvbsCaps{
+ .modulationCap =
+ static_cast<int32_t>(halInfo.frontendCaps.dvbsCaps().modulationCap),
+ .innerfecCap =
+ static_cast<int64_t>(halInfo.frontendCaps.dvbsCaps().innerfecCap),
+ .standard = static_cast<int8_t>(halInfo.frontendCaps.dvbsCaps().standard),
+ };
+ caps.set<FrontendCapabilities::dvbsCaps>(dvbsCaps);
+ }
+ break;
+ }
+ case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBT: {
+ if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps ==
+ halInfo.frontendCaps.getDiscriminator()) {
+ FrontendDvbtCapabilities dvbtCaps{
+ .transmissionModeCap = static_cast<int32_t>(
+ halInfo.frontendCaps.dvbtCaps().transmissionModeCap),
+ .bandwidthCap =
+ static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().bandwidthCap),
+ .constellationCap =
+ static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().constellationCap),
+ .coderateCap =
+ static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().coderateCap),
+ .hierarchyCap =
+ static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().hierarchyCap),
+ .guardIntervalCap =
+ static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().guardIntervalCap),
+ .isT2Supported = halInfo.frontendCaps.dvbtCaps().isT2Supported,
+ .isMisoSupported = halInfo.frontendCaps.dvbtCaps().isMisoSupported,
+ };
+ caps.set<FrontendCapabilities::dvbtCaps>(dvbtCaps);
+ }
+ break;
+ }
+ case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBS: {
+ if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps ==
+ halInfo.frontendCaps.getDiscriminator()) {
+ FrontendIsdbsCapabilities isdbsCaps{
+ .modulationCap =
+ static_cast<int32_t>(halInfo.frontendCaps.isdbsCaps().modulationCap),
+ .coderateCap =
+ static_cast<int32_t>(halInfo.frontendCaps.isdbsCaps().coderateCap),
+ };
+ caps.set<FrontendCapabilities::isdbsCaps>(isdbsCaps);
+ }
+ break;
+ }
+ case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBS3: {
+ if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps ==
+ halInfo.frontendCaps.getDiscriminator()) {
+ FrontendIsdbs3Capabilities isdbs3Caps{
+ .modulationCap =
+ static_cast<int32_t>(halInfo.frontendCaps.isdbs3Caps().modulationCap),
+ .coderateCap =
+ static_cast<int32_t>(halInfo.frontendCaps.isdbs3Caps().coderateCap),
+ };
+ caps.set<FrontendCapabilities::isdbs3Caps>(isdbs3Caps);
+ }
+ break;
+ }
+ case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBT: {
+ if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps ==
+ halInfo.frontendCaps.getDiscriminator()) {
+ FrontendIsdbtCapabilities isdbtCaps{
+ .modeCap = static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().modeCap),
+ .bandwidthCap =
+ static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().bandwidthCap),
+ .modulationCap =
+ static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().modulationCap),
+ .coderateCap =
+ static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().coderateCap),
+ .guardIntervalCap =
+ static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().guardIntervalCap),
+ };
+ caps.set<FrontendCapabilities::isdbtCaps>(isdbtCaps);
+ }
+ break;
+ }
+ default: {
+ if (static_cast<HidlFrontendType>(info.type) == HidlFrontendType::DTMB) {
+ FrontendDtmbCapabilities dtmbCaps{
+ .transmissionModeCap = static_cast<int32_t>(halDtmbCaps.transmissionModeCap),
+ .bandwidthCap = static_cast<int32_t>(halDtmbCaps.bandwidthCap),
+ .modulationCap = static_cast<int32_t>(halDtmbCaps.modulationCap),
+ .codeRateCap = static_cast<int32_t>(halDtmbCaps.codeRateCap),
+ .guardIntervalCap = static_cast<int32_t>(halDtmbCaps.guardIntervalCap),
+ .interleaveModeCap = static_cast<int32_t>(halDtmbCaps.interleaveModeCap),
+ };
+ caps.set<FrontendCapabilities::dtmbCaps>(dtmbCaps);
+ }
+ break;
+ }
+ }
+
+ info.frontendCaps = caps;
+ return info;
+}
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
diff --git a/services/tuner/hidl/TunerHidlService.h b/services/tuner/hidl/TunerHidlService.h
new file mode 100644
index 0000000..9f5f371
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlService.h
@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2021, 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_MEDIA_TUNERHIDLSERVICE_H
+#define ANDROID_MEDIA_TUNERHIDLSERVICE_H
+
+#include <aidl/android/hardware/tv/tuner/DemuxFilterEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterStatus.h>
+#include <aidl/android/media/tv/tuner/BnTunerService.h>
+#include <aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.h>
+#include <android/hardware/tv/tuner/1.1/ITuner.h>
+
+#include "TunerHelper.h"
+
+using ::aidl::android::hardware::tv::tuner::DemuxCapabilities;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterStatus;
+using ::aidl::android::hardware::tv::tuner::FrontendInfo;
+using ::aidl::android::media::tv::tuner::ITunerDemux;
+using ::aidl::android::media::tv::tuner::ITunerDescrambler;
+using ::aidl::android::media::tv::tuner::ITunerFrontend;
+using ::aidl::android::media::tv::tuner::ITunerLnb;
+using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::std::shared_ptr;
+using ::std::vector;
+
+using HidlFrontendDtmbCapabilities = ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities;
+using HidlDemuxFilterEvent = ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using HidlDemuxFilterStatus = ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using HidlDemuxCapabilities = ::android::hardware::tv::tuner::V1_0::DemuxCapabilities;
+using HidlFrontendInfo = ::android::hardware::tv::tuner::V1_0::FrontendInfo;
+using HidlITuner = ::android::hardware::tv::tuner::V1_0::ITuner;
+using HidlResult = ::android::hardware::tv::tuner::V1_0::Result;
+using HidlFrontendId = ::android::hardware::tv::tuner::V1_0::FrontendId;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+class TunerHidlService : public BnTunerService {
+public:
+ static char const* getServiceName() { return "media.tuner"; }
+ static binder_status_t instantiate();
+ TunerHidlService();
+ virtual ~TunerHidlService();
+
+ ::ndk::ScopedAStatus getFrontendIds(vector<int32_t>* out_ids) override;
+ ::ndk::ScopedAStatus getFrontendInfo(int32_t in_frontendHandle,
+ FrontendInfo* _aidl_return) override;
+ ::ndk::ScopedAStatus openFrontend(int32_t in_frontendHandle,
+ shared_ptr<ITunerFrontend>* _aidl_return) override;
+ ::ndk::ScopedAStatus openLnb(int32_t in_lnbHandle,
+ shared_ptr<ITunerLnb>* _aidl_return) override;
+ ::ndk::ScopedAStatus openLnbByName(const std::string& in_lnbName,
+ shared_ptr<ITunerLnb>* _aidl_return) override;
+ ::ndk::ScopedAStatus openDemux(int32_t in_demuxHandle,
+ shared_ptr<ITunerDemux>* _aidl_return) override;
+ ::ndk::ScopedAStatus getDemuxCaps(DemuxCapabilities* _aidl_return) override;
+ ::ndk::ScopedAStatus openDescrambler(int32_t in_descramblerHandle,
+ shared_ptr<ITunerDescrambler>* _aidl_return) override;
+ ::ndk::ScopedAStatus getTunerHalVersion(int32_t* _aidl_return) override;
+
+private:
+ bool hasITuner();
+ bool hasITuner_1_1();
+ void updateTunerResources();
+ vector<TunerFrontendInfo> getTRMFrontendInfos();
+ vector<int32_t> getTRMLnbHandles();
+ HidlResult getHidlFrontendIds(hidl_vec<HidlFrontendId>& ids);
+ HidlResult getHidlFrontendInfo(const int id, HidlFrontendInfo& info);
+ DemuxCapabilities getAidlDemuxCaps(const HidlDemuxCapabilities& caps);
+ FrontendInfo getAidlFrontendInfo(const HidlFrontendInfo& halInfo,
+ const HidlFrontendDtmbCapabilities& dtmbCaps);
+
+ sp<HidlITuner> mTuner;
+ sp<::android::hardware::tv::tuner::V1_1::ITuner> mTuner_1_1;
+ int mTunerVersion = TUNER_HAL_VERSION_UNKNOWN;
+};
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
+
+#endif // ANDROID_MEDIA_TUNERHIDLSERVICE_H
diff --git a/services/tuner/hidl/TunerHidlTimeFilter.cpp b/services/tuner/hidl/TunerHidlTimeFilter.cpp
new file mode 100644
index 0000000..d0606d6
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlTimeFilter.cpp
@@ -0,0 +1,133 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#define LOG_TAG "TunerHidlTimeFilter"
+
+#include "TunerHidlTimeFilter.h"
+
+#include <aidl/android/hardware/tv/tuner/Constant64Bit.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
+
+using ::aidl::android::hardware::tv::tuner::Constant64Bit;
+using ::aidl::android::hardware::tv::tuner::Result;
+
+using HidlResult = ::android::hardware::tv::tuner::V1_0::Result;
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+TunerHidlTimeFilter::TunerHidlTimeFilter(sp<HidlITimeFilter> timeFilter) {
+ mTimeFilter = timeFilter;
+}
+
+TunerHidlTimeFilter::~TunerHidlTimeFilter() {
+ mTimeFilter = nullptr;
+}
+
+::ndk::ScopedAStatus TunerHidlTimeFilter::setTimeStamp(int64_t timeStamp) {
+ if (mTimeFilter == nullptr) {
+ ALOGE("ITimeFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mTimeFilter->setTimeStamp(static_cast<uint64_t>(timeStamp));
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlTimeFilter::clearTimeStamp() {
+ if (mTimeFilter == nullptr) {
+ ALOGE("ITimeFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status = mTimeFilter->clearTimeStamp();
+ if (status != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlTimeFilter::getSourceTime(int64_t* _aidl_return) {
+ if (mTimeFilter == nullptr) {
+ *_aidl_return = (int64_t)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ ALOGE("ITimeFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status;
+ mTimeFilter->getSourceTime([&](HidlResult r, uint64_t t) {
+ status = r;
+ *_aidl_return = static_cast<int64_t>(t);
+ });
+ if (status != HidlResult::SUCCESS) {
+ *_aidl_return = static_cast<int64_t>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlTimeFilter::getTimeStamp(int64_t* _aidl_return) {
+ if (mTimeFilter == nullptr) {
+ *_aidl_return = (int64_t)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ ALOGE("ITimeFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult status;
+ mTimeFilter->getTimeStamp([&](HidlResult r, uint64_t t) {
+ status = r;
+ *_aidl_return = static_cast<int64_t>(t);
+ });
+ if (status != HidlResult::SUCCESS) {
+ *_aidl_return = static_cast<int64_t>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlTimeFilter::close() {
+ if (mTimeFilter == nullptr) {
+ ALOGE("ITimeFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ HidlResult res = mTimeFilter->close();
+ mTimeFilter = nullptr;
+
+ if (res != HidlResult::SUCCESS) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
diff --git a/services/tuner/hidl/TunerHidlTimeFilter.h b/services/tuner/hidl/TunerHidlTimeFilter.h
new file mode 100644
index 0000000..97d59dc
--- /dev/null
+++ b/services/tuner/hidl/TunerHidlTimeFilter.h
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2021, 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_MEDIA_TUNERHIDLTIMEFILTER_H
+#define ANDROID_MEDIA_TUNERHIDLTIMEFILTER_H
+
+#include <aidl/android/media/tv/tuner/BnTunerTimeFilter.h>
+#include <android/hardware/tv/tuner/1.0/ITimeFilter.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <utils/Log.h>
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using HidlITimeFilter = ::android::hardware::tv::tuner::V1_0::ITimeFilter;
+
+namespace aidl {
+namespace android {
+namespace media {
+namespace tv {
+namespace tuner {
+
+class TunerHidlTimeFilter : public BnTunerTimeFilter {
+public:
+ TunerHidlTimeFilter(sp<HidlITimeFilter> timeFilter);
+ virtual ~TunerHidlTimeFilter();
+
+ ::ndk::ScopedAStatus setTimeStamp(int64_t in_timeStamp) override;
+ ::ndk::ScopedAStatus clearTimeStamp() override;
+ ::ndk::ScopedAStatus getSourceTime(int64_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getTimeStamp(int64_t* _aidl_return) override;
+ ::ndk::ScopedAStatus close() override;
+
+private:
+ sp<HidlITimeFilter> mTimeFilter;
+};
+
+} // namespace tuner
+} // namespace tv
+} // namespace media
+} // namespace android
+} // namespace aidl
+
+#endif // ANDROID_MEDIA_TUNERHIDLTIMEFILTER_H
diff --git a/services/tuner/main_tunerservice.cpp b/services/tuner/main_tunerservice.cpp
index bda2f71..a014dea 100644
--- a/services/tuner/main_tunerservice.cpp
+++ b/services/tuner/main_tunerservice.cpp
@@ -20,7 +20,9 @@
#include <utils/Log.h>
#include "TunerService.h"
+#include "hidl/TunerHidlService.h"
+using ::aidl::android::media::tv::tuner::TunerHidlService;
using ::aidl::android::media::tv::tuner::TunerService;
using namespace android;
@@ -31,8 +33,12 @@
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
- binder_status_t status = TunerService::instantiate();
- CHECK(status == STATUS_OK);
+ // Check legacy HIDL HAL first. If it's not existed, use AIDL HAL.
+ binder_status_t status = TunerHidlService::instantiate();
+ if (status != STATUS_OK) {
+ status = TunerService::instantiate();
+ CHECK(status == STATUS_OK);
+ }
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();