1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define LOG_TAG "PoseClient"
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <dvr/pose_client.h>
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <stdint.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
64fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko#include <log/log.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/client.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/default_transport/client_channel_factory.h>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/file_handle.h>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/buffer_hub_client.h>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/pose-ipc.h>
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/pose_client_internal.h>
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/sensor_constants.h>
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalHandle;
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalChannelHandle;
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Status;
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Transaction;
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
204fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko#define arraysize(x) (static_cast<int32_t>(std::extent<decltype(x)>::value))
214fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace dvr {
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// PoseClient is a remote interface to the pose service in sensord.
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass PoseClient : public pdx::ClientBase<PoseClient> {
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ~PoseClient() override {}
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Casts C handle into an instance of this class.
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static PoseClient* FromC(DvrPose* client) {
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return reinterpret_cast<PoseClient*>(client);
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Polls the pose service for the current state and stores it in *state.
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns zero on success, a negative error code otherwise.
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Poll(DvrPoseState* state) {
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Status<int> status =
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        trans.Send<int>(DVR_POSE_POLL, nullptr, 0, state, sizeof(*state));
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE_IF(!status, "Pose poll() failed because: %s\n",
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko             status.GetErrorMessage().c_str());
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(status);
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetPose(uint32_t vsync_count, DvrPoseAsync* out_pose) {
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!mapped_pose_buffer_) {
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      int ret = GetRingBuffer(nullptr);
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (ret < 0)
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        return ret;
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *out_pose =
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        mapped_pose_buffer_->ring[vsync_count & kPoseAsyncBufferIndexMask];
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint32_t GetVsyncCount() {
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!mapped_pose_buffer_) {
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      int ret = GetRingBuffer(nullptr);
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (ret < 0)
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        return 0;
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return mapped_pose_buffer_->vsync_count;
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetControllerPose(int32_t controller_id, uint32_t vsync_count,
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                        DvrPoseAsync* out_pose) {
684fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko    if (controller_id < 0 || controller_id >= arraysize(controllers_)) {
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -EINVAL;
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!controllers_[controller_id].mapped_pose_buffer) {
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      int ret = GetControllerRingBuffer(controller_id);
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (ret < 0)
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        return ret;
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *out_pose =
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        controllers_[controller_id]
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            .mapped_pose_buffer[vsync_count & kPoseAsyncBufferIndexMask];
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int LogController(bool enable) {
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Status<int> status = trans.Send<int>(DVR_POSE_LOG_CONTROLLER, &enable,
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                         sizeof(enable), nullptr, 0);
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE_IF(!status, "Pose LogController() failed because: %s",
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko             status.GetErrorMessage().c_str());
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(status);
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Freezes the pose to the provided state. Future poll operations will return
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // this state until a different state is frozen or SetMode() is called with a
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // different mode.
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns zero on success, a negative error code otherwise.
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Freeze(const DvrPoseState& frozen_state) {
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Status<int> status = trans.Send<int>(DVR_POSE_FREEZE, &frozen_state,
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                         sizeof(frozen_state), nullptr, 0);
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE_IF(!status, "Pose Freeze() failed because: %s\n",
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko             status.GetErrorMessage().c_str());
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(status);
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Sets the data mode for the pose service.
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int SetMode(DvrPoseMode mode) {
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Status<int> status =
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        trans.Send<int>(DVR_POSE_SET_MODE, &mode, sizeof(mode), nullptr, 0);
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE_IF(!status, "Pose SetPoseMode() failed because: %s",
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko             status.GetErrorMessage().c_str());
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(status);
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Gets the data mode for the pose service.
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetMode(DvrPoseMode* out_mode) {
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    int mode;
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Status<int> status =
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        trans.Send<int>(DVR_POSE_GET_MODE, nullptr, 0, &mode, sizeof(mode));
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE_IF(!status, "Pose GetPoseMode() failed because: %s",
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko             status.GetErrorMessage().c_str());
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (status)
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *out_mode = DvrPoseMode(mode);
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(status);
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (pose_buffer_.get()) {
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (out_info) {
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        GetPoseRingBufferInfo(out_info);
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return 0;
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Status<LocalChannelHandle> status =
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        trans.Send<LocalChannelHandle>(DVR_POSE_GET_RING_BUFFER);
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!status) {
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGE("Pose GetRingBuffer() failed because: %s",
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            status.GetErrorMessage().c_str());
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -status.error();
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto buffer = BufferConsumer::Import(status.take());
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!buffer) {
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGE("Pose failed to import ring buffer");
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -EIO;
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* addr = nullptr;
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    int ret = buffer->GetBlobReadOnlyPointer(sizeof(DvrPoseRingBuffer), &addr);
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (ret < 0 || !addr) {
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -EIO;
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    pose_buffer_.swap(buffer);
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    mapped_pose_buffer_ = static_cast<const DvrPoseRingBuffer*>(addr);
1574fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko    ALOGI("Mapped pose data translation %f,%f,%f quat %f,%f,%f,%f",
1584fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko          mapped_pose_buffer_->ring[0].translation[0],
1594fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko          mapped_pose_buffer_->ring[0].translation[1],
1604fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko          mapped_pose_buffer_->ring[0].translation[2],
1614fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko          mapped_pose_buffer_->ring[0].orientation[0],
1624fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko          mapped_pose_buffer_->ring[0].orientation[1],
1634fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko          mapped_pose_buffer_->ring[0].orientation[2],
1644fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko          mapped_pose_buffer_->ring[0].orientation[3]);
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (out_info) {
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      GetPoseRingBufferInfo(out_info);
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetControllerRingBuffer(int32_t controller_id) {
1724fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko    if (controller_id < 0 || controller_id >= arraysize(controllers_)) {
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -EINVAL;
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ControllerClientState& client_state = controllers_[controller_id];
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (client_state.pose_buffer.get()) {
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return 0;
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Status<LocalChannelHandle> status = trans.Send<LocalChannelHandle>(
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        DVR_POSE_GET_CONTROLLER_RING_BUFFER, &controller_id,
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        sizeof(controller_id), nullptr, 0);
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!status) {
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -status.error();
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto buffer = BufferConsumer::Import(status.take());
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!buffer) {
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGE("Pose failed to import ring buffer");
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -EIO;
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    constexpr size_t size = kPoseAsyncBufferTotalCount * sizeof(DvrPoseAsync);
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* addr = nullptr;
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    int ret = buffer->GetBlobReadOnlyPointer(size, &addr);
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (ret < 0 || !addr) {
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -EIO;
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    client_state.pose_buffer.swap(buffer);
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    client_state.mapped_pose_buffer = static_cast<const DvrPoseAsync*>(addr);
2024fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko    ALOGI(
2034fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko        "Mapped controller %d pose data translation %f,%f,%f quat %f,%f,%f,%f",
2044fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko        controller_id, client_state.mapped_pose_buffer[0].translation[0],
2054fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko        client_state.mapped_pose_buffer[0].translation[1],
2064fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko        client_state.mapped_pose_buffer[0].translation[2],
2074fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko        client_state.mapped_pose_buffer[0].orientation[0],
2084fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko        client_state.mapped_pose_buffer[0].orientation[1],
2094fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko        client_state.mapped_pose_buffer[0].orientation[2],
2104fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko        client_state.mapped_pose_buffer[0].orientation[3]);
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int NotifyVsync(uint32_t vsync_count, int64_t display_timestamp,
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                  int64_t display_period_ns,
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                  int64_t right_eye_photon_offset_ns) {
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const struct iovec data[] = {
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        {.iov_base = &vsync_count, .iov_len = sizeof(vsync_count)},
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        {.iov_base = &display_timestamp, .iov_len = sizeof(display_timestamp)},
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        {.iov_base = &display_period_ns, .iov_len = sizeof(display_period_ns)},
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        {.iov_base = &right_eye_photon_offset_ns,
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko         .iov_len = sizeof(right_eye_photon_offset_ns)},
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    };
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Status<int> status =
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        trans.SendVector<int>(DVR_POSE_NOTIFY_VSYNC, data, nullptr);
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE_IF(!status, "Pose NotifyVsync() failed because: %s\n",
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko             status.GetErrorMessage().c_str());
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(status);
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetRingBufferFd(LocalHandle* fd) {
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    int ret = GetRingBuffer(nullptr);
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (ret < 0)
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return ret;
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *fd = pose_buffer_->GetBlobFd();
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend BASE;
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Set up a channel to the pose service.
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PoseClient()
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      : BASE(pdx::default_transport::ClientChannelFactory::Create(
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            DVR_POSE_SERVICE_CLIENT)) {
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // TODO(eieio): Cache the pose and make timeout 0 so that the API doesn't
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // block while waiting for the pose service to come back up.
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    EnableAutoReconnect(kInfiniteTimeout);
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PoseClient(const PoseClient&) = delete;
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PoseClient& operator=(const PoseClient&) = delete;
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void GetPoseRingBufferInfo(DvrPoseRingBufferInfo* out_info) const {
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    out_info->min_future_count = kPoseAsyncBufferMinFutureCount;
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    out_info->total_count = kPoseAsyncBufferTotalCount;
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    out_info->buffer = mapped_pose_buffer_->ring;
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::unique_ptr<BufferConsumer> pose_buffer_;
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const DvrPoseRingBuffer* mapped_pose_buffer_ = nullptr;
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  struct ControllerClientState {
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::unique_ptr<BufferConsumer> pose_buffer;
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const DvrPoseAsync* mapped_pose_buffer = nullptr;
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  };
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ControllerClientState controllers_[2];
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace dvr
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::dvr::PoseClient;
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct DvrPose {};
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoextern "C" {
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoDvrPose* dvrPoseCreate() {
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PoseClient* client = PoseClient::Create().release();
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return reinterpret_cast<DvrPose*>(client);
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid dvrPoseDestroy(DvrPose* client) { delete PoseClient::FromC(client); }
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose) {
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->GetPose(vsync_count, out_pose);
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkouint32_t dvrPoseGetVsyncCount(DvrPose* client) {
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->GetVsyncCount();
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint dvrPoseGetController(DvrPose* client, int32_t controller_id,
296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                         uint32_t vsync_count, DvrPoseAsync* out_pose) {
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->GetControllerPose(controller_id,
298e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                      vsync_count, out_pose);
299e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
300e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
301e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint dvrPoseLogController(DvrPose* client, bool enable) {
302e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->LogController(enable);
303e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
304e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
305e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint dvrPosePoll(DvrPose* client, DvrPoseState* state) {
306e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->Poll(state);
307e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
308e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
309e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state) {
310e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->Freeze(*frozen_state);
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
313e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint dvrPoseSetMode(DvrPose* client, DvrPoseMode mode) {
314e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->SetMode(mode);
315e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
316e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
317e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode) {
318e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->GetMode(mode);
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
320e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info) {
322e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->GetRingBuffer(out_info);
323e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
324e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
325e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
326e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                              int64_t display_timestamp,
327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                              int64_t display_period_ns,
328e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                              int64_t right_eye_photon_offset_ns) {
329e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->NotifyVsync(vsync_count, display_timestamp,
330e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                display_period_ns,
331e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                right_eye_photon_offset_ns);
332e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
333e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
334e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint privateDvrPoseGetRingBufferFd(DvrPose* client, LocalHandle* fd) {
335e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return PoseClient::FromC(client)->GetRingBufferFd(fd);
336e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
337e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
338e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // extern "C"
339