1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker #include <media/SensorPoseProvider.h>
18*ec779b8eSAndroid Build Coastguard Worker
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "SensorPoseProvider"
20*ec779b8eSAndroid Build Coastguard Worker
21*ec779b8eSAndroid Build Coastguard Worker #include <algorithm>
22*ec779b8eSAndroid Build Coastguard Worker #include <future>
23*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <limits>
25*ec779b8eSAndroid Build Coastguard Worker #include <map>
26*ec779b8eSAndroid Build Coastguard Worker #include <thread>
27*ec779b8eSAndroid Build Coastguard Worker
28*ec779b8eSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <android-base/thread_annotations.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <log/log_main.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <sensor/SensorEventQueue.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <sensor/SensorManager.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <utils/Looper.h>
34*ec779b8eSAndroid Build Coastguard Worker
35*ec779b8eSAndroid Build Coastguard Worker #include "media/QuaternionUtil.h"
36*ec779b8eSAndroid Build Coastguard Worker
37*ec779b8eSAndroid Build Coastguard Worker namespace android {
38*ec779b8eSAndroid Build Coastguard Worker namespace media {
39*ec779b8eSAndroid Build Coastguard Worker namespace {
40*ec779b8eSAndroid Build Coastguard Worker
41*ec779b8eSAndroid Build Coastguard Worker using android::base::StringAppendF;
42*ec779b8eSAndroid Build Coastguard Worker
43*ec779b8eSAndroid Build Coastguard Worker // Identifier to use for our event queue on the loop.
44*ec779b8eSAndroid Build Coastguard Worker // The number 19 is arbitrary, only useful if using multiple objects on the same looper.
45*ec779b8eSAndroid Build Coastguard Worker // Note: Instead of a fixed number, the SensorEventQueue's fd could be used instead.
46*ec779b8eSAndroid Build Coastguard Worker constexpr int kIdent = 19;
47*ec779b8eSAndroid Build Coastguard Worker
ALooper_to_Looper(ALooper * alooper)48*ec779b8eSAndroid Build Coastguard Worker static inline Looper* ALooper_to_Looper(ALooper* alooper) {
49*ec779b8eSAndroid Build Coastguard Worker return reinterpret_cast<Looper*>(alooper);
50*ec779b8eSAndroid Build Coastguard Worker }
51*ec779b8eSAndroid Build Coastguard Worker
Looper_to_ALooper(Looper * looper)52*ec779b8eSAndroid Build Coastguard Worker static inline ALooper* Looper_to_ALooper(Looper* looper) {
53*ec779b8eSAndroid Build Coastguard Worker return reinterpret_cast<ALooper*>(looper);
54*ec779b8eSAndroid Build Coastguard Worker }
55*ec779b8eSAndroid Build Coastguard Worker
56*ec779b8eSAndroid Build Coastguard Worker /**
57*ec779b8eSAndroid Build Coastguard Worker * RAII-wrapper around SensorEventQueue, which unregisters it on destruction.
58*ec779b8eSAndroid Build Coastguard Worker */
59*ec779b8eSAndroid Build Coastguard Worker class EventQueueGuard {
60*ec779b8eSAndroid Build Coastguard Worker public:
EventQueueGuard(const sp<SensorEventQueue> & queue,Looper * looper)61*ec779b8eSAndroid Build Coastguard Worker EventQueueGuard(const sp<SensorEventQueue>& queue, Looper* looper) : mQueue(queue) {
62*ec779b8eSAndroid Build Coastguard Worker mQueue->looper = Looper_to_ALooper(looper);
63*ec779b8eSAndroid Build Coastguard Worker mQueue->requestAdditionalInfo = false;
64*ec779b8eSAndroid Build Coastguard Worker looper->addFd(mQueue->getFd(), kIdent, ALOOPER_EVENT_INPUT,
65*ec779b8eSAndroid Build Coastguard Worker nullptr /* callback */, nullptr /* data */);
66*ec779b8eSAndroid Build Coastguard Worker }
67*ec779b8eSAndroid Build Coastguard Worker
~EventQueueGuard()68*ec779b8eSAndroid Build Coastguard Worker ~EventQueueGuard() {
69*ec779b8eSAndroid Build Coastguard Worker if (mQueue) {
70*ec779b8eSAndroid Build Coastguard Worker ALooper_to_Looper(mQueue->looper)->removeFd(mQueue->getFd());
71*ec779b8eSAndroid Build Coastguard Worker }
72*ec779b8eSAndroid Build Coastguard Worker }
73*ec779b8eSAndroid Build Coastguard Worker
74*ec779b8eSAndroid Build Coastguard Worker EventQueueGuard(const EventQueueGuard&) = delete;
75*ec779b8eSAndroid Build Coastguard Worker EventQueueGuard& operator=(const EventQueueGuard&) = delete;
76*ec779b8eSAndroid Build Coastguard Worker
get() const77*ec779b8eSAndroid Build Coastguard Worker [[nodiscard]] SensorEventQueue* get() const { return mQueue.get(); }
78*ec779b8eSAndroid Build Coastguard Worker
79*ec779b8eSAndroid Build Coastguard Worker private:
80*ec779b8eSAndroid Build Coastguard Worker const sp<SensorEventQueue> mQueue;
81*ec779b8eSAndroid Build Coastguard Worker };
82*ec779b8eSAndroid Build Coastguard Worker
83*ec779b8eSAndroid Build Coastguard Worker /**
84*ec779b8eSAndroid Build Coastguard Worker * RAII-wrapper around an enabled sensor, which disables it upon destruction.
85*ec779b8eSAndroid Build Coastguard Worker */
86*ec779b8eSAndroid Build Coastguard Worker class SensorEnableGuard {
87*ec779b8eSAndroid Build Coastguard Worker public:
SensorEnableGuard(const sp<SensorEventQueue> & queue,int32_t sensor)88*ec779b8eSAndroid Build Coastguard Worker SensorEnableGuard(const sp<SensorEventQueue>& queue, int32_t sensor)
89*ec779b8eSAndroid Build Coastguard Worker : mQueue(queue), mSensor(sensor) {}
90*ec779b8eSAndroid Build Coastguard Worker
~SensorEnableGuard()91*ec779b8eSAndroid Build Coastguard Worker ~SensorEnableGuard() {
92*ec779b8eSAndroid Build Coastguard Worker if (mSensor != SensorPoseProvider::INVALID_HANDLE) {
93*ec779b8eSAndroid Build Coastguard Worker int ret = mQueue->disableSensor(mSensor);
94*ec779b8eSAndroid Build Coastguard Worker if (ret) {
95*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to disable sensor: %s", strerror(ret));
96*ec779b8eSAndroid Build Coastguard Worker }
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker }
99*ec779b8eSAndroid Build Coastguard Worker
100*ec779b8eSAndroid Build Coastguard Worker // Enable move and delete default copy-ctor/copy-assignment.
SensorEnableGuard(SensorEnableGuard && other)101*ec779b8eSAndroid Build Coastguard Worker SensorEnableGuard(SensorEnableGuard&& other) : mQueue(other.mQueue), mSensor(other.mSensor) {
102*ec779b8eSAndroid Build Coastguard Worker other.mSensor = SensorPoseProvider::INVALID_HANDLE;
103*ec779b8eSAndroid Build Coastguard Worker }
104*ec779b8eSAndroid Build Coastguard Worker
105*ec779b8eSAndroid Build Coastguard Worker private:
106*ec779b8eSAndroid Build Coastguard Worker sp<SensorEventQueue> const mQueue;
107*ec779b8eSAndroid Build Coastguard Worker int32_t mSensor;
108*ec779b8eSAndroid Build Coastguard Worker };
109*ec779b8eSAndroid Build Coastguard Worker
110*ec779b8eSAndroid Build Coastguard Worker /**
111*ec779b8eSAndroid Build Coastguard Worker * Streams the required events to a PoseListener, based on events originating from the Sensor stack.
112*ec779b8eSAndroid Build Coastguard Worker */
113*ec779b8eSAndroid Build Coastguard Worker class SensorPoseProviderImpl : public SensorPoseProvider {
114*ec779b8eSAndroid Build Coastguard Worker public:
create(const char * packageName,Listener * listener)115*ec779b8eSAndroid Build Coastguard Worker static std::unique_ptr<SensorPoseProvider> create(const char* packageName, Listener* listener) {
116*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<SensorPoseProviderImpl> result(
117*ec779b8eSAndroid Build Coastguard Worker new SensorPoseProviderImpl(packageName, listener));
118*ec779b8eSAndroid Build Coastguard Worker return result->waitInitFinished() ? std::move(result) : nullptr;
119*ec779b8eSAndroid Build Coastguard Worker }
120*ec779b8eSAndroid Build Coastguard Worker
~SensorPoseProviderImpl()121*ec779b8eSAndroid Build Coastguard Worker ~SensorPoseProviderImpl() override {
122*ec779b8eSAndroid Build Coastguard Worker // Disable all active sensors.
123*ec779b8eSAndroid Build Coastguard Worker mEnabledSensors.clear();
124*ec779b8eSAndroid Build Coastguard Worker mQuit = true;
125*ec779b8eSAndroid Build Coastguard Worker mLooper->wake();
126*ec779b8eSAndroid Build Coastguard Worker mThread.join();
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker
startSensor(int32_t sensor,std::chrono::microseconds samplingPeriod)129*ec779b8eSAndroid Build Coastguard Worker bool startSensor(int32_t sensor, std::chrono::microseconds samplingPeriod) override {
130*ec779b8eSAndroid Build Coastguard Worker // Figure out the sensor's data format.
131*ec779b8eSAndroid Build Coastguard Worker DataFormat format = getSensorFormat(sensor);
132*ec779b8eSAndroid Build Coastguard Worker if (format == DataFormat::kUnknown) {
133*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Unknown format for sensor %" PRId32, __func__, sensor);
134*ec779b8eSAndroid Build Coastguard Worker return false;
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker
137*ec779b8eSAndroid Build Coastguard Worker {
138*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lock(mMutex);
139*ec779b8eSAndroid Build Coastguard Worker mEnabledSensorsExtra.emplace(
140*ec779b8eSAndroid Build Coastguard Worker sensor,
141*ec779b8eSAndroid Build Coastguard Worker SensorExtra{.format = format,
142*ec779b8eSAndroid Build Coastguard Worker .samplingPeriod = static_cast<int32_t>(samplingPeriod.count())});
143*ec779b8eSAndroid Build Coastguard Worker }
144*ec779b8eSAndroid Build Coastguard Worker
145*ec779b8eSAndroid Build Coastguard Worker // Enable the sensor.
146*ec779b8eSAndroid Build Coastguard Worker if (mQueue->enableSensor(sensor, samplingPeriod.count(), 0, 0)) {
147*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Failed to enable sensor %" PRId32, __func__, sensor);
148*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lock(mMutex);
149*ec779b8eSAndroid Build Coastguard Worker mEnabledSensorsExtra.erase(sensor);
150*ec779b8eSAndroid Build Coastguard Worker return false;
151*ec779b8eSAndroid Build Coastguard Worker }
152*ec779b8eSAndroid Build Coastguard Worker
153*ec779b8eSAndroid Build Coastguard Worker mEnabledSensors.emplace(sensor, SensorEnableGuard(mQueue, sensor));
154*ec779b8eSAndroid Build Coastguard Worker ALOGD("%s: Sensor %" PRId32 " started", __func__, sensor);
155*ec779b8eSAndroid Build Coastguard Worker return true;
156*ec779b8eSAndroid Build Coastguard Worker }
157*ec779b8eSAndroid Build Coastguard Worker
stopSensor(int handle)158*ec779b8eSAndroid Build Coastguard Worker void stopSensor(int handle) override {
159*ec779b8eSAndroid Build Coastguard Worker ALOGD("%s: Sensor %" PRId32 " stopped", __func__, handle);
160*ec779b8eSAndroid Build Coastguard Worker mEnabledSensors.erase(handle);
161*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lock(mMutex);
162*ec779b8eSAndroid Build Coastguard Worker mEnabledSensorsExtra.erase(handle);
163*ec779b8eSAndroid Build Coastguard Worker }
164*ec779b8eSAndroid Build Coastguard Worker
toString(unsigned level)165*ec779b8eSAndroid Build Coastguard Worker std::string toString(unsigned level) override {
166*ec779b8eSAndroid Build Coastguard Worker std::string prefixSpace(level, ' ');
167*ec779b8eSAndroid Build Coastguard Worker std::string ss = prefixSpace + "SensorPoseProvider:\n";
168*ec779b8eSAndroid Build Coastguard Worker bool needUnlock = false;
169*ec779b8eSAndroid Build Coastguard Worker
170*ec779b8eSAndroid Build Coastguard Worker prefixSpace += " ";
171*ec779b8eSAndroid Build Coastguard Worker auto now = std::chrono::steady_clock::now();
172*ec779b8eSAndroid Build Coastguard Worker if (!mMutex.try_lock_until(now + media::kSpatializerDumpSysTimeOutInSecond)) {
173*ec779b8eSAndroid Build Coastguard Worker ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
174*ec779b8eSAndroid Build Coastguard Worker } else {
175*ec779b8eSAndroid Build Coastguard Worker needUnlock = true;
176*ec779b8eSAndroid Build Coastguard Worker }
177*ec779b8eSAndroid Build Coastguard Worker
178*ec779b8eSAndroid Build Coastguard Worker // Enabled sensor information
179*ec779b8eSAndroid Build Coastguard Worker StringAppendF(&ss, "%sSensors total number %zu:\n", prefixSpace.c_str(),
180*ec779b8eSAndroid Build Coastguard Worker mEnabledSensorsExtra.size());
181*ec779b8eSAndroid Build Coastguard Worker for (auto sensor : mEnabledSensorsExtra) {
182*ec779b8eSAndroid Build Coastguard Worker StringAppendF(&ss,
183*ec779b8eSAndroid Build Coastguard Worker "%s[Handle: 0x%08x, Format %s Period (set %d max %0.4f min %0.4f) ms",
184*ec779b8eSAndroid Build Coastguard Worker prefixSpace.c_str(), sensor.first, toString(sensor.second.format).c_str(),
185*ec779b8eSAndroid Build Coastguard Worker sensor.second.samplingPeriod, media::nsToFloatMs(sensor.second.maxPeriod),
186*ec779b8eSAndroid Build Coastguard Worker media::nsToFloatMs(sensor.second.minPeriod));
187*ec779b8eSAndroid Build Coastguard Worker if (sensor.second.discontinuityCount.has_value()) {
188*ec779b8eSAndroid Build Coastguard Worker StringAppendF(&ss, ", DiscontinuityCount: %d",
189*ec779b8eSAndroid Build Coastguard Worker sensor.second.discontinuityCount.value());
190*ec779b8eSAndroid Build Coastguard Worker }
191*ec779b8eSAndroid Build Coastguard Worker ss += "]\n";
192*ec779b8eSAndroid Build Coastguard Worker }
193*ec779b8eSAndroid Build Coastguard Worker
194*ec779b8eSAndroid Build Coastguard Worker if (needUnlock) {
195*ec779b8eSAndroid Build Coastguard Worker mMutex.unlock();
196*ec779b8eSAndroid Build Coastguard Worker }
197*ec779b8eSAndroid Build Coastguard Worker return ss;
198*ec779b8eSAndroid Build Coastguard Worker }
199*ec779b8eSAndroid Build Coastguard Worker
200*ec779b8eSAndroid Build Coastguard Worker private:
201*ec779b8eSAndroid Build Coastguard Worker enum DataFormat {
202*ec779b8eSAndroid Build Coastguard Worker kUnknown,
203*ec779b8eSAndroid Build Coastguard Worker kQuaternion,
204*ec779b8eSAndroid Build Coastguard Worker kRotationVectorsAndDiscontinuityCount,
205*ec779b8eSAndroid Build Coastguard Worker };
206*ec779b8eSAndroid Build Coastguard Worker
207*ec779b8eSAndroid Build Coastguard Worker struct PoseEvent {
208*ec779b8eSAndroid Build Coastguard Worker Pose3f pose;
209*ec779b8eSAndroid Build Coastguard Worker std::optional<Twist3f> twist;
210*ec779b8eSAndroid Build Coastguard Worker bool isNewReference;
211*ec779b8eSAndroid Build Coastguard Worker };
212*ec779b8eSAndroid Build Coastguard Worker
213*ec779b8eSAndroid Build Coastguard Worker struct SensorExtra {
214*ec779b8eSAndroid Build Coastguard Worker DataFormat format = DataFormat::kUnknown;
215*ec779b8eSAndroid Build Coastguard Worker int32_t samplingPeriod = 0;
216*ec779b8eSAndroid Build Coastguard Worker int64_t latestTimestamp = 0;
217*ec779b8eSAndroid Build Coastguard Worker int64_t maxPeriod = 0;
218*ec779b8eSAndroid Build Coastguard Worker int64_t minPeriod = std::numeric_limits<int64_t>::max();
219*ec779b8eSAndroid Build Coastguard Worker std::optional<int32_t> discontinuityCount;
220*ec779b8eSAndroid Build Coastguard Worker };
221*ec779b8eSAndroid Build Coastguard Worker
222*ec779b8eSAndroid Build Coastguard Worker bool mQuit = false;
223*ec779b8eSAndroid Build Coastguard Worker sp<Looper> mLooper;
224*ec779b8eSAndroid Build Coastguard Worker Listener* const mListener;
225*ec779b8eSAndroid Build Coastguard Worker SensorManager* const mSensorManager;
226*ec779b8eSAndroid Build Coastguard Worker std::timed_mutex mMutex;
227*ec779b8eSAndroid Build Coastguard Worker sp<SensorEventQueue> mQueue;
228*ec779b8eSAndroid Build Coastguard Worker std::map<int32_t, SensorEnableGuard> mEnabledSensors;
229*ec779b8eSAndroid Build Coastguard Worker std::map<int32_t, SensorExtra> mEnabledSensorsExtra GUARDED_BY(mMutex);
230*ec779b8eSAndroid Build Coastguard Worker
231*ec779b8eSAndroid Build Coastguard Worker // We must do some of the initialization operations on the worker thread, because the API relies
232*ec779b8eSAndroid Build Coastguard Worker // on the thread-local looper. In addition, as a matter of convenience, we store some of the
233*ec779b8eSAndroid Build Coastguard Worker // state on the stack.
234*ec779b8eSAndroid Build Coastguard Worker // For that reason, we use a two-step initialization approach, where the ctor mostly just starts
235*ec779b8eSAndroid Build Coastguard Worker // the worker thread and that thread would notify, via the promise below whenever initialization
236*ec779b8eSAndroid Build Coastguard Worker // is finished, and whether it was successful.
237*ec779b8eSAndroid Build Coastguard Worker std::promise<bool> mInitPromise;
238*ec779b8eSAndroid Build Coastguard Worker std::thread mThread;
239*ec779b8eSAndroid Build Coastguard Worker
SensorPoseProviderImpl(const char * packageName,Listener * listener)240*ec779b8eSAndroid Build Coastguard Worker SensorPoseProviderImpl(const char* packageName, Listener* listener)
241*ec779b8eSAndroid Build Coastguard Worker : mListener(listener),
242*ec779b8eSAndroid Build Coastguard Worker mSensorManager(&SensorManager::getInstanceForPackage(String16(packageName))) {
243*ec779b8eSAndroid Build Coastguard Worker mThread = std::thread([this] { threadFunc(); });
244*ec779b8eSAndroid Build Coastguard Worker }
initFinished(bool success)245*ec779b8eSAndroid Build Coastguard Worker void initFinished(bool success) { mInitPromise.set_value(success); }
246*ec779b8eSAndroid Build Coastguard Worker
waitInitFinished()247*ec779b8eSAndroid Build Coastguard Worker bool waitInitFinished() { return mInitPromise.get_future().get(); }
248*ec779b8eSAndroid Build Coastguard Worker
threadFunc()249*ec779b8eSAndroid Build Coastguard Worker void threadFunc() {
250*ec779b8eSAndroid Build Coastguard Worker // Name our std::thread to help identification. As is, canCallJava == false.
251*ec779b8eSAndroid Build Coastguard Worker androidSetThreadName("SensorPoseProvider-looper");
252*ec779b8eSAndroid Build Coastguard Worker
253*ec779b8eSAndroid Build Coastguard Worker // Run at the highest non-realtime priority.
254*ec779b8eSAndroid Build Coastguard Worker androidSetThreadPriority(gettid(), PRIORITY_URGENT_AUDIO);
255*ec779b8eSAndroid Build Coastguard Worker
256*ec779b8eSAndroid Build Coastguard Worker // The looper is started on the created std::thread.
257*ec779b8eSAndroid Build Coastguard Worker mLooper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
258*ec779b8eSAndroid Build Coastguard Worker
259*ec779b8eSAndroid Build Coastguard Worker // Create event queue.
260*ec779b8eSAndroid Build Coastguard Worker mQueue = mSensorManager->createEventQueue();
261*ec779b8eSAndroid Build Coastguard Worker
262*ec779b8eSAndroid Build Coastguard Worker if (mQueue == nullptr) {
263*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to create a sensor event queue");
264*ec779b8eSAndroid Build Coastguard Worker initFinished(false);
265*ec779b8eSAndroid Build Coastguard Worker return;
266*ec779b8eSAndroid Build Coastguard Worker }
267*ec779b8eSAndroid Build Coastguard Worker
268*ec779b8eSAndroid Build Coastguard Worker EventQueueGuard eventQueueGuard(mQueue, mLooper.get());
269*ec779b8eSAndroid Build Coastguard Worker
270*ec779b8eSAndroid Build Coastguard Worker initFinished(true);
271*ec779b8eSAndroid Build Coastguard Worker
272*ec779b8eSAndroid Build Coastguard Worker while (!mQuit) {
273*ec779b8eSAndroid Build Coastguard Worker const int ret = mLooper->pollOnce(-1 /* no timeout */, nullptr /* outFd */,
274*ec779b8eSAndroid Build Coastguard Worker nullptr /* outEvents */, nullptr /* outData */);
275*ec779b8eSAndroid Build Coastguard Worker
276*ec779b8eSAndroid Build Coastguard Worker switch (ret) {
277*ec779b8eSAndroid Build Coastguard Worker case ALOOPER_POLL_WAKE:
278*ec779b8eSAndroid Build Coastguard Worker // Continue to see if mQuit flag is set.
279*ec779b8eSAndroid Build Coastguard Worker // This can be spurious (due to bugreport being taken).
280*ec779b8eSAndroid Build Coastguard Worker continue;
281*ec779b8eSAndroid Build Coastguard Worker
282*ec779b8eSAndroid Build Coastguard Worker case kIdent:
283*ec779b8eSAndroid Build Coastguard Worker // Possible events on our queue.
284*ec779b8eSAndroid Build Coastguard Worker break;
285*ec779b8eSAndroid Build Coastguard Worker
286*ec779b8eSAndroid Build Coastguard Worker default:
287*ec779b8eSAndroid Build Coastguard Worker // Besides WAKE and kIdent, there should be no timeouts, callbacks,
288*ec779b8eSAndroid Build Coastguard Worker // ALOOPER_POLL_ERROR, or other events.
289*ec779b8eSAndroid Build Coastguard Worker // Exit now to avoid high frequency log spam on error,
290*ec779b8eSAndroid Build Coastguard Worker // e.g. if the fd becomes invalid (b/31093485).
291*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Unexpected status out of Looper::pollOnce: %d", __func__, ret);
292*ec779b8eSAndroid Build Coastguard Worker mQuit = true;
293*ec779b8eSAndroid Build Coastguard Worker continue;
294*ec779b8eSAndroid Build Coastguard Worker }
295*ec779b8eSAndroid Build Coastguard Worker
296*ec779b8eSAndroid Build Coastguard Worker // Process an event.
297*ec779b8eSAndroid Build Coastguard Worker ASensorEvent event;
298*ec779b8eSAndroid Build Coastguard Worker ssize_t actual = mQueue->read(&event, 1);
299*ec779b8eSAndroid Build Coastguard Worker if (actual > 0) {
300*ec779b8eSAndroid Build Coastguard Worker mQueue->sendAck(&event, actual);
301*ec779b8eSAndroid Build Coastguard Worker }
302*ec779b8eSAndroid Build Coastguard Worker ssize_t size = mQueue->filterEvents(&event, actual);
303*ec779b8eSAndroid Build Coastguard Worker
304*ec779b8eSAndroid Build Coastguard Worker if (size < 0 || size > 1) {
305*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Unexpected return value from SensorEventQueue::filterEvents: %zd",
306*ec779b8eSAndroid Build Coastguard Worker __func__, size);
307*ec779b8eSAndroid Build Coastguard Worker break;
308*ec779b8eSAndroid Build Coastguard Worker }
309*ec779b8eSAndroid Build Coastguard Worker if (size == 0) {
310*ec779b8eSAndroid Build Coastguard Worker // No events.
311*ec779b8eSAndroid Build Coastguard Worker continue;
312*ec779b8eSAndroid Build Coastguard Worker }
313*ec779b8eSAndroid Build Coastguard Worker
314*ec779b8eSAndroid Build Coastguard Worker handleEvent(event);
315*ec779b8eSAndroid Build Coastguard Worker }
316*ec779b8eSAndroid Build Coastguard Worker ALOGD("%s: Exiting sensor event loop", __func__);
317*ec779b8eSAndroid Build Coastguard Worker }
318*ec779b8eSAndroid Build Coastguard Worker
handleEvent(const ASensorEvent & event)319*ec779b8eSAndroid Build Coastguard Worker void handleEvent(const ASensorEvent& event) {
320*ec779b8eSAndroid Build Coastguard Worker PoseEvent value;
321*ec779b8eSAndroid Build Coastguard Worker {
322*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lock(mMutex);
323*ec779b8eSAndroid Build Coastguard Worker auto iter = mEnabledSensorsExtra.find(event.sensor);
324*ec779b8eSAndroid Build Coastguard Worker if (iter == mEnabledSensorsExtra.end()) {
325*ec779b8eSAndroid Build Coastguard Worker // This can happen if we have any pending events shortly after stopping.
326*ec779b8eSAndroid Build Coastguard Worker return;
327*ec779b8eSAndroid Build Coastguard Worker }
328*ec779b8eSAndroid Build Coastguard Worker value = parseEvent(event, iter->second.format, &iter->second.discontinuityCount);
329*ec779b8eSAndroid Build Coastguard Worker updateEventTimestamp(event, iter->second);
330*ec779b8eSAndroid Build Coastguard Worker }
331*ec779b8eSAndroid Build Coastguard Worker mListener->onPose(event.timestamp, event.sensor, value.pose, value.twist,
332*ec779b8eSAndroid Build Coastguard Worker value.isNewReference);
333*ec779b8eSAndroid Build Coastguard Worker }
334*ec779b8eSAndroid Build Coastguard Worker
getSensorFormat(int32_t handle)335*ec779b8eSAndroid Build Coastguard Worker DataFormat getSensorFormat(int32_t handle) {
336*ec779b8eSAndroid Build Coastguard Worker std::optional<const Sensor> sensor = getSensorByHandle(handle);
337*ec779b8eSAndroid Build Coastguard Worker if (!sensor) {
338*ec779b8eSAndroid Build Coastguard Worker ALOGE("Sensor not found: %d", handle);
339*ec779b8eSAndroid Build Coastguard Worker return DataFormat::kUnknown;
340*ec779b8eSAndroid Build Coastguard Worker }
341*ec779b8eSAndroid Build Coastguard Worker if (sensor->getType() == ASENSOR_TYPE_ROTATION_VECTOR ||
342*ec779b8eSAndroid Build Coastguard Worker sensor->getType() == ASENSOR_TYPE_GAME_ROTATION_VECTOR) {
343*ec779b8eSAndroid Build Coastguard Worker return DataFormat::kQuaternion;
344*ec779b8eSAndroid Build Coastguard Worker }
345*ec779b8eSAndroid Build Coastguard Worker
346*ec779b8eSAndroid Build Coastguard Worker if (sensor->getType() == ASENSOR_TYPE_HEAD_TRACKER) {
347*ec779b8eSAndroid Build Coastguard Worker return DataFormat::kRotationVectorsAndDiscontinuityCount;
348*ec779b8eSAndroid Build Coastguard Worker }
349*ec779b8eSAndroid Build Coastguard Worker
350*ec779b8eSAndroid Build Coastguard Worker return DataFormat::kUnknown;
351*ec779b8eSAndroid Build Coastguard Worker }
352*ec779b8eSAndroid Build Coastguard Worker
getSensorByHandle(int32_t handle)353*ec779b8eSAndroid Build Coastguard Worker std::optional<const Sensor> getSensorByHandle(int32_t handle) override {
354*ec779b8eSAndroid Build Coastguard Worker const Sensor* const* list;
355*ec779b8eSAndroid Build Coastguard Worker ssize_t size;
356*ec779b8eSAndroid Build Coastguard Worker
357*ec779b8eSAndroid Build Coastguard Worker // Search static sensor list.
358*ec779b8eSAndroid Build Coastguard Worker size = mSensorManager->getSensorList(&list);
359*ec779b8eSAndroid Build Coastguard Worker if (size < 0) {
360*ec779b8eSAndroid Build Coastguard Worker ALOGE("getSensorList failed with error code %zd", size);
361*ec779b8eSAndroid Build Coastguard Worker return std::nullopt;
362*ec779b8eSAndroid Build Coastguard Worker }
363*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i) {
364*ec779b8eSAndroid Build Coastguard Worker if (list[i]->getHandle() == handle) {
365*ec779b8eSAndroid Build Coastguard Worker return *list[i];
366*ec779b8eSAndroid Build Coastguard Worker }
367*ec779b8eSAndroid Build Coastguard Worker }
368*ec779b8eSAndroid Build Coastguard Worker
369*ec779b8eSAndroid Build Coastguard Worker // Search dynamic sensor list.
370*ec779b8eSAndroid Build Coastguard Worker Vector<Sensor> dynList;
371*ec779b8eSAndroid Build Coastguard Worker size = mSensorManager->getDynamicSensorList(dynList);
372*ec779b8eSAndroid Build Coastguard Worker if (size < 0) {
373*ec779b8eSAndroid Build Coastguard Worker ALOGE("getDynamicSensorList failed with error code %zd", size);
374*ec779b8eSAndroid Build Coastguard Worker return std::nullopt;
375*ec779b8eSAndroid Build Coastguard Worker }
376*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i) {
377*ec779b8eSAndroid Build Coastguard Worker if (dynList[i].getHandle() == handle) {
378*ec779b8eSAndroid Build Coastguard Worker return dynList[i];
379*ec779b8eSAndroid Build Coastguard Worker }
380*ec779b8eSAndroid Build Coastguard Worker }
381*ec779b8eSAndroid Build Coastguard Worker
382*ec779b8eSAndroid Build Coastguard Worker return std::nullopt;
383*ec779b8eSAndroid Build Coastguard Worker }
384*ec779b8eSAndroid Build Coastguard Worker
updateEventTimestamp(const ASensorEvent & event,SensorExtra & extra)385*ec779b8eSAndroid Build Coastguard Worker void updateEventTimestamp(const ASensorEvent& event, SensorExtra& extra) {
386*ec779b8eSAndroid Build Coastguard Worker if (extra.latestTimestamp != 0) {
387*ec779b8eSAndroid Build Coastguard Worker int64_t gap = event.timestamp - extra.latestTimestamp;
388*ec779b8eSAndroid Build Coastguard Worker extra.maxPeriod = std::max(gap, extra.maxPeriod);
389*ec779b8eSAndroid Build Coastguard Worker extra.minPeriod = std::min(gap, extra.minPeriod);
390*ec779b8eSAndroid Build Coastguard Worker }
391*ec779b8eSAndroid Build Coastguard Worker extra.latestTimestamp = event.timestamp;
392*ec779b8eSAndroid Build Coastguard Worker }
393*ec779b8eSAndroid Build Coastguard Worker
parseEvent(const ASensorEvent & event,DataFormat format,std::optional<int32_t> * discontinutyCount)394*ec779b8eSAndroid Build Coastguard Worker static PoseEvent parseEvent(const ASensorEvent& event, DataFormat format,
395*ec779b8eSAndroid Build Coastguard Worker std::optional<int32_t>* discontinutyCount) {
396*ec779b8eSAndroid Build Coastguard Worker switch (format) {
397*ec779b8eSAndroid Build Coastguard Worker case DataFormat::kQuaternion: {
398*ec779b8eSAndroid Build Coastguard Worker Eigen::Quaternionf quat(event.data[3], event.data[0], event.data[1], event.data[2]);
399*ec779b8eSAndroid Build Coastguard Worker // Adapt to different frame convention.
400*ec779b8eSAndroid Build Coastguard Worker quat *= rotateX(-M_PI_2);
401*ec779b8eSAndroid Build Coastguard Worker return PoseEvent{Pose3f(quat), std::optional<Twist3f>(), false};
402*ec779b8eSAndroid Build Coastguard Worker }
403*ec779b8eSAndroid Build Coastguard Worker
404*ec779b8eSAndroid Build Coastguard Worker case DataFormat::kRotationVectorsAndDiscontinuityCount: {
405*ec779b8eSAndroid Build Coastguard Worker Eigen::Vector3f rotation = {event.head_tracker.rx, event.head_tracker.ry,
406*ec779b8eSAndroid Build Coastguard Worker event.head_tracker.rz};
407*ec779b8eSAndroid Build Coastguard Worker Eigen::Vector3f twist = {event.head_tracker.vx, event.head_tracker.vy,
408*ec779b8eSAndroid Build Coastguard Worker event.head_tracker.vz};
409*ec779b8eSAndroid Build Coastguard Worker Eigen::Quaternionf quat = rotationVectorToQuaternion(rotation);
410*ec779b8eSAndroid Build Coastguard Worker bool isNewReference =
411*ec779b8eSAndroid Build Coastguard Worker !discontinutyCount->has_value() ||
412*ec779b8eSAndroid Build Coastguard Worker discontinutyCount->value() != event.head_tracker.discontinuity_count;
413*ec779b8eSAndroid Build Coastguard Worker *discontinutyCount = event.head_tracker.discontinuity_count;
414*ec779b8eSAndroid Build Coastguard Worker
415*ec779b8eSAndroid Build Coastguard Worker return PoseEvent{Pose3f(quat), Twist3f(Eigen::Vector3f::Zero(), twist),
416*ec779b8eSAndroid Build Coastguard Worker isNewReference};
417*ec779b8eSAndroid Build Coastguard Worker }
418*ec779b8eSAndroid Build Coastguard Worker
419*ec779b8eSAndroid Build Coastguard Worker default:
420*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Unexpected sensor type: %d", static_cast<int>(format));
421*ec779b8eSAndroid Build Coastguard Worker }
422*ec779b8eSAndroid Build Coastguard Worker }
423*ec779b8eSAndroid Build Coastguard Worker
toString(DataFormat format)424*ec779b8eSAndroid Build Coastguard Worker const static std::string toString(DataFormat format) {
425*ec779b8eSAndroid Build Coastguard Worker switch (format) {
426*ec779b8eSAndroid Build Coastguard Worker case DataFormat::kUnknown:
427*ec779b8eSAndroid Build Coastguard Worker return "kUnknown";
428*ec779b8eSAndroid Build Coastguard Worker case DataFormat::kQuaternion:
429*ec779b8eSAndroid Build Coastguard Worker return "kQuaternion";
430*ec779b8eSAndroid Build Coastguard Worker case DataFormat::kRotationVectorsAndDiscontinuityCount:
431*ec779b8eSAndroid Build Coastguard Worker return "kRotationVectorsAndDiscontinuityCount";
432*ec779b8eSAndroid Build Coastguard Worker default:
433*ec779b8eSAndroid Build Coastguard Worker return "NotImplemented";
434*ec779b8eSAndroid Build Coastguard Worker }
435*ec779b8eSAndroid Build Coastguard Worker }
436*ec779b8eSAndroid Build Coastguard Worker };
437*ec779b8eSAndroid Build Coastguard Worker
438*ec779b8eSAndroid Build Coastguard Worker } // namespace
439*ec779b8eSAndroid Build Coastguard Worker
create(const char * packageName,Listener * listener)440*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<SensorPoseProvider> SensorPoseProvider::create(const char* packageName,
441*ec779b8eSAndroid Build Coastguard Worker Listener* listener) {
442*ec779b8eSAndroid Build Coastguard Worker return SensorPoseProviderImpl::create(packageName, listener);
443*ec779b8eSAndroid Build Coastguard Worker }
444*ec779b8eSAndroid Build Coastguard Worker
445*ec779b8eSAndroid Build Coastguard Worker } // namespace media
446*ec779b8eSAndroid Build Coastguard Worker } // namespace android
447