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 = std::shared_ptr<TvInputCallbackWrapper>(new TvInputCallbackWrapper(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 if (!mTvInput->setTvMessageEnabled(deviceId, streamId,
151 static_cast<AidlTvMessageEventType>(type), enabled)
152 .isOk()) {
153 ALOGE("Error in setTvMessageEnabled. device id:%d stream id:%d", deviceId, streamId);
154 return BAD_VALUE;
155 }
156 return NO_ERROR;
157 }
158
getStreamConfigs(int deviceId)159 const std::vector<AidlTvStreamConfig> JTvInputHal::getStreamConfigs(int deviceId) {
160 std::vector<AidlTvStreamConfig> list;
161 ::ndk::ScopedAStatus status = mTvInput->getStreamConfigurations(deviceId, &list);
162 if (!status.isOk()) {
163 ALOGE("Couldn't get stream configs for device id:%d result:%d", deviceId,
164 status.getServiceSpecificError());
165 return std::vector<AidlTvStreamConfig>();
166 }
167 return list;
168 }
169
170 static const std::map<std::pair<AidlAudioDeviceType, std::string>, audio_devices_t>
171 aidlToNativeAudioType = {
172 {{AidlAudioDeviceType::IN_DEVICE, AidlAudioDeviceDescription::CONNECTION_ANALOG},
173 AUDIO_DEVICE_IN_LINE},
174 {{AidlAudioDeviceType::IN_DEVICE, AidlAudioDeviceDescription::CONNECTION_HDMI},
175 AUDIO_DEVICE_IN_HDMI},
176 {{AidlAudioDeviceType::IN_DEVICE, AidlAudioDeviceDescription::CONNECTION_HDMI_ARC},
177 AUDIO_DEVICE_IN_HDMI_ARC},
178 {{AidlAudioDeviceType::IN_DEVICE, AidlAudioDeviceDescription::CONNECTION_HDMI_EARC},
179 AUDIO_DEVICE_IN_HDMI_EARC},
180 {{AidlAudioDeviceType::IN_DEVICE, AidlAudioDeviceDescription::CONNECTION_IP_V4},
181 AUDIO_DEVICE_IN_IP},
182 {{AidlAudioDeviceType::IN_DEVICE, AidlAudioDeviceDescription::CONNECTION_SPDIF},
183 AUDIO_DEVICE_IN_SPDIF},
184 {{AidlAudioDeviceType::IN_LOOPBACK, ""}, AUDIO_DEVICE_IN_LOOPBACK},
185 {{AidlAudioDeviceType::IN_TV_TUNER, ""}, AUDIO_DEVICE_IN_TV_TUNER},
186 };
187
onDeviceAvailable(const TvInputDeviceInfoWrapper & info)188 void JTvInputHal::onDeviceAvailable(const TvInputDeviceInfoWrapper& info) {
189 {
190 Mutex::Autolock autoLock(&mStreamLock);
191 mConnections.add(info.deviceId, KeyedVector<int, Connection>());
192 }
193 JNIEnv* env = AndroidRuntime::getJNIEnv();
194 jobject builder = env->NewObject(gTvInputHardwareInfoBuilderClassInfo.clazz,
195 gTvInputHardwareInfoBuilderClassInfo.constructor);
196 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.deviceId);
197 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.type, info.type);
198 if (info.type == TvInputType::HDMI) {
199 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId,
200 info.portId);
201 }
202 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.cableConnectionStatus,
203 info.cableConnectionStatus);
204 if (info.isHidl) {
205 hidlSetUpAudioInfo(env, builder, info);
206 } else {
207 auto it = aidlToNativeAudioType.find({info.aidlAudioDevice.type.type,
208 info.aidlAudioDevice.type.connection});
209 audio_devices_t nativeAudioType = AUDIO_DEVICE_NONE;
210 if (it != aidlToNativeAudioType.end()) {
211 nativeAudioType = it->second;
212 }
213 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.audioType,
214 nativeAudioType);
215 if (info.aidlAudioDevice.type.type != AidlAudioDeviceType::NONE) {
216 std::stringstream ss;
217 switch (info.aidlAudioDevice.address.getTag()) {
218 case AidlAudioDeviceAddress::id:
219 ss << info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::id>();
220 break;
221 case AidlAudioDeviceAddress::mac: {
222 std::vector<uint8_t> addrList =
223 info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::mac>();
224 for (int i = 0; i < addrList.size(); i++) {
225 if (i != 0) {
226 ss << ':';
227 }
228 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex
229 << static_cast<int32_t>(addrList[i]);
230 }
231 } break;
232 case AidlAudioDeviceAddress::ipv4: {
233 std::vector<uint8_t> addrList =
234 info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::ipv4>();
235 for (int i = 0; i < addrList.size(); i++) {
236 if (i != 0) {
237 ss << '.';
238 }
239 ss << static_cast<int32_t>(addrList[i]);
240 }
241 } break;
242 case AidlAudioDeviceAddress::ipv6: {
243 std::vector<int32_t> addrList =
244 info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::ipv6>();
245 for (int i = 0; i < addrList.size(); i++) {
246 if (i != 0) {
247 ss << ':';
248 }
249 ss << std::uppercase << std::setfill('0') << std::setw(4) << std::hex
250 << addrList[i];
251 }
252 } break;
253 case AidlAudioDeviceAddress::alsa: {
254 std::vector<int32_t> addrList =
255 info.aidlAudioDevice.address.get<AidlAudioDeviceAddress::alsa>();
256 ss << "card=" << addrList[0] << ";device=" << addrList[1];
257 } break;
258 }
259 std::string bufferStr = ss.str();
260 jstring audioAddress = env->NewStringUTF(bufferStr.c_str());
261 env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.audioAddress,
262 audioAddress);
263 env->DeleteLocalRef(audioAddress);
264 }
265 }
266
267 jobject infoObject = env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.build);
268
269 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.deviceAvailable, infoObject);
270
271 env->DeleteLocalRef(builder);
272 env->DeleteLocalRef(infoObject);
273 }
274
onDeviceUnavailable(int deviceId)275 void JTvInputHal::onDeviceUnavailable(int deviceId) {
276 {
277 Mutex::Autolock autoLock(&mStreamLock);
278 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
279 for (size_t i = 0; i < connections.size(); ++i) {
280 removeStream(deviceId, connections.keyAt(i));
281 }
282 connections.clear();
283 mConnections.removeItem(deviceId);
284 }
285 JNIEnv* env = AndroidRuntime::getJNIEnv();
286 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.deviceUnavailable, deviceId);
287 }
288
onStreamConfigurationsChanged(int deviceId,int cableConnectionStatus)289 void JTvInputHal::onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus) {
290 {
291 Mutex::Autolock autoLock(&mStreamLock);
292 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
293 for (size_t i = 0; i < connections.size(); ++i) {
294 removeStream(deviceId, connections.keyAt(i));
295 }
296 connections.clear();
297 }
298 JNIEnv* env = AndroidRuntime::getJNIEnv();
299 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.streamConfigsChanged, deviceId,
300 cableConnectionStatus);
301 }
302
onTvMessage(int deviceId,int streamId,AidlTvMessageEventType type,AidlTvMessage & message,signed char data[],int dataLength)303 void JTvInputHal::onTvMessage(int deviceId, int streamId, AidlTvMessageEventType type,
304 AidlTvMessage& message, signed char data[], int dataLength) {
305 JNIEnv* env = AndroidRuntime::getJNIEnv();
306 ScopedLocalRef<jobject> bundle(env,
307 env->NewObject(gBundleClassInfo.clazz,
308 gBundleClassInfo.constructor));
309 ScopedLocalRef<jbyteArray> convertedData(env, env->NewByteArray(dataLength));
310 env->SetByteArrayRegion(convertedData.get(), 0, dataLength, reinterpret_cast<jbyte*>(data));
311 std::string key = "android.media.tv.TvInputManager.raw_data";
312 ScopedLocalRef<jstring> jkey(env, env->NewStringUTF(key.c_str()));
313 env->CallVoidMethod(bundle.get(), gBundleClassInfo.putByteArray, jkey.get(),
314 convertedData.get());
315 ScopedLocalRef<jstring> subtype(env, env->NewStringUTF(message.subType.c_str()));
316 key = "android.media.tv.TvInputManager.subtype";
317 jkey = ScopedLocalRef<jstring>(env, env->NewStringUTF(key.c_str()));
318 env->CallVoidMethod(bundle.get(), gBundleClassInfo.putString, jkey.get(), subtype.get());
319 key = "android.media.tv.TvInputManager.group_id";
320 jkey = ScopedLocalRef<jstring>(env, env->NewStringUTF(key.c_str()));
321 env->CallVoidMethod(bundle.get(), gBundleClassInfo.putInt, jkey.get(), message.groupId);
322 key = "android.media.tv.TvInputManager.stream_id";
323 jkey = ScopedLocalRef<jstring>(env, env->NewStringUTF(key.c_str()));
324 env->CallVoidMethod(bundle.get(), gBundleClassInfo.putInt, jkey.get(), streamId);
325 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.tvMessageReceived, deviceId,
326 static_cast<jint>(type), bundle.get());
327 }
328
onCaptured(int deviceId,int streamId,uint32_t seq,bool succeeded)329 void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) {
330 sp<BufferProducerThread> thread;
331 {
332 Mutex::Autolock autoLock(&mStreamLock);
333 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
334 Connection& connection = connections.editValueFor(streamId);
335 if (connection.mThread == NULL) {
336 ALOGE("capture thread not existing.");
337 return;
338 }
339 thread = connection.mThread;
340 }
341 thread->onCaptured(seq, succeeded);
342 if (seq == 0) {
343 JNIEnv* env = AndroidRuntime::getJNIEnv();
344 env->CallVoidMethod(mThiz, gTvInputHalClassInfo.firstFrameCaptured, deviceId, streamId);
345 }
346 }
347
348 JTvInputHal::TvInputDeviceInfoWrapper
createDeviceInfoWrapper(const AidlTvInputDeviceInfo & aidlTvInputDeviceInfo)349 JTvInputHal::TvInputDeviceInfoWrapper::createDeviceInfoWrapper(
350 const AidlTvInputDeviceInfo& aidlTvInputDeviceInfo) {
351 TvInputDeviceInfoWrapper deviceInfo;
352 deviceInfo.isHidl = false;
353 deviceInfo.deviceId = aidlTvInputDeviceInfo.deviceId;
354 deviceInfo.type = aidlTvInputDeviceInfo.type;
355 deviceInfo.portId = aidlTvInputDeviceInfo.portId;
356 deviceInfo.cableConnectionStatus = aidlTvInputDeviceInfo.cableConnectionStatus;
357 deviceInfo.aidlAudioDevice = aidlTvInputDeviceInfo.audioDevice;
358 return deviceInfo;
359 }
360
createEventWrapper(const AidlTvInputEvent & aidlTvInputEvent)361 JTvInputHal::TvInputEventWrapper JTvInputHal::TvInputEventWrapper::createEventWrapper(
362 const AidlTvInputEvent& aidlTvInputEvent) {
363 TvInputEventWrapper event;
364 event.type = aidlTvInputEvent.type;
365 event.deviceInfo =
366 TvInputDeviceInfoWrapper::createDeviceInfoWrapper(aidlTvInputEvent.deviceInfo);
367 return event;
368 }
369
createEventWrapper(const AidlTvMessageEvent & aidlTvMessageEvent,bool isLegacyMessage)370 JTvInputHal::TvMessageEventWrapper JTvInputHal::TvMessageEventWrapper::createEventWrapper(
371 const AidlTvMessageEvent& aidlTvMessageEvent, bool isLegacyMessage) {
372 auto messageList = aidlTvMessageEvent.messages;
373 TvMessageEventWrapper event;
374 // Handle backwards compatibility for V1
375 if (isLegacyMessage) {
376 event.deviceId = messageList[0].groupId;
377 event.messages.insert(event.messages.begin(), std::begin(messageList) + 1,
378 std::end(messageList));
379 } else {
380 event.deviceId = aidlTvMessageEvent.deviceId;
381 event.messages.insert(event.messages.begin(), std::begin(messageList),
382 std::end(messageList));
383 }
384 event.streamId = aidlTvMessageEvent.streamId;
385 event.type = aidlTvMessageEvent.type;
386 return event;
387 }
388
NotifyHandler(JTvInputHal * hal,const TvInputEventWrapper & event)389 JTvInputHal::NotifyHandler::NotifyHandler(JTvInputHal* hal, const TvInputEventWrapper& event) {
390 mHal = hal;
391 mEvent = event;
392 }
393
handleMessage(const Message & message)394 void JTvInputHal::NotifyHandler::handleMessage(const Message& message) {
395 switch (mEvent.type) {
396 case TvInputEventType::DEVICE_AVAILABLE: {
397 mHal->onDeviceAvailable(mEvent.deviceInfo);
398 } break;
399 case TvInputEventType::DEVICE_UNAVAILABLE: {
400 mHal->onDeviceUnavailable(mEvent.deviceInfo.deviceId);
401 } break;
402 case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED: {
403 int cableConnectionStatus = static_cast<int>(mEvent.deviceInfo.cableConnectionStatus);
404 mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId, cableConnectionStatus);
405 } break;
406 default:
407 ALOGE("Unrecognizable event");
408 }
409 }
410
NotifyTvMessageHandler(JTvInputHal * hal,const TvMessageEventWrapper & event)411 JTvInputHal::NotifyTvMessageHandler::NotifyTvMessageHandler(JTvInputHal* hal,
412 const TvMessageEventWrapper& event) {
413 mHal = hal;
414 mEvent = event;
415 }
416
handleMessage(const Message & message)417 void JTvInputHal::NotifyTvMessageHandler::handleMessage(const Message& message) {
418 std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> queue =
419 mHal->mQueueMap[mEvent.deviceId][mEvent.streamId];
420 for (AidlTvMessage item : mEvent.messages) {
421 if (queue == NULL || !queue->isValid() || queue->availableToRead() < item.dataLengthBytes) {
422 MQDescriptor<int8_t, SynchronizedReadWrite> queueDesc;
423 if (mHal->mTvInput->getTvMessageQueueDesc(&queueDesc, mEvent.deviceId, mEvent.streamId)
424 .isOk()) {
425 queue = std::make_shared<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(queueDesc,
426 false);
427 }
428 if (queue == NULL || !queue->isValid() ||
429 queue->availableToRead() < item.dataLengthBytes) {
430 ALOGE("Incomplete TvMessageQueue data or missing queue");
431 return;
432 }
433 mHal->mQueueMap[mEvent.deviceId][mEvent.streamId] = queue;
434 }
435 signed char* buffer = new signed char[item.dataLengthBytes];
436 if (queue->read(buffer, item.dataLengthBytes)) {
437 mHal->onTvMessage(mEvent.deviceId, mEvent.streamId, mEvent.type, item, buffer,
438 item.dataLengthBytes);
439 } else {
440 ALOGE("Failed to read from TvMessageQueue");
441 }
442 delete[] buffer;
443 }
444 }
445
TvInputCallbackWrapper(JTvInputHal * hal)446 JTvInputHal::TvInputCallbackWrapper::TvInputCallbackWrapper(JTvInputHal* hal) {
447 aidlTvInputCallback = ::ndk::SharedRefBase::make<AidlTvInputCallback>(hal);
448 hidlTvInputCallback = sp<HidlTvInputCallback>::make(hal);
449 }
450
AidlTvInputCallback(JTvInputHal * hal)451 JTvInputHal::AidlTvInputCallback::AidlTvInputCallback(JTvInputHal* hal) {
452 mHal = hal;
453 }
454
notify(const AidlTvInputEvent & event)455 ::ndk::ScopedAStatus JTvInputHal::AidlTvInputCallback::notify(const AidlTvInputEvent& event) {
456 mHal->mLooper->sendMessage(new NotifyHandler(mHal,
457 TvInputEventWrapper::createEventWrapper(event)),
458 static_cast<int>(event.type));
459 return ::ndk::ScopedAStatus::ok();
460 }
461
notifyTvMessageEvent(const AidlTvMessageEvent & event)462 ::ndk::ScopedAStatus JTvInputHal::AidlTvInputCallback::notifyTvMessageEvent(
463 const AidlTvMessageEvent& event) {
464 const std::string DEVICE_ID_SUBTYPE = "device_id";
465 ::ndk::ScopedAStatus status = ::ndk::ScopedAStatus::ok();
466 int32_t aidlVersion = 0;
467 if (mHal->mTvInput->getAidlInterfaceVersion(&aidlVersion).isOk() && event.messages.size() > 0) {
468 bool validLegacyMessage = aidlVersion == 1 &&
469 event.messages[0].subType == DEVICE_ID_SUBTYPE && event.messages.size() > 1;
470 bool validTvMessage = aidlVersion > 1 && event.messages.size() > 0;
471 if (validLegacyMessage || validTvMessage) {
472 mHal->mLooper->sendMessage(
473 new NotifyTvMessageHandler(mHal,
474 TvMessageEventWrapper::
475 createEventWrapper(event,
476 validLegacyMessage)),
477 static_cast<int>(event.type));
478 } else {
479 status = ::ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
480 ALOGE("The TVMessage event was malformed for HAL version: %d", aidlVersion);
481 }
482 } else {
483 status = ::ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
484 ALOGE("The TVMessage event was empty or the HAL version (version: %d) could not "
485 "be inferred.",
486 aidlVersion);
487 }
488 return status;
489 }
490
ITvInputWrapper(std::shared_ptr<AidlITvInput> & aidlTvInput)491 JTvInputHal::ITvInputWrapper::ITvInputWrapper(std::shared_ptr<AidlITvInput>& aidlTvInput)
492 : mIsHidl(false), mAidlTvInput(aidlTvInput) {}
493
setCallback(const std::shared_ptr<TvInputCallbackWrapper> & in_callback)494 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::setCallback(
495 const std::shared_ptr<TvInputCallbackWrapper>& in_callback) {
496 if (mIsHidl) {
497 if (in_callback == nullptr) {
498 return hidlSetCallback(nullptr);
499 }
500 else {
501 in_callback->aidlTvInputCallback = nullptr;
502 return hidlSetCallback(in_callback->hidlTvInputCallback);
503 }
504 } else {
505 if (in_callback == nullptr) {
506 return mAidlTvInput->setCallback(nullptr);
507 }
508 else {
509 in_callback->hidlTvInputCallback = nullptr;
510 return mAidlTvInput->setCallback(in_callback->aidlTvInputCallback);
511 }
512 }
513 }
514
getStreamConfigurations(int32_t in_deviceId,std::vector<AidlTvStreamConfig> * _aidl_return)515 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::getStreamConfigurations(
516 int32_t in_deviceId, std::vector<AidlTvStreamConfig>* _aidl_return) {
517 if (mIsHidl) {
518 return hidlGetStreamConfigurations(in_deviceId, _aidl_return);
519 } else {
520 return mAidlTvInput->getStreamConfigurations(in_deviceId, _aidl_return);
521 }
522 }
523
openStream(int32_t in_deviceId,int32_t in_streamId,AidlNativeHandle * _aidl_return)524 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::openStream(int32_t in_deviceId,
525 int32_t in_streamId,
526 AidlNativeHandle* _aidl_return) {
527 if (mIsHidl) {
528 return hidlOpenStream(in_deviceId, in_streamId, _aidl_return);
529 } else {
530 return mAidlTvInput->openStream(in_deviceId, in_streamId, _aidl_return);
531 }
532 }
533
closeStream(int32_t in_deviceId,int32_t in_streamId)534 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::closeStream(int32_t in_deviceId,
535 int32_t in_streamId) {
536 if (mIsHidl) {
537 return hidlCloseStream(in_deviceId, in_streamId);
538 } else {
539 return mAidlTvInput->closeStream(in_deviceId, in_streamId);
540 }
541 }
542
setTvMessageEnabled(int32_t deviceId,int32_t streamId,TvMessageEventType in_type,bool enabled)543 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::setTvMessageEnabled(int32_t deviceId,
544 int32_t streamId,
545 TvMessageEventType in_type,
546 bool enabled) {
547 if (mIsHidl) {
548 return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
549 } else {
550 return mAidlTvInput->setTvMessageEnabled(deviceId, streamId, in_type, enabled);
551 }
552 }
553
getTvMessageQueueDesc(MQDescriptor<int8_t,SynchronizedReadWrite> * out_queue,int32_t in_deviceId,int32_t in_streamId)554 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::getTvMessageQueueDesc(
555 MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue, int32_t in_deviceId,
556 int32_t in_streamId) {
557 if (mIsHidl) {
558 return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
559 } else {
560 return mAidlTvInput->getTvMessageQueueDesc(out_queue, in_deviceId, in_streamId);
561 }
562 }
563
getAidlInterfaceVersion(int32_t * _aidl_return)564 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::getAidlInterfaceVersion(int32_t* _aidl_return) {
565 if (mIsHidl) {
566 return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
567 } else {
568 return mAidlTvInput->getInterfaceVersion(_aidl_return);
569 }
570 }
571
572 } // namespace android
573