| Ytai Ben-Tsvi | 779d1ee | 2021-07-27 05:56:22 -0700 | [diff] [blame^] | 1 | /* | 
 | 2 |  * Copyright (C) 2021 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | #include <media/SensorPoseProvider.h> | 
 | 18 |  | 
 | 19 | #define LOG_TAG "SensorPoseProvider" | 
 | 20 |  | 
 | 21 | #include <inttypes.h> | 
 | 22 |  | 
 | 23 | #include <future> | 
 | 24 | #include <iostream> | 
 | 25 | #include <map> | 
 | 26 | #include <thread> | 
 | 27 |  | 
 | 28 | #include <android/looper.h> | 
 | 29 | #include <log/log_main.h> | 
 | 30 |  | 
 | 31 | namespace android { | 
 | 32 | namespace media { | 
 | 33 | namespace { | 
 | 34 |  | 
 | 35 | /** | 
 | 36 |  * RAII-wrapper around ASensorEventQueue, which destroys it on destruction. | 
 | 37 |  */ | 
 | 38 | class EventQueueGuard { | 
 | 39 |   public: | 
 | 40 |     EventQueueGuard(ASensorManager* manager, ASensorEventQueue* queue) | 
 | 41 |         : mManager(manager), mQueue(queue) {} | 
 | 42 |  | 
 | 43 |     ~EventQueueGuard() { | 
 | 44 |         if (mQueue) { | 
 | 45 |             int ret = ASensorManager_destroyEventQueue(mManager, mQueue); | 
 | 46 |             if (ret) { | 
 | 47 |                 ALOGE("Failed to destroy event queue: %s\n", strerror(ret)); | 
 | 48 |             } | 
 | 49 |         } | 
 | 50 |     } | 
 | 51 |  | 
 | 52 |     EventQueueGuard(const EventQueueGuard&) = delete; | 
 | 53 |     EventQueueGuard& operator=(const EventQueueGuard&) = delete; | 
 | 54 |  | 
 | 55 |     [[nodiscard]] ASensorEventQueue* get() const { return mQueue; } | 
 | 56 |  | 
 | 57 |   private: | 
 | 58 |     ASensorManager* const mManager; | 
 | 59 |     ASensorEventQueue* mQueue; | 
 | 60 | }; | 
 | 61 |  | 
 | 62 | /** | 
 | 63 |  * RAII-wrapper around an enabled sensor, which disables it upon destruction. | 
 | 64 |  */ | 
 | 65 | class SensorEnableGuard { | 
 | 66 |   public: | 
 | 67 |     SensorEnableGuard(ASensorEventQueue* queue, const ASensor* sensor) | 
 | 68 |         : mQueue(queue), mSensor(sensor) {} | 
 | 69 |  | 
 | 70 |     ~SensorEnableGuard() { | 
 | 71 |         if (mSensor) { | 
 | 72 |             int ret = ASensorEventQueue_disableSensor(mQueue, mSensor); | 
 | 73 |             if (ret) { | 
 | 74 |                 ALOGE("Failed to disable sensor: %s\n", strerror(ret)); | 
 | 75 |             } | 
 | 76 |         } | 
 | 77 |     } | 
 | 78 |  | 
 | 79 |     SensorEnableGuard(const SensorEnableGuard&) = delete; | 
 | 80 |     SensorEnableGuard& operator=(const SensorEnableGuard&) = delete; | 
 | 81 |  | 
 | 82 |     // Enable moving. | 
 | 83 |     SensorEnableGuard(SensorEnableGuard&& other) : mQueue(other.mQueue), mSensor(other.mSensor) { | 
 | 84 |         other.mSensor = nullptr; | 
 | 85 |     } | 
 | 86 |  | 
 | 87 |   private: | 
 | 88 |     ASensorEventQueue* const mQueue; | 
 | 89 |     const ASensor* mSensor; | 
 | 90 | }; | 
 | 91 |  | 
 | 92 | /** | 
 | 93 |  * Streams the required events to a PoseListener, based on events originating from the Sensor stack. | 
 | 94 |  */ | 
 | 95 | class SensorPoseProviderImpl : public SensorPoseProvider { | 
 | 96 |   public: | 
 | 97 |     static std::unique_ptr<SensorPoseProvider> create(const char* packageName, Listener* listener) { | 
 | 98 |         std::unique_ptr<SensorPoseProviderImpl> result( | 
 | 99 |                 new SensorPoseProviderImpl(packageName, listener)); | 
 | 100 |         return result->waitInitFinished() ? std::move(result) : nullptr; | 
 | 101 |     } | 
 | 102 |  | 
 | 103 |     ~SensorPoseProviderImpl() override { | 
 | 104 |         ALooper_wake(mLooper); | 
 | 105 |         mThread.join(); | 
 | 106 |     } | 
 | 107 |  | 
 | 108 |     int32_t startSensor(const ASensor* sensor, std::chrono::microseconds samplingPeriod) override { | 
 | 109 |         int32_t handle = ASensor_getHandle(sensor); | 
 | 110 |  | 
 | 111 |         // Enable the sensor. | 
 | 112 |         if (ASensorEventQueue_registerSensor(mQueue->get(), sensor, samplingPeriod.count(), 0)) { | 
 | 113 |             ALOGE("Failed to enable sensor"); | 
 | 114 |             return INVALID_HANDLE; | 
 | 115 |         } | 
 | 116 |  | 
 | 117 |         mEnabledSensors.emplace(handle, SensorEnableGuard(mQueue->get(), sensor)); | 
 | 118 |         return handle; | 
 | 119 |     } | 
 | 120 |  | 
 | 121 |     void stopSensor(int handle) override { mEnabledSensors.erase(handle); } | 
 | 122 |  | 
 | 123 |   private: | 
 | 124 |     ALooper* mLooper; | 
 | 125 |     Listener* const mListener; | 
 | 126 |     std::thread mThread; | 
 | 127 |     std::map<int32_t, SensorEnableGuard> mEnabledSensors; | 
 | 128 |     std::unique_ptr<EventQueueGuard> mQueue; | 
 | 129 |  | 
 | 130 |     // We must do some of the initialization operations on the worker thread, because the API relies | 
 | 131 |     // on the thread-local looper. In addition, as a matter of convenience, we store some of the | 
 | 132 |     // state on the stack. | 
 | 133 |     // For that reason, we use a two-step initialization approach, where the ctor mostly just starts | 
 | 134 |     // the worker thread and that thread would notify, via the promise below whenever initialization | 
 | 135 |     // is finished, and whether it was successful. | 
 | 136 |     std::promise<bool> mInitPromise; | 
 | 137 |  | 
 | 138 |     SensorPoseProviderImpl(const char* packageName, Listener* listener) | 
 | 139 |         : mListener(listener), | 
 | 140 |           mThread([this, p = std::string(packageName)] { threadFunc(p.c_str()); }) {} | 
 | 141 |  | 
 | 142 |     void initFinished(bool success) { mInitPromise.set_value(success); } | 
 | 143 |  | 
 | 144 |     bool waitInitFinished() { return mInitPromise.get_future().get(); } | 
 | 145 |  | 
 | 146 |     void threadFunc(const char* packageName) { | 
 | 147 |         // The number 19 is arbitrary, only useful if using multiple objects on the same looper. | 
 | 148 |         constexpr int kIdent = 19; | 
 | 149 |  | 
 | 150 |         // Obtain sensor manager. | 
 | 151 |         ASensorManager* sensor_manager = ASensorManager_getInstanceForPackage(packageName); | 
 | 152 |         if (!sensor_manager) { | 
 | 153 |             ALOGE("Failed to get a sensor manager"); | 
 | 154 |             initFinished(false); | 
 | 155 |             return; | 
 | 156 |         } | 
 | 157 |  | 
 | 158 |         // Obtain looper. | 
 | 159 |         mLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); | 
 | 160 |  | 
 | 161 |         // Create event queue. | 
 | 162 |         ASensorEventQueue* queue = | 
 | 163 |                 ASensorManager_createEventQueue(sensor_manager, mLooper, kIdent, nullptr, nullptr); | 
 | 164 |  | 
 | 165 |         if (queue == nullptr) { | 
 | 166 |             ALOGE("Failed to create a sensor event queue"); | 
 | 167 |             initFinished(false); | 
 | 168 |             return; | 
 | 169 |         } | 
 | 170 |  | 
 | 171 |         mQueue.reset(new EventQueueGuard(sensor_manager, queue)); | 
 | 172 |  | 
 | 173 |         initFinished(true); | 
 | 174 |  | 
 | 175 |         while (true) { | 
 | 176 |             int ret = ALooper_pollOnce(-1 /* no timeout */, nullptr, nullptr, nullptr); | 
 | 177 |  | 
 | 178 |             switch (ret) { | 
 | 179 |                 case ALOOPER_POLL_WAKE: | 
 | 180 |                     // Normal way to exit. | 
 | 181 |                     return; | 
 | 182 |  | 
 | 183 |                 case kIdent: | 
 | 184 |                     // Possible events on our queue. | 
 | 185 |                     break; | 
 | 186 |  | 
 | 187 |                 default: | 
 | 188 |                     ALOGE("Unexpected status out of ALooper_pollOnce: %d", ret); | 
 | 189 |             } | 
 | 190 |  | 
 | 191 |             // Process an event. | 
 | 192 |             ASensorEvent event; | 
 | 193 |             ssize_t size = ASensorEventQueue_getEvents(queue, &event, 1); | 
 | 194 |             if (size < 0 || size > 1) { | 
 | 195 |                 ALOGE("Unexpected return value from ASensorEventQueue_getEvents: %zd", size); | 
 | 196 |                 break; | 
 | 197 |             } | 
 | 198 |             if (size == 0) { | 
 | 199 |                 // No events. | 
 | 200 |                 continue; | 
 | 201 |             } | 
 | 202 |  | 
 | 203 |             handleEvent(event); | 
 | 204 |         } | 
 | 205 |     } | 
 | 206 |  | 
 | 207 |     void handleEvent(const ASensorEvent& event) { | 
 | 208 |         auto value = parseEvent(event); | 
 | 209 |         mListener->onPose(event.timestamp, event.sensor, std::get<0>(value), std::get<1>(value)); | 
 | 210 |     } | 
 | 211 |  | 
 | 212 |     static std::tuple<Pose3f, std::optional<Twist3f>> parseEvent(const ASensorEvent& event) { | 
 | 213 |         // TODO(ytai): Add more types. | 
 | 214 |         switch (event.type) { | 
 | 215 |             case ASENSOR_TYPE_ROTATION_VECTOR: | 
 | 216 |             case ASENSOR_TYPE_GAME_ROTATION_VECTOR: { | 
 | 217 |                 Eigen::Quaternionf quat(event.data[3], event.data[0], event.data[1], event.data[2]); | 
 | 218 |                 return std::make_tuple(Pose3f(quat), std::optional<Twist3f>()); | 
 | 219 |             } | 
 | 220 |  | 
 | 221 |             default: | 
 | 222 |                 ALOGE("Unsupported sensor type: %" PRId32, event.type); | 
 | 223 |                 return std::make_tuple(Pose3f(), std::optional<Twist3f>()); | 
 | 224 |         } | 
 | 225 |     } | 
 | 226 | }; | 
 | 227 |  | 
 | 228 | }  // namespace | 
 | 229 |  | 
 | 230 | std::unique_ptr<SensorPoseProvider> SensorPoseProvider::create(const char* packageName, | 
 | 231 |                                                                Listener* listener) { | 
 | 232 |     return SensorPoseProviderImpl::create(packageName, listener); | 
 | 233 | } | 
 | 234 |  | 
 | 235 | }  // namespace media | 
 | 236 | }  // namespace android |