1 #define LOG_TAG "PoseClient"
2 #include <dvr/pose_client.h>
7 #include <pdx/client.h>
8 #include <pdx/default_transport/client_channel_factory.h>
9 #include <pdx/file_handle.h>
10 #include <private/dvr/buffer_hub_client.h>
11 #include <private/dvr/pose-ipc.h>
12 #include <private/dvr/pose_client_internal.h>
13 #include <private/dvr/sensor_constants.h>
15 using android::pdx::LocalHandle;
16 using android::pdx::LocalChannelHandle;
17 using android::pdx::Status;
18 using android::pdx::Transaction;
20 #define arraysize(x) (static_cast<int32_t>(std::extent<decltype(x)>::value))
25 // PoseClient is a remote interface to the pose service in sensord.
26 class PoseClient : public pdx::ClientBase<PoseClient> {
28 ~PoseClient() override {}
30 // Casts C handle into an instance of this class.
31 static PoseClient* FromC(DvrPose* client) {
32 return reinterpret_cast<PoseClient*>(client);
35 // Polls the pose service for the current state and stores it in *state.
36 // Returns zero on success, a negative error code otherwise.
37 int Poll(DvrPoseState* state) {
38 Transaction trans{*this};
40 trans.Send<int>(DVR_POSE_POLL, nullptr, 0, state, sizeof(*state));
41 ALOGE_IF(!status, "Pose poll() failed because: %s\n",
42 status.GetErrorMessage().c_str());
43 return ReturnStatusOrError(status);
46 int GetPose(uint32_t vsync_count, DvrPoseAsync* out_pose) {
47 if (!mapped_pose_buffer_) {
48 int ret = GetRingBuffer(nullptr);
53 mapped_pose_buffer_->ring[vsync_count & kPoseAsyncBufferIndexMask];
57 uint32_t GetVsyncCount() {
58 if (!mapped_pose_buffer_) {
59 int ret = GetRingBuffer(nullptr);
63 return mapped_pose_buffer_->vsync_count;
66 int GetControllerPose(int32_t controller_id, uint32_t vsync_count,
67 DvrPoseAsync* out_pose) {
68 if (controller_id < 0 || controller_id >= arraysize(controllers_)) {
71 if (!controllers_[controller_id].mapped_pose_buffer) {
72 int ret = GetControllerRingBuffer(controller_id);
77 controllers_[controller_id]
78 .mapped_pose_buffer[vsync_count & kPoseAsyncBufferIndexMask];
82 int LogController(bool enable) {
83 Transaction trans{*this};
84 Status<int> status = trans.Send<int>(DVR_POSE_LOG_CONTROLLER, &enable,
85 sizeof(enable), nullptr, 0);
86 ALOGE_IF(!status, "Pose LogController() failed because: %s",
87 status.GetErrorMessage().c_str());
88 return ReturnStatusOrError(status);
91 // Freezes the pose to the provided state. Future poll operations will return
92 // this state until a different state is frozen or SetMode() is called with a
94 // Returns zero on success, a negative error code otherwise.
95 int Freeze(const DvrPoseState& frozen_state) {
96 Transaction trans{*this};
97 Status<int> status = trans.Send<int>(DVR_POSE_FREEZE, &frozen_state,
98 sizeof(frozen_state), nullptr, 0);
99 ALOGE_IF(!status, "Pose Freeze() failed because: %s\n",
100 status.GetErrorMessage().c_str());
101 return ReturnStatusOrError(status);
104 // Sets the data mode for the pose service.
105 int SetMode(DvrPoseMode mode) {
106 Transaction trans{*this};
108 trans.Send<int>(DVR_POSE_SET_MODE, &mode, sizeof(mode), nullptr, 0);
109 ALOGE_IF(!status, "Pose SetPoseMode() failed because: %s",
110 status.GetErrorMessage().c_str());
111 return ReturnStatusOrError(status);
114 // Gets the data mode for the pose service.
115 int GetMode(DvrPoseMode* out_mode) {
117 Transaction trans{*this};
119 trans.Send<int>(DVR_POSE_GET_MODE, nullptr, 0, &mode, sizeof(mode));
120 ALOGE_IF(!status, "Pose GetPoseMode() failed because: %s",
121 status.GetErrorMessage().c_str());
123 *out_mode = DvrPoseMode(mode);
124 return ReturnStatusOrError(status);
127 int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
128 if (pose_buffer_.get()) {
130 GetPoseRingBufferInfo(out_info);
135 Transaction trans{*this};
136 Status<LocalChannelHandle> status =
137 trans.Send<LocalChannelHandle>(DVR_POSE_GET_RING_BUFFER);
139 ALOGE("Pose GetRingBuffer() failed because: %s",
140 status.GetErrorMessage().c_str());
141 return -status.error();
144 auto buffer = BufferConsumer::Import(status.take());
146 ALOGE("Pose failed to import ring buffer");
149 void* addr = nullptr;
150 int ret = buffer->GetBlobReadOnlyPointer(sizeof(DvrPoseRingBuffer), &addr);
151 if (ret < 0 || !addr) {
152 ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
155 pose_buffer_.swap(buffer);
156 mapped_pose_buffer_ = static_cast<const DvrPoseRingBuffer*>(addr);
157 ALOGI("Mapped pose data translation %f,%f,%f quat %f,%f,%f,%f",
158 mapped_pose_buffer_->ring[0].translation[0],
159 mapped_pose_buffer_->ring[0].translation[1],
160 mapped_pose_buffer_->ring[0].translation[2],
161 mapped_pose_buffer_->ring[0].orientation[0],
162 mapped_pose_buffer_->ring[0].orientation[1],
163 mapped_pose_buffer_->ring[0].orientation[2],
164 mapped_pose_buffer_->ring[0].orientation[3]);
166 GetPoseRingBufferInfo(out_info);
171 int GetControllerRingBuffer(int32_t controller_id) {
172 if (controller_id < 0 || controller_id >= arraysize(controllers_)) {
175 ControllerClientState& client_state = controllers_[controller_id];
176 if (client_state.pose_buffer.get()) {
180 Transaction trans{*this};
181 Status<LocalChannelHandle> status = trans.Send<LocalChannelHandle>(
182 DVR_POSE_GET_CONTROLLER_RING_BUFFER, &controller_id,
183 sizeof(controller_id), nullptr, 0);
185 return -status.error();
188 auto buffer = BufferConsumer::Import(status.take());
190 ALOGE("Pose failed to import ring buffer");
193 constexpr size_t size = kPoseAsyncBufferTotalCount * sizeof(DvrPoseAsync);
194 void* addr = nullptr;
195 int ret = buffer->GetBlobReadOnlyPointer(size, &addr);
196 if (ret < 0 || !addr) {
197 ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
200 client_state.pose_buffer.swap(buffer);
201 client_state.mapped_pose_buffer = static_cast<const DvrPoseAsync*>(addr);
203 "Mapped controller %d pose data translation %f,%f,%f quat %f,%f,%f,%f",
204 controller_id, client_state.mapped_pose_buffer[0].translation[0],
205 client_state.mapped_pose_buffer[0].translation[1],
206 client_state.mapped_pose_buffer[0].translation[2],
207 client_state.mapped_pose_buffer[0].orientation[0],
208 client_state.mapped_pose_buffer[0].orientation[1],
209 client_state.mapped_pose_buffer[0].orientation[2],
210 client_state.mapped_pose_buffer[0].orientation[3]);
214 int NotifyVsync(uint32_t vsync_count, int64_t display_timestamp,
215 int64_t display_period_ns,
216 int64_t right_eye_photon_offset_ns) {
217 const struct iovec data[] = {
218 {.iov_base = &vsync_count, .iov_len = sizeof(vsync_count)},
219 {.iov_base = &display_timestamp, .iov_len = sizeof(display_timestamp)},
220 {.iov_base = &display_period_ns, .iov_len = sizeof(display_period_ns)},
221 {.iov_base = &right_eye_photon_offset_ns,
222 .iov_len = sizeof(right_eye_photon_offset_ns)},
224 Transaction trans{*this};
226 trans.SendVector<int>(DVR_POSE_NOTIFY_VSYNC, data, nullptr);
227 ALOGE_IF(!status, "Pose NotifyVsync() failed because: %s\n",
228 status.GetErrorMessage().c_str());
229 return ReturnStatusOrError(status);
232 int GetRingBufferFd(LocalHandle* fd) {
233 int ret = GetRingBuffer(nullptr);
236 *fd = pose_buffer_->GetBlobFd();
243 // Set up a channel to the pose service.
245 : BASE(pdx::default_transport::ClientChannelFactory::Create(
246 DVR_POSE_SERVICE_CLIENT)) {
247 // TODO(eieio): Cache the pose and make timeout 0 so that the API doesn't
248 // block while waiting for the pose service to come back up.
249 EnableAutoReconnect(kInfiniteTimeout);
252 PoseClient(const PoseClient&) = delete;
253 PoseClient& operator=(const PoseClient&) = delete;
255 void GetPoseRingBufferInfo(DvrPoseRingBufferInfo* out_info) const {
256 out_info->min_future_count = kPoseAsyncBufferMinFutureCount;
257 out_info->total_count = kPoseAsyncBufferTotalCount;
258 out_info->buffer = mapped_pose_buffer_->ring;
261 std::unique_ptr<BufferConsumer> pose_buffer_;
262 const DvrPoseRingBuffer* mapped_pose_buffer_ = nullptr;
264 struct ControllerClientState {
265 std::unique_ptr<BufferConsumer> pose_buffer;
266 const DvrPoseAsync* mapped_pose_buffer = nullptr;
268 ControllerClientState controllers_[2];
272 } // namespace android
274 using android::dvr::PoseClient;
280 DvrPose* dvrPoseCreate() {
281 PoseClient* client = PoseClient::Create().release();
282 return reinterpret_cast<DvrPose*>(client);
285 void dvrPoseDestroy(DvrPose* client) { delete PoseClient::FromC(client); }
287 int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose) {
288 return PoseClient::FromC(client)->GetPose(vsync_count, out_pose);
291 uint32_t dvrPoseGetVsyncCount(DvrPose* client) {
292 return PoseClient::FromC(client)->GetVsyncCount();
295 int dvrPoseGetController(DvrPose* client, int32_t controller_id,
296 uint32_t vsync_count, DvrPoseAsync* out_pose) {
297 return PoseClient::FromC(client)->GetControllerPose(controller_id,
298 vsync_count, out_pose);
301 int dvrPoseLogController(DvrPose* client, bool enable) {
302 return PoseClient::FromC(client)->LogController(enable);
305 int dvrPosePoll(DvrPose* client, DvrPoseState* state) {
306 return PoseClient::FromC(client)->Poll(state);
309 int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state) {
310 return PoseClient::FromC(client)->Freeze(*frozen_state);
313 int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode) {
314 return PoseClient::FromC(client)->SetMode(mode);
317 int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode) {
318 return PoseClient::FromC(client)->GetMode(mode);
321 int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info) {
322 return PoseClient::FromC(client)->GetRingBuffer(out_info);
325 int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
326 int64_t display_timestamp,
327 int64_t display_period_ns,
328 int64_t right_eye_photon_offset_ns) {
329 return PoseClient::FromC(client)->NotifyVsync(vsync_count, display_timestamp,
331 right_eye_photon_offset_ns);
334 int privateDvrPoseGetRingBufferFd(DvrPose* client, LocalHandle* fd) {
335 return PoseClient::FromC(client)->GetRingBufferFd(fd);