1 /**
2 * Copyright 2021, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "TunerFilter"
18
19 #include "TunerFilter.h"
20
21 #include <aidl/android/hardware/tv/tuner/Result.h>
22 #include <binder/IPCThreadState.h>
23
24 #include "TunerHelper.h"
25 #include "TunerService.h"
26
27 using ::aidl::android::hardware::tv::tuner::Result;
28
29 namespace aidl {
30 namespace android {
31 namespace media {
32 namespace tv {
33 namespace tuner {
34
35 using ::android::IPCThreadState;
36
37 using namespace std;
38
TunerFilter(const shared_ptr<IFilter> filter,const shared_ptr<FilterCallback> cb,const DemuxFilterType type,const shared_ptr<TunerService> tuner)39 TunerFilter::TunerFilter(const shared_ptr<IFilter> filter, const shared_ptr<FilterCallback> cb,
40 const DemuxFilterType type, const shared_ptr<TunerService> tuner)
41 : mFilter(filter),
42 mType(type),
43 mStarted(false),
44 mShared(false),
45 mClientPid(-1),
46 mFilterCallback(cb),
47 mTunerService(tuner) {}
48
~TunerFilter()49 TunerFilter::~TunerFilter() {
50 close();
51 freeSharedFilterToken("");
52 {
53 Mutex::Autolock _l(mLock);
54 mFilter = nullptr;
55 mTunerService = nullptr;
56 }
57 }
58
getQueueDesc(AidlMQDesc * _aidl_return)59 ::ndk::ScopedAStatus TunerFilter::getQueueDesc(AidlMQDesc* _aidl_return) {
60 Mutex::Autolock _l(mLock);
61 if (mShared) {
62 IPCThreadState* ipc = IPCThreadState::self();
63 int32_t callingPid = ipc->getCallingPid();
64 if (callingPid == mClientPid) {
65 ALOGD("%s is called in wrong process", __FUNCTION__);
66 return ::ndk::ScopedAStatus::fromServiceSpecificError(
67 static_cast<int32_t>(Result::INVALID_STATE));
68 }
69 }
70
71 return mFilter->getQueueDesc(_aidl_return);
72 }
73
getId(int32_t * _aidl_return)74 ::ndk::ScopedAStatus TunerFilter::getId(int32_t* _aidl_return) {
75 Mutex::Autolock _l(mLock);
76 if (mShared) {
77 ALOGD("%s is called on a shared filter", __FUNCTION__);
78 return ::ndk::ScopedAStatus::fromServiceSpecificError(
79 static_cast<int32_t>(Result::INVALID_STATE));
80 }
81
82 auto status = mFilter->getId(&mId);
83 if (status.isOk()) {
84 *_aidl_return = mId;
85 }
86 return status;
87 }
88
getId64Bit(int64_t * _aidl_return)89 ::ndk::ScopedAStatus TunerFilter::getId64Bit(int64_t* _aidl_return) {
90 Mutex::Autolock _l(mLock);
91 if (mShared) {
92 ALOGD("%s is called on a shared filter", __FUNCTION__);
93 return ::ndk::ScopedAStatus::fromServiceSpecificError(
94 static_cast<int32_t>(Result::INVALID_STATE));
95 }
96
97 auto status = mFilter->getId64Bit(&mId64Bit);
98 if (status.isOk()) {
99 *_aidl_return = mId64Bit;
100 }
101 return status;
102 }
103
configure(const DemuxFilterSettings & in_settings)104 ::ndk::ScopedAStatus TunerFilter::configure(const DemuxFilterSettings& in_settings) {
105 Mutex::Autolock _l(mLock);
106 if (mShared) {
107 ALOGD("%s is called on a shared filter", __FUNCTION__);
108 return ::ndk::ScopedAStatus::fromServiceSpecificError(
109 static_cast<int32_t>(Result::INVALID_STATE));
110 }
111
112 return mFilter->configure(in_settings);
113 }
114
configureMonitorEvent(int32_t monitorEventType)115 ::ndk::ScopedAStatus TunerFilter::configureMonitorEvent(int32_t monitorEventType) {
116 Mutex::Autolock _l(mLock);
117 if (mShared) {
118 ALOGD("%s is called on a shared filter", __FUNCTION__);
119 return ::ndk::ScopedAStatus::fromServiceSpecificError(
120 static_cast<int32_t>(Result::INVALID_STATE));
121 }
122
123 return mFilter->configureMonitorEvent(monitorEventType);
124 }
125
configureIpFilterContextId(int32_t cid)126 ::ndk::ScopedAStatus TunerFilter::configureIpFilterContextId(int32_t cid) {
127 Mutex::Autolock _l(mLock);
128 if (mShared) {
129 ALOGD("%s is called on a shared filter", __FUNCTION__);
130 return ::ndk::ScopedAStatus::fromServiceSpecificError(
131 static_cast<int32_t>(Result::INVALID_STATE));
132 }
133
134 return mFilter->configureIpCid(cid);
135 }
136
configureAvStreamType(const AvStreamType & in_avStreamType)137 ::ndk::ScopedAStatus TunerFilter::configureAvStreamType(const AvStreamType& in_avStreamType) {
138 Mutex::Autolock _l(mLock);
139 if (mShared) {
140 ALOGD("%s is called on a shared filter", __FUNCTION__);
141 return ::ndk::ScopedAStatus::fromServiceSpecificError(
142 static_cast<int32_t>(Result::INVALID_STATE));
143 }
144
145 return mFilter->configureAvStreamType(in_avStreamType);
146 }
147
setDataSource(const shared_ptr<ITunerFilter> & filter)148 ::ndk::ScopedAStatus TunerFilter::setDataSource(const shared_ptr<ITunerFilter>& filter) {
149 Mutex::Autolock _l(mLock);
150 if (filter == nullptr) {
151 return ::ndk::ScopedAStatus::fromServiceSpecificError(
152 static_cast<int32_t>(Result::INVALID_ARGUMENT));
153 }
154
155 if (mShared) {
156 ALOGD("%s is called on a shared filter", __FUNCTION__);
157 return ::ndk::ScopedAStatus::fromServiceSpecificError(
158 static_cast<int32_t>(Result::INVALID_STATE));
159 }
160
161 shared_ptr<IFilter> halFilter = static_cast<TunerFilter*>(filter.get())->getHalFilter();
162 return mFilter->setDataSource(halFilter);
163 }
164
getAvSharedHandle(NativeHandle * out_avMemory,int64_t * _aidl_return)165 ::ndk::ScopedAStatus TunerFilter::getAvSharedHandle(NativeHandle* out_avMemory,
166 int64_t* _aidl_return) {
167 Mutex::Autolock _l(mLock);
168 if (mShared) {
169 ALOGD("%s is called on a shared filter", __FUNCTION__);
170 return ::ndk::ScopedAStatus::fromServiceSpecificError(
171 static_cast<int32_t>(Result::INVALID_STATE));
172 }
173
174 return mFilter->getAvSharedHandle(out_avMemory, _aidl_return);
175 }
176
releaseAvHandle(const NativeHandle & in_handle,int64_t in_avDataId)177 ::ndk::ScopedAStatus TunerFilter::releaseAvHandle(const NativeHandle& in_handle,
178 int64_t in_avDataId) {
179 Mutex::Autolock _l(mLock);
180 if (mShared) {
181 ALOGD("%s is called on a shared filter", __FUNCTION__);
182 return ::ndk::ScopedAStatus::fromServiceSpecificError(
183 static_cast<int32_t>(Result::INVALID_STATE));
184 }
185
186 return mFilter->releaseAvHandle(in_handle, in_avDataId);
187 }
188
start()189 ::ndk::ScopedAStatus TunerFilter::start() {
190 Mutex::Autolock _l(mLock);
191 if (mShared) {
192 IPCThreadState* ipc = IPCThreadState::self();
193 int32_t callingPid = ipc->getCallingPid();
194 if (callingPid == mClientPid) {
195 ALOGD("%s is called in wrong process", __FUNCTION__);
196 return ::ndk::ScopedAStatus::fromServiceSpecificError(
197 static_cast<int32_t>(Result::INVALID_STATE));
198 }
199 }
200
201 auto res = mFilter->start();
202 if (res.isOk()) {
203 mStarted = true;
204 }
205 return res;
206 }
207
stop()208 ::ndk::ScopedAStatus TunerFilter::stop() {
209 Mutex::Autolock _l(mLock);
210 if (mShared) {
211 IPCThreadState* ipc = IPCThreadState::self();
212 int32_t callingPid = ipc->getCallingPid();
213 if (callingPid == mClientPid) {
214 ALOGD("%s is called in wrong process", __FUNCTION__);
215 return ::ndk::ScopedAStatus::fromServiceSpecificError(
216 static_cast<int32_t>(Result::INVALID_STATE));
217 }
218 }
219
220 auto res = mFilter->stop();
221 mStarted = false;
222
223 return res;
224 }
225
flush()226 ::ndk::ScopedAStatus TunerFilter::flush() {
227 Mutex::Autolock _l(mLock);
228 if (mShared) {
229 IPCThreadState* ipc = IPCThreadState::self();
230 int32_t callingPid = ipc->getCallingPid();
231 if (callingPid == mClientPid) {
232 ALOGD("%s is called in wrong process", __FUNCTION__);
233 return ::ndk::ScopedAStatus::fromServiceSpecificError(
234 static_cast<int32_t>(Result::INVALID_STATE));
235 }
236 }
237
238 return mFilter->flush();
239 }
240
close()241 ::ndk::ScopedAStatus TunerFilter::close() {
242 Mutex::Autolock _l(mLock);
243 if (mShared) {
244 IPCThreadState* ipc = IPCThreadState::self();
245 int32_t callingPid = ipc->getCallingPid();
246 if (callingPid == mClientPid) {
247 if (mFilterCallback != nullptr) {
248 mFilterCallback->sendSharedFilterStatus(STATUS_INACCESSIBLE);
249 mFilterCallback->detachSharedFilterCallback();
250 }
251 mTunerService->removeSharedFilter(this->ref<TunerFilter>());
252 } else {
253 // Calling from shared process, do not really close this filter.
254 if (mFilterCallback != nullptr) {
255 mFilterCallback->detachSharedFilterCallback();
256 }
257 mStarted = false;
258 return ::ndk::ScopedAStatus::ok();
259 }
260 }
261
262 if (mFilterCallback != nullptr) {
263 mFilterCallback->detachCallbacks();
264 }
265 auto res = mFilter->close();
266 mStarted = false;
267 mShared = false;
268 mClientPid = -1;
269
270 return res;
271 }
272
acquireSharedFilterToken(string * _aidl_return)273 ::ndk::ScopedAStatus TunerFilter::acquireSharedFilterToken(string* _aidl_return) {
274 Mutex::Autolock _l(mLock);
275 if (mShared || mStarted) {
276 ALOGD("create SharedFilter in wrong state");
277 return ::ndk::ScopedAStatus::fromServiceSpecificError(
278 static_cast<int32_t>(Result::INVALID_STATE));
279 }
280
281 IPCThreadState* ipc = IPCThreadState::self();
282 mClientPid = ipc->getCallingPid();
283 string token = mTunerService->addFilterToShared(this->ref<TunerFilter>());
284 _aidl_return->assign(token);
285 mShared = true;
286
287 return ::ndk::ScopedAStatus::ok();
288 }
289
freeSharedFilterToken(const string &)290 ::ndk::ScopedAStatus TunerFilter::freeSharedFilterToken(const string& /* in_filterToken */) {
291 Mutex::Autolock _l(mLock);
292 if (!mShared) {
293 // The filter is not shared or the shared filter has been closed.
294 return ::ndk::ScopedAStatus::ok();
295 }
296
297 if (mFilterCallback != nullptr) {
298 mFilterCallback->sendSharedFilterStatus(STATUS_INACCESSIBLE);
299 mFilterCallback->detachSharedFilterCallback();
300 }
301
302 mTunerService->removeSharedFilter(this->ref<TunerFilter>());
303 mShared = false;
304
305 return ::ndk::ScopedAStatus::ok();
306 }
307
getFilterType(DemuxFilterType * _aidl_return)308 ::ndk::ScopedAStatus TunerFilter::getFilterType(DemuxFilterType* _aidl_return) {
309 Mutex::Autolock _l(mLock);
310 *_aidl_return = mType;
311 return ::ndk::ScopedAStatus::ok();
312 }
313
setDelayHint(const FilterDelayHint & in_hint)314 ::ndk::ScopedAStatus TunerFilter::setDelayHint(const FilterDelayHint& in_hint) {
315 Mutex::Autolock _l(mLock);
316 return mFilter->setDelayHint(in_hint);
317 }
318
isSharedFilterAllowed(int callingPid)319 bool TunerFilter::isSharedFilterAllowed(int callingPid) {
320 return mShared && mClientPid != callingPid;
321 }
322
attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback> & in_cb)323 void TunerFilter::attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback>& in_cb) {
324 if (mFilterCallback != nullptr) {
325 mFilterCallback->attachSharedFilterCallback(in_cb);
326 }
327 }
328
getHalFilter()329 shared_ptr<IFilter> TunerFilter::getHalFilter() {
330 return mFilter;
331 }
332
333 /////////////// FilterCallback ///////////////////////
onFilterStatus(DemuxFilterStatus status)334 ::ndk::ScopedAStatus TunerFilter::FilterCallback::onFilterStatus(DemuxFilterStatus status) {
335 Mutex::Autolock _l(mCallbackLock);
336 if (mTunerFilterCallback != nullptr) {
337 mTunerFilterCallback->onFilterStatus(status);
338 }
339 return ::ndk::ScopedAStatus::ok();
340 }
341
onFilterEvent(const vector<DemuxFilterEvent> & events)342 ::ndk::ScopedAStatus TunerFilter::FilterCallback::onFilterEvent(
343 const vector<DemuxFilterEvent>& events) {
344 Mutex::Autolock _l(mCallbackLock);
345 if (mTunerFilterCallback != nullptr) {
346 mTunerFilterCallback->onFilterEvent(events);
347 }
348 return ::ndk::ScopedAStatus::ok();
349 }
350
sendSharedFilterStatus(int32_t status)351 void TunerFilter::FilterCallback::sendSharedFilterStatus(int32_t status) {
352 Mutex::Autolock _l(mCallbackLock);
353 if (mTunerFilterCallback != nullptr && mOriginalCallback != nullptr) {
354 mTunerFilterCallback->onFilterStatus(static_cast<DemuxFilterStatus>(status));
355 }
356 }
357
attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback> & in_cb)358 void TunerFilter::FilterCallback::attachSharedFilterCallback(
359 const shared_ptr<ITunerFilterCallback>& in_cb) {
360 Mutex::Autolock _l(mCallbackLock);
361 mOriginalCallback = mTunerFilterCallback;
362 mTunerFilterCallback = in_cb;
363 }
364
detachSharedFilterCallback()365 void TunerFilter::FilterCallback::detachSharedFilterCallback() {
366 Mutex::Autolock _l(mCallbackLock);
367 if (mTunerFilterCallback != nullptr && mOriginalCallback != nullptr) {
368 mTunerFilterCallback = mOriginalCallback;
369 mOriginalCallback = nullptr;
370 }
371 }
372
detachCallbacks()373 void TunerFilter::FilterCallback::detachCallbacks() {
374 Mutex::Autolock _l(mCallbackLock);
375 mOriginalCallback = nullptr;
376 mTunerFilterCallback = nullptr;
377 }
378
379 } // namespace tuner
380 } // namespace tv
381 } // namespace media
382 } // namespace android
383 } // namespace aidl
384