TV Input HAL 2.0 default implementation

Initial version, fixed tabs.
Addressed comments.
Updated based on new AIDL interface changes.

Bug: 227673740
Test: atest VtsHalTvInputTargetTest
Change-Id: I49af8baa30404700fc38662b813913fe8cf08c0f
This commit is contained in:
Yixiao Luo
2022-08-11 18:44:50 -07:00
parent 3bbb6087f8
commit aaa523018f
8 changed files with 380 additions and 0 deletions

View File

@@ -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",
],
}

View File

@@ -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 <utils/Log.h>
#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<TvInputDeviceInfoWrapper>(
new TvInputDeviceInfoWrapper(0, TvInputType::TUNER, true));
mDeviceInfos[1] = shared_ptr<TvInputDeviceInfoWrapper>(
new TvInputDeviceInfoWrapper(1, TvInputType::HDMI, true));
mDeviceInfos[3] = shared_ptr<TvInputDeviceInfoWrapper>(
new TvInputDeviceInfoWrapper(3, TvInputType::DISPLAY_PORT, true));
mStreamConfigs[0] = {
{1, shared_ptr<TvStreamConfigWrapper>(new TvStreamConfigWrapper(1, 720, 1080, false))}};
mStreamConfigs[1] = {{11, shared_ptr<TvStreamConfigWrapper>(
new TvStreamConfigWrapper(11, 360, 480, false))}};
mStreamConfigs[3] = {{5, shared_ptr<TvStreamConfigWrapper>(
new TvStreamConfigWrapper(5, 1080, 1920, false))}};
}
::ndk::ScopedAStatus TvInput::setCallback(const shared_ptr<ITvInputCallback>& 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<TvStreamConfig>* _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

View File

@@ -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 <aidl/android/hardware/tv/input/BnTvInput.h>
#include <utils/KeyedVector.h>
#include <map>
#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<ITvInputCallback>& in_callback) override;
::ndk::ScopedAStatus getStreamConfigurations(int32_t in_deviceId,
vector<TvStreamConfig>* _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<ITvInputCallback> mCallback;
map<int32_t, shared_ptr<TvInputDeviceInfoWrapper>> mDeviceInfos;
map<int32_t, map<int32_t, shared_ptr<TvStreamConfigWrapper>>> mStreamConfigs;
};
} // namespace input
} // namespace tv
} // namespace hardware
} // namespace android
} // namespace aidl

View File

@@ -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 <aidl/android/hardware/tv/input/TvInputDeviceInfo.h>
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

View File

@@ -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 <aidl/android/hardware/tv/input/TvStreamConfig.h>
#include <aidlcommonsupport/NativeHandle.h>
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

View File

@@ -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

View File

@@ -0,0 +1,6 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.tv.input</name>
<fqname>ITvInput/default</fqname>
</hal>
</manifest>

View File

@@ -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 <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <utils/Log.h>
#include "TvInput.h"
using ::aidl::android::hardware::tv::input::TvInput;
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(8);
std::shared_ptr<TvInput> tvInput = ndk::SharedRefBase::make<TvInput>();
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
}