| #ifndef ANDROID_DVR_SERVICES_DISPLAYD_VSYNC_SERVICE_H_ |
| #define ANDROID_DVR_SERVICES_DISPLAYD_VSYNC_SERVICE_H_ |
| |
| #include <pdx/service.h> |
| |
| #include <list> |
| #include <memory> |
| #include <mutex> |
| #include <thread> |
| |
| #include "display_service.h" |
| |
| namespace android { |
| namespace dvr { |
| |
| // VSyncWaiter encapsulates a client blocked waiting for the next vsync. |
| // It is used to enqueue the Message to reply to when the next vsync event |
| // occurs. |
| class VSyncWaiter { |
| public: |
| explicit VSyncWaiter(pdx::Message& message) : message_(std::move(message)) {} |
| |
| void Notify(int64_t timestamp); |
| |
| private: |
| pdx::Status<int64_t> OnWait(pdx::Message& message); |
| |
| pdx::Message message_; |
| int64_t timestamp_ = 0; |
| |
| VSyncWaiter(const VSyncWaiter&) = delete; |
| void operator=(const VSyncWaiter&) = delete; |
| }; |
| |
| // VSyncChannel manages the service-side per-client context for each client |
| // using the service. |
| class VSyncChannel : public pdx::Channel { |
| public: |
| VSyncChannel(pdx::Service& service, int pid, int cid) |
| : service_(service), pid_(pid), cid_(cid) {} |
| |
| void Ack(); |
| void Signal(); |
| |
| private: |
| pdx::Service& service_; |
| pid_t pid_; |
| int cid_; |
| |
| VSyncChannel(const VSyncChannel&) = delete; |
| void operator=(const VSyncChannel&) = delete; |
| }; |
| |
| // VSyncService implements the displayd vsync service over ServiceFS. |
| class VSyncService : public pdx::ServiceBase<VSyncService> { |
| public: |
| ~VSyncService() override; |
| |
| pdx::Status<void> HandleMessage(pdx::Message& message) override; |
| |
| std::shared_ptr<pdx::Channel> OnChannelOpen(pdx::Message& message) override; |
| void OnChannelClose(pdx::Message& message, |
| const std::shared_ptr<pdx::Channel>& channel) override; |
| |
| // Called by the hardware composer HAL, or similar, whenever a vsync event |
| // occurs on the primary display. |compositor_time_ns| is the number of ns |
| // before the next vsync when the compositor will preempt the GPU to do EDS |
| // and lens warp. |
| void VSyncEvent(int64_t timestamp_ns, int64_t compositor_time_ns, |
| uint32_t vsync_count); |
| |
| private: |
| friend BASE; |
| |
| VSyncService(); |
| |
| pdx::Status<int64_t> OnGetLastTimestamp(pdx::Message& message); |
| pdx::Status<display::VSyncSchedInfo> OnGetSchedInfo(pdx::Message& message); |
| pdx::Status<void> OnAcknowledge(pdx::Message& message); |
| |
| void NotifierThreadFunction(); |
| |
| void AddWaiter(pdx::Message& message); |
| void NotifyWaiters(); |
| void UpdateClients(); |
| |
| void AddClient(const std::shared_ptr<VSyncChannel>& client); |
| void RemoveClient(const std::shared_ptr<VSyncChannel>& client); |
| |
| int64_t last_vsync_; |
| int64_t current_vsync_; |
| int64_t compositor_time_ns_; |
| uint32_t current_vsync_count_; |
| |
| std::mutex mutex_; |
| |
| std::list<std::unique_ptr<VSyncWaiter>> waiters_; |
| std::list<std::shared_ptr<VSyncChannel>> clients_; |
| |
| VSyncService(const VSyncService&) = delete; |
| void operator=(VSyncService&) = delete; |
| }; |
| |
| } // namespace dvr |
| } // namespace android |
| |
| #endif // ANDROID_DVR_SERVICES_DISPLAYD_VSYNC_SERVICE_H_ |