1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "libdisplayservicehidl" 18 19#include <displayservice/DisplayEventReceiver.h> 20 21#include <android-base/logging.h> 22#include <android/frameworks/displayservice/1.0/BpHwEventCallback.h> 23 24#include <thread> 25 26namespace android { 27namespace frameworks { 28namespace displayservice { 29namespace V1_0 { 30namespace implementation { 31 32sp<Looper> getLooper() { 33 static sp<Looper> looper = []() { 34 sp<Looper> looper = new Looper(false /* allowNonCallbacks */); 35 36 std::thread{[&](){ 37 int pollResult = looper->pollAll(-1 /* timeout */); 38 LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult; 39 }}.detach(); 40 41 return looper; 42 }(); 43 44 return looper; 45} 46 47DisplayEventReceiver::AttachedEvent::AttachedEvent(const sp<IEventCallback> &callback) 48 : mCallback(callback) 49{ 50 mLooperAttached = getLooper()->addFd(mFwkReceiver.getFd(), 51 Looper::POLL_CALLBACK, 52 Looper::EVENT_INPUT, 53 this, 54 nullptr); 55} 56 57DisplayEventReceiver::AttachedEvent::~AttachedEvent() { 58 if (!detach()) { 59 LOG(ERROR) << "Could not remove fd from looper."; 60 } 61} 62 63bool DisplayEventReceiver::AttachedEvent::detach() { 64 if (!valid()) { 65 return true; 66 } 67 68 return getLooper()->removeFd(mFwkReceiver.getFd()); 69} 70 71bool DisplayEventReceiver::AttachedEvent::valid() const { 72 return mFwkReceiver.initCheck() == OK && mLooperAttached; 73} 74 75DisplayEventReceiver::FwkReceiver &DisplayEventReceiver::AttachedEvent::receiver() { 76 return mFwkReceiver; 77} 78 79int DisplayEventReceiver::AttachedEvent::handleEvent(int fd, int events, void* /* data */) { 80 CHECK(fd == mFwkReceiver.getFd()); 81 82 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { 83 LOG(ERROR) << "AttachedEvent handleEvent received error or hangup:" << events; 84 return 0; // remove the callback 85 } 86 87 if (!(events & Looper::EVENT_INPUT)) { 88 LOG(ERROR) << "AttachedEvent handleEvent unhandled poll event:" << events; 89 return 1; // keep the callback 90 } 91 92 constexpr size_t SIZE = 1; 93 94 ssize_t n; 95 FwkReceiver::Event buf[SIZE]; 96 while ((n = mFwkReceiver.getEvents(buf, SIZE)) > 0) { 97 for (size_t i = 0; i < static_cast<size_t>(n); ++i) { 98 const FwkReceiver::Event &event = buf[i]; 99 100 uint32_t type = event.header.type; 101 uint64_t timestamp = event.header.timestamp; 102 103 switch(buf[i].header.type) { 104 case FwkReceiver::DISPLAY_EVENT_VSYNC: { 105 mCallback->onVsync(timestamp, event.vsync.count); 106 } break; 107 case FwkReceiver::DISPLAY_EVENT_HOTPLUG: { 108 mCallback->onHotplug(timestamp, event.hotplug.connected); 109 } break; 110 default: { 111 LOG(ERROR) << "AttachedEvent handleEvent unknown type: " << type; 112 } 113 } 114 } 115 } 116 117 return 1; // keep on going 118} 119 120Return<Status> DisplayEventReceiver::init(const sp<IEventCallback>& callback) { 121 std::unique_lock<std::mutex> lock(mMutex); 122 123 if (mAttached != nullptr || callback == nullptr) { 124 return Status::BAD_VALUE; 125 } 126 127 mAttached = new AttachedEvent(callback); 128 129 return mAttached->valid() ? Status::SUCCESS : Status::UNKNOWN; 130} 131 132Return<Status> DisplayEventReceiver::setVsyncRate(int32_t count) { 133 std::unique_lock<std::mutex> lock(mMutex); 134 135 if (mAttached == nullptr || count < 0) { 136 return Status::BAD_VALUE; 137 } 138 139 bool success = OK == mAttached->receiver().setVsyncRate(count); 140 return success ? Status::SUCCESS : Status::UNKNOWN; 141} 142 143Return<Status> DisplayEventReceiver::requestNextVsync() { 144 std::unique_lock<std::mutex> lock(mMutex); 145 146 if (mAttached == nullptr) { 147 return Status::BAD_VALUE; 148 } 149 150 bool success = OK == mAttached->receiver().requestNextVsync(); 151 return success ? Status::SUCCESS : Status::UNKNOWN; 152} 153 154Return<Status> DisplayEventReceiver::close() { 155 std::unique_lock<std::mutex> lock(mMutex); 156 if (mAttached == nullptr) { 157 return Status::BAD_VALUE; 158 } 159 160 bool success = mAttached->detach(); 161 mAttached = nullptr; 162 163 return success ? Status::SUCCESS : Status::UNKNOWN; 164} 165 166} // namespace implementation 167} // namespace V1_0 168} // namespace displayservice 169} // namespace frameworks 170} // namespace android 171