summaryrefslogtreecommitdiff
path: root/libs/vr/libvrflinger/vr_flinger.cpp
blob: a8a847664fa43f38a997e4338eb0e7faf6aec401 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <dvr/vr_flinger.h>

#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <memory>

#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <private/dvr/display_client.h>
#include <processgroup/sched_policy.h>
#include <sys/prctl.h>
#include <sys/resource.h>

#include <functional>

#include "DisplayHardware/ComposerHal.h"
#include "display_manager_service.h"
#include "display_service.h"

namespace android {
namespace dvr {

std::unique_ptr<VrFlinger> VrFlinger::Create(
    Hwc2::Composer* hidl, hwc2_display_t primary_display_id,
    RequestDisplayCallback request_display_callback) {
  std::unique_ptr<VrFlinger> vr_flinger(new VrFlinger);
  if (vr_flinger->Init(hidl, primary_display_id, request_display_callback))
    return vr_flinger;
  else
    return nullptr;
}

VrFlinger::VrFlinger() {}

VrFlinger::~VrFlinger() {
  if (persistent_vr_state_callback_.get()) {
    sp<IVrManager> vr_manager = interface_cast<IVrManager>(
        defaultServiceManager()->checkService(String16("vrmanager")));
    if (vr_manager.get()) {
      vr_manager->unregisterPersistentVrStateListener(
          persistent_vr_state_callback_);
    }
  }

  if (dispatcher_)
    dispatcher_->SetCanceled(true);
  if (dispatcher_thread_.joinable())
    dispatcher_thread_.join();
}

bool VrFlinger::Init(Hwc2::Composer* hidl,
                     hwc2_display_t primary_display_id,
                     RequestDisplayCallback request_display_callback) {
  if (!hidl || !request_display_callback)
    return false;

  std::shared_ptr<android::pdx::Service> service;

  ALOGI("Starting up VrFlinger...");

  // We need to be able to create endpoints with full perms.
  umask(0000);

  android::ProcessState::self()->startThreadPool();

  request_display_callback_ = request_display_callback;

  dispatcher_ = android::pdx::ServiceDispatcher::Create();
  CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");

  display_service_ = android::dvr::DisplayService::Create(
      hidl, primary_display_id, request_display_callback);
  CHECK_ERROR(!display_service_, error, "Failed to create display service.");
  dispatcher_->AddService(display_service_);

  service = android::dvr::DisplayManagerService::Create(display_service_);
  CHECK_ERROR(!service, error, "Failed to create display manager service.");
  dispatcher_->AddService(service);

  dispatcher_thread_ = std::thread([this]() {
    prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0);
    ALOGI("Entering message loop.");

    setpriority(PRIO_PROCESS, 0, android::PRIORITY_URGENT_DISPLAY);
    set_sched_policy(0, SP_FOREGROUND);

    int ret = dispatcher_->EnterDispatchLoop();
    if (ret < 0) {
      ALOGE("Dispatch loop exited because: %s\n", strerror(-ret));
    }
  });

  return true;

error:
  return false;
}

void VrFlinger::OnBootFinished() {
  display_service_->OnBootFinished();
  sp<IVrManager> vr_manager = interface_cast<IVrManager>(
      defaultServiceManager()->checkService(String16("vrmanager")));
  if (vr_manager.get()) {
    persistent_vr_state_callback_ =
        new PersistentVrStateCallback(request_display_callback_);
    vr_manager->registerPersistentVrStateListener(
        persistent_vr_state_callback_);
  } else {
    ALOGE("Unable to register vr flinger for persistent vr mode changes");
  }
}

void VrFlinger::GrantDisplayOwnership() {
  display_service_->GrantDisplayOwnership();
}

void VrFlinger::SeizeDisplayOwnership() {
  display_service_->SeizeDisplayOwnership();
}

std::string VrFlinger::Dump() {
  // TODO(karthikrs): Add more state information here.
  return display_service_->DumpState(0/*unused*/);
}

void VrFlinger::PersistentVrStateCallback::onPersistentVrStateChanged(
    bool enabled) {
  ALOGV("Notified persistent vr mode is %s", enabled ? "on" : "off");
  // TODO(eieio): Determine the correct signal to request display control.
  // Persistent VR mode is not enough.
  // request_display_callback_(enabled);
}
}  // namespace dvr
}  // namespace android