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 <functional>
22
23#include "DisplayHardware/ComposerHal.h"
24#include "display_manager_service.h"
25#include "display_service.h"
26#include "vsync_service.h"
27
28namespace android {
29namespace dvr {
30
31std::unique_ptr<VrFlinger> VrFlinger::Create(
32    Hwc2::Composer* hidl, hwc2_display_t primary_display_id,
33    RequestDisplayCallback request_display_callback) {
34  std::unique_ptr<VrFlinger> vr_flinger(new VrFlinger);
35  if (vr_flinger->Init(hidl, primary_display_id, request_display_callback))
36    return vr_flinger;
37  else
38    return nullptr;
39}
40
41VrFlinger::VrFlinger() {}
42
43VrFlinger::~VrFlinger() {
44  if (persistent_vr_state_callback_.get()) {
45    sp<IVrManager> vr_manager = interface_cast<IVrManager>(
46        defaultServiceManager()->checkService(String16("vrmanager")));
47    if (vr_manager.get()) {
48      vr_manager->unregisterPersistentVrStateListener(
49          persistent_vr_state_callback_);
50    }
51  }
52
53  if (dispatcher_)
54    dispatcher_->SetCanceled(true);
55  if (dispatcher_thread_.joinable())
56    dispatcher_thread_.join();
57}
58
59bool VrFlinger::Init(Hwc2::Composer* hidl,
60                     hwc2_display_t primary_display_id,
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  // We need to be able to create endpoints with full perms.
70  umask(0000);
71
72  android::ProcessState::self()->startThreadPool();
73
74  request_display_callback_ = request_display_callback;
75
76  dispatcher_ = android::pdx::ServiceDispatcher::Create();
77  CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");
78
79  display_service_ = android::dvr::DisplayService::Create(
80      hidl, primary_display_id, request_display_callback);
81  CHECK_ERROR(!display_service_, error, "Failed to create display service.");
82  dispatcher_->AddService(display_service_);
83
84  service = android::dvr::DisplayManagerService::Create(display_service_);
85  CHECK_ERROR(!service, error, "Failed to create display manager service.");
86  dispatcher_->AddService(service);
87
88  service = android::dvr::VSyncService::Create();
89  CHECK_ERROR(!service, error, "Failed to create vsync service.");
90  dispatcher_->AddService(service);
91
92  display_service_->SetVSyncCallback(
93      std::bind(&android::dvr::VSyncService::VSyncEvent,
94                std::static_pointer_cast<android::dvr::VSyncService>(service),
95                std::placeholders::_1, std::placeholders::_2,
96                std::placeholders::_3));
97
98  dispatcher_thread_ = std::thread([this]() {
99    prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0);
100    ALOGI("Entering message loop.");
101
102    setpriority(PRIO_PROCESS, 0, android::PRIORITY_URGENT_DISPLAY);
103    set_sched_policy(0, SP_FOREGROUND);
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  display_service_->OnBootFinished();
119  sp<IVrManager> vr_manager = interface_cast<IVrManager>(
120      defaultServiceManager()->checkService(String16("vrmanager")));
121  if (vr_manager.get()) {
122    persistent_vr_state_callback_ =
123        new PersistentVrStateCallback(request_display_callback_);
124    vr_manager->registerPersistentVrStateListener(
125        persistent_vr_state_callback_);
126  } else {
127    ALOGE("Unable to register vr flinger for persistent vr mode changes");
128  }
129}
130
131void VrFlinger::GrantDisplayOwnership() {
132  display_service_->GrantDisplayOwnership();
133}
134
135void VrFlinger::SeizeDisplayOwnership() {
136  display_service_->SeizeDisplayOwnership();
137}
138
139std::string VrFlinger::Dump() {
140  // TODO(karthikrs): Add more state information here.
141  return display_service_->DumpState(0/*unused*/);
142}
143
144void VrFlinger::PersistentVrStateCallback::onPersistentVrStateChanged(
145    bool enabled) {
146  ALOGV("Notified persistent vr mode is %s", enabled ? "on" : "off");
147  // TODO(eieio): Determine the correct signal to request display control.
148  // Persistent VR mode is not enough.
149  // request_display_callback_(enabled);
150}
151}  // namespace dvr
152}  // namespace android
153