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(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 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 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 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 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 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. 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. 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 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 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 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 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 191 void VSyncWaiter::Notify(int64_t timestamp) { 192 timestamp_ = timestamp; 193 DispatchRemoteMethod<VSyncProtocol::Wait>(*this, &VSyncWaiter::OnWait, 194 message_); 195 } 196 197 pdx::Status<int64_t> VSyncWaiter::OnWait(pdx::Message& /*message*/) { 198 return {timestamp_}; 199 } 200 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 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