blob: f6a64c4b40869f6ef1d171a8d9d84b1f7a4d4a4e [file] [log] [blame]
Yixiao Luoaaa52302022-08-11 18:44:50 -07001/*
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#define LOG_TAG "android.hardware.tv.input-service.example"
18
19#include <utils/Log.h>
20
21#include "TvInput.h"
22
23namespace aidl {
24namespace android {
25namespace hardware {
26namespace tv {
27namespace input {
28
29TvInput::TvInput() {}
30
31void TvInput::init() {
32 // Set up TvInputDeviceInfo and TvStreamConfig
33 mDeviceInfos[0] = shared_ptr<TvInputDeviceInfoWrapper>(
34 new TvInputDeviceInfoWrapper(0, TvInputType::TUNER, true));
35 mDeviceInfos[1] = shared_ptr<TvInputDeviceInfoWrapper>(
36 new TvInputDeviceInfoWrapper(1, TvInputType::HDMI, true));
37 mDeviceInfos[3] = shared_ptr<TvInputDeviceInfoWrapper>(
38 new TvInputDeviceInfoWrapper(3, TvInputType::DISPLAY_PORT, true));
39
40 mStreamConfigs[0] = {
41 {1, shared_ptr<TvStreamConfigWrapper>(new TvStreamConfigWrapper(1, 720, 1080, false))}};
42 mStreamConfigs[1] = {{11, shared_ptr<TvStreamConfigWrapper>(
43 new TvStreamConfigWrapper(11, 360, 480, false))}};
44 mStreamConfigs[3] = {{5, shared_ptr<TvStreamConfigWrapper>(
45 new TvStreamConfigWrapper(5, 1080, 1920, false))}};
David Zhao0dc2bc62023-10-17 11:56:52 -070046
47 mQueue = shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(
48 new (std::nothrow) AidlMessageQueue<int8_t, SynchronizedReadWrite>(8));
Yixiao Luoaaa52302022-08-11 18:44:50 -070049}
50
51::ndk::ScopedAStatus TvInput::setCallback(const shared_ptr<ITvInputCallback>& in_callback) {
52 ALOGV("%s", __FUNCTION__);
53
54 mCallback = in_callback;
55
56 TvInputEvent event;
57 event.type = TvInputEventType::DEVICE_AVAILABLE;
58
59 event.deviceInfo = mDeviceInfos[0]->deviceInfo;
60 mCallback->notify(event);
61
62 event.deviceInfo = mDeviceInfos[1]->deviceInfo;
63 mCallback->notify(event);
64
65 event.deviceInfo = mDeviceInfos[3]->deviceInfo;
66 mCallback->notify(event);
67
68 return ::ndk::ScopedAStatus::ok();
69}
70
David Zhao6bdbc5e2023-01-12 16:51:03 -080071::ndk::ScopedAStatus TvInput::setTvMessageEnabled(int32_t deviceId, int32_t streamId,
72 TvMessageEventType in_type, bool enabled) {
73 ALOGV("%s", __FUNCTION__);
David Zhaoeb955ce2023-05-16 17:51:15 -070074
75 if (mStreamConfigs.count(deviceId) == 0) {
76 ALOGW("Device with id %d isn't available", deviceId);
77 return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
78 }
79
David Zhao0dc2bc62023-10-17 11:56:52 -070080 // When calling notifyTvMessage, make sure to verify against this map.
David Zhaoeb955ce2023-05-16 17:51:15 -070081 mTvMessageEventEnabled[deviceId][streamId][in_type] = enabled;
David Zhao0dc2bc62023-10-17 11:56:52 -070082
David Zhao6bdbc5e2023-01-12 16:51:03 -080083 return ::ndk::ScopedAStatus::ok();
84}
85
86::ndk::ScopedAStatus TvInput::getTvMessageQueueDesc(
87 MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue, int32_t in_deviceId,
88 int32_t in_streamId) {
89 ALOGV("%s", __FUNCTION__);
David Zhao0dc2bc62023-10-17 11:56:52 -070090 ::ndk::ScopedAStatus status = ::ndk::ScopedAStatus::ok();
David Zhao17a91902023-05-17 16:36:38 -070091 if (mStreamConfigs.count(in_deviceId) == 0) {
92 ALOGW("Device with id %d isn't available", in_deviceId);
David Zhao0dc2bc62023-10-17 11:56:52 -070093 status = ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
94 } else if (!mQueue->isValid()) {
95 ALOGE("Tv Message Queue was not properly initialized");
96 status = ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_STATE);
97 } else {
98 *out_queue = mQueue->dupeDesc();
David Zhao17a91902023-05-17 16:36:38 -070099 }
David Zhao0dc2bc62023-10-17 11:56:52 -0700100 return status;
David Zhao6bdbc5e2023-01-12 16:51:03 -0800101}
102
Yixiao Luoaaa52302022-08-11 18:44:50 -0700103::ndk::ScopedAStatus TvInput::getStreamConfigurations(int32_t in_deviceId,
104 vector<TvStreamConfig>* _aidl_return) {
105 ALOGV("%s", __FUNCTION__);
106
107 if (mStreamConfigs.count(in_deviceId) == 0) {
108 ALOGW("Device with id %d isn't available", in_deviceId);
109 return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
110 }
111
112 for (auto const& iconfig : mStreamConfigs[in_deviceId]) {
113 _aidl_return->push_back(iconfig.second->streamConfig);
114 }
115
116 return ::ndk::ScopedAStatus::ok();
117}
118
119::ndk::ScopedAStatus TvInput::openStream(int32_t in_deviceId, int32_t in_streamId,
120 NativeHandle* _aidl_return) {
121 ALOGV("%s", __FUNCTION__);
122
123 if (mStreamConfigs.count(in_deviceId) == 0 ||
124 mStreamConfigs[in_deviceId].count(in_streamId) == 0) {
125 ALOGW("Stream with device id %d, stream id %d isn't available", in_deviceId, in_streamId);
126 return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
127 }
128 if (mStreamConfigs[in_deviceId][in_streamId]->isOpen) {
129 ALOGW("Stream with device id %d, stream id %d is already opened", in_deviceId, in_streamId);
130 return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_STATE);
131 }
132 mStreamConfigs[in_deviceId][in_streamId]->handle = createNativeHandle(in_streamId);
Yixiao Luoe1a73052022-10-18 16:40:14 -0700133 *_aidl_return = makeToAidl(mStreamConfigs[in_deviceId][in_streamId]->handle);
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700134 mStreamConfigs[in_deviceId][in_streamId]->isOpen = true;
Yixiao Luoaaa52302022-08-11 18:44:50 -0700135 return ::ndk::ScopedAStatus::ok();
136}
137
138::ndk::ScopedAStatus TvInput::closeStream(int32_t in_deviceId, int32_t in_streamId) {
139 ALOGV("%s", __FUNCTION__);
140
141 if (mStreamConfigs.count(in_deviceId) == 0 ||
142 mStreamConfigs[in_deviceId].count(in_streamId) == 0) {
143 ALOGW("Stream with device id %d, stream id %d isn't available", in_deviceId, in_streamId);
144 return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
145 }
146 if (!mStreamConfigs[in_deviceId][in_streamId]->isOpen) {
147 ALOGW("Stream with device id %d, stream id %d is already closed", in_deviceId, in_streamId);
148 return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_STATE);
149 }
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700150 native_handle_delete(mStreamConfigs[in_deviceId][in_streamId]->handle);
Yixiao Luoaaa52302022-08-11 18:44:50 -0700151 mStreamConfigs[in_deviceId][in_streamId]->handle = nullptr;
152 mStreamConfigs[in_deviceId][in_streamId]->isOpen = false;
153 return ::ndk::ScopedAStatus::ok();
154}
155
156native_handle_t* TvInput::createNativeHandle(int fd) {
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700157 native_handle_t* handle = native_handle_create(1, 1);
158 if (handle == nullptr) {
Yixiao Luoaaa52302022-08-11 18:44:50 -0700159 ALOGE("[TVInput] Failed to create native_handle %d", errno);
160 return nullptr;
161 }
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700162 handle->data[0] = dup(0);
163 handle->data[1] = fd;
164 return handle;
Yixiao Luoaaa52302022-08-11 18:44:50 -0700165}
166
167} // namespace input
168} // namespace tv
169} // namespace hardware
170} // namespace android
171} // namespace aidl