blob: cda815c9817f0616f86f6b1816565dfc82006984 [file] [log] [blame]
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001#include "vsync_service.h"
2
3#include <log/log.h>
4#include <hardware/hwcomposer.h>
5#include <poll.h>
6#include <sys/prctl.h>
7#include <time.h>
8#include <utils/Trace.h>
9
10#include <pdx/default_transport/service_endpoint.h>
11#include <private/dvr/clock_ns.h>
Corey Tabaka3f82d312017-04-20 14:42:08 -070012#include <private/dvr/display_protocol.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080013#include <private/dvr/display_types.h>
14
15using android::pdx::Channel;
16using android::pdx::Message;
17using android::pdx::MessageInfo;
18using android::pdx::default_transport::Endpoint;
19using android::pdx::rpc::DispatchRemoteMethod;
20
21namespace android {
22namespace dvr {
23
24VSyncService::VSyncService()
25 : BASE("VSyncService", Endpoint::Create(DisplayVSyncRPC::kClientPath)),
26 last_vsync_(0),
27 current_vsync_(0),
28 compositor_time_ns_(0),
29 current_vsync_count_(0) {}
30
31VSyncService::~VSyncService() {}
32
33void VSyncService::VSyncEvent(int display, int64_t timestamp_ns,
34 int64_t compositor_time_ns,
35 uint32_t vsync_count) {
36 ATRACE_NAME("VSyncService::VSyncEvent");
37 std::lock_guard<std::mutex> autolock(mutex_);
38
39 if (display == HWC_DISPLAY_PRIMARY) {
40 last_vsync_ = current_vsync_;
41 current_vsync_ = timestamp_ns;
42 compositor_time_ns_ = compositor_time_ns;
43 current_vsync_count_ = vsync_count;
44
45 NotifyWaiters();
46 UpdateClients();
47 }
48}
49
50std::shared_ptr<Channel> VSyncService::OnChannelOpen(pdx::Message& message) {
51 const MessageInfo& info = message.GetInfo();
52
53 auto client = std::make_shared<VSyncChannel>(*this, info.pid, info.cid);
54 AddClient(client);
55
56 return client;
57}
58
59void VSyncService::OnChannelClose(pdx::Message& /*message*/,
60 const std::shared_ptr<Channel>& channel) {
61 auto client = std::static_pointer_cast<VSyncChannel>(channel);
62 if (!client) {
63 ALOGW("WARNING: VSyncChannel was NULL!!!\n");
64 return;
65 }
66
67 RemoveClient(client);
68}
69
70void VSyncService::AddWaiter(pdx::Message& message) {
71 std::lock_guard<std::mutex> autolock(mutex_);
72 std::unique_ptr<VSyncWaiter> waiter(new VSyncWaiter(message));
73 waiters_.push_back(std::move(waiter));
74}
75
76void VSyncService::AddClient(const std::shared_ptr<VSyncChannel>& client) {
77 std::lock_guard<std::mutex> autolock(mutex_);
78 clients_.push_back(client);
79}
80
81void VSyncService::RemoveClient(const std::shared_ptr<VSyncChannel>& client) {
82 std::lock_guard<std::mutex> autolock(mutex_);
83 clients_.remove(client);
84}
85
86// Private. Assumes mutex is held.
87void VSyncService::NotifyWaiters() {
88 ATRACE_NAME("VSyncService::NotifyWaiters");
89 auto first = waiters_.begin();
90 auto last = waiters_.end();
91
92 while (first != last) {
93 (*first)->Notify(current_vsync_);
94 waiters_.erase(first++);
95 }
96}
97
98// Private. Assumes mutex is held.
99void VSyncService::UpdateClients() {
100 ATRACE_NAME("VSyncService::UpdateClients");
101 auto first = clients_.begin();
102 auto last = clients_.end();
103
104 while (first != last) {
105 (*first)->Signal();
106 first++;
107 }
108}
109
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700110pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800111 switch (message.GetOp()) {
112 case DisplayVSyncRPC::Wait::Opcode:
113 AddWaiter(message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700114 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800115
116 case DisplayVSyncRPC::GetLastTimestamp::Opcode:
117 DispatchRemoteMethod<DisplayVSyncRPC::GetLastTimestamp>(
118 *this, &VSyncService::OnGetLastTimestamp, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700119 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800120
121 case DisplayVSyncRPC::GetSchedInfo::Opcode:
122 DispatchRemoteMethod<DisplayVSyncRPC::GetSchedInfo>(
123 *this, &VSyncService::OnGetSchedInfo, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700124 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800125
126 case DisplayVSyncRPC::Acknowledge::Opcode:
127 DispatchRemoteMethod<DisplayVSyncRPC::Acknowledge>(
128 *this, &VSyncService::OnAcknowledge, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700129 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800130
131 default:
132 return Service::HandleMessage(message);
133 }
134}
135
136int64_t VSyncService::OnGetLastTimestamp(pdx::Message& message) {
137 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
138 std::lock_guard<std::mutex> autolock(mutex_);
139
140 // Getting the timestamp has the side effect of ACKing.
141 client->Ack();
142 return current_vsync_;
143}
144
145VSyncSchedInfo VSyncService::OnGetSchedInfo(pdx::Message& message) {
146 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
147 std::lock_guard<std::mutex> autolock(mutex_);
148
149 // Getting the timestamp has the side effect of ACKing.
150 client->Ack();
151
152 uint32_t next_vsync_count = current_vsync_count_ + 1;
153 int64_t current_time = GetSystemClockNs();
154 int64_t vsync_period_ns = 0;
155 int64_t next_warp;
156 if (current_vsync_ == 0 || last_vsync_ == 0) {
157 // Handle startup when current_vsync_ or last_vsync_ are 0.
158 // Normally should not happen because vsync_service is running before
159 // applications, but in case it does a sane time prevents applications
160 // from malfunctioning.
161 vsync_period_ns = 20000000;
162 next_warp = current_time;
163 } else {
164 // TODO(jbates) When we have an accurate reading of the true vsync
165 // period, use that instead of this estimated value.
166 vsync_period_ns = current_vsync_ - last_vsync_;
167 // Clamp the period, because when there are no surfaces the last_vsync_
168 // value will get stale. Note this is temporary and goes away as soon
169 // as we have an accurate vsync period reported by the system.
170 vsync_period_ns = std::min(vsync_period_ns, INT64_C(20000000));
171 next_warp = current_vsync_ + vsync_period_ns - compositor_time_ns_;
172 // If the request missed the present window, move up to the next vsync.
173 if (current_time > next_warp) {
174 next_warp += vsync_period_ns;
175 ++next_vsync_count;
176 }
177 }
178
179 return {vsync_period_ns, next_warp, next_vsync_count};
180}
181
182int VSyncService::OnAcknowledge(pdx::Message& message) {
183 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
184 std::lock_guard<std::mutex> autolock(mutex_);
185 client->Ack();
186 return 0;
187}
188
189void VSyncWaiter::Notify(int64_t timestamp) {
190 timestamp_ = timestamp;
191 DispatchRemoteMethod<DisplayVSyncRPC::Wait>(*this, &VSyncWaiter::OnWait,
192 message_);
193}
194
195int64_t VSyncWaiter::OnWait(pdx::Message& /*message*/) { return timestamp_; }
196
197void VSyncChannel::Ack() {
198 ALOGD_IF(TRACE, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_);
199 service_.ModifyChannelEvents(cid_, POLLPRI, 0);
200}
201
202void VSyncChannel::Signal() {
203 ALOGD_IF(TRACE, "VSyncChannel::Signal: pid=%d cid=%d\n", pid_, cid_);
204 service_.ModifyChannelEvents(cid_, 0, POLLPRI);
205}
206
207} // namespace dvr
208} // namespace android