1 /*
2 * Copyright 2022 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 #include "JTvInputHal.h"
18
19 #include <nativehelper/ScopedLocalRef.h>
20
21 namespace android {
22
JTvInputHal(JNIEnv * env,jobject thiz,std::shared_ptr<ITvInputWrapper> tvInput,const sp<Looper> & looper)23 JTvInputHal::JTvInputHal(JNIEnv* env, jobject thiz, std::shared_ptr<ITvInputWrapper> tvInput,
24 const sp<Looper>& looper) {
25 mThiz = env->NewWeakGlobalRef(thiz);
26 mTvInput = tvInput;
27 mLooper = looper;
28 mTvInputCallback = ::ndk::SharedRefBase::make<TvInputCallback>(this);
29 mTvInput->setCallback(mTvInputCallback);
30 }
31
~JTvInputHal()32 JTvInputHal::~JTvInputHal() {
33 mTvInput->setCallback(nullptr);
34 JNIEnv* env = AndroidRuntime::getJNIEnv();
35 env->DeleteWeakGlobalRef(mThiz);
36 mThiz = NULL;
37 }
38
createInstance(JNIEnv * env,jobject thiz,const sp<Looper> & looper)39 JTvInputHal* JTvInputHal::createInstance(JNIEnv* env, jobject thiz, const sp<Looper>& looper) {
40 sp<HidlITvInput> hidlITvInput = HidlITvInput::getService();
41 if (hidlITvInput != nullptr) {
42 ALOGD("tv.input service is HIDL.");
43 return new JTvInputHal(env, thiz,
44 std::shared_ptr<ITvInputWrapper>(new ITvInputWrapper(hidlITvInput)),
45 looper);
46 }
47 std::shared_ptr<AidlITvInput> aidlITvInput = nullptr;
48 if (AServiceManager_isDeclared(TV_INPUT_AIDL_SERVICE_NAME)) {
49 ::ndk::SpAIBinder binder(AServiceManager_waitForService(TV_INPUT_AIDL_SERVICE_NAME));
50 aidlITvInput = AidlITvInput::fromBinder(binder);
51 }
52 if (aidlITvInput == nullptr) {
53 ALOGE("Couldn't get tv.input service.");
54 return nullptr;
55 }
56 return new JTvInputHal(env, thiz,
57 std::shared_ptr<ITvInputWrapper>(new ITvInputWrapper(aidlITvInput)),
58 looper);
59 }
60
addOrUpdateStream(int deviceId,int streamId,const sp<Surface> & surface)61 int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface) {
62 Mutex::Autolock autoLock(&mStreamLock);
63 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
64 if (connections.indexOfKey(streamId) < 0) {
65 connections.add(streamId, Connection());
66 }
67 Connection& connection = connections.editValueFor(streamId);
68 if (connection.mSurface == surface) {
69 // Nothing to do
70 return NO_ERROR;
71 }
72 // Clear the surface in the connection.
73 if (connection.mSurface != NULL) {
74 if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) {
75 if (Surface::isValid(connection.mSurface)) {
76 connection.mSurface->setSidebandStream(NULL);
77 }
78 }
79 connection.mSurface.clear();
80 }
81 if (connection.mSourceHandle == NULL && connection.mThread == NULL) {
82 // Need to configure stream
83 ::ndk::ScopedAStatus status;
84 std::vector<AidlTvStreamConfig> list;
85 status = mTvInput->getStreamConfigurations(deviceId, &list);
86 if (!status.isOk()) {
87 ALOGE("Couldn't get stream configs for device id:%d result:%d", deviceId,
88 status.getServiceSpecificError());
89 return UNKNOWN_ERROR;
90 }
91 int configIndex = -1;
92 for (size_t i = 0; i < list.size(); ++i) {
93 if (list[i].streamId == streamId) {
94 configIndex = i;
95 break;
96 }
97 }
98 if (configIndex == -1) {
99 ALOGE("Cannot find a config with given stream ID: %d", streamId);
100 return BAD_VALUE;
101 }
102 connection.mStreamType = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE;
103
104 AidlNativeHandle sidebandStream;
105 status = mTvInput->openStream(deviceId, streamId, &sidebandStream);
106 if (!status.isOk()) {
107 ALOGE("Couldn't open stream. device id:%d stream id:%d result:%d", deviceId, streamId,
108 status.getServiceSpecificError());
109 return UNKNOWN_ERROR;
110 }
111 connection.mSourceHandle = NativeHandle::create(dupFromAidl(sidebandStream), true);
112 }
113 connection.mSurface = surface;
114 if (connection.mSurface != nullptr) {
115 connection.mSurface->setSidebandStream(connection.mSourceHandle);
116 }
117 return NO_ERROR;
118 }
119
removeStream(int deviceId,int streamId)120 int JTvInputHal::removeStream(int deviceId, int streamId) {
121 Mutex::Autolock autoLock(&mStreamLock);
122 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
123 if (connections.indexOfKey(streamId) < 0) {
124 return BAD_VALUE;
125 }
126 Connection& connection = connections.editValueFor(streamId);
127 if (connection.mSurface == NULL) {
128 // Nothing to do
129 return NO_ERROR;
130 }
131 if (Surface::isValid(connection.mSurface)) {
132 connection.mSurface->setSidebandStream(NULL);
133 }
134 connection.mSurface.clear();
135 if (connection.mThread != NULL) {
136 connection.mThread->shutdown();
137 connection.mThread.clear();
138 }
139 if (!mTvInput->closeStream(deviceId, streamId).isOk()) {
140 ALOGE("Couldn't close stream. device id:%d stream id:%d", deviceId, streamId);
141 return BAD_VALUE;
142 }
143 if (connection.mSourceHandle != NULL) {
144 connection.mSourceHandle.clear();
145 }
146 return NO_ERROR;
147 }
148
setTvMessageEnabled(int deviceId,int streamId,int type,bool enabled)149 int JTvInputHal::setTvMessageEnabled(int deviceId, int streamId, int type, bool enabled) {
150 Mutex::Autolock autoLock(&mLock);
151 if (!mTvInput->setTvMessageEnabled(deviceId, streamId,
152 static_cast<AidlTvMessageEventType>(type), enabled)
153 .isOk()) {
154 ALOGE("Error in setTvMessageEnabled. device id:%d stream id:%d", deviceId, streamId);
155 return BAD_VALUE;
156 }
157 return NO_ERROR;
158 }
159
getStreamConfigs(int deviceId)160 const std::vector<AidlTvStreamConfig> JTvInputHal::getStreamConfigs(int deviceId) {
161 std::vector<AidlTvStreamConfig> list;
162 ::ndk::ScopedAStatus status = mTvInput->getStreamConfigurations(deviceId, &list);
163 if (!status.isOk()) {
164 ALOGE("Couldn't get stream configs for device id:%d result:%d", deviceId,
165 status.getServiceSpecificError());
166 return std::vector<AidlTvStreamConfig>();
167 }
168 return list;
169 }
170
onDeviceAvailable(const TvInputDeviceInfoWrapper & info)171 void JTvInputHal::onDeviceAvailable(const TvInputDeviceInfoWrapper& info) {
172 {
173 Mutex::Autolock autoLock(&mLock);
174 mConnections.add(info.deviceId, KeyedVector<int, Connection>());
175 }
176 JNIEnv* env = AndroidRuntime::getJNIEnv();
177 jobject builder = env->NewObject(gTvInputHardwareInfoBuilderClassInfo.clazz,
178 gTvInputHardwareInfoBuilderClassInfo.constructor);
179 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.deviceId);
180 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.type, info.type);
181 if (info.type == TvInputType::HDMI) {
182 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId,
183 info.portId);
184 }
185 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.cableConnectionStatus,
186 info.cableConnectionStatus);
187 if (info.isHidl) {
188 hidlSetUpAudioInfo(env, builder, info);
189 } else {
190 AidlAudioDeviceType audioType = info.aidlAudioDevice.type.type;
191 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.audioType, audioType);
192 if (audioType != AidlAudioDeviceType::NONE) {
193 std::stringstream ss;
194 switch (info.aidlAudioDevice.address.getTag()) {
195 case AidlAudioDeviceAddress::id:
196 ss << info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::id>();
197 break;
198 case AidlAudioDeviceAddress::mac: {
199 std::vector<uint8_t> addrList =
200 info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::mac>();
201 for (int i = 0; i < addrList.size(); i++) {
202 if (i != 0) {
203 ss << ':';
204 }
205 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex
206 << static_cast<int32_t>(addrList[i]);
207 }
208 } break;
209 case AidlAudioDeviceAddress::ipv4: {
210 std::vector<uint8_t> addrList =
211 info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::ipv4>();
212 for (int i = 0; i < addrList.size(); i++) {
213 if (i != 0) {
214 ss << '.';
215 }
216 ss << static_cast<int32_t>(addrList[i]);
217 }
218 } break;
219 case AidlAudioDeviceAddress::ipv6: {
220 std::vector<int32_t> addrList =
221 info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::ipv6>();
222 for (int i = 0; i < addrList.size(); i++) {
223 if (i != 0) {
224 ss << ':';
225 }
226 ss << std::uppercase << std::setfill('0') << std::setw(4) << std::hex
227 << addrList[i];
228 }
229 } break;
230 case AidlAudioDeviceAddress::alsa: {
231 std::vector<int32_t> addrList =
232 info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::alsa>();
233 ss << "card=" << addrList[0] << ";device=" << addrList[1];
234 } break;
235 }
236 std::string bufferStr = ss.str();
237 jstring audioAddress = env->NewStringUTF(bufferStr.c_str());
238 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.audioAddress,
239 audioAddress);
240 env->DeleteLocalRef(audioAddress);
241 }
242 }
243
244 jobject infoObject = env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.build);
245
246 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.deviceAvailable, infoObject);
247
248 env->DeleteLocalRef(builder);
249 env->DeleteLocalRef(infoObject);
250 }
251
onDeviceUnavailable(int deviceId)252 void JTvInputHal::onDeviceUnavailable(int deviceId) {
253 {
254 Mutex::Autolock autoLock(&mLock);
255 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
256 for (size_t i = 0; i < connections.size(); ++i) {
257 removeStream(deviceId, connections.keyAt(i));
258 }
259 connections.clear();
260 mConnections.removeItem(deviceId);
261 }
262 JNIEnv* env = AndroidRuntime::getJNIEnv();
263 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.deviceUnavailable, deviceId);
264 }
265
onStreamConfigurationsChanged(int deviceId,int cableConnectionStatus)266 void JTvInputHal::onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus) {
267 {
268 Mutex::Autolock autoLock(&mLock);
269 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
270 for (size_t i = 0; i < connections.size(); ++i) {
271 removeStream(deviceId, connections.keyAt(i));
272 }
273 connections.clear();
274 }
275 JNIEnv* env = AndroidRuntime::getJNIEnv();
276 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.streamConfigsChanged, deviceId,
277 cableConnectionStatus);
278 }
279
onTvMessage(int deviceId,int streamId,AidlTvMessageEventType type,AidlTvMessage & message,signed char data[],int dataLength)280 void JTvInputHal::onTvMessage(int deviceId, int streamId, AidlTvMessageEventType type,
281 AidlTvMessage& message, signed char data[], int dataLength) {
282 JNIEnv* env = AndroidRuntime::getJNIEnv();
283 ScopedLocalRef<jobject> bundle(env,
284 env->NewObject(gBundleClassInfo.clazz,
285 gBundleClassInfo.constructor));
286 ScopedLocalRef<jbyteArray> convertedData(env, env->NewByteArray(dataLength));
287 env->SetByteArrayRegion(convertedData.get(), 0, dataLength, reinterpret_cast<jbyte*>(data));
288 std::string key = "android.media.tv.TvInputManager.raw_data";
289 ScopedLocalRef<jstring> jkey(env, env->NewStringUTF(key.c_str()));
290 env->CallVoidMethod(bundle.get(), gBundleClassInfo.putByteArray, jkey.get(),
291 convertedData.get());
292 ScopedLocalRef<jstring> subtype(env, env->NewStringUTF(message.subType.c_str()));
293 key = "android.media.tv.TvInputManager.subtype";
294 jkey = ScopedLocalRef<jstring>(env, env->NewStringUTF(key.c_str()));
295 env->CallVoidMethod(bundle.get(), gBundleClassInfo.putString, jkey.get(), subtype.get());
296 key = "android.media.tv.TvInputManager.group_id";
297 jkey = ScopedLocalRef<jstring>(env, env->NewStringUTF(key.c_str()));
298 env->CallVoidMethod(bundle.get(), gBundleClassInfo.putInt, jkey.get(), message.groupId);
299 key = "android.media.tv.TvInputManager.stream_id";
300 jkey = ScopedLocalRef<jstring>(env, env->NewStringUTF(key.c_str()));
301 env->CallVoidMethod(bundle.get(), gBundleClassInfo.putInt, jkey.get(), streamId);
302 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.tvMessageReceived, deviceId,
303 static_cast<jint>(type), bundle.get());
304 }
305
onCaptured(int deviceId,int streamId,uint32_t seq,bool succeeded)306 void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) {
307 sp<BufferProducerThread> thread;
308 {
309 Mutex::Autolock autoLock(&mLock);
310 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
311 Connection& connection = connections.editValueFor(streamId);
312 if (connection.mThread == NULL) {
313 ALOGE("capture thread not existing.");
314 return;
315 }
316 thread = connection.mThread;
317 }
318 thread->onCaptured(seq, succeeded);
319 if (seq == 0) {
320 JNIEnv* env = AndroidRuntime::getJNIEnv();
321 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.firstFrameCaptured, deviceId, streamId);
322 }
323 }
324
325 JTvInputHal::TvInputDeviceInfoWrapper
createDeviceInfoWrapper(const AidlTvInputDeviceInfo & aidlTvInputDeviceInfo)326 JTvInputHal::TvInputDeviceInfoWrapper::createDeviceInfoWrapper(
327 const AidlTvInputDeviceInfo& aidlTvInputDeviceInfo) {
328 TvInputDeviceInfoWrapper deviceInfo;
329 deviceInfo.isHidl = false;
330 deviceInfo.deviceId = aidlTvInputDeviceInfo.deviceId;
331 deviceInfo.type = aidlTvInputDeviceInfo.type;
332 deviceInfo.portId = aidlTvInputDeviceInfo.portId;
333 deviceInfo.cableConnectionStatus = aidlTvInputDeviceInfo.cableConnectionStatus;
334 deviceInfo.aidlAudioDevice = aidlTvInputDeviceInfo.audioDevice;
335 return deviceInfo;
336 }
337
createEventWrapper(const AidlTvInputEvent & aidlTvInputEvent)338 JTvInputHal::TvInputEventWrapper JTvInputHal::TvInputEventWrapper::createEventWrapper(
339 const AidlTvInputEvent& aidlTvInputEvent) {
340 TvInputEventWrapper event;
341 event.type = aidlTvInputEvent.type;
342 event.deviceInfo =
343 TvInputDeviceInfoWrapper::createDeviceInfoWrapper(aidlTvInputEvent.deviceInfo);
344 return event;
345 }
346
createEventWrapper(const AidlTvMessageEvent & aidlTvMessageEvent)347 JTvInputHal::TvMessageEventWrapper JTvInputHal::TvMessageEventWrapper::createEventWrapper(
348 const AidlTvMessageEvent& aidlTvMessageEvent) {
349 TvMessageEventWrapper event;
350 event.messages.insert(event.messages.begin(), std::begin(aidlTvMessageEvent.messages) + 1,
351 std::end(aidlTvMessageEvent.messages));
352 event.streamId = aidlTvMessageEvent.streamId;
353 event.deviceId = aidlTvMessageEvent.messages[0].groupId;
354 event.type = aidlTvMessageEvent.type;
355 return event;
356 }
357
NotifyHandler(JTvInputHal * hal,const TvInputEventWrapper & event)358 JTvInputHal::NotifyHandler::NotifyHandler(JTvInputHal* hal, const TvInputEventWrapper& event) {
359 mHal = hal;
360 mEvent = event;
361 }
362
handleMessage(const Message & message)363 void JTvInputHal::NotifyHandler::handleMessage(const Message& message) {
364 switch (mEvent.type) {
365 case TvInputEventType::DEVICE_AVAILABLE: {
366 mHal->onDeviceAvailable(mEvent.deviceInfo);
367 } break;
368 case TvInputEventType::DEVICE_UNAVAILABLE: {
369 mHal->onDeviceUnavailable(mEvent.deviceInfo.deviceId);
370 } break;
371 case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED: {
372 int cableConnectionStatus = static_cast<int>(mEvent.deviceInfo.cableConnectionStatus);
373 mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId, cableConnectionStatus);
374 } break;
375 default:
376 ALOGE("Unrecognizable event");
377 }
378 }
379
NotifyTvMessageHandler(JTvInputHal * hal,const TvMessageEventWrapper & event)380 JTvInputHal::NotifyTvMessageHandler::NotifyTvMessageHandler(JTvInputHal* hal,
381 const TvMessageEventWrapper& event) {
382 mHal = hal;
383 mEvent = event;
384 }
385
handleMessage(const Message & message)386 void JTvInputHal::NotifyTvMessageHandler::handleMessage(const Message& message) {
387 std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> queue =
388 mHal->mQueueMap[mEvent.deviceId][mEvent.streamId];
389 for (AidlTvMessage item : mEvent.messages) {
390 if (queue == NULL || !queue->isValid() || queue->availableToRead() < item.dataLengthBytes) {
391 MQDescriptor<int8_t, SynchronizedReadWrite> queueDesc;
392 if (mHal->mTvInput->getTvMessageQueueDesc(&queueDesc, mEvent.deviceId, mEvent.streamId)
393 .isOk()) {
394 queue = std::make_shared<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(queueDesc,
395 false);
396 }
397 if (queue == NULL || !queue->isValid() ||
398 queue->availableToRead() < item.dataLengthBytes) {
399 ALOGE("Incomplete TvMessageQueue data or missing queue");
400 return;
401 }
402 mHal->mQueueMap[mEvent.deviceId][mEvent.streamId] = queue;
403 }
404 signed char* buffer = new signed char[item.dataLengthBytes];
405 if (queue->read(buffer, item.dataLengthBytes)) {
406 mHal->onTvMessage(mEvent.deviceId, mEvent.streamId, mEvent.type, item, buffer,
407 item.dataLengthBytes);
408 } else {
409 ALOGE("Failed to read from TvMessageQueue");
410 }
411 delete[] buffer;
412 }
413 }
414
TvInputCallback(JTvInputHal * hal)415 JTvInputHal::TvInputCallback::TvInputCallback(JTvInputHal* hal) {
416 mHal = hal;
417 }
418
notify(const AidlTvInputEvent & event)419 ::ndk::ScopedAStatus JTvInputHal::TvInputCallback::notify(const AidlTvInputEvent& event) {
420 mHal->mLooper->sendMessage(new NotifyHandler(mHal,
421 TvInputEventWrapper::createEventWrapper(event)),
422 static_cast<int>(event.type));
423 return ::ndk::ScopedAStatus::ok();
424 }
425
notifyTvMessageEvent(const AidlTvMessageEvent & event)426 ::ndk::ScopedAStatus JTvInputHal::TvInputCallback::notifyTvMessageEvent(
427 const AidlTvMessageEvent& event) {
428 const std::string DEVICE_ID_SUBTYPE = "device_id";
429 if (event.messages.size() > 1 && event.messages[0].subType == DEVICE_ID_SUBTYPE) {
430 mHal->mLooper
431 ->sendMessage(new NotifyTvMessageHandler(mHal,
432 TvMessageEventWrapper::createEventWrapper(
433 event)),
434 static_cast<int>(event.type));
435 }
436
437 return ::ndk::ScopedAStatus::ok();
438 }
439
ITvInputWrapper(std::shared_ptr<AidlITvInput> & aidlTvInput)440 JTvInputHal::ITvInputWrapper::ITvInputWrapper(std::shared_ptr<AidlITvInput>& aidlTvInput)
441 : mIsHidl(false), mAidlTvInput(aidlTvInput) {}
442
setCallback(const std::shared_ptr<TvInputCallback> & in_callback)443 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::setCallback(
444 const std::shared_ptr<TvInputCallback>& in_callback) {
445 if (mIsHidl) {
446 return hidlSetCallback(in_callback);
447 } else {
448 return mAidlTvInput->setCallback(in_callback);
449 }
450 }
451
getStreamConfigurations(int32_t in_deviceId,std::vector<AidlTvStreamConfig> * _aidl_return)452 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::getStreamConfigurations(
453 int32_t in_deviceId, std::vector<AidlTvStreamConfig>* _aidl_return) {
454 if (mIsHidl) {
455 return hidlGetStreamConfigurations(in_deviceId, _aidl_return);
456 } else {
457 return mAidlTvInput->getStreamConfigurations(in_deviceId, _aidl_return);
458 }
459 }
460
openStream(int32_t in_deviceId,int32_t in_streamId,AidlNativeHandle * _aidl_return)461 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::openStream(int32_t in_deviceId,
462 int32_t in_streamId,
463 AidlNativeHandle* _aidl_return) {
464 if (mIsHidl) {
465 return hidlOpenStream(in_deviceId, in_streamId, _aidl_return);
466 } else {
467 return mAidlTvInput->openStream(in_deviceId, in_streamId, _aidl_return);
468 }
469 }
470
closeStream(int32_t in_deviceId,int32_t in_streamId)471 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::closeStream(int32_t in_deviceId,
472 int32_t in_streamId) {
473 if (mIsHidl) {
474 return hidlCloseStream(in_deviceId, in_streamId);
475 } else {
476 return mAidlTvInput->closeStream(in_deviceId, in_streamId);
477 }
478 }
479
setTvMessageEnabled(int32_t deviceId,int32_t streamId,TvMessageEventType in_type,bool enabled)480 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::setTvMessageEnabled(int32_t deviceId,
481 int32_t streamId,
482 TvMessageEventType in_type,
483 bool enabled) {
484 if (mIsHidl) {
485 return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
486 } else {
487 return mAidlTvInput->setTvMessageEnabled(deviceId, streamId, in_type, enabled);
488 }
489 }
490
getTvMessageQueueDesc(MQDescriptor<int8_t,SynchronizedReadWrite> * out_queue,int32_t in_deviceId,int32_t in_streamId)491 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::getTvMessageQueueDesc(
492 MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue, int32_t in_deviceId,
493 int32_t in_streamId) {
494 if (mIsHidl) {
495 return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
496 } else {
497 return mAidlTvInput->getTvMessageQueueDesc(out_queue, in_deviceId, in_streamId);
498 }
499 }
500
501 } // namespace android
502