1 #include "vsync_service.h"
2
3 #include <hardware/hwcomposer.h>
4 #include <log/log.h>
5 #include <poll.h>
6 #include <sys/prctl.h>
7 #include <time.h>
8 #include <utils/Trace.h>
9
10 #include <dvr/dvr_display_types.h>
11 #include <pdx/default_transport/service_endpoint.h>
12 #include <private/dvr/clock_ns.h>
13 #include <private/dvr/display_protocol.h>
14
15 using android::dvr::display::VSyncProtocol;
16 using android::dvr::display::VSyncSchedInfo;
17 using android::pdx::Channel;
18 using android::pdx::Message;
19 using android::pdx::MessageInfo;
20 using android::pdx::default_transport::Endpoint;
21 using android::pdx::rpc::DispatchRemoteMethod;
22
23 namespace android {
24 namespace dvr {
25
VSyncService()26 VSyncService::VSyncService()
27 : BASE("VSyncService", Endpoint::Create(VSyncProtocol::kClientPath)),
28 last_vsync_(0),
29 current_vsync_(0),
30 compositor_time_ns_(0),
31 current_vsync_count_(0) {}
32
~VSyncService()33 VSyncService::~VSyncService() {}
34
VSyncEvent(int64_t timestamp_ns,int64_t compositor_time_ns,uint32_t vsync_count)35 void VSyncService::VSyncEvent(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 last_vsync_ = current_vsync_;
42 current_vsync_ = timestamp_ns;
43 compositor_time_ns_ = compositor_time_ns;
44 current_vsync_count_ = vsync_count;
45
46 NotifyWaiters();
47 UpdateClients();
48 }
49
OnChannelOpen(pdx::Message & message)50 std::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
OnChannelClose(pdx::Message &,const std::shared_ptr<Channel> & channel)59 void 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
AddWaiter(pdx::Message & message)70 void 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
AddClient(const std::shared_ptr<VSyncChannel> & client)76 void VSyncService::AddClient(const std::shared_ptr<VSyncChannel>& client) {
77 std::lock_guard<std::mutex> autolock(mutex_);
78 clients_.push_back(client);
79 }
80
RemoveClient(const std::shared_ptr<VSyncChannel> & client)81 void 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.
NotifyWaiters()87 void 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.
UpdateClients()99 void 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
HandleMessage(pdx::Message & message)110 pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
111 ATRACE_NAME("VSyncService::HandleMessage");
112 switch (message.GetOp()) {
113 case VSyncProtocol::Wait::Opcode:
114 AddWaiter(message);
115 return {};
116
117 case VSyncProtocol::GetLastTimestamp::Opcode:
118 DispatchRemoteMethod<VSyncProtocol::GetLastTimestamp>(
119 *this, &VSyncService::OnGetLastTimestamp, message);
120 return {};
121
122 case VSyncProtocol::GetSchedInfo::Opcode:
123 DispatchRemoteMethod<VSyncProtocol::GetSchedInfo>(
124 *this, &VSyncService::OnGetSchedInfo, message);
125 return {};
126
127 case VSyncProtocol::Acknowledge::Opcode:
128 DispatchRemoteMethod<VSyncProtocol::Acknowledge>(
129 *this, &VSyncService::OnAcknowledge, message);
130 return {};
131
132 default:
133 return Service::HandleMessage(message);
134 }
135 }
136
OnGetLastTimestamp(pdx::Message & message)137 pdx::Status<int64_t> VSyncService::OnGetLastTimestamp(pdx::Message& message) {
138 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
139 std::lock_guard<std::mutex> autolock(mutex_);
140
141 // Getting the timestamp has the side effect of ACKing.
142 client->Ack();
143 return {current_vsync_};
144 }
145
OnGetSchedInfo(pdx::Message & message)146 pdx::Status<VSyncSchedInfo> VSyncService::OnGetSchedInfo(
147 pdx::Message& message) {
148 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
149 std::lock_guard<std::mutex> autolock(mutex_);
150
151 // Getting the timestamp has the side effect of ACKing.
152 client->Ack();
153
154 uint32_t next_vsync_count = current_vsync_count_ + 1;
155 int64_t current_time = GetSystemClockNs();
156 int64_t vsync_period_ns = 0;
157 int64_t next_warp;
158 if (current_vsync_ == 0 || last_vsync_ == 0) {
159 // Handle startup when current_vsync_ or last_vsync_ are 0.
160 // Normally should not happen because vsync_service is running before
161 // applications, but in case it does a sane time prevents applications
162 // from malfunctioning.
163 vsync_period_ns = 20000000;
164 next_warp = current_time;
165 } else {
166 // TODO(jbates) When we have an accurate reading of the true vsync
167 // period, use that instead of this estimated value.
168 vsync_period_ns = current_vsync_ - last_vsync_;
169 // Clamp the period, because when there are no surfaces the last_vsync_
170 // value will get stale. Note this is temporary and goes away as soon
171 // as we have an accurate vsync period reported by the system.
172 vsync_period_ns = std::min(vsync_period_ns, INT64_C(20000000));
173 next_warp = current_vsync_ + vsync_period_ns - compositor_time_ns_;
174 // If the request missed the present window, move up to the next vsync.
175 if (current_time > next_warp) {
176 next_warp += vsync_period_ns;
177 ++next_vsync_count;
178 }
179 }
180
181 return {{vsync_period_ns, next_warp, next_vsync_count}};
182 }
183
OnAcknowledge(pdx::Message & message)184 pdx::Status<void> VSyncService::OnAcknowledge(pdx::Message& message) {
185 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
186 std::lock_guard<std::mutex> autolock(mutex_);
187 client->Ack();
188 return {};
189 }
190
Notify(int64_t timestamp)191 void VSyncWaiter::Notify(int64_t timestamp) {
192 timestamp_ = timestamp;
193 DispatchRemoteMethod<VSyncProtocol::Wait>(*this, &VSyncWaiter::OnWait,
194 message_);
195 }
196
OnWait(pdx::Message &)197 pdx::Status<int64_t> VSyncWaiter::OnWait(pdx::Message& /*message*/) {
198 return {timestamp_};
199 }
200
Ack()201 void VSyncChannel::Ack() {
202 ALOGD_IF(TRACE > 1, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_);
203 service_.ModifyChannelEvents(cid_, POLLPRI, 0);
204 }
205
Signal()206 void VSyncChannel::Signal() {
207 ALOGD_IF(TRACE > 1, "VSyncChannel::Signal: pid=%d cid=%d\n", pid_, cid_);
208 service_.ModifyChannelEvents(cid_, 0, POLLPRI);
209 }
210
211 } // namespace dvr
212 } // namespace android
213