• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(int display,int64_t timestamp_ns,int64_t compositor_time_ns,uint32_t vsync_count)35 void 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 
OnChannelOpen(pdx::Message & message)52 std::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 
OnChannelClose(pdx::Message &,const std::shared_ptr<Channel> & channel)61 void 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 
AddWaiter(pdx::Message & message)72 void 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 
AddClient(const std::shared_ptr<VSyncChannel> & client)78 void VSyncService::AddClient(const std::shared_ptr<VSyncChannel>& client) {
79   std::lock_guard<std::mutex> autolock(mutex_);
80   clients_.push_back(client);
81 }
82 
RemoveClient(const std::shared_ptr<VSyncChannel> & client)83 void 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.
NotifyWaiters()89 void 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.
UpdateClients()101 void 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 
HandleMessage(pdx::Message & message)112 pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
113   ATRACE_NAME("VSyncService::HandleMessage");
114   switch (message.GetOp()) {
115     case VSyncProtocol::Wait::Opcode:
116       AddWaiter(message);
117       return {};
118 
119     case VSyncProtocol::GetLastTimestamp::Opcode:
120       DispatchRemoteMethod<VSyncProtocol::GetLastTimestamp>(
121           *this, &VSyncService::OnGetLastTimestamp, message);
122       return {};
123 
124     case VSyncProtocol::GetSchedInfo::Opcode:
125       DispatchRemoteMethod<VSyncProtocol::GetSchedInfo>(
126           *this, &VSyncService::OnGetSchedInfo, message);
127       return {};
128 
129     case VSyncProtocol::Acknowledge::Opcode:
130       DispatchRemoteMethod<VSyncProtocol::Acknowledge>(
131           *this, &VSyncService::OnAcknowledge, message);
132       return {};
133 
134     default:
135       return Service::HandleMessage(message);
136   }
137 }
138 
OnGetLastTimestamp(pdx::Message & message)139 pdx::Status<int64_t> VSyncService::OnGetLastTimestamp(pdx::Message& message) {
140   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();
145   return {current_vsync_};
146 }
147 
OnGetSchedInfo(pdx::Message & message)148 pdx::Status<VSyncSchedInfo> VSyncService::OnGetSchedInfo(
149     pdx::Message& message) {
150   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 
183   return {{vsync_period_ns, next_warp, next_vsync_count}};
184 }
185 
OnAcknowledge(pdx::Message & message)186 pdx::Status<void> VSyncService::OnAcknowledge(pdx::Message& message) {
187   auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
188   std::lock_guard<std::mutex> autolock(mutex_);
189   client->Ack();
190   return {};
191 }
192 
Notify(int64_t timestamp)193 void VSyncWaiter::Notify(int64_t timestamp) {
194   timestamp_ = timestamp;
195   DispatchRemoteMethod<VSyncProtocol::Wait>(*this, &VSyncWaiter::OnWait,
196                                             message_);
197 }
198 
OnWait(pdx::Message &)199 pdx::Status<int64_t> VSyncWaiter::OnWait(pdx::Message& /*message*/) {
200   return {timestamp_};
201 }
202 
Ack()203 void VSyncChannel::Ack() {
204   ALOGD_IF(TRACE > 1, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_);
205   service_.ModifyChannelEvents(cid_, POLLPRI, 0);
206 }
207 
Signal()208 void VSyncChannel::Signal() {
209   ALOGD_IF(TRACE > 1, "VSyncChannel::Signal: pid=%d cid=%d\n", pid_, cid_);
210   service_.ModifyChannelEvents(cid_, 0, POLLPRI);
211 }
212 
213 }  // namespace dvr
214 }  // namespace android
215