Add SharedFilter to tuner service.
Bug: 196124225
Test: atest android.media.tv.tuner.cts on both AIDL and HIDL HAL.
Change-Id: I91b1f9ef09b0bda868b7817be4d946d11629b16c
diff --git a/services/tuner/TunerDemux.cpp b/services/tuner/TunerDemux.cpp
index 34efe01..a6f3a2c 100644
--- a/services/tuner/TunerDemux.cpp
+++ b/services/tuner/TunerDemux.cpp
@@ -84,10 +84,12 @@
}
shared_ptr<IFilter> filter;
- shared_ptr<IFilterCallback> cb = ::ndk::SharedRefBase::make<TunerFilter::FilterCallback>(in_cb);
+ shared_ptr<TunerFilter::FilterCallback> filterCb =
+ ::ndk::SharedRefBase::make<TunerFilter::FilterCallback>(in_cb);
+ shared_ptr<IFilterCallback> cb = filterCb;
auto status = mDemux->openFilter(in_type, in_bufferSize, cb, &filter);
if (status.isOk()) {
- *_aidl_return = ::ndk::SharedRefBase::make<TunerFilter>(filter, in_type);
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerFilter>(filter, filterCb, in_type);
}
return status;
diff --git a/services/tuner/TunerDescrambler.cpp b/services/tuner/TunerDescrambler.cpp
index 8e2d6c7..70aee20 100644
--- a/services/tuner/TunerDescrambler.cpp
+++ b/services/tuner/TunerDescrambler.cpp
@@ -20,6 +20,7 @@
#include <aidl/android/hardware/tv/tuner/IFilter.h>
#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <utils/Log.h>
#include "TunerDemux.h"
#include "TunerFilter.h"
diff --git a/services/tuner/TunerDvr.cpp b/services/tuner/TunerDvr.cpp
index fb03b06..8776f7e 100644
--- a/services/tuner/TunerDvr.cpp
+++ b/services/tuner/TunerDvr.cpp
@@ -19,6 +19,7 @@
#include "TunerDvr.h"
#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <utils/Log.h>
#include "TunerFilter.h"
diff --git a/services/tuner/TunerFilter.cpp b/services/tuner/TunerFilter.cpp
index 005445a..bf9c917 100644
--- a/services/tuner/TunerFilter.cpp
+++ b/services/tuner/TunerFilter.cpp
@@ -19,6 +19,10 @@
#include "TunerFilter.h"
#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <binder/IPCThreadState.h>
+
+#include "TunerHelper.h"
+#include "TunerService.h"
using ::aidl::android::hardware::tv::tuner::Result;
@@ -28,32 +32,54 @@
namespace tv {
namespace tuner {
+using ::android::IPCThreadState;
+
using namespace std;
-TunerFilter::TunerFilter(shared_ptr<IFilter> filter, DemuxFilterType type)
- : mFilter(filter), mType(type) {}
+TunerFilter::TunerFilter(shared_ptr<IFilter> filter, shared_ptr<FilterCallback> cb,
+ DemuxFilterType type)
+ : mFilter(filter), mType(type), mStarted(false), mShared(false), mFilterCallback(cb) {}
TunerFilter::~TunerFilter() {
+ Mutex::Autolock _l(mLock);
mFilter = nullptr;
}
::ndk::ScopedAStatus TunerFilter::getQueueDesc(AidlMQDesc* _aidl_return) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ ALOGD("%s is called in wrong process", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+ }
+
return mFilter->getQueueDesc(_aidl_return);
}
::ndk::ScopedAStatus TunerFilter::getId(int32_t* _aidl_return) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
auto status = mFilter->getId(&mId);
if (status.isOk()) {
*_aidl_return = mId;
@@ -62,12 +88,19 @@
}
::ndk::ScopedAStatus TunerFilter::getId64Bit(int64_t* _aidl_return) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
auto status = mFilter->getId64Bit(&mId64Bit);
if (status.isOk()) {
*_aidl_return = mId64Bit;
@@ -76,46 +109,75 @@
}
::ndk::ScopedAStatus TunerFilter::configure(const DemuxFilterSettings& in_settings) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
return mFilter->configure(in_settings);
}
::ndk::ScopedAStatus TunerFilter::configureMonitorEvent(int32_t monitorEventType) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
return mFilter->configureMonitorEvent(monitorEventType);
}
::ndk::ScopedAStatus TunerFilter::configureIpFilterContextId(int32_t cid) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
return mFilter->configureIpCid(cid);
}
::ndk::ScopedAStatus TunerFilter::configureAvStreamType(const AvStreamType& in_avStreamType) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
return mFilter->configureAvStreamType(in_avStreamType);
}
::ndk::ScopedAStatus TunerFilter::setDataSource(const shared_ptr<ITunerFilter>& filter) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
@@ -127,80 +189,231 @@
static_cast<int32_t>(Result::INVALID_ARGUMENT));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
shared_ptr<IFilter> halFilter = static_cast<TunerFilter*>(filter.get())->getHalFilter();
return mFilter->setDataSource(halFilter);
}
::ndk::ScopedAStatus TunerFilter::getAvSharedHandle(NativeHandle* out_avMemory,
int64_t* _aidl_return) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
return mFilter->getAvSharedHandle(out_avMemory, _aidl_return);
}
::ndk::ScopedAStatus TunerFilter::releaseAvHandle(const NativeHandle& in_handle,
int64_t in_avDataId) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
return mFilter->releaseAvHandle(in_handle, in_avDataId);
}
::ndk::ScopedAStatus TunerFilter::start() {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
- return mFilter->start();
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ ALOGD("%s is called in wrong process", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+ }
+
+ auto res = mFilter->start();
+ if (res.isOk()) {
+ mStarted = true;
+ }
+ return res;
}
::ndk::ScopedAStatus TunerFilter::stop() {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ ALOGD("%s is called in wrong process", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+ }
+
+ mStarted = false;
return mFilter->stop();
}
::ndk::ScopedAStatus TunerFilter::flush() {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ ALOGD("%s is called in wrong process", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+ }
+
return mFilter->flush();
}
::ndk::ScopedAStatus TunerFilter::close() {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ if (mFilterCallback != nullptr) {
+ mFilterCallback->sendSharedFilterStatus(STATUS_INACCESSIBLE);
+ mFilterCallback->detachSharedFilterCallback();
+ }
+ TunerService::getTunerService()->removeSharedFilter(this->ref<TunerFilter>());
+ } else {
+ // Calling from shared process, do not really close this filter.
+ if (mFilterCallback != nullptr) {
+ mFilterCallback->detachSharedFilterCallback();
+ }
+ mStarted = false;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ }
+
auto res = mFilter->close();
mFilter = nullptr;
+ mStarted = false;
+ mShared = false;
return res;
}
+::ndk::ScopedAStatus TunerFilter::createSharedFilter(string* _aidl_return) {
+ Mutex::Autolock _l(mLock);
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (mShared || mStarted) {
+ ALOGD("create SharedFilter in wrong state");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
+ IPCThreadState* ipc = IPCThreadState::self();
+ mClientPid = ipc->getCallingPid();
+ string token = TunerService::getTunerService()->addFilterToShared(this->ref<TunerFilter>());
+ _aidl_return->assign(token);
+ mShared = true;
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerFilter::releaseSharedFilter(const string& /* in_filterToken */) {
+ Mutex::Autolock _l(mLock);
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (!mShared) {
+ // The filter is not shared or the shared filter has been closed.
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ if (mFilterCallback != nullptr) {
+ mFilterCallback->sendSharedFilterStatus(STATUS_INACCESSIBLE);
+ mFilterCallback->detachSharedFilterCallback();
+ }
+
+ TunerService::getTunerService()->removeSharedFilter(this->ref<TunerFilter>());
+ mShared = false;
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerFilter::getFilterType(DemuxFilterType* _aidl_return) {
+ Mutex::Autolock _l(mLock);
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ *_aidl_return = mType;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+bool TunerFilter::isSharedFilterAllowed(int callingPid) {
+ return mClientPid != callingPid;
+}
+
+void TunerFilter::attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback>& in_cb) {
+ if (mFilterCallback != nullptr) {
+ mFilterCallback->attachSharedFilterCallback(in_cb);
+ }
+}
+
shared_ptr<IFilter> TunerFilter::getHalFilter() {
return mFilter;
}
/////////////// FilterCallback ///////////////////////
::ndk::ScopedAStatus TunerFilter::FilterCallback::onFilterStatus(DemuxFilterStatus status) {
+ Mutex::Autolock _l(mCallbackLock);
if (mTunerFilterCallback != nullptr) {
mTunerFilterCallback->onFilterStatus(status);
}
@@ -209,12 +422,33 @@
::ndk::ScopedAStatus TunerFilter::FilterCallback::onFilterEvent(
const vector<DemuxFilterEvent>& events) {
+ Mutex::Autolock _l(mCallbackLock);
if (mTunerFilterCallback != nullptr) {
mTunerFilterCallback->onFilterEvent(events);
}
return ::ndk::ScopedAStatus::ok();
}
+void TunerFilter::FilterCallback::sendSharedFilterStatus(int32_t status) {
+ Mutex::Autolock _l(mCallbackLock);
+ if (mTunerFilterCallback != nullptr && mOriginalCallback != nullptr) {
+ mTunerFilterCallback->onFilterStatus(static_cast<DemuxFilterStatus>(status));
+ }
+}
+
+void TunerFilter::FilterCallback::attachSharedFilterCallback(
+ const shared_ptr<ITunerFilterCallback>& in_cb) {
+ Mutex::Autolock _l(mCallbackLock);
+ mOriginalCallback = mTunerFilterCallback;
+ mTunerFilterCallback = in_cb;
+}
+
+void TunerFilter::FilterCallback::detachSharedFilterCallback() {
+ Mutex::Autolock _l(mCallbackLock);
+ mTunerFilterCallback = mOriginalCallback;
+ mOriginalCallback = nullptr;
+}
+
} // namespace tuner
} // namespace tv
} // namespace media
diff --git a/services/tuner/TunerFilter.h b/services/tuner/TunerFilter.h
index 06c5b80..c6b41d3 100644
--- a/services/tuner/TunerFilter.h
+++ b/services/tuner/TunerFilter.h
@@ -26,7 +26,7 @@
#include <aidl/android/hardware/tv/tuner/IFilter.h>
#include <aidl/android/media/tv/tuner/BnTunerFilter.h>
#include <aidl/android/media/tv/tuner/ITunerFilterCallback.h>
-#include <media/stagefright/foundation/ADebug.h>
+#include <utils/Mutex.h>
using ::aidl::android::hardware::common::NativeHandle;
using ::aidl::android::hardware::common::fmq::MQDescriptor;
@@ -39,6 +39,7 @@
using ::aidl::android::hardware::tv::tuner::DemuxFilterType;
using ::aidl::android::hardware::tv::tuner::IFilter;
using ::aidl::android::media::tv::tuner::BnTunerFilter;
+using ::android::Mutex;
using namespace std;
@@ -53,7 +54,25 @@
class TunerFilter : public BnTunerFilter {
public:
- TunerFilter(shared_ptr<IFilter> filter, DemuxFilterType type);
+ class FilterCallback : public BnFilterCallback {
+ public:
+ FilterCallback(const shared_ptr<ITunerFilterCallback>& tunerFilterCallback)
+ : mTunerFilterCallback(tunerFilterCallback), mOriginalCallback(nullptr){};
+
+ ::ndk::ScopedAStatus onFilterEvent(const vector<DemuxFilterEvent>& events) override;
+ ::ndk::ScopedAStatus onFilterStatus(DemuxFilterStatus status) override;
+
+ void sendSharedFilterStatus(int32_t status);
+ void attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback>& in_cb);
+ void detachSharedFilterCallback();
+
+ private:
+ shared_ptr<ITunerFilterCallback> mTunerFilterCallback;
+ shared_ptr<ITunerFilterCallback> mOriginalCallback;
+ Mutex mCallbackLock;
+ };
+
+ TunerFilter(shared_ptr<IFilter> filter, shared_ptr<FilterCallback> cb, DemuxFilterType type);
virtual ~TunerFilter();
::ndk::ScopedAStatus getId(int32_t* _aidl_return) override;
@@ -72,26 +91,24 @@
::ndk::ScopedAStatus stop() override;
::ndk::ScopedAStatus flush() override;
::ndk::ScopedAStatus close() override;
+ ::ndk::ScopedAStatus createSharedFilter(string* _aidl_return) override;
+ ::ndk::ScopedAStatus releaseSharedFilter(const string& in_filterToken) override;
+ ::ndk::ScopedAStatus getFilterType(DemuxFilterType* _aidl_return) override;
+ bool isSharedFilterAllowed(int32_t pid);
+ void attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback>& in_cb);
shared_ptr<IFilter> getHalFilter();
- class FilterCallback : public BnFilterCallback {
- public:
- FilterCallback(const shared_ptr<ITunerFilterCallback> tunerFilterCallback)
- : mTunerFilterCallback(tunerFilterCallback){};
-
- ::ndk::ScopedAStatus onFilterEvent(const vector<DemuxFilterEvent>& events) override;
- ::ndk::ScopedAStatus onFilterStatus(DemuxFilterStatus status) override;
-
- private:
- shared_ptr<ITunerFilterCallback> mTunerFilterCallback;
- };
-
private:
shared_ptr<IFilter> mFilter;
int32_t mId;
int64_t mId64Bit;
DemuxFilterType mType;
+ bool mStarted;
+ bool mShared;
+ int32_t mClientPid;
+ shared_ptr<FilterCallback> mFilterCallback;
+ Mutex mLock;
};
} // namespace tuner
diff --git a/services/tuner/TunerFrontend.h b/services/tuner/TunerFrontend.h
index 4106941..417d969 100644
--- a/services/tuner/TunerFrontend.h
+++ b/services/tuner/TunerFrontend.h
@@ -21,7 +21,6 @@
#include <aidl/android/hardware/tv/tuner/IFrontend.h>
#include <aidl/android/hardware/tv/tuner/IFrontendCallback.h>
#include <aidl/android/media/tv/tuner/BnTunerFrontend.h>
-#include <media/stagefright/foundation/ADebug.h>
#include <utils/Log.h>
using ::aidl::android::hardware::tv::tuner::BnFrontendCallback;
diff --git a/services/tuner/TunerHelper.h b/services/tuner/TunerHelper.h
index 0d8d6a5..c1252b9 100644
--- a/services/tuner/TunerHelper.h
+++ b/services/tuner/TunerHelper.h
@@ -36,6 +36,11 @@
const static int TUNER_HAL_VERSION_1_1 = (1 << 16) | 1;
const static int TUNER_HAL_VERSION_2_0 = 2 << 16;
+// Keep syncing with ShareFilter.java
+const static int STATUS_INACCESSIBLE = 1 << 7;
+
+const static String16 sSharedFilterPermission("android.permission.ACCESS_TV_SHARED_FILTER");
+
typedef enum {
FRONTEND,
LNB,
diff --git a/services/tuner/TunerLnb.h b/services/tuner/TunerLnb.h
index 37efdf8..72988a6 100644
--- a/services/tuner/TunerLnb.h
+++ b/services/tuner/TunerLnb.h
@@ -20,7 +20,6 @@
#include <aidl/android/hardware/tv/tuner/BnLnbCallback.h>
#include <aidl/android/hardware/tv/tuner/ILnb.h>
#include <aidl/android/media/tv/tuner/BnTunerLnb.h>
-#include <media/stagefright/foundation/ADebug.h>
#include <utils/Log.h>
using ::aidl::android::hardware::tv::tuner::BnLnbCallback;
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index fe5d4ca..36e4cd1 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -25,8 +25,12 @@
#include <aidl/android/hardware/tv/tuner/ILnb.h>
#include <aidl/android/hardware/tv/tuner/Result.h>
#include <android/binder_manager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/PermissionCache.h>
#include <utils/Log.h>
+#include <string>
+
#include "TunerDemux.h"
#include "TunerDescrambler.h"
#include "TunerFrontend.h"
@@ -37,6 +41,8 @@
using ::aidl::android::hardware::tv::tuner::IDescrambler;
using ::aidl::android::hardware::tv::tuner::IFrontend;
using ::aidl::android::hardware::tv::tuner::Result;
+using ::android::IPCThreadState;
+using ::android::PermissionCache;
using ::android::sp;
namespace aidl {
@@ -45,6 +51,8 @@
namespace tv {
namespace tuner {
+shared_ptr<TunerService> TunerService::sTunerService = nullptr;
+
TunerService::TunerService() {
if (!TunerHelper::checkTunerFeature()) {
ALOGD("Device doesn't have tuner hardware.");
@@ -57,9 +65,12 @@
TunerService::~TunerService() {}
binder_status_t TunerService::instantiate() {
- shared_ptr<TunerService> service =
- ::ndk::SharedRefBase::make<TunerService>();
- return AServiceManager_addService(service->asBinder().get(), getServiceName());
+ sTunerService = ::ndk::SharedRefBase::make<TunerService>();
+ return AServiceManager_addService(sTunerService->asBinder().get(), getServiceName());
+}
+
+shared_ptr<TunerService> TunerService::getTunerService() {
+ return sTunerService;
}
bool TunerService::hasITuner() {
@@ -210,6 +221,61 @@
return ::ndk::ScopedAStatus::ok();
}
+::ndk::ScopedAStatus TunerService::openSharedFilter(const string& in_filterToken,
+ const shared_ptr<ITunerFilterCallback>& in_cb,
+ shared_ptr<ITunerFilter>* _aidl_return) {
+ if (!hasITuner()) {
+ ALOGE("get ITuner failed");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (!PermissionCache::checkCallingPermission(sSharedFilterPermission)) {
+ ALOGE("Request requires android.permission.ACCESS_TV_SHARED_FILTER");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Mutex::Autolock _l(mSharedFiltersLock);
+ if (mSharedFilters.find(in_filterToken) == mSharedFilters.end()) {
+ *_aidl_return = nullptr;
+ ALOGD("fail to find %s", in_filterToken.c_str());
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
+ shared_ptr<TunerFilter> filter = mSharedFilters.at(in_filterToken);
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ if (!filter->isSharedFilterAllowed(pid)) {
+ *_aidl_return = nullptr;
+ ALOGD("shared filter %s is opened in the same process", in_filterToken.c_str());
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
+ filter->attachSharedFilterCallback(in_cb);
+
+ *_aidl_return = filter;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+string TunerService::addFilterToShared(const shared_ptr<TunerFilter>& sharedFilter) {
+ Mutex::Autolock _l(mSharedFiltersLock);
+
+ // Use sharedFilter address as token.
+ string token = to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get()));
+ mSharedFilters[token] = sharedFilter;
+ return token;
+}
+
+void TunerService::removeSharedFilter(const shared_ptr<TunerFilter>& sharedFilter) {
+ Mutex::Autolock _l(mSharedFiltersLock);
+
+ // Use sharedFilter address as token.
+ mSharedFilters.erase(to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get())));
+}
+
void TunerService::updateTunerResources() {
if (!hasITuner()) {
ALOGE("Failed to updateTunerResources");
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index 159e53e..7bf50b6 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -22,7 +22,11 @@
#include <aidl/android/hardware/tv/tuner/ITuner.h>
#include <aidl/android/media/tv/tuner/BnTunerService.h>
#include <aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.h>
+#include <utils/Mutex.h>
+#include <map>
+
+#include "TunerFilter.h"
#include "TunerHelper.h"
using ::aidl::android::hardware::tv::tuner::DemuxCapabilities;
@@ -32,9 +36,12 @@
using ::aidl::android::hardware::tv::tuner::ITuner;
using ::aidl::android::media::tv::tuner::BnTunerService;
using ::aidl::android::media::tv::tuner::ITunerDemux;
+using ::aidl::android::media::tv::tuner::ITunerFilter;
+using ::aidl::android::media::tv::tuner::ITunerFilterCallback;
using ::aidl::android::media::tv::tuner::ITunerFrontend;
using ::aidl::android::media::tv::tuner::ITunerLnb;
using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
+using ::android::Mutex;
using namespace std;
@@ -66,6 +73,14 @@
::ndk::ScopedAStatus openDescrambler(int32_t in_descramblerHandle,
shared_ptr<ITunerDescrambler>* _aidl_return) override;
::ndk::ScopedAStatus getTunerHalVersion(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus openSharedFilter(const string& in_filterToken,
+ const shared_ptr<ITunerFilterCallback>& in_cb,
+ shared_ptr<ITunerFilter>* _aidl_return) override;
+
+ string addFilterToShared(const shared_ptr<TunerFilter>& sharedFilter);
+ void removeSharedFilter(const shared_ptr<TunerFilter>& sharedFilter);
+
+ static shared_ptr<TunerService> getTunerService();
private:
bool hasITuner();
@@ -75,6 +90,10 @@
shared_ptr<ITuner> mTuner;
int mTunerVersion = TUNER_HAL_VERSION_UNKNOWN;
+ Mutex mSharedFiltersLock;
+ map<string, shared_ptr<TunerFilter>> mSharedFilters;
+
+ static shared_ptr<TunerService> sTunerService;
};
} // namespace tuner
diff --git a/services/tuner/TunerTimeFilter.h b/services/tuner/TunerTimeFilter.h
index c111694..31a47cd 100644
--- a/services/tuner/TunerTimeFilter.h
+++ b/services/tuner/TunerTimeFilter.h
@@ -19,7 +19,6 @@
#include <aidl/android/hardware/tv/tuner/ITimeFilter.h>
#include <aidl/android/media/tv/tuner/BnTunerTimeFilter.h>
-#include <media/stagefright/foundation/ADebug.h>
#include <utils/Log.h>
using ::aidl::android::hardware::tv::tuner::ITimeFilter;
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl
index b043fb4..0450a57 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl
@@ -20,6 +20,7 @@
import android.hardware.common.fmq.SynchronizedReadWrite;
import android.hardware.common.NativeHandle;
import android.hardware.tv.tuner.DemuxFilterSettings;
+import android.hardware.tv.tuner.DemuxFilterType;
import android.hardware.tv.tuner.AvStreamType;
import android.hardware.tv.tuner.DemuxFilterMonitorEventType;
@@ -98,4 +99,26 @@
* Close the filter.
*/
void close();
+
+ /**
+ * Create a new SharedFilter instance.
+ *
+ * @return a token of the newly created SharedFilter instance.
+ */
+ String createSharedFilter();
+
+ /**
+ * Release a SharedFilter instance.
+ *
+ * @param filterToken the SharedFilter will be released.
+ * @return a token of the newly created SharedFilter instance.
+ */
+ void releaseSharedFilter(in String filterToken);
+
+ /**
+ * Get filter type.
+ *
+ * @return filter type.
+ */
+ DemuxFilterType getFilterType();
}
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
index c5733a5..e6a1a5c 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
@@ -20,6 +20,8 @@
import android.hardware.tv.tuner.FrontendInfo;
import android.media.tv.tuner.ITunerDemux;
import android.media.tv.tuner.ITunerDescrambler;
+import android.media.tv.tuner.ITunerFilter;
+import android.media.tv.tuner.ITunerFilterCallback;
import android.media.tv.tuner.ITunerFrontend;
import android.media.tv.tuner.ITunerLnb;
@@ -93,4 +95,13 @@
* value is unknown version 0.
*/
int getTunerHalVersion();
+
+ /**
+ * Open a new SharedFilter instance of ITunerFilter.
+ *
+ * @param filterToken the SharedFilter token created by ITunerFilter.
+ * @param cb the ITunerFilterCallback used to receive callback events
+ * @return a newly created ITunerFilter interface.
+ */
+ ITunerFilter openSharedFilter(in String filterToken, in ITunerFilterCallback cb);
}
diff --git a/services/tuner/hidl/TunerHidlDemux.cpp b/services/tuner/hidl/TunerHidlDemux.cpp
index 5a921b9..a8151d2 100644
--- a/services/tuner/hidl/TunerHidlDemux.cpp
+++ b/services/tuner/hidl/TunerHidlDemux.cpp
@@ -121,8 +121,8 @@
}
HidlResult status;
sp<HidlIFilter> filterSp;
- sp<::android::hardware::tv::tuner::V1_0::IFilterCallback> cbSp =
- new TunerHidlFilter::FilterCallback(in_cb);
+ sp<TunerHidlFilter::FilterCallback> filterCb = new TunerHidlFilter::FilterCallback(in_cb);
+ sp<::android::hardware::tv::tuner::V1_0::IFilterCallback> cbSp = filterCb;
mDemux->openFilter(filterType, static_cast<uint32_t>(in_bufferSize), cbSp,
[&](HidlResult r, const sp<HidlIFilter>& filter) {
filterSp = filter;
@@ -132,7 +132,7 @@
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
}
- *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlFilter>(filterSp, in_type);
+ *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlFilter>(filterSp, filterCb, in_type);
return ::ndk::ScopedAStatus::ok();
}
diff --git a/services/tuner/hidl/TunerHidlFilter.cpp b/services/tuner/hidl/TunerHidlFilter.cpp
index de82855..a3393bb 100644
--- a/services/tuner/hidl/TunerHidlFilter.cpp
+++ b/services/tuner/hidl/TunerHidlFilter.cpp
@@ -21,8 +21,12 @@
#include <aidl/android/hardware/tv/tuner/Constant.h>
#include <aidl/android/hardware/tv/tuner/Result.h>
#include <aidlcommonsupport/NativeHandle.h>
+#include <binder/IPCThreadState.h>
#include <fmq/ConvertMQDescriptors.h>
+#include "TunerHelper.h"
+#include "TunerHidlService.h"
+
using ::aidl::android::hardware::tv::tuner::AudioExtraMetaData;
using ::aidl::android::hardware::tv::tuner::Constant;
using ::aidl::android::hardware::tv::tuner::DemuxAlpFilterSettings;
@@ -59,6 +63,7 @@
using ::aidl::android::hardware::tv::tuner::Result;
using ::aidl::android::hardware::tv::tuner::ScramblingStatus;
using ::android::dupToAidl;
+using ::android::IPCThreadState;
using ::android::makeFromAidl;
using ::android::unsafeHidlToAidlMQDescriptor;
using ::android::hardware::hidl_handle;
@@ -84,23 +89,36 @@
namespace tv {
namespace tuner {
-TunerHidlFilter::TunerHidlFilter(sp<HidlIFilter> filter, DemuxFilterType type)
- : mFilter(filter), mType(type) {
+TunerHidlFilter::TunerHidlFilter(sp<HidlIFilter> filter, sp<FilterCallback> cb,
+ DemuxFilterType type)
+ : mFilter(filter), mType(type), mStarted(false), mShared(false), mFilterCallback(cb) {
mFilter_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(filter);
}
TunerHidlFilter::~TunerHidlFilter() {
+ Mutex::Autolock _l(mLock);
mFilter = nullptr;
mFilter_1_1 = nullptr;
}
::ndk::ScopedAStatus TunerHidlFilter::getQueueDesc(AidlMQDesc* _aidl_return) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ ALOGD("%s is called in wrong process", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+ }
+
MQDesc filterMQDesc;
HidlResult res;
mFilter->getQueueDesc([&](HidlResult r, const MQDesc& desc) {
@@ -119,12 +137,19 @@
}
::ndk::ScopedAStatus TunerHidlFilter::getId(int32_t* _aidl_return) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
HidlResult res;
mFilter->getId([&](HidlResult r, uint32_t filterId) {
res = r;
@@ -139,12 +164,19 @@
}
::ndk::ScopedAStatus TunerHidlFilter::getId64Bit(int64_t* _aidl_return) {
+ Mutex::Autolock _l(mLock);
if (mFilter_1_1 == nullptr) {
ALOGE("IFilter_1_1 is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
HidlResult res;
mFilter_1_1->getId64Bit([&](HidlResult r, uint64_t filterId) {
res = r;
@@ -159,12 +191,19 @@
}
::ndk::ScopedAStatus TunerHidlFilter::configure(const DemuxFilterSettings& in_settings) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
HidlDemuxFilterSettings settings;
switch (in_settings.getTag()) {
case DemuxFilterSettings::ts: {
@@ -198,12 +237,19 @@
}
::ndk::ScopedAStatus TunerHidlFilter::configureMonitorEvent(int32_t monitorEventType) {
+ Mutex::Autolock _l(mLock);
if (mFilter_1_1 == nullptr) {
ALOGE("IFilter_1_1 is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
HidlResult res = mFilter_1_1->configureMonitorEvent(monitorEventType);
if (res != HidlResult::SUCCESS) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
@@ -213,12 +259,19 @@
}
::ndk::ScopedAStatus TunerHidlFilter::configureIpFilterContextId(int32_t cid) {
+ Mutex::Autolock _l(mLock);
if (mFilter_1_1 == nullptr) {
ALOGE("IFilter_1_1 is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
HidlResult res = mFilter_1_1->configureIpCid(cid);
if (res != HidlResult::SUCCESS) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
@@ -228,12 +281,19 @@
}
::ndk::ScopedAStatus TunerHidlFilter::configureAvStreamType(const AvStreamType& in_avStreamType) {
+ Mutex::Autolock _l(mLock);
if (mFilter_1_1 == nullptr) {
ALOGE("IFilter_1_1 is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
HidlAvStreamType type;
if (!getHidlAvStreamType(in_avStreamType, type)) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(
@@ -249,6 +309,7 @@
}
::ndk::ScopedAStatus TunerHidlFilter::setDataSource(const shared_ptr<ITunerFilter>& filter) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
@@ -260,6 +321,12 @@
static_cast<int32_t>(Result::INVALID_ARGUMENT));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
sp<HidlIFilter> hidlFilter = static_cast<TunerHidlFilter*>(filter.get())->getHalFilter();
HidlResult res = mFilter->setDataSource(hidlFilter);
if (res != HidlResult::SUCCESS) {
@@ -271,12 +338,19 @@
::ndk::ScopedAStatus TunerHidlFilter::getAvSharedHandle(NativeHandle* out_avMemory,
int64_t* _aidl_return) {
+ Mutex::Autolock _l(mLock);
if (mFilter_1_1 == nullptr) {
ALOGE("IFilter_1_1 is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
HidlResult res;
mFilter_1_1->getAvSharedHandle([&](HidlResult r, hidl_handle avMemory, uint64_t avMemSize) {
res = r;
@@ -295,12 +369,19 @@
::ndk::ScopedAStatus TunerHidlFilter::releaseAvHandle(const NativeHandle& in_handle,
int64_t in_avDataId) {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ ALOGD("%s is called on a shared filter", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
HidlResult res = mFilter->releaseAvHandle(hidl_handle(makeFromAidl(in_handle)), in_avDataId);
if (res != HidlResult::SUCCESS) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
@@ -315,42 +396,77 @@
}
::ndk::ScopedAStatus TunerHidlFilter::start() {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ ALOGD("%s is called in wrong process", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+ }
+
HidlResult res = mFilter->start();
if (res != HidlResult::SUCCESS) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
}
+ mStarted = true;
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus TunerHidlFilter::stop() {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ ALOGD("%s is called in wrong process", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+ }
+
HidlResult res = mFilter->stop();
if (res != HidlResult::SUCCESS) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
}
+ mStarted = false;
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus TunerHidlFilter::flush() {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ ALOGD("%s is called in wrong process", __FUNCTION__);
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+ }
+
HidlResult res = mFilter->flush();
if (res != HidlResult::SUCCESS) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
@@ -360,15 +476,37 @@
}
::ndk::ScopedAStatus TunerHidlFilter::close() {
+ Mutex::Autolock _l(mLock);
if (mFilter == nullptr) {
ALOGE("IFilter is not initialized");
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::UNAVAILABLE));
}
+ if (mShared) {
+ IPCThreadState* ipc = IPCThreadState::self();
+ int32_t callingPid = ipc->getCallingPid();
+ if (callingPid == mClientPid) {
+ if (mFilterCallback != nullptr) {
+ mFilterCallback->sendSharedFilterStatus(STATUS_INACCESSIBLE);
+ mFilterCallback->detachSharedFilterCallback();
+ }
+ TunerHidlService::getTunerService()->removeSharedFilter(this->ref<TunerHidlFilter>());
+ } else {
+ // Calling from shared process, do not really close this filter.
+ if (mFilterCallback != nullptr) {
+ mFilterCallback->detachSharedFilterCallback();
+ }
+ mStarted = false;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ }
+
HidlResult res = mFilter->close();
mFilter = nullptr;
mFilter_1_1 = nullptr;
+ mStarted = false;
+ mShared = false;
if (res != HidlResult::SUCCESS) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
@@ -377,6 +515,75 @@
return ::ndk::ScopedAStatus::ok();
}
+::ndk::ScopedAStatus TunerHidlFilter::createSharedFilter(string* _aidl_return) {
+ Mutex::Autolock _l(mLock);
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (mShared || mStarted) {
+ ALOGD("create SharedFilter in wrong state");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
+ IPCThreadState* ipc = IPCThreadState::self();
+ mClientPid = ipc->getCallingPid();
+ string token =
+ TunerHidlService::getTunerService()->addFilterToShared(this->ref<TunerHidlFilter>());
+ _aidl_return->assign(token);
+ mShared = true;
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::releaseSharedFilter(const string& /* in_filterToken */) {
+ Mutex::Autolock _l(mLock);
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (!mShared) {
+ // The filter is not shared or the shared filter has been closed.
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ if (mFilterCallback != nullptr) {
+ mFilterCallback->sendSharedFilterStatus(STATUS_INACCESSIBLE);
+ mFilterCallback->detachSharedFilterCallback();
+ }
+
+ TunerHidlService::getTunerService()->removeSharedFilter(this->ref<TunerHidlFilter>());
+ mShared = false;
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TunerHidlFilter::getFilterType(DemuxFilterType* _aidl_return) {
+ if (mFilter == nullptr) {
+ ALOGE("IFilter is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ *_aidl_return = mType;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+bool TunerHidlFilter::isSharedFilterAllowed(int callingPid) {
+ return mClientPid != callingPid;
+}
+
+void TunerHidlFilter::attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback>& in_cb) {
+ if (mFilterCallback != nullptr) {
+ mFilterCallback->attachSharedFilterCallback(in_cb);
+ }
+}
+
sp<HidlIFilter> TunerHidlFilter::getHalFilter() {
return mFilter;
}
@@ -681,7 +888,8 @@
/////////////// FilterCallback ///////////////////////
Return<void> TunerHidlFilter::FilterCallback::onFilterStatus(HidlDemuxFilterStatus status) {
- if (mTunerFilterCallback != NULL) {
+ Mutex::Autolock _l(mCallbackLock);
+ if (mTunerFilterCallback != nullptr) {
mTunerFilterCallback->onFilterStatus(static_cast<DemuxFilterStatus>(status));
}
return Void();
@@ -699,7 +907,8 @@
Return<void> TunerHidlFilter::FilterCallback::onFilterEvent_1_1(
const HidlDemuxFilterEvent& filterEvent, const HidlDemuxFilterEventExt& filterEventExt) {
- if (mTunerFilterCallback != NULL) {
+ Mutex::Autolock _l(mCallbackLock);
+ if (mTunerFilterCallback != nullptr) {
vector<HidlDemuxFilterEvent::Event> events = filterEvent.events;
vector<HidlDemuxFilterEventExt::Event> eventsExt = filterEventExt.events;
vector<DemuxFilterEvent> tunerEvents;
@@ -710,6 +919,26 @@
return Void();
}
+void TunerHidlFilter::FilterCallback::sendSharedFilterStatus(int32_t status) {
+ Mutex::Autolock _l(mCallbackLock);
+ if (mTunerFilterCallback != nullptr && mOriginalCallback != nullptr) {
+ mTunerFilterCallback->onFilterStatus(static_cast<DemuxFilterStatus>(status));
+ }
+}
+
+void TunerHidlFilter::FilterCallback::attachSharedFilterCallback(
+ const shared_ptr<ITunerFilterCallback>& in_cb) {
+ Mutex::Autolock _l(mCallbackLock);
+ mOriginalCallback = mTunerFilterCallback;
+ mTunerFilterCallback = in_cb;
+}
+
+void TunerHidlFilter::FilterCallback::detachSharedFilterCallback() {
+ Mutex::Autolock _l(mCallbackLock);
+ mTunerFilterCallback = mOriginalCallback;
+ mOriginalCallback = nullptr;
+}
+
/////////////// FilterCallback Helper Methods ///////////////////////
void TunerHidlFilter::FilterCallback::getAidlFilterEvent(
const vector<HidlDemuxFilterEvent::Event>& events,
diff --git a/services/tuner/hidl/TunerHidlFilter.h b/services/tuner/hidl/TunerHidlFilter.h
index 0111e00..548b753 100644
--- a/services/tuner/hidl/TunerHidlFilter.h
+++ b/services/tuner/hidl/TunerHidlFilter.h
@@ -34,7 +34,9 @@
#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>
+#include <utils/Mutex.h>
+
+#include <map>
using ::aidl::android::hardware::common::NativeHandle;
using ::aidl::android::hardware::common::fmq::MQDescriptor;
@@ -52,12 +54,14 @@
using ::aidl::android::hardware::tv::tuner::DemuxIpAddressIpAddress;
using ::aidl::android::media::tv::tuner::BnTunerFilter;
using ::aidl::android::media::tv::tuner::ITunerFilterCallback;
+using ::android::Mutex;
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::string;
using ::std::vector;
using HidlAvStreamType = ::android::hardware::tv::tuner::V1_1::AvStreamType;
@@ -111,29 +115,8 @@
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 {
+ class FilterCallback : public HidlIFilterCallback {
+ public:
FilterCallback(const shared_ptr<ITunerFilterCallback> tunerFilterCallback)
: mTunerFilterCallback(tunerFilterCallback){};
@@ -142,6 +125,11 @@
const HidlDemuxFilterEventExt& filterEventExt);
virtual Return<void> onFilterStatus(HidlDemuxFilterStatus status);
+ void sendSharedFilterStatus(int32_t status);
+ void attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback>& in_cb);
+ void detachSharedFilterCallback();
+
+ private:
void getAidlFilterEvent(const vector<HidlDemuxFilterEvent::Event>& events,
const vector<HidlDemuxFilterEventExt::Event>& eventsExt,
vector<DemuxFilterEvent>& aidlEvents);
@@ -169,9 +157,39 @@
void getRestartEvent(const vector<HidlDemuxFilterEventExt::Event>& eventsExt,
vector<DemuxFilterEvent>& res);
+ private:
shared_ptr<ITunerFilterCallback> mTunerFilterCallback;
+ shared_ptr<ITunerFilterCallback> mOriginalCallback;
+ Mutex mCallbackLock;
};
+ TunerHidlFilter(sp<HidlIFilter> filter, sp<FilterCallback> cb, 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;
+ ::ndk::ScopedAStatus createSharedFilter(string* _aidl_return) override;
+ ::ndk::ScopedAStatus releaseSharedFilter(const string& in_filterToken) override;
+ ::ndk::ScopedAStatus getFilterType(DemuxFilterType* _aidl_return) override;
+
+ bool isSharedFilterAllowed(int32_t pid);
+ void attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback>& in_cb);
+ sp<HidlIFilter> getHalFilter();
+
private:
bool isAudioFilter();
bool isVideoFilter();
@@ -204,6 +222,11 @@
int32_t mId;
int64_t mId64Bit;
DemuxFilterType mType;
+ bool mStarted;
+ bool mShared;
+ int32_t mClientPid;
+ sp<FilterCallback> mFilterCallback;
+ Mutex mLock;
};
} // namespace tuner
diff --git a/services/tuner/hidl/TunerHidlFrontend.h b/services/tuner/hidl/TunerHidlFrontend.h
index 0abd80b..6a3a04a 100644
--- a/services/tuner/hidl/TunerHidlFrontend.h
+++ b/services/tuner/hidl/TunerHidlFrontend.h
@@ -22,7 +22,6 @@
#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;
diff --git a/services/tuner/hidl/TunerHidlLnb.h b/services/tuner/hidl/TunerHidlLnb.h
index c496f48..becf848 100644
--- a/services/tuner/hidl/TunerHidlLnb.h
+++ b/services/tuner/hidl/TunerHidlLnb.h
@@ -21,7 +21,6 @@
#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;
diff --git a/services/tuner/hidl/TunerHidlService.cpp b/services/tuner/hidl/TunerHidlService.cpp
index 9d9bc7e..8d4053a 100644
--- a/services/tuner/hidl/TunerHidlService.cpp
+++ b/services/tuner/hidl/TunerHidlService.cpp
@@ -21,6 +21,8 @@
#include <aidl/android/hardware/tv/tuner/Result.h>
#include <android/binder_manager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/PermissionCache.h>
#include <utils/Log.h>
#include "TunerHelper.h"
@@ -43,6 +45,8 @@
using ::aidl::android::hardware::tv::tuner::FrontendType;
using ::aidl::android::hardware::tv::tuner::Result;
using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
+using ::android::IPCThreadState;
+using ::android::PermissionCache;
using ::android::hardware::hidl_vec;
using HidlFrontendId = ::android::hardware::tv::tuner::V1_0::FrontendId;
@@ -57,6 +61,8 @@
namespace tv {
namespace tuner {
+shared_ptr<TunerHidlService> TunerHidlService::sTunerService = nullptr;
+
TunerHidlService::TunerHidlService() {
if (!TunerHelper::checkTunerFeature()) {
ALOGD("Device doesn't have tuner hardware.");
@@ -74,8 +80,12 @@
return STATUS_NAME_NOT_FOUND;
}
- shared_ptr<TunerHidlService> service = ::ndk::SharedRefBase::make<TunerHidlService>();
- return AServiceManager_addService(service->asBinder().get(), getServiceName());
+ sTunerService = ::ndk::SharedRefBase::make<TunerHidlService>();
+ return AServiceManager_addService(sTunerService->asBinder().get(), getServiceName());
+}
+
+shared_ptr<TunerHidlService> TunerHidlService::getTunerService() {
+ return sTunerService;
}
bool TunerHidlService::hasITuner() {
@@ -304,6 +314,62 @@
return ::ndk::ScopedAStatus::ok();
}
+::ndk::ScopedAStatus TunerHidlService::openSharedFilter(
+ const string& in_filterToken, const shared_ptr<ITunerFilterCallback>& in_cb,
+ shared_ptr<ITunerFilter>* _aidl_return) {
+ if (!hasITuner()) {
+ ALOGE("get ITuner failed");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ if (!PermissionCache::checkCallingPermission(sSharedFilterPermission)) {
+ ALOGE("Request requires android.permission.ACCESS_TV_SHARED_FILTER");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ Mutex::Autolock _l(mSharedFiltersLock);
+ if (mSharedFilters.find(in_filterToken) == mSharedFilters.end()) {
+ *_aidl_return = nullptr;
+ ALOGD("fail to find %s", in_filterToken.c_str());
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
+ shared_ptr<TunerHidlFilter> filter = mSharedFilters.at(in_filterToken);
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ if (!filter->isSharedFilterAllowed(pid)) {
+ *_aidl_return = nullptr;
+ ALOGD("shared filter %s is opened in the same process", in_filterToken.c_str());
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_STATE));
+ }
+
+ filter->attachSharedFilterCallback(in_cb);
+
+ *_aidl_return = filter;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+string TunerHidlService::addFilterToShared(const shared_ptr<TunerHidlFilter>& sharedFilter) {
+ Mutex::Autolock _l(mSharedFiltersLock);
+
+ // Use sharedFilter address as token.
+ string token = to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get()));
+ mSharedFilters[token] = sharedFilter;
+
+ return token;
+}
+
+void TunerHidlService::removeSharedFilter(const shared_ptr<TunerHidlFilter>& sharedFilter) {
+ Mutex::Autolock _l(mSharedFiltersLock);
+
+ // Use sharedFilter address as token.
+ mSharedFilters.erase(to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get())));
+}
+
void TunerHidlService::updateTunerResources() {
if (!hasITuner()) {
ALOGE("Failed to updateTunerResources");
diff --git a/services/tuner/hidl/TunerHidlService.h b/services/tuner/hidl/TunerHidlService.h
index 9f5f371..2b8750e 100644
--- a/services/tuner/hidl/TunerHidlService.h
+++ b/services/tuner/hidl/TunerHidlService.h
@@ -22,8 +22,10 @@
#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 <utils/Mutex.h>
#include "TunerHelper.h"
+#include "TunerHidlFilter.h"
using ::aidl::android::hardware::tv::tuner::DemuxCapabilities;
using ::aidl::android::hardware::tv::tuner::DemuxFilterEvent;
@@ -34,11 +36,13 @@
using ::aidl::android::media::tv::tuner::ITunerFrontend;
using ::aidl::android::media::tv::tuner::ITunerLnb;
using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
+using ::android::Mutex;
using ::android::sp;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::std::shared_ptr;
+using ::std::string;
using ::std::vector;
using HidlFrontendDtmbCapabilities = ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities;
@@ -78,6 +82,14 @@
::ndk::ScopedAStatus openDescrambler(int32_t in_descramblerHandle,
shared_ptr<ITunerDescrambler>* _aidl_return) override;
::ndk::ScopedAStatus getTunerHalVersion(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus openSharedFilter(const string& in_filterToken,
+ const shared_ptr<ITunerFilterCallback>& in_cb,
+ shared_ptr<ITunerFilter>* _aidl_return) override;
+
+ string addFilterToShared(const shared_ptr<TunerHidlFilter>& sharedFilter);
+ void removeSharedFilter(const shared_ptr<TunerHidlFilter>& sharedFilter);
+
+ static shared_ptr<TunerHidlService> getTunerService();
private:
bool hasITuner();
@@ -94,6 +106,10 @@
sp<HidlITuner> mTuner;
sp<::android::hardware::tv::tuner::V1_1::ITuner> mTuner_1_1;
int mTunerVersion = TUNER_HAL_VERSION_UNKNOWN;
+ Mutex mSharedFiltersLock;
+ map<string, shared_ptr<TunerHidlFilter>> mSharedFilters;
+
+ static shared_ptr<TunerHidlService> sTunerService;
};
} // namespace tuner
diff --git a/services/tuner/hidl/TunerHidlTimeFilter.h b/services/tuner/hidl/TunerHidlTimeFilter.h
index 97d59dc..78f9c5e 100644
--- a/services/tuner/hidl/TunerHidlTimeFilter.h
+++ b/services/tuner/hidl/TunerHidlTimeFilter.h
@@ -19,7 +19,6 @@
#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;