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 26 namespace android { 27 namespace frameworks { 28 namespace displayservice { 29 namespace V1_0 { 30 namespace implementation { 31 32 sp<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 47 DisplayEventReceiver::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 57 DisplayEventReceiver::AttachedEvent::~AttachedEvent() { 58 if (!detach()) { 59 LOG(ERROR) << "Could not remove fd from looper."; 60 } 61 } 62 63 bool DisplayEventReceiver::AttachedEvent::detach() { 64 if (!valid()) { 65 return true; 66 } 67 68 return getLooper()->removeFd(mFwkReceiver.getFd()); 69 } 70 71 bool DisplayEventReceiver::AttachedEvent::valid() const { 72 return mFwkReceiver.initCheck() == OK && mLooperAttached; 73 } 74 75 DisplayEventReceiver::FwkReceiver &DisplayEventReceiver::AttachedEvent::receiver() { 76 return mFwkReceiver; 77 } 78 79 int 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 auto ret = mCallback->onVsync(timestamp, event.vsync.count); 106 if (!ret.isOk()) { 107 LOG(ERROR) << "AttachedEvent handleEvent fails on onVsync callback" 108 << " because of " << ret.description(); 109 return 0; // remove the callback 110 } 111 } break; 112 case FwkReceiver::DISPLAY_EVENT_HOTPLUG: { 113 auto ret = mCallback->onHotplug(timestamp, event.hotplug.connected); 114 if (!ret.isOk()) { 115 LOG(ERROR) << "AttachedEvent handleEvent fails on onHotplug callback" 116 << " because of " << ret.description(); 117 return 0; // remove the callback 118 } 119 } break; 120 default: { 121 LOG(ERROR) << "AttachedEvent handleEvent unknown type: " << type; 122 } 123 } 124 } 125 } 126 127 return 1; // keep on going 128 } 129 130 Return<Status> DisplayEventReceiver::init(const sp<IEventCallback>& callback) { 131 std::unique_lock<std::mutex> lock(mMutex); 132 133 if (mAttached != nullptr || callback == nullptr) { 134 return Status::BAD_VALUE; 135 } 136 137 mAttached = new AttachedEvent(callback); 138 139 return mAttached->valid() ? Status::SUCCESS : Status::UNKNOWN; 140 } 141 142 Return<Status> DisplayEventReceiver::setVsyncRate(int32_t count) { 143 std::unique_lock<std::mutex> lock(mMutex); 144 145 if (mAttached == nullptr || count < 0) { 146 return Status::BAD_VALUE; 147 } 148 149 bool success = OK == mAttached->receiver().setVsyncRate(count); 150 return success ? Status::SUCCESS : Status::UNKNOWN; 151 } 152 153 Return<Status> DisplayEventReceiver::requestNextVsync() { 154 std::unique_lock<std::mutex> lock(mMutex); 155 156 if (mAttached == nullptr) { 157 return Status::BAD_VALUE; 158 } 159 160 bool success = OK == mAttached->receiver().requestNextVsync(); 161 return success ? Status::SUCCESS : Status::UNKNOWN; 162 } 163 164 Return<Status> DisplayEventReceiver::close() { 165 std::unique_lock<std::mutex> lock(mMutex); 166 if (mAttached == nullptr) { 167 return Status::BAD_VALUE; 168 } 169 170 bool success = mAttached->detach(); 171 mAttached = nullptr; 172 173 return success ? Status::SUCCESS : Status::UNKNOWN; 174 } 175 176 } // namespace implementation 177 } // namespace V1_0 178 } // namespace displayservice 179 } // namespace frameworks 180 } // namespace android 181