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

Commit 6ad20f72 authored by Steven Moreland's avatar Steven Moreland
Browse files

Add displayservice.

This hidl service provides information about vsync and hotplug
to vendor services which is required by at least some camera
hal implementations.

Test: VtsFwkDisplayServiceV1_0TargetTest
Bug: 38311538
Change-Id: Ifc344c11ca4b3c8cebc6f0145f506d1aa774506d
parent b57d3d22
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
//
// Copyright (C) 2017 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.
//

cc_library_shared {
    name: "libdisplayservicehidl",

    srcs: [
        "DisplayService.cpp",
        "DisplayEventReceiver.cpp",
    ],

    shared_libs: [
        "libbase",
        "liblog",
        "libgui",
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "android.frameworks.displayservice@1.0",
    ],

    export_include_dirs: ["include"],
    export_shared_lib_headers: [
        "android.frameworks.displayservice@1.0",
        "libgui",
        "libutils",
    ],

    cflags: [
        "-Werror",
        "-Wall",
    ]
}
+167 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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 "libdisplayservicehidl"

#include <displayservice/DisplayEventReceiver.h>

#include <android-base/logging.h>
#include <android/frameworks/displayservice/1.0/BpHwEventCallback.h>

#include <thread>

namespace android {
namespace frameworks {
namespace displayservice {
namespace V1_0 {
namespace implementation {

sp<Looper> getLooper() {
    static sp<Looper> looper = []() {
        sp<Looper> looper = new Looper(false /* allowNonCallbacks */);

        std::thread{[&](){
            int pollResult = looper->pollAll(-1 /* timeout */);
            LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult;
        }}.detach();

        return looper;
    }();

    return looper;
}

DisplayEventReceiver::AttachedEvent::AttachedEvent(const sp<IEventCallback> &callback) : mCallback(callback) {
    mLooperAttached = getLooper()->addFd(mFwkReceiver.getFd(),
                                         Looper::POLL_CALLBACK,
                                         Looper::EVENT_INPUT,
                                         this,
                                         nullptr);
}

DisplayEventReceiver::AttachedEvent::~AttachedEvent() {
    if (!detach()) {
        LOG(ERROR) << "Could not remove fd from looper.";
    }
}

bool DisplayEventReceiver::AttachedEvent::detach() {
    if (!valid()) {
        return true;
    }

    return getLooper()->removeFd(mFwkReceiver.getFd());
}

bool DisplayEventReceiver::AttachedEvent::valid() const {
    return mFwkReceiver.initCheck() == OK && mLooperAttached;
}

DisplayEventReceiver::FwkReceiver &DisplayEventReceiver::AttachedEvent::receiver() {
    return mFwkReceiver;
}

int DisplayEventReceiver::AttachedEvent::handleEvent(int fd, int events, void* /* data */) {
    CHECK(fd == mFwkReceiver.getFd());

    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
        LOG(ERROR) << "AttachedEvent handleEvent received error or hangup:" << events;
        return 0; // remove the callback
    }

    if (!(events & Looper::EVENT_INPUT)) {
        LOG(ERROR) << "AttachedEvent handleEvent unhandled poll event:" << events;
        return 1; // keep the callback
    }

    const static size_t SIZE = 1;

    ssize_t n;
    FwkReceiver::Event buf[SIZE];
    while ((n = mFwkReceiver.getEvents(buf, SIZE)) > 0) {
        for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
            const FwkReceiver::Event &event = buf[i];

            uint32_t type = event.header.type;
            uint64_t timestamp = event.header.timestamp;

            switch(buf[i].header.type) {
                case FwkReceiver::DISPLAY_EVENT_VSYNC: {
                    mCallback->onVsync(timestamp, event.vsync.count);
                } break;
                case FwkReceiver::DISPLAY_EVENT_HOTPLUG: {
                    mCallback->onHotplug(timestamp, event.hotplug.connected);
                } break;
                default: {
                    LOG(ERROR) << "AttachedEvent handleEvent unknown type: " << type;
                }
            }
        }
    }

    return 1; // keep on going
}

Return<Status> DisplayEventReceiver::init(const sp<IEventCallback>& callback) {
    std::unique_lock<std::mutex> lock(mMutex);

    if (mAttached != nullptr || callback == nullptr) {
        return Status::BAD_VALUE;
    }

    mAttached = new AttachedEvent(callback);

    return mAttached->valid() ? Status::SUCCESS : Status::UNKNOWN;
}

Return<Status> DisplayEventReceiver::setVsyncRate(int32_t count) {
    std::unique_lock<std::mutex> lock(mMutex);

    if (mAttached == nullptr || count < 0) {
        return Status::BAD_VALUE;
    }

    bool success = OK == mAttached->receiver().setVsyncRate(count);
    return success ? Status::SUCCESS : Status::UNKNOWN;
}

Return<Status> DisplayEventReceiver::requestNextVsync() {
    std::unique_lock<std::mutex> lock(mMutex);

    if (mAttached == nullptr) {
        return Status::BAD_VALUE;
    }

    bool success = OK == mAttached->receiver().requestNextVsync();
    return success ? Status::SUCCESS : Status::UNKNOWN;
}

Return<Status> DisplayEventReceiver::close() {
    if (mAttached == nullptr) {
        return Status::BAD_VALUE;
    }

    std::unique_lock<std::mutex> lock(mMutex);
    bool success = mAttached->detach();
    mAttached = nullptr;

    return success ? Status::SUCCESS : Status::UNKNOWN;
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace displayservice
}  // namespace frameworks
}  // namespace android
+18 −0
Original line number Diff line number Diff line
#include <displayservice/DisplayService.h>
#include <displayservice/DisplayEventReceiver.h>

namespace android {
namespace frameworks {
namespace displayservice {
namespace V1_0 {
namespace implementation {

Return<sp<IDisplayEventReceiver>> DisplayService::getEventReceiver() {
    return new DisplayEventReceiver();
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace displayservice
}  // namespace frameworks
}  // namespace android
+56 −0
Original line number Diff line number Diff line
#ifndef ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
#define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H

#include <android/frameworks/displayservice/1.0/IDisplayEventReceiver.h>
#include <gui/DisplayEventReceiver.h>
#include <hidl/Status.h>
#include <gui/DisplayEventReceiver.h>
#include <utils/Looper.h>

#include <mutex>

namespace android {
namespace frameworks {
namespace displayservice {
namespace V1_0 {
namespace implementation {

using ::android::hardware::Return;
using ::android::hardware::Void;

class DisplayEventReceiver : public IDisplayEventReceiver {
public:
    Return<Status> init(const sp<IEventCallback>& callback) override;
    Return<Status> setVsyncRate(int32_t count) override;
    Return<Status> requestNextVsync() override;
    Return<Status> close() override;

private:
    using FwkReceiver = ::android::DisplayEventReceiver;

    struct AttachedEvent : LooperCallback {
        AttachedEvent(const sp<IEventCallback> &callback);
        ~AttachedEvent();

        bool detach();
        bool valid() const;
        FwkReceiver &receiver();
        virtual int handleEvent(int fd, int events, void* /* data */) override;

    private:
        FwkReceiver mFwkReceiver;
        sp<IEventCallback> mCallback;
        bool mLooperAttached;
    };

    sp<AttachedEvent> mAttached;
    std::mutex mMutex;
};

}  // namespace implementation
}  // namespace V1_0
}  // namespace displayservice
}  // namespace frameworks
}  // namespace android

#endif  // ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
+26 −0
Original line number Diff line number Diff line
#ifndef ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
#define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H

#include <android/frameworks/displayservice/1.0/IDisplayService.h>
#include <hidl/Status.h>

namespace android {
namespace frameworks {
namespace displayservice {
namespace V1_0 {
namespace implementation {

using ::android::hardware::Return;
using ::android::hardware::Void;

struct DisplayService : public IDisplayService {
    Return<sp<IDisplayEventReceiver>> getEventReceiver() override;
};

}  // namespace implementation
}  // namespace V1_0
}  // namespace displayservice
}  // namespace frameworks
}  // namespace android

#endif  // ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
Loading