1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright 2022 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "android.hardware.tv.input-service.example"
18*4d7e907cSAndroid Build Coastguard Worker
19*4d7e907cSAndroid Build Coastguard Worker #include <utils/Log.h>
20*4d7e907cSAndroid Build Coastguard Worker
21*4d7e907cSAndroid Build Coastguard Worker #include "TvInput.h"
22*4d7e907cSAndroid Build Coastguard Worker
23*4d7e907cSAndroid Build Coastguard Worker namespace aidl {
24*4d7e907cSAndroid Build Coastguard Worker namespace android {
25*4d7e907cSAndroid Build Coastguard Worker namespace hardware {
26*4d7e907cSAndroid Build Coastguard Worker namespace tv {
27*4d7e907cSAndroid Build Coastguard Worker namespace input {
28*4d7e907cSAndroid Build Coastguard Worker
TvInput()29*4d7e907cSAndroid Build Coastguard Worker TvInput::TvInput() {}
30*4d7e907cSAndroid Build Coastguard Worker
init()31*4d7e907cSAndroid Build Coastguard Worker void TvInput::init() {
32*4d7e907cSAndroid Build Coastguard Worker // Set up TvInputDeviceInfo and TvStreamConfig
33*4d7e907cSAndroid Build Coastguard Worker mDeviceInfos[0] = shared_ptr<TvInputDeviceInfoWrapper>(
34*4d7e907cSAndroid Build Coastguard Worker new TvInputDeviceInfoWrapper(0, TvInputType::TUNER, true));
35*4d7e907cSAndroid Build Coastguard Worker mDeviceInfos[1] = shared_ptr<TvInputDeviceInfoWrapper>(
36*4d7e907cSAndroid Build Coastguard Worker new TvInputDeviceInfoWrapper(1, TvInputType::HDMI, true));
37*4d7e907cSAndroid Build Coastguard Worker mDeviceInfos[3] = shared_ptr<TvInputDeviceInfoWrapper>(
38*4d7e907cSAndroid Build Coastguard Worker new TvInputDeviceInfoWrapper(3, TvInputType::DISPLAY_PORT, true));
39*4d7e907cSAndroid Build Coastguard Worker
40*4d7e907cSAndroid Build Coastguard Worker mStreamConfigs[0] = {
41*4d7e907cSAndroid Build Coastguard Worker {1, shared_ptr<TvStreamConfigWrapper>(new TvStreamConfigWrapper(1, 720, 1080, false))}};
42*4d7e907cSAndroid Build Coastguard Worker mStreamConfigs[1] = {{11, shared_ptr<TvStreamConfigWrapper>(
43*4d7e907cSAndroid Build Coastguard Worker new TvStreamConfigWrapper(11, 360, 480, false))}};
44*4d7e907cSAndroid Build Coastguard Worker mStreamConfigs[3] = {{5, shared_ptr<TvStreamConfigWrapper>(
45*4d7e907cSAndroid Build Coastguard Worker new TvStreamConfigWrapper(5, 1080, 1920, false))}};
46*4d7e907cSAndroid Build Coastguard Worker
47*4d7e907cSAndroid Build Coastguard Worker mQueue = shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(
48*4d7e907cSAndroid Build Coastguard Worker new (std::nothrow) AidlMessageQueue<int8_t, SynchronizedReadWrite>(8));
49*4d7e907cSAndroid Build Coastguard Worker }
50*4d7e907cSAndroid Build Coastguard Worker
setCallback(const shared_ptr<ITvInputCallback> & in_callback)51*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus TvInput::setCallback(const shared_ptr<ITvInputCallback>& in_callback) {
52*4d7e907cSAndroid Build Coastguard Worker ALOGV("%s", __FUNCTION__);
53*4d7e907cSAndroid Build Coastguard Worker
54*4d7e907cSAndroid Build Coastguard Worker mCallback = in_callback;
55*4d7e907cSAndroid Build Coastguard Worker
56*4d7e907cSAndroid Build Coastguard Worker TvInputEvent event;
57*4d7e907cSAndroid Build Coastguard Worker event.type = TvInputEventType::DEVICE_AVAILABLE;
58*4d7e907cSAndroid Build Coastguard Worker
59*4d7e907cSAndroid Build Coastguard Worker event.deviceInfo = mDeviceInfos[0]->deviceInfo;
60*4d7e907cSAndroid Build Coastguard Worker mCallback->notify(event);
61*4d7e907cSAndroid Build Coastguard Worker
62*4d7e907cSAndroid Build Coastguard Worker event.deviceInfo = mDeviceInfos[1]->deviceInfo;
63*4d7e907cSAndroid Build Coastguard Worker mCallback->notify(event);
64*4d7e907cSAndroid Build Coastguard Worker
65*4d7e907cSAndroid Build Coastguard Worker event.deviceInfo = mDeviceInfos[3]->deviceInfo;
66*4d7e907cSAndroid Build Coastguard Worker mCallback->notify(event);
67*4d7e907cSAndroid Build Coastguard Worker
68*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::ok();
69*4d7e907cSAndroid Build Coastguard Worker }
70*4d7e907cSAndroid Build Coastguard Worker
setTvMessageEnabled(int32_t deviceId,int32_t streamId,TvMessageEventType in_type,bool enabled)71*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus TvInput::setTvMessageEnabled(int32_t deviceId, int32_t streamId,
72*4d7e907cSAndroid Build Coastguard Worker TvMessageEventType in_type, bool enabled) {
73*4d7e907cSAndroid Build Coastguard Worker ALOGV("%s", __FUNCTION__);
74*4d7e907cSAndroid Build Coastguard Worker
75*4d7e907cSAndroid Build Coastguard Worker if (mStreamConfigs.count(deviceId) == 0) {
76*4d7e907cSAndroid Build Coastguard Worker ALOGW("Device with id %d isn't available", deviceId);
77*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
78*4d7e907cSAndroid Build Coastguard Worker }
79*4d7e907cSAndroid Build Coastguard Worker
80*4d7e907cSAndroid Build Coastguard Worker // When calling notifyTvMessage, make sure to verify against this map.
81*4d7e907cSAndroid Build Coastguard Worker mTvMessageEventEnabled[deviceId][streamId][in_type] = enabled;
82*4d7e907cSAndroid Build Coastguard Worker
83*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::ok();
84*4d7e907cSAndroid Build Coastguard Worker }
85*4d7e907cSAndroid Build Coastguard Worker
getTvMessageQueueDesc(MQDescriptor<int8_t,SynchronizedReadWrite> * out_queue,int32_t in_deviceId,int32_t in_streamId)86*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus TvInput::getTvMessageQueueDesc(
87*4d7e907cSAndroid Build Coastguard Worker MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue, int32_t in_deviceId,
88*4d7e907cSAndroid Build Coastguard Worker int32_t in_streamId) {
89*4d7e907cSAndroid Build Coastguard Worker ALOGV("%s", __FUNCTION__);
90*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = ::ndk::ScopedAStatus::ok();
91*4d7e907cSAndroid Build Coastguard Worker if (mStreamConfigs.count(in_deviceId) == 0) {
92*4d7e907cSAndroid Build Coastguard Worker ALOGW("Device with id %d isn't available", in_deviceId);
93*4d7e907cSAndroid Build Coastguard Worker status = ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
94*4d7e907cSAndroid Build Coastguard Worker } else if (!mQueue->isValid()) {
95*4d7e907cSAndroid Build Coastguard Worker ALOGE("Tv Message Queue was not properly initialized");
96*4d7e907cSAndroid Build Coastguard Worker status = ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_STATE);
97*4d7e907cSAndroid Build Coastguard Worker } else {
98*4d7e907cSAndroid Build Coastguard Worker *out_queue = mQueue->dupeDesc();
99*4d7e907cSAndroid Build Coastguard Worker }
100*4d7e907cSAndroid Build Coastguard Worker return status;
101*4d7e907cSAndroid Build Coastguard Worker }
102*4d7e907cSAndroid Build Coastguard Worker
getStreamConfigurations(int32_t in_deviceId,vector<TvStreamConfig> * _aidl_return)103*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus TvInput::getStreamConfigurations(int32_t in_deviceId,
104*4d7e907cSAndroid Build Coastguard Worker vector<TvStreamConfig>* _aidl_return) {
105*4d7e907cSAndroid Build Coastguard Worker ALOGV("%s", __FUNCTION__);
106*4d7e907cSAndroid Build Coastguard Worker
107*4d7e907cSAndroid Build Coastguard Worker if (mStreamConfigs.count(in_deviceId) == 0) {
108*4d7e907cSAndroid Build Coastguard Worker ALOGW("Device with id %d isn't available", in_deviceId);
109*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
110*4d7e907cSAndroid Build Coastguard Worker }
111*4d7e907cSAndroid Build Coastguard Worker
112*4d7e907cSAndroid Build Coastguard Worker for (auto const& iconfig : mStreamConfigs[in_deviceId]) {
113*4d7e907cSAndroid Build Coastguard Worker _aidl_return->push_back(iconfig.second->streamConfig);
114*4d7e907cSAndroid Build Coastguard Worker }
115*4d7e907cSAndroid Build Coastguard Worker
116*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::ok();
117*4d7e907cSAndroid Build Coastguard Worker }
118*4d7e907cSAndroid Build Coastguard Worker
openStream(int32_t in_deviceId,int32_t in_streamId,NativeHandle * _aidl_return)119*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus TvInput::openStream(int32_t in_deviceId, int32_t in_streamId,
120*4d7e907cSAndroid Build Coastguard Worker NativeHandle* _aidl_return) {
121*4d7e907cSAndroid Build Coastguard Worker ALOGV("%s", __FUNCTION__);
122*4d7e907cSAndroid Build Coastguard Worker
123*4d7e907cSAndroid Build Coastguard Worker if (mStreamConfigs.count(in_deviceId) == 0 ||
124*4d7e907cSAndroid Build Coastguard Worker mStreamConfigs[in_deviceId].count(in_streamId) == 0) {
125*4d7e907cSAndroid Build Coastguard Worker ALOGW("Stream with device id %d, stream id %d isn't available", in_deviceId, in_streamId);
126*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
127*4d7e907cSAndroid Build Coastguard Worker }
128*4d7e907cSAndroid Build Coastguard Worker if (mStreamConfigs[in_deviceId][in_streamId]->isOpen) {
129*4d7e907cSAndroid Build Coastguard Worker ALOGW("Stream with device id %d, stream id %d is already opened", in_deviceId, in_streamId);
130*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_STATE);
131*4d7e907cSAndroid Build Coastguard Worker }
132*4d7e907cSAndroid Build Coastguard Worker mStreamConfigs[in_deviceId][in_streamId]->handle = createNativeHandle(in_streamId);
133*4d7e907cSAndroid Build Coastguard Worker *_aidl_return = makeToAidl(mStreamConfigs[in_deviceId][in_streamId]->handle);
134*4d7e907cSAndroid Build Coastguard Worker mStreamConfigs[in_deviceId][in_streamId]->isOpen = true;
135*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::ok();
136*4d7e907cSAndroid Build Coastguard Worker }
137*4d7e907cSAndroid Build Coastguard Worker
closeStream(int32_t in_deviceId,int32_t in_streamId)138*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus TvInput::closeStream(int32_t in_deviceId, int32_t in_streamId) {
139*4d7e907cSAndroid Build Coastguard Worker ALOGV("%s", __FUNCTION__);
140*4d7e907cSAndroid Build Coastguard Worker
141*4d7e907cSAndroid Build Coastguard Worker if (mStreamConfigs.count(in_deviceId) == 0 ||
142*4d7e907cSAndroid Build Coastguard Worker mStreamConfigs[in_deviceId].count(in_streamId) == 0) {
143*4d7e907cSAndroid Build Coastguard Worker ALOGW("Stream with device id %d, stream id %d isn't available", in_deviceId, in_streamId);
144*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
145*4d7e907cSAndroid Build Coastguard Worker }
146*4d7e907cSAndroid Build Coastguard Worker if (!mStreamConfigs[in_deviceId][in_streamId]->isOpen) {
147*4d7e907cSAndroid Build Coastguard Worker ALOGW("Stream with device id %d, stream id %d is already closed", in_deviceId, in_streamId);
148*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_STATE);
149*4d7e907cSAndroid Build Coastguard Worker }
150*4d7e907cSAndroid Build Coastguard Worker native_handle_delete(mStreamConfigs[in_deviceId][in_streamId]->handle);
151*4d7e907cSAndroid Build Coastguard Worker mStreamConfigs[in_deviceId][in_streamId]->handle = nullptr;
152*4d7e907cSAndroid Build Coastguard Worker mStreamConfigs[in_deviceId][in_streamId]->isOpen = false;
153*4d7e907cSAndroid Build Coastguard Worker return ::ndk::ScopedAStatus::ok();
154*4d7e907cSAndroid Build Coastguard Worker }
155*4d7e907cSAndroid Build Coastguard Worker
createNativeHandle(int fd)156*4d7e907cSAndroid Build Coastguard Worker native_handle_t* TvInput::createNativeHandle(int fd) {
157*4d7e907cSAndroid Build Coastguard Worker native_handle_t* handle = native_handle_create(1, 1);
158*4d7e907cSAndroid Build Coastguard Worker if (handle == nullptr) {
159*4d7e907cSAndroid Build Coastguard Worker ALOGE("[TVInput] Failed to create native_handle %d", errno);
160*4d7e907cSAndroid Build Coastguard Worker return nullptr;
161*4d7e907cSAndroid Build Coastguard Worker }
162*4d7e907cSAndroid Build Coastguard Worker handle->data[0] = dup(0);
163*4d7e907cSAndroid Build Coastguard Worker handle->data[1] = fd;
164*4d7e907cSAndroid Build Coastguard Worker return handle;
165*4d7e907cSAndroid Build Coastguard Worker }
166*4d7e907cSAndroid Build Coastguard Worker
167*4d7e907cSAndroid Build Coastguard Worker } // namespace input
168*4d7e907cSAndroid Build Coastguard Worker } // namespace tv
169*4d7e907cSAndroid Build Coastguard Worker } // namespace hardware
170*4d7e907cSAndroid Build Coastguard Worker } // namespace android
171*4d7e907cSAndroid Build Coastguard Worker } // namespace aidl
172