1 #define LOG_TAG "PoseClient"
2 #include <dvr/dvr_shared_buffers.h>
3 #include <dvr/pose_client.h>
4
5 #include <stdint.h>
6
7 #include <log/log.h>
8 #include <pdx/client.h>
9 #include <pdx/default_transport/client_channel_factory.h>
10 #include <pdx/file_handle.h>
11 #include <private/dvr/buffer_hub_client.h>
12 #include <private/dvr/buffer_hub_queue_client.h>
13 #include <private/dvr/display_client.h>
14 #include <private/dvr/pose-ipc.h>
15 #include <private/dvr/shared_buffer_helpers.h>
16
17 using android::dvr::ConsumerQueue;
18 using android::pdx::LocalHandle;
19 using android::pdx::LocalChannelHandle;
20 using android::pdx::Status;
21 using android::pdx::Transaction;
22
23 namespace android {
24 namespace dvr {
25 namespace {
26
27 typedef CPUMappedBroadcastRing<DvrPoseRing> SensorPoseRing;
28
29 constexpr static int32_t MAX_CONTROLLERS = 2;
30 } // namespace
31
32 // PoseClient is a remote interface to the pose service in sensord.
33 class PoseClient : public pdx::ClientBase<PoseClient> {
34 public:
~PoseClient()35 ~PoseClient() override {}
36
37 // Casts C handle into an instance of this class.
FromC(DvrPoseClient * client)38 static PoseClient* FromC(DvrPoseClient* client) {
39 return reinterpret_cast<PoseClient*>(client);
40 }
41
42 // Polls the pose service for the current state and stores it in *state.
43 // Returns zero on success, a negative error code otherwise.
Poll(DvrPose * state)44 int Poll(DvrPose* state) {
45 // Allocate the helper class to access the sensor pose buffer.
46 if (sensor_pose_buffer_ == nullptr) {
47 sensor_pose_buffer_ = std::make_unique<SensorPoseRing>(
48 DvrGlobalBuffers::kSensorPoseBuffer, CPUUsageMode::READ_RARELY);
49 }
50
51 if (state) {
52 if (sensor_pose_buffer_->GetNewest(state)) {
53 return 0;
54 } else {
55 return -EAGAIN;
56 }
57 }
58
59 return -EINVAL;
60 }
61
GetPose(uint32_t vsync_count,DvrPoseAsync * out_pose)62 int GetPose(uint32_t vsync_count, DvrPoseAsync* out_pose) {
63 const auto vsync_buffer = GetVsyncBuffer();
64 if (vsync_buffer) {
65 *out_pose =
66 vsync_buffer
67 ->vsync_poses[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
68 return 0;
69 } else {
70 return -EAGAIN;
71 }
72 }
73
GetVsyncCount()74 uint32_t GetVsyncCount() {
75 const auto vsync_buffer = GetVsyncBuffer();
76 if (vsync_buffer) {
77 return vsync_buffer->vsync_count;
78 }
79
80 return 0;
81 }
82
GetControllerPose(int32_t controller_id,uint32_t vsync_count,DvrPoseAsync * out_pose)83 int GetControllerPose(int32_t controller_id, uint32_t vsync_count,
84 DvrPoseAsync* out_pose) {
85 if (controller_id < 0 || controller_id >= MAX_CONTROLLERS) {
86 return -EINVAL;
87 }
88 if (!controllers_[controller_id].mapped_pose_buffer) {
89 int ret = GetControllerRingBuffer(controller_id);
90 if (ret < 0)
91 return ret;
92 }
93 *out_pose =
94 controllers_[controller_id]
95 .mapped_pose_buffer[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
96 return 0;
97 }
98
LogController(bool enable)99 int LogController(bool enable) {
100 Transaction trans{*this};
101 Status<int> status = trans.Send<int>(DVR_POSE_LOG_CONTROLLER, &enable,
102 sizeof(enable), nullptr, 0);
103 ALOGE_IF(!status, "Pose LogController() failed because: %s",
104 status.GetErrorMessage().c_str());
105 return ReturnStatusOrError(status);
106 }
107
108 // Freezes the pose to the provided state. Future poll operations will return
109 // this state until a different state is frozen or SetMode() is called with a
110 // different mode.
111 // Returns zero on success, a negative error code otherwise.
Freeze(const DvrPose & frozen_state)112 int Freeze(const DvrPose& frozen_state) {
113 Transaction trans{*this};
114 Status<int> status = trans.Send<int>(DVR_POSE_FREEZE, &frozen_state,
115 sizeof(frozen_state), nullptr, 0);
116 ALOGE_IF(!status, "Pose Freeze() failed because: %s\n",
117 status.GetErrorMessage().c_str());
118 return ReturnStatusOrError(status);
119 }
120
121 // Sets the data mode for the pose service.
SetMode(DvrPoseMode mode)122 int SetMode(DvrPoseMode mode) {
123 Transaction trans{*this};
124 Status<int> status =
125 trans.Send<int>(DVR_POSE_SET_MODE, &mode, sizeof(mode), nullptr, 0);
126 ALOGE_IF(!status, "Pose SetPoseMode() failed because: %s",
127 status.GetErrorMessage().c_str());
128 return ReturnStatusOrError(status);
129 }
130
131 // Gets the data mode for the pose service.
GetMode(DvrPoseMode * out_mode)132 int GetMode(DvrPoseMode* out_mode) {
133 int mode;
134 Transaction trans{*this};
135 Status<int> status =
136 trans.Send<int>(DVR_POSE_GET_MODE, nullptr, 0, &mode, sizeof(mode));
137 ALOGE_IF(!status, "Pose GetPoseMode() failed because: %s",
138 status.GetErrorMessage().c_str());
139 if (status)
140 *out_mode = DvrPoseMode(mode);
141 return ReturnStatusOrError(status);
142 }
143
GetTangoReaderHandle(uint64_t data_type,ConsumerQueue ** queue_out)144 int GetTangoReaderHandle(uint64_t data_type, ConsumerQueue** queue_out) {
145 // Get buffer.
146 Transaction trans{*this};
147 Status<LocalChannelHandle> status = trans.Send<LocalChannelHandle>(
148 DVR_POSE_GET_TANGO_READER, &data_type, sizeof(data_type), nullptr, 0);
149
150 if (!status) {
151 ALOGE("PoseClient GetTangoReaderHandle() failed because: %s",
152 status.GetErrorMessage().c_str());
153 *queue_out = nullptr;
154 return -status.error();
155 }
156
157 std::unique_ptr<ConsumerQueue> consumer_queue =
158 ConsumerQueue::Import(status.take());
159 *queue_out = consumer_queue.release();
160 return 0;
161 }
162
DataCapture(const DvrPoseDataCaptureRequest * request)163 int DataCapture(const DvrPoseDataCaptureRequest* request) {
164 Transaction trans{*this};
165 Status<int> status = trans.Send<int>(DVR_POSE_DATA_CAPTURE, request,
166 sizeof(*request), nullptr, 0);
167 ALOGE_IF(!status, "PoseClient DataCapture() failed because: %s\n",
168 status.GetErrorMessage().c_str());
169 return ReturnStatusOrError(status);
170 }
171
DataReaderDestroy(uint64_t data_type)172 int DataReaderDestroy(uint64_t data_type) {
173 Transaction trans{*this};
174 Status<int> status = trans.Send<int>(DVR_POSE_TANGO_READER_DESTROY,
175 &data_type, sizeof(data_type), nullptr,
176 0);
177 ALOGE_IF(!status, "PoseClient DataReaderDestroy() failed because: %s\n",
178 status.GetErrorMessage().c_str());
179 return ReturnStatusOrError(status);
180 }
181
182 // Enables or disables all pose processing from sensors
EnableSensors(bool enabled)183 int EnableSensors(bool enabled) {
184 Transaction trans{*this};
185 Status<int> status = trans.Send<int>(DVR_POSE_SENSORS_ENABLE, &enabled,
186 sizeof(enabled), nullptr, 0);
187 ALOGE_IF(!status, "Pose EnableSensors() failed because: %s\n",
188 status.GetErrorMessage().c_str());
189 return ReturnStatusOrError(status);
190 }
191
GetRingBuffer(DvrPoseRingBufferInfo * out_info)192 int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
193 // First time mapping the buffer?
194 const auto vsync_buffer = GetVsyncBuffer();
195 if (vsync_buffer) {
196 if (out_info) {
197 out_info->min_future_count = DvrVsyncPoseBuffer::kMinFutureCount;
198 out_info->total_count = DvrVsyncPoseBuffer::kSize;
199 out_info->buffer = vsync_buffer->vsync_poses;
200 }
201 return -EINVAL;
202 }
203
204 return -EAGAIN;
205 }
206
GetControllerRingBuffer(int32_t controller_id)207 int GetControllerRingBuffer(int32_t controller_id) {
208 if (controller_id < 0 || controller_id >= MAX_CONTROLLERS) {
209 return -EINVAL;
210 }
211 ControllerClientState& client_state = controllers_[controller_id];
212 if (client_state.pose_buffer.get()) {
213 return 0;
214 }
215
216 Transaction trans{*this};
217 Status<LocalChannelHandle> status = trans.Send<LocalChannelHandle>(
218 DVR_POSE_GET_CONTROLLER_RING_BUFFER, &controller_id,
219 sizeof(controller_id), nullptr, 0);
220 if (!status) {
221 return -status.error();
222 }
223
224 auto buffer = BufferConsumer::Import(status.take());
225 if (!buffer) {
226 ALOGE("Pose failed to import ring buffer");
227 return -EIO;
228 }
229 constexpr size_t size = DvrVsyncPoseBuffer::kSize * sizeof(DvrPoseAsync);
230 void* addr = nullptr;
231 int ret = buffer->GetBlobReadOnlyPointer(size, &addr);
232 if (ret < 0 || !addr) {
233 ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
234 return -EIO;
235 }
236 client_state.pose_buffer.swap(buffer);
237 client_state.mapped_pose_buffer = static_cast<const DvrPoseAsync*>(addr);
238 ALOGI(
239 "Mapped controller %d pose data translation %f,%f,%f quat %f,%f,%f,%f",
240 controller_id, client_state.mapped_pose_buffer[0].position[0],
241 client_state.mapped_pose_buffer[0].position[1],
242 client_state.mapped_pose_buffer[0].position[2],
243 client_state.mapped_pose_buffer[0].orientation[0],
244 client_state.mapped_pose_buffer[0].orientation[1],
245 client_state.mapped_pose_buffer[0].orientation[2],
246 client_state.mapped_pose_buffer[0].orientation[3]);
247 return 0;
248 }
249
250 private:
251 friend BASE;
252
253 // Set up a channel to the pose service.
PoseClient()254 PoseClient()
255 : BASE(pdx::default_transport::ClientChannelFactory::Create(
256 DVR_POSE_SERVICE_CLIENT)) {
257 // TODO(eieio): Cache the pose and make timeout 0 so that the API doesn't
258 // block while waiting for the pose service to come back up.
259 EnableAutoReconnect(kInfiniteTimeout);
260 }
261
262 PoseClient(const PoseClient&) = delete;
263 PoseClient& operator=(const PoseClient&) = delete;
264
GetVsyncBuffer()265 const DvrVsyncPoseBuffer* GetVsyncBuffer() {
266 if (mapped_vsync_pose_buffer_ == nullptr) {
267 if (vsync_pose_buffer_ == nullptr) {
268 // The constructor tries mapping it so we do not need TryMapping after.
269 vsync_pose_buffer_ = std::make_unique<CPUMappedBuffer>(
270 DvrGlobalBuffers::kVsyncPoseBuffer, CPUUsageMode::READ_OFTEN);
271 } else if (vsync_pose_buffer_->IsMapped() == false) {
272 vsync_pose_buffer_->TryMapping();
273 }
274
275 if (vsync_pose_buffer_->IsMapped()) {
276 mapped_vsync_pose_buffer_ =
277 static_cast<DvrVsyncPoseBuffer*>(vsync_pose_buffer_->Address());
278 }
279 }
280
281 return mapped_vsync_pose_buffer_;
282 }
283
284 // The vsync pose buffer if already mapped.
285 std::unique_ptr<CPUMappedBuffer> vsync_pose_buffer_;
286
287 // The direct sensor pose buffer.
288 std::unique_ptr<SensorPoseRing> sensor_pose_buffer_;
289
290 const DvrVsyncPoseBuffer* mapped_vsync_pose_buffer_ = nullptr;
291
292 struct ControllerClientState {
293 std::unique_ptr<BufferConsumer> pose_buffer;
294 const DvrPoseAsync* mapped_pose_buffer = nullptr;
295 };
296 ControllerClientState controllers_[MAX_CONTROLLERS];
297 };
298
dvrPoseClientGetDataReaderHandle(DvrPoseClient * client,uint64_t type,ConsumerQueue ** queue_out)299 int dvrPoseClientGetDataReaderHandle(DvrPoseClient* client, uint64_t type,
300 ConsumerQueue** queue_out) {
301 return PoseClient::FromC(client)->GetTangoReaderHandle(type, queue_out);
302 }
303
304 } // namespace dvr
305 } // namespace android
306
307 using android::dvr::PoseClient;
308
309 extern "C" {
310
dvrPoseClientCreate()311 DvrPoseClient* dvrPoseClientCreate() {
312 auto* client = PoseClient::Create().release();
313 return reinterpret_cast<DvrPoseClient*>(client);
314 }
315
dvrPoseClientDestroy(DvrPoseClient * client)316 void dvrPoseClientDestroy(DvrPoseClient* client) {
317 delete PoseClient::FromC(client);
318 }
319
dvrPoseClientGet(DvrPoseClient * client,uint32_t vsync_count,DvrPoseAsync * out_pose)320 int dvrPoseClientGet(DvrPoseClient* client, uint32_t vsync_count,
321 DvrPoseAsync* out_pose) {
322 return PoseClient::FromC(client)->GetPose(vsync_count, out_pose);
323 }
324
dvrPoseClientGetVsyncCount(DvrPoseClient * client)325 uint32_t dvrPoseClientGetVsyncCount(DvrPoseClient* client) {
326 return PoseClient::FromC(client)->GetVsyncCount();
327 }
328
dvrPoseClientGetController(DvrPoseClient * client,int32_t controller_id,uint32_t vsync_count,DvrPoseAsync * out_pose)329 int dvrPoseClientGetController(DvrPoseClient* client, int32_t controller_id,
330 uint32_t vsync_count, DvrPoseAsync* out_pose) {
331 return PoseClient::FromC(client)->GetControllerPose(controller_id,
332 vsync_count, out_pose);
333 }
334
dvrPoseClientLogController(DvrPoseClient * client,bool enable)335 int dvrPoseClientLogController(DvrPoseClient* client, bool enable) {
336 return PoseClient::FromC(client)->LogController(enable);
337 }
338
dvrPoseClientPoll(DvrPoseClient * client,DvrPose * state)339 int dvrPoseClientPoll(DvrPoseClient* client, DvrPose* state) {
340 return PoseClient::FromC(client)->Poll(state);
341 }
342
dvrPoseClientFreeze(DvrPoseClient * client,const DvrPose * frozen_state)343 int dvrPoseClientFreeze(DvrPoseClient* client, const DvrPose* frozen_state) {
344 return PoseClient::FromC(client)->Freeze(*frozen_state);
345 }
346
dvrPoseClientModeSet(DvrPoseClient * client,DvrPoseMode mode)347 int dvrPoseClientModeSet(DvrPoseClient* client, DvrPoseMode mode) {
348 return PoseClient::FromC(client)->SetMode(mode);
349 }
350
dvrPoseClientModeGet(DvrPoseClient * client,DvrPoseMode * mode)351 int dvrPoseClientModeGet(DvrPoseClient* client, DvrPoseMode* mode) {
352 return PoseClient::FromC(client)->GetMode(mode);
353 }
354
dvrPoseClientSensorsEnable(DvrPoseClient * client,bool enabled)355 int dvrPoseClientSensorsEnable(DvrPoseClient* client, bool enabled) {
356 return PoseClient::FromC(client)->EnableSensors(enabled);
357 }
358
dvrPoseClientDataCapture(DvrPoseClient * client,const DvrPoseDataCaptureRequest * request)359 int dvrPoseClientDataCapture(DvrPoseClient* client,
360 const DvrPoseDataCaptureRequest* request) {
361 return PoseClient::FromC(client)->DataCapture(request);
362 }
363
dvrPoseClientDataReaderDestroy(DvrPoseClient * client,uint64_t data_type)364 int dvrPoseClientDataReaderDestroy(DvrPoseClient* client, uint64_t data_type) {
365 return PoseClient::FromC(client)->DataReaderDestroy(data_type);
366 }
367
368 } // extern "C"
369