blob: fdeb899f66eb2366ad230b2a0639b3f31b930a4d [file] [log] [blame]
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001#include "vsync_service.h"
2
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08003#include <hardware/hwcomposer.h>
Corey Tabaka2251d822017-04-20 16:04:07 -07004#include <log/log.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08005#include <poll.h>
6#include <sys/prctl.h>
7#include <time.h>
8#include <utils/Trace.h>
9
Corey Tabaka2251d822017-04-20 16:04:07 -070010#include <dvr/dvr_display_types.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080011#include <pdx/default_transport/service_endpoint.h>
12#include <private/dvr/clock_ns.h>
Corey Tabaka3f82d312017-04-20 14:42:08 -070013#include <private/dvr/display_protocol.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080014
Corey Tabaka2251d822017-04-20 16:04:07 -070015using android::dvr::display::VSyncProtocol;
16using android::dvr::display::VSyncSchedInfo;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080017using android::pdx::Channel;
18using android::pdx::Message;
19using android::pdx::MessageInfo;
20using android::pdx::default_transport::Endpoint;
21using android::pdx::rpc::DispatchRemoteMethod;
22
23namespace android {
24namespace dvr {
25
26VSyncService::VSyncService()
Corey Tabaka2251d822017-04-20 16:04:07 -070027 : BASE("VSyncService", Endpoint::Create(VSyncProtocol::kClientPath)),
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080028 last_vsync_(0),
29 current_vsync_(0),
30 compositor_time_ns_(0),
31 current_vsync_count_(0) {}
32
33VSyncService::~VSyncService() {}
34
35void VSyncService::VSyncEvent(int display, int64_t timestamp_ns,
36 int64_t compositor_time_ns,
37 uint32_t vsync_count) {
38 ATRACE_NAME("VSyncService::VSyncEvent");
39 std::lock_guard<std::mutex> autolock(mutex_);
40
41 if (display == HWC_DISPLAY_PRIMARY) {
42 last_vsync_ = current_vsync_;
43 current_vsync_ = timestamp_ns;
44 compositor_time_ns_ = compositor_time_ns;
45 current_vsync_count_ = vsync_count;
46
47 NotifyWaiters();
48 UpdateClients();
49 }
50}
51
52std::shared_ptr<Channel> VSyncService::OnChannelOpen(pdx::Message& message) {
53 const MessageInfo& info = message.GetInfo();
54
55 auto client = std::make_shared<VSyncChannel>(*this, info.pid, info.cid);
56 AddClient(client);
57
58 return client;
59}
60
61void VSyncService::OnChannelClose(pdx::Message& /*message*/,
62 const std::shared_ptr<Channel>& channel) {
63 auto client = std::static_pointer_cast<VSyncChannel>(channel);
64 if (!client) {
65 ALOGW("WARNING: VSyncChannel was NULL!!!\n");
66 return;
67 }
68
69 RemoveClient(client);
70}
71
72void VSyncService::AddWaiter(pdx::Message& message) {
73 std::lock_guard<std::mutex> autolock(mutex_);
74 std::unique_ptr<VSyncWaiter> waiter(new VSyncWaiter(message));
75 waiters_.push_back(std::move(waiter));
76}
77
78void VSyncService::AddClient(const std::shared_ptr<VSyncChannel>& client) {
79 std::lock_guard<std::mutex> autolock(mutex_);
80 clients_.push_back(client);
81}
82
83void VSyncService::RemoveClient(const std::shared_ptr<VSyncChannel>& client) {
84 std::lock_guard<std::mutex> autolock(mutex_);
85 clients_.remove(client);
86}
87
88// Private. Assumes mutex is held.
89void VSyncService::NotifyWaiters() {
90 ATRACE_NAME("VSyncService::NotifyWaiters");
91 auto first = waiters_.begin();
92 auto last = waiters_.end();
93
94 while (first != last) {
95 (*first)->Notify(current_vsync_);
96 waiters_.erase(first++);
97 }
98}
99
100// Private. Assumes mutex is held.
101void VSyncService::UpdateClients() {
102 ATRACE_NAME("VSyncService::UpdateClients");
103 auto first = clients_.begin();
104 auto last = clients_.end();
105
106 while (first != last) {
107 (*first)->Signal();
108 first++;
109 }
110}
111
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700112pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
Corey Tabakab3732f02017-09-16 00:58:54 -0700113 ATRACE_NAME("VSyncService::HandleMessage");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800114 switch (message.GetOp()) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700115 case VSyncProtocol::Wait::Opcode:
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800116 AddWaiter(message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700117 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800118
Corey Tabaka2251d822017-04-20 16:04:07 -0700119 case VSyncProtocol::GetLastTimestamp::Opcode:
120 DispatchRemoteMethod<VSyncProtocol::GetLastTimestamp>(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800121 *this, &VSyncService::OnGetLastTimestamp, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700122 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800123
Corey Tabaka2251d822017-04-20 16:04:07 -0700124 case VSyncProtocol::GetSchedInfo::Opcode:
125 DispatchRemoteMethod<VSyncProtocol::GetSchedInfo>(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800126 *this, &VSyncService::OnGetSchedInfo, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700127 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800128
Corey Tabaka2251d822017-04-20 16:04:07 -0700129 case VSyncProtocol::Acknowledge::Opcode:
130 DispatchRemoteMethod<VSyncProtocol::Acknowledge>(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800131 *this, &VSyncService::OnAcknowledge, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700132 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800133
134 default:
135 return Service::HandleMessage(message);
136 }
137}
138
Corey Tabaka2251d822017-04-20 16:04:07 -0700139pdx::Status<int64_t> VSyncService::OnGetLastTimestamp(pdx::Message& message) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800140 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
141 std::lock_guard<std::mutex> autolock(mutex_);
142
143 // Getting the timestamp has the side effect of ACKing.
144 client->Ack();
Corey Tabaka2251d822017-04-20 16:04:07 -0700145 return {current_vsync_};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800146}
147
Corey Tabaka2251d822017-04-20 16:04:07 -0700148pdx::Status<VSyncSchedInfo> VSyncService::OnGetSchedInfo(
149 pdx::Message& message) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800150 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
151 std::lock_guard<std::mutex> autolock(mutex_);
152
153 // Getting the timestamp has the side effect of ACKing.
154 client->Ack();
155
156 uint32_t next_vsync_count = current_vsync_count_ + 1;
157 int64_t current_time = GetSystemClockNs();
158 int64_t vsync_period_ns = 0;
159 int64_t next_warp;
160 if (current_vsync_ == 0 || last_vsync_ == 0) {
161 // Handle startup when current_vsync_ or last_vsync_ are 0.
162 // Normally should not happen because vsync_service is running before
163 // applications, but in case it does a sane time prevents applications
164 // from malfunctioning.
165 vsync_period_ns = 20000000;
166 next_warp = current_time;
167 } else {
168 // TODO(jbates) When we have an accurate reading of the true vsync
169 // period, use that instead of this estimated value.
170 vsync_period_ns = current_vsync_ - last_vsync_;
171 // Clamp the period, because when there are no surfaces the last_vsync_
172 // value will get stale. Note this is temporary and goes away as soon
173 // as we have an accurate vsync period reported by the system.
174 vsync_period_ns = std::min(vsync_period_ns, INT64_C(20000000));
175 next_warp = current_vsync_ + vsync_period_ns - compositor_time_ns_;
176 // If the request missed the present window, move up to the next vsync.
177 if (current_time > next_warp) {
178 next_warp += vsync_period_ns;
179 ++next_vsync_count;
180 }
181 }
182
Corey Tabaka2251d822017-04-20 16:04:07 -0700183 return {{vsync_period_ns, next_warp, next_vsync_count}};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800184}
185
Corey Tabaka2251d822017-04-20 16:04:07 -0700186pdx::Status<void> VSyncService::OnAcknowledge(pdx::Message& message) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800187 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
188 std::lock_guard<std::mutex> autolock(mutex_);
189 client->Ack();
Corey Tabaka2251d822017-04-20 16:04:07 -0700190 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800191}
192
193void VSyncWaiter::Notify(int64_t timestamp) {
194 timestamp_ = timestamp;
Corey Tabaka2251d822017-04-20 16:04:07 -0700195 DispatchRemoteMethod<VSyncProtocol::Wait>(*this, &VSyncWaiter::OnWait,
196 message_);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800197}
198
Corey Tabaka2251d822017-04-20 16:04:07 -0700199pdx::Status<int64_t> VSyncWaiter::OnWait(pdx::Message& /*message*/) {
200 return {timestamp_};
201}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800202
203void VSyncChannel::Ack() {
Corey Tabaka89bbefc2017-06-06 16:14:21 -0700204 ALOGD_IF(TRACE > 1, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800205 service_.ModifyChannelEvents(cid_, POLLPRI, 0);
206}
207
208void VSyncChannel::Signal() {
Corey Tabaka89bbefc2017-06-06 16:14:21 -0700209 ALOGD_IF(TRACE > 1, "VSyncChannel::Signal: pid=%d cid=%d\n", pid_, cid_);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800210 service_.ModifyChannelEvents(cid_, 0, POLLPRI);
211}
212
213} // namespace dvr
214} // namespace android