1#include <dvr/vr_flinger.h>
2
3#include <errno.h>
4#include <fcntl.h>
5#include <poll.h>
6#include <signal.h>
7#include <string.h>
8#include <time.h>
9#include <unistd.h>
10#include <memory>
11
12#include <binder/IServiceManager.h>
13#include <binder/ProcessState.h>
14#include <cutils/properties.h>
15#include <cutils/sched_policy.h>
16#include <log/log.h>
17#include <private/dvr/display_client.h>
18#include <sys/prctl.h>
19#include <sys/resource.h>
20
21#include <pdx/default_transport/service_dispatcher.h>
22
23#include <functional>
24
25#include "DisplayHardware/ComposerHal.h"
26#include "display_manager_service.h"
27#include "display_service.h"
28#include "vsync_service.h"
29
30namespace android {
31namespace dvr {
32
33std::unique_ptr<VrFlinger> VrFlinger::Create(
34    Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) {
35  std::unique_ptr<VrFlinger> vr_flinger(new VrFlinger);
36  if (vr_flinger->Init(hidl, request_display_callback))
37    return vr_flinger;
38  else
39    return nullptr;
40}
41
42VrFlinger::VrFlinger() {}
43
44VrFlinger::~VrFlinger() {
45  if (persistent_vr_state_callback_.get()) {
46    sp<IVrManager> vr_manager = interface_cast<IVrManager>(
47        defaultServiceManager()->checkService(String16("vrmanager")));
48    if (vr_manager.get()) {
49      vr_manager->unregisterPersistentVrStateListener(
50          persistent_vr_state_callback_);
51    }
52  }
53
54  if (dispatcher_)
55    dispatcher_->SetCanceled(true);
56  if (dispatcher_thread_.joinable())
57    dispatcher_thread_.join();
58}
59
60bool VrFlinger::Init(Hwc2::Composer* hidl,
61                     RequestDisplayCallback request_display_callback) {
62  if (!hidl || !request_display_callback)
63    return false;
64
65  std::shared_ptr<android::pdx::Service> service;
66
67  ALOGI("Starting up VrFlinger...");
68
69  setpriority(PRIO_PROCESS, 0, android::PRIORITY_URGENT_DISPLAY);
70  set_sched_policy(0, SP_FOREGROUND);
71
72  // We need to be able to create endpoints with full perms.
73  umask(0000);
74
75  android::ProcessState::self()->startThreadPool();
76
77  request_display_callback_ = request_display_callback;
78
79  dispatcher_ = android::pdx::default_transport::ServiceDispatcher::Create();
80  CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");
81
82  display_service_ =
83      android::dvr::DisplayService::Create(hidl, request_display_callback);
84  CHECK_ERROR(!display_service_, error, "Failed to create display service.");
85  dispatcher_->AddService(display_service_);
86
87  service = android::dvr::DisplayManagerService::Create(display_service_);
88  CHECK_ERROR(!service, error, "Failed to create display manager service.");
89  dispatcher_->AddService(service);
90
91  service = android::dvr::VSyncService::Create();
92  CHECK_ERROR(!service, error, "Failed to create vsync service.");
93  dispatcher_->AddService(service);
94
95  display_service_->SetVSyncCallback(
96      std::bind(&android::dvr::VSyncService::VSyncEvent,
97                std::static_pointer_cast<android::dvr::VSyncService>(service),
98                std::placeholders::_1, std::placeholders::_2,
99                std::placeholders::_3, std::placeholders::_4));
100
101  dispatcher_thread_ = std::thread([this]() {
102    prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0);
103    ALOGI("Entering message loop.");
104
105    int ret = dispatcher_->EnterDispatchLoop();
106    if (ret < 0) {
107      ALOGE("Dispatch loop exited because: %s\n", strerror(-ret));
108    }
109  });
110
111  return true;
112
113error:
114  return false;
115}
116
117void VrFlinger::OnBootFinished() {
118  sp<IVrManager> vr_manager = interface_cast<IVrManager>(
119      defaultServiceManager()->checkService(String16("vrmanager")));
120  if (vr_manager.get()) {
121    persistent_vr_state_callback_ =
122        new PersistentVrStateCallback(request_display_callback_);
123    vr_manager->registerPersistentVrStateListener(
124        persistent_vr_state_callback_);
125  } else {
126    ALOGE("Unable to register vr flinger for persistent vr mode changes");
127  }
128}
129
130void VrFlinger::GrantDisplayOwnership() {
131  display_service_->GrantDisplayOwnership();
132}
133
134void VrFlinger::SeizeDisplayOwnership() {
135  display_service_->SeizeDisplayOwnership();
136}
137
138void VrFlinger::OnHardwareComposerRefresh() {
139  display_service_->OnHardwareComposerRefresh();
140}
141
142void VrFlinger::PersistentVrStateCallback::onPersistentVrStateChanged(
143    bool enabled) {
144  ALOGV("Notified persistent vr mode is %s", enabled ? "on" : "off");
145  // TODO(eieio): Determine the correct signal to request display control.
146  // Persistent VR mode is not enough.
147  // request_display_callback_(enabled);
148}
149
150}  // namespace dvr
151}  // namespace android
152