blob: a7fd3c5cba8458c7dc58a76ae9d4082607726f34 [file] [log] [blame]
Steven Moreland6ad20f72017-05-16 17:42:50 -07001/*
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#define LOG_TAG "libdisplayservicehidl"
17
18#include <displayservice/DisplayEventReceiver.h>
19
20#include <android-base/logging.h>
21#include <android/frameworks/displayservice/1.0/BpHwEventCallback.h>
22
23#include <thread>
24
25namespace android {
26namespace frameworks {
27namespace displayservice {
28namespace V1_0 {
29namespace implementation {
30
31sp<Looper> getLooper() {
32 static sp<Looper> looper = []() {
33 sp<Looper> looper = new Looper(false /* allowNonCallbacks */);
34
35 std::thread{[&](){
36 int pollResult = looper->pollAll(-1 /* timeout */);
37 LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult;
38 }}.detach();
39
40 return looper;
41 }();
42
43 return looper;
44}
45
46DisplayEventReceiver::AttachedEvent::AttachedEvent(const sp<IEventCallback> &callback) : mCallback(callback) {
47 mLooperAttached = getLooper()->addFd(mFwkReceiver.getFd(),
48 Looper::POLL_CALLBACK,
49 Looper::EVENT_INPUT,
50 this,
51 nullptr);
52}
53
54DisplayEventReceiver::AttachedEvent::~AttachedEvent() {
55 if (!detach()) {
56 LOG(ERROR) << "Could not remove fd from looper.";
57 }
58}
59
60bool DisplayEventReceiver::AttachedEvent::detach() {
61 if (!valid()) {
62 return true;
63 }
64
65 return getLooper()->removeFd(mFwkReceiver.getFd());
66}
67
68bool DisplayEventReceiver::AttachedEvent::valid() const {
69 return mFwkReceiver.initCheck() == OK && mLooperAttached;
70}
71
72DisplayEventReceiver::FwkReceiver &DisplayEventReceiver::AttachedEvent::receiver() {
73 return mFwkReceiver;
74}
75
76int DisplayEventReceiver::AttachedEvent::handleEvent(int fd, int events, void* /* data */) {
77 CHECK(fd == mFwkReceiver.getFd());
78
79 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
80 LOG(ERROR) << "AttachedEvent handleEvent received error or hangup:" << events;
81 return 0; // remove the callback
82 }
83
84 if (!(events & Looper::EVENT_INPUT)) {
85 LOG(ERROR) << "AttachedEvent handleEvent unhandled poll event:" << events;
86 return 1; // keep the callback
87 }
88
89 const static size_t SIZE = 1;
90
91 ssize_t n;
92 FwkReceiver::Event buf[SIZE];
93 while ((n = mFwkReceiver.getEvents(buf, SIZE)) > 0) {
94 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
95 const FwkReceiver::Event &event = buf[i];
96
97 uint32_t type = event.header.type;
98 uint64_t timestamp = event.header.timestamp;
99
100 switch(buf[i].header.type) {
101 case FwkReceiver::DISPLAY_EVENT_VSYNC: {
102 mCallback->onVsync(timestamp, event.vsync.count);
103 } break;
104 case FwkReceiver::DISPLAY_EVENT_HOTPLUG: {
105 mCallback->onHotplug(timestamp, event.hotplug.connected);
106 } break;
107 default: {
108 LOG(ERROR) << "AttachedEvent handleEvent unknown type: " << type;
109 }
110 }
111 }
112 }
113
114 return 1; // keep on going
115}
116
117Return<Status> DisplayEventReceiver::init(const sp<IEventCallback>& callback) {
118 std::unique_lock<std::mutex> lock(mMutex);
119
120 if (mAttached != nullptr || callback == nullptr) {
121 return Status::BAD_VALUE;
122 }
123
124 mAttached = new AttachedEvent(callback);
125
126 return mAttached->valid() ? Status::SUCCESS : Status::UNKNOWN;
127}
128
129Return<Status> DisplayEventReceiver::setVsyncRate(int32_t count) {
130 std::unique_lock<std::mutex> lock(mMutex);
131
132 if (mAttached == nullptr || count < 0) {
133 return Status::BAD_VALUE;
134 }
135
136 bool success = OK == mAttached->receiver().setVsyncRate(count);
137 return success ? Status::SUCCESS : Status::UNKNOWN;
138}
139
140Return<Status> DisplayEventReceiver::requestNextVsync() {
141 std::unique_lock<std::mutex> lock(mMutex);
142
143 if (mAttached == nullptr) {
144 return Status::BAD_VALUE;
145 }
146
147 bool success = OK == mAttached->receiver().requestNextVsync();
148 return success ? Status::SUCCESS : Status::UNKNOWN;
149}
150
151Return<Status> DisplayEventReceiver::close() {
152 if (mAttached == nullptr) {
153 return Status::BAD_VALUE;
154 }
155
156 std::unique_lock<std::mutex> lock(mMutex);
157 bool success = mAttached->detach();
158 mAttached = nullptr;
159
160 return success ? Status::SUCCESS : Status::UNKNOWN;
161}
162
163} // namespace implementation
164} // namespace V1_0
165} // namespace displayservice
166} // namespace frameworks
167} // namespace android