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 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 33 VSyncService::~VSyncService() {} 34 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 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 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 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 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 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. 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. 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 112 pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) { 113 switch (message.GetOp()) { 114 case VSyncProtocol::Wait::Opcode: 115 AddWaiter(message); 116 return {}; 117 118 case VSyncProtocol::GetLastTimestamp::Opcode: 119 DispatchRemoteMethod<VSyncProtocol::GetLastTimestamp>( 120 *this, &VSyncService::OnGetLastTimestamp, message); 121 return {}; 122 123 case VSyncProtocol::GetSchedInfo::Opcode: 124 DispatchRemoteMethod<VSyncProtocol::GetSchedInfo>( 125 *this, &VSyncService::OnGetSchedInfo, message); 126 return {}; 127 128 case VSyncProtocol::Acknowledge::Opcode: 129 DispatchRemoteMethod<VSyncProtocol::Acknowledge>( 130 *this, &VSyncService::OnAcknowledge, message); 131 return {}; 132 133 default: 134 return Service::HandleMessage(message); 135 } 136 } 137 138 pdx::Status<int64_t> VSyncService::OnGetLastTimestamp(pdx::Message& message) { 139 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel()); 140 std::lock_guard<std::mutex> autolock(mutex_); 141 142 // Getting the timestamp has the side effect of ACKing. 143 client->Ack(); 144 return {current_vsync_}; 145 } 146 147 pdx::Status<VSyncSchedInfo> VSyncService::OnGetSchedInfo( 148 pdx::Message& message) { 149 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel()); 150 std::lock_guard<std::mutex> autolock(mutex_); 151 152 // Getting the timestamp has the side effect of ACKing. 153 client->Ack(); 154 155 uint32_t next_vsync_count = current_vsync_count_ + 1; 156 int64_t current_time = GetSystemClockNs(); 157 int64_t vsync_period_ns = 0; 158 int64_t next_warp; 159 if (current_vsync_ == 0 || last_vsync_ == 0) { 160 // Handle startup when current_vsync_ or last_vsync_ are 0. 161 // Normally should not happen because vsync_service is running before 162 // applications, but in case it does a sane time prevents applications 163 // from malfunctioning. 164 vsync_period_ns = 20000000; 165 next_warp = current_time; 166 } else { 167 // TODO(jbates) When we have an accurate reading of the true vsync 168 // period, use that instead of this estimated value. 169 vsync_period_ns = current_vsync_ - last_vsync_; 170 // Clamp the period, because when there are no surfaces the last_vsync_ 171 // value will get stale. Note this is temporary and goes away as soon 172 // as we have an accurate vsync period reported by the system. 173 vsync_period_ns = std::min(vsync_period_ns, INT64_C(20000000)); 174 next_warp = current_vsync_ + vsync_period_ns - compositor_time_ns_; 175 // If the request missed the present window, move up to the next vsync. 176 if (current_time > next_warp) { 177 next_warp += vsync_period_ns; 178 ++next_vsync_count; 179 } 180 } 181 182 return {{vsync_period_ns, next_warp, next_vsync_count}}; 183 } 184 185 pdx::Status<void> VSyncService::OnAcknowledge(pdx::Message& message) { 186 auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel()); 187 std::lock_guard<std::mutex> autolock(mutex_); 188 client->Ack(); 189 return {}; 190 } 191 192 void VSyncWaiter::Notify(int64_t timestamp) { 193 timestamp_ = timestamp; 194 DispatchRemoteMethod<VSyncProtocol::Wait>(*this, &VSyncWaiter::OnWait, 195 message_); 196 } 197 198 pdx::Status<int64_t> VSyncWaiter::OnWait(pdx::Message& /*message*/) { 199 return {timestamp_}; 200 } 201 202 void VSyncChannel::Ack() { 203 ALOGD_IF(TRACE, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_); 204 service_.ModifyChannelEvents(cid_, POLLPRI, 0); 205 } 206 207 void VSyncChannel::Signal() { 208 ALOGD_IF(TRACE, "VSyncChannel::Signal: pid=%d cid=%d\n", pid_, cid_); 209 service_.ModifyChannelEvents(cid_, 0, POLLPRI); 210 } 211 212 } // namespace dvr 213 } // namespace android 214