diff --git a/tv/input/aidl/default/Android.bp b/tv/input/aidl/default/Android.bp new file mode 100644 index 0000000000..66148c8aaa --- /dev/null +++ b/tv/input/aidl/default/Android.bp @@ -0,0 +1,31 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_binary { + name: "android.hardware.tv.input-service.example", + relative_install_path: "hw", + init_rc: ["input-default.rc"], + vintf_fragments: ["input-default.xml"], + vendor: true, + srcs: [ + "TvInput.cpp", + "service.cpp", + ], + static_libs: [ + "libaidlcommonsupport", + ], + shared_libs: [ + "libbase", + "liblog", + "libutils", + "libcutils", + "libbinder_ndk", + "android.hardware.tv.input-V1-ndk", + ], +} diff --git a/tv/input/aidl/default/TvInput.cpp b/tv/input/aidl/default/TvInput.cpp new file mode 100644 index 0000000000..6c3a138155 --- /dev/null +++ b/tv/input/aidl/default/TvInput.cpp @@ -0,0 +1,143 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.input-service.example" + +#include + +#include "TvInput.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace tv { +namespace input { + +TvInput::TvInput() {} + +void TvInput::init() { + // Set up TvInputDeviceInfo and TvStreamConfig + mDeviceInfos[0] = shared_ptr( + new TvInputDeviceInfoWrapper(0, TvInputType::TUNER, true)); + mDeviceInfos[1] = shared_ptr( + new TvInputDeviceInfoWrapper(1, TvInputType::HDMI, true)); + mDeviceInfos[3] = shared_ptr( + new TvInputDeviceInfoWrapper(3, TvInputType::DISPLAY_PORT, true)); + + mStreamConfigs[0] = { + {1, shared_ptr(new TvStreamConfigWrapper(1, 720, 1080, false))}}; + mStreamConfigs[1] = {{11, shared_ptr( + new TvStreamConfigWrapper(11, 360, 480, false))}}; + mStreamConfigs[3] = {{5, shared_ptr( + new TvStreamConfigWrapper(5, 1080, 1920, false))}}; +} + +::ndk::ScopedAStatus TvInput::setCallback(const shared_ptr& in_callback) { + ALOGV("%s", __FUNCTION__); + + mCallback = in_callback; + + TvInputEvent event; + event.type = TvInputEventType::DEVICE_AVAILABLE; + + event.deviceInfo = mDeviceInfos[0]->deviceInfo; + mCallback->notify(event); + + event.deviceInfo = mDeviceInfos[1]->deviceInfo; + mCallback->notify(event); + + event.deviceInfo = mDeviceInfos[3]->deviceInfo; + mCallback->notify(event); + + return ::ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus TvInput::getStreamConfigurations(int32_t in_deviceId, + vector* _aidl_return) { + ALOGV("%s", __FUNCTION__); + + if (mStreamConfigs.count(in_deviceId) == 0) { + ALOGW("Device with id %d isn't available", in_deviceId); + return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS); + } + + for (auto const& iconfig : mStreamConfigs[in_deviceId]) { + _aidl_return->push_back(iconfig.second->streamConfig); + } + + return ::ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus TvInput::openStream(int32_t in_deviceId, int32_t in_streamId, + NativeHandle* _aidl_return) { + ALOGV("%s", __FUNCTION__); + + if (mStreamConfigs.count(in_deviceId) == 0 || + mStreamConfigs[in_deviceId].count(in_streamId) == 0) { + ALOGW("Stream with device id %d, stream id %d isn't available", in_deviceId, in_streamId); + return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS); + } + if (mStreamConfigs[in_deviceId][in_streamId]->isOpen) { + ALOGW("Stream with device id %d, stream id %d is already opened", in_deviceId, in_streamId); + return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_STATE); + } + mStreamConfigs[in_deviceId][in_streamId]->handle = createNativeHandle(in_streamId); + mStreamConfigs[in_deviceId][in_streamId]->isOpen = true; + NativeHandle aidlHandle = makeToAidl(mStreamConfigs[in_deviceId][in_streamId]->handle); + _aidl_return = &aidlHandle; + return ::ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus TvInput::closeStream(int32_t in_deviceId, int32_t in_streamId) { + ALOGV("%s", __FUNCTION__); + + if (mStreamConfigs.count(in_deviceId) == 0 || + mStreamConfigs[in_deviceId].count(in_streamId) == 0) { + ALOGW("Stream with device id %d, stream id %d isn't available", in_deviceId, in_streamId); + return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS); + } + if (!mStreamConfigs[in_deviceId][in_streamId]->isOpen) { + ALOGW("Stream with device id %d, stream id %d is already closed", in_deviceId, in_streamId); + return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_STATE); + } + releaseNativeHandle(mStreamConfigs[in_deviceId][in_streamId]->handle); + mStreamConfigs[in_deviceId][in_streamId]->handle = nullptr; + mStreamConfigs[in_deviceId][in_streamId]->isOpen = false; + return ::ndk::ScopedAStatus::ok(); +} + +native_handle_t* TvInput::createNativeHandle(int fd) { + native_handle_t* nativeHandle = native_handle_create(1, 0); + if (nativeHandle == nullptr) { + ALOGE("[TVInput] Failed to create native_handle %d", errno); + return nullptr; + } + if (nativeHandle->numFds > 0) { + nativeHandle->data[0] = dup(fd); + } + return nativeHandle; +} + +void TvInput::releaseNativeHandle(native_handle_t* handle) { + native_handle_close(handle); + native_handle_delete(handle); +} + +} // namespace input +} // namespace tv +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/tv/input/aidl/default/TvInput.h b/tv/input/aidl/default/TvInput.h new file mode 100644 index 0000000000..a72bca3806 --- /dev/null +++ b/tv/input/aidl/default/TvInput.h @@ -0,0 +1,62 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include +#include "TvInputDeviceInfoWrapper.h" +#include "TvStreamConfigWrapper.h" + +using namespace android; +using namespace std; +using ::aidl::android::hardware::common::NativeHandle; + +namespace aidl { +namespace android { +namespace hardware { +namespace tv { +namespace input { + +class TvInput : public BnTvInput { + public: + TvInput(); + + ::ndk::ScopedAStatus setCallback(const shared_ptr& in_callback) override; + ::ndk::ScopedAStatus getStreamConfigurations(int32_t in_deviceId, + vector* _aidl_return) override; + ::ndk::ScopedAStatus openStream(int32_t in_deviceId, int32_t in_streamId, + NativeHandle* _aidl_return) override; + ::ndk::ScopedAStatus closeStream(int32_t in_deviceId, int32_t in_streamId) override; + + void init(); + + private: + native_handle_t* createNativeHandle(int fd); + void releaseNativeHandle(native_handle_t* handle); + + shared_ptr mCallback; + map> mDeviceInfos; + map>> mStreamConfigs; +}; + +} // namespace input +} // namespace tv +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/tv/input/aidl/default/TvInputDeviceInfoWrapper.h b/tv/input/aidl/default/TvInputDeviceInfoWrapper.h new file mode 100644 index 0000000000..d844cc88fb --- /dev/null +++ b/tv/input/aidl/default/TvInputDeviceInfoWrapper.h @@ -0,0 +1,43 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace tv { +namespace input { + +class TvInputDeviceInfoWrapper { + public: + TvInputDeviceInfoWrapper() {} + TvInputDeviceInfoWrapper(int32_t deviceId_, TvInputType type_, bool isAvailable_) { + deviceInfo.deviceId = deviceId_; + deviceInfo.type = type_; + isAvailable = isAvailable_; + } + + TvInputDeviceInfo deviceInfo; + bool isAvailable; +}; +} // namespace input +} // namespace tv +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/tv/input/aidl/default/TvStreamConfigWrapper.h b/tv/input/aidl/default/TvStreamConfigWrapper.h new file mode 100644 index 0000000000..05c7ca35b2 --- /dev/null +++ b/tv/input/aidl/default/TvStreamConfigWrapper.h @@ -0,0 +1,50 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +using namespace std; + +namespace aidl { +namespace android { +namespace hardware { +namespace tv { +namespace input { + +class TvStreamConfigWrapper { + public: + TvStreamConfigWrapper() {} + TvStreamConfigWrapper(int32_t streamId_, int32_t maxVideoWidth_, int32_t maxVideoHeight_, + bool isOpen_) { + streamConfig.streamId = streamId_; + streamConfig.maxVideoWidth = maxVideoWidth_; + streamConfig.maxVideoHeight = maxVideoHeight_; + isOpen = isOpen_; + handle = nullptr; + } + + TvStreamConfig streamConfig; + bool isOpen; + native_handle_t* handle; +}; +} // namespace input +} // namespace tv +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/tv/input/aidl/default/input-default.rc b/tv/input/aidl/default/input-default.rc new file mode 100644 index 0000000000..1958b5c292 --- /dev/null +++ b/tv/input/aidl/default/input-default.rc @@ -0,0 +1,5 @@ +service vendor.input-default /vendor/bin/hw/android.hardware.tv.input-service.example + interface aidl android.hardware.tv.input.ITvInput/default + class hal + user system + group system diff --git a/tv/input/aidl/default/input-default.xml b/tv/input/aidl/default/input-default.xml new file mode 100644 index 0000000000..38ba1512ba --- /dev/null +++ b/tv/input/aidl/default/input-default.xml @@ -0,0 +1,6 @@ + + + android.hardware.tv.input + ITvInput/default + + \ No newline at end of file diff --git a/tv/input/aidl/default/service.cpp b/tv/input/aidl/default/service.cpp new file mode 100644 index 0000000000..1021206153 --- /dev/null +++ b/tv/input/aidl/default/service.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.input-service.example" + +#include +#include +#include +#include + +#include "TvInput.h" + +using ::aidl::android::hardware::tv::input::TvInput; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(8); + std::shared_ptr tvInput = ndk::SharedRefBase::make(); + tvInput->init(); + + const std::string instance = std::string() + TvInput::descriptor + "/default"; + binder_status_t status = + AServiceManager_addService(tvInput->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reached +}