Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aaa52301 authored by Yixiao Luo's avatar Yixiao Luo
Browse files

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
parent 3bbb6087
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
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",
    ],
}
+143 −0
Original line number Diff line number Diff line
/*
 * 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
+62 −0
Original line number Diff line number Diff line
/*
 * 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
+43 −0
Original line number Diff line number Diff line
/*
 * 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
+50 −0
Original line number Diff line number Diff line
/*
 * 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
Loading