Loading include/android/sensor.h +24 −0 Original line number Diff line number Diff line Loading @@ -495,6 +495,7 @@ struct ASensorEventQueue; * - ASensorEventQueue_hasEvents() * - ASensorEventQueue_getEvents() * - ASensorEventQueue_setEventRate() * - ASensorEventQueue_requestAdditionalInfoEvents() */ typedef struct ASensorEventQueue ASensorEventQueue; Loading Loading @@ -779,6 +780,29 @@ int ASensorEventQueue_hasEvents(ASensorEventQueue* queue); */ ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count); #if __ANDROID_API__ >= __ANDROID_API_Q__ /** * Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on * the given {@link ASensorEventQueue}. * * Sensor data events are always delivered to the {@ASensorEventQueue}. * * The {@link ASENSOR_TYPE_ADDITIONAL_INFO} events will be returned through * {@link ASensorEventQueue_getEvents}. The client is responsible for checking * {@link ASensorEvent#type} to determine the event type prior to handling of * the event. * * The client must be tolerant of any value for * {@link AAdditionalInfoEvent#type}, as new values may be defined in the future * and may delivered to the client. * * \param queue {@link ASensorEventQueue} to configure * \param enable true to request {@link ASENSOR_TYPE_ADDITIONAL_INFO} events, * false to stop receiving events * \return 0 on success or a negative error code on failure */ int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable); #endif /* __ANDROID_API__ >= __ANDRDOID_API_Q__ */ /*****************************************************************************/ Loading libs/sensor/SensorEventQueue.cpp +47 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <sensor/ISensorEventConnection.h> #include <android/sensor.h> #include <hardware/sensors-base.h> using std::min; Loading Loading @@ -188,6 +189,52 @@ void SensorEventQueue::sendAck(const ASensorEvent* events, int count) { return; } ssize_t SensorEventQueue::filterEvents(ASensorEvent* events, size_t count) const { // Check if this Sensor Event Queue is registered to receive each type of event. If it is not, // then do not copy the event into the final buffer. Minimize the number of copy operations by // finding consecutive sequences of events that the Sensor Event Queue should receive and only // copying the events once an unregistered event type is reached. bool intervalStartLocSet = false; size_t intervalStartLoc = 0; size_t eventsInInterval = 0; ssize_t eventsCopied = 0; for (size_t i = 0; i < count; i++) { bool includeEvent = (events[i].type != SENSOR_TYPE_ADDITIONAL_INFO || requestAdditionalInfo); if (includeEvent) { // Do not copy events yet since there may be more consecutive events that should be // copied together. Track the start location and number of events in the current // sequence. if (!intervalStartLocSet) { intervalStartLoc = i; intervalStartLocSet = true; eventsInInterval = 0; } eventsInInterval++; } // Shift the events from the already processed interval once an event that should not be // included is reached or if this is the final event to be processed. if (!includeEvent || (i + 1 == count)) { // Only shift the events if the interval did not start with the first event. If the // interval started with the first event, the events are already in their correct // location. if (intervalStartLoc > 0) { memmove(&events[eventsCopied], &events[intervalStartLoc], eventsInInterval * sizeof(ASensorEvent)); } eventsCopied += eventsInInterval; // Reset the interval information eventsInInterval = 0; intervalStartLocSet = false; } } return eventsCopied; } // ---------------------------------------------------------------------------- }; // namespace android libs/sensor/include/sensor/SensorEventQueue.h +8 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ struct ASensorEvent; // Concrete types for the NDK struct ASensorEventQueue { ALooper* looper; bool requestAdditionalInfo; }; // ---------------------------------------------------------------------------- Loading Loading @@ -92,6 +93,13 @@ public: void sendAck(const ASensorEvent* events, int count); status_t injectSensorEvent(const ASensorEvent& event); // Filters the given sensor events in place and returns the new number of events. // // The filtering is controlled by ASensorEventQueue.requestAdditionalInfo, and if this value is // false, then all SENSOR_TYPE_ADDITIONAL_INFO sensor events will be removed. ssize_t filterEvents(ASensorEvent* events, size_t count) const; private: sp<Looper> getLooper() const; sp<ISensorEventConnection> mSensorEventConnection; Loading libs/sensor/tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ cc_test { srcs: [ "Sensor_test.cpp", "SensorEventQueue_test.cpp", ], shared_libs: [ Loading libs/sensor/tests/SensorEventQueue_test.cpp 0 → 100644 +172 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdint.h> #include <gtest/gtest.h> #include <utils/Errors.h> #include <android/sensor.h> #include <hardware/sensors-base.h> #include <sensor/SensorManager.h> #include <sensor/SensorEventQueue.h> namespace android { class SensorEventQueueTest : public ::testing::Test { protected: typedef std::vector<int32_t> Events; SensorEventQueueTest() {}; virtual void SetUp() override { SensorManager& manager = SensorManager::getInstanceForPackage(String16("SensorEventQueueTest")); mQueue = manager.createEventQueue(); } void configureAdditionalInfo(bool enable) { mQueue->requestAdditionalInfo = enable; } Events filterEvents(const Events &types) const { // Convert the events into SensorEvent array ASensorEvent* events = new ASensorEvent[types.size()]; for (size_t i = 0; i < types.size(); i++) { events[i].type = types[i]; } // Filter the events ssize_t filteredCount = mQueue->filterEvents(events, types.size()); // Copy the result into an output vector Events result; for (size_t i = 0; i < filteredCount; i++) { result.push_back(events[i].type); } delete[] events; return result; } Events getExpectedEvents(const Events &events) const { Events output; for (size_t i = 0; i != events.size(); i++) { // Copy events if the event queue is configured to receive them if (events[i] != SENSOR_TYPE_ADDITIONAL_INFO || mQueue->requestAdditionalInfo) { output.push_back(events[i]); } } return output; } void runFilterTest(const Events& events) { Events filtered = filterEvents(events); Events expected = getExpectedEvents(events); EXPECT_EQ(expected.size(), filtered.size()); EXPECT_EQ(expected, filtered); } private: sp<SensorEventQueue> mQueue; }; TEST_F(SensorEventQueueTest, FilterZeroEvents) { configureAdditionalInfo(false /* enable */); runFilterTest({}); } TEST_F(SensorEventQueueTest, FilterEvents_ReceiveAdditionalInfo) { configureAdditionalInfo(true /* enable */); runFilterTest({SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_MAGNETIC_FIELD}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveAll) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveFirst) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_MAGNETIC_FIELD}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveAllButOne) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_ADDITIONAL_INFO}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveLast) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_MAGNETIC_FIELD, SENSOR_TYPE_ADDITIONAL_INFO}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveConsecutive) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_MAGNETIC_FIELD, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveInterleaved) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_MAGNETIC_FIELD}); } TEST_F(SensorEventQueueTest, FilterEvents_ReconfigureAdditionalInfo) { configureAdditionalInfo(false /* enable */); const Events events = {SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_MAGNETIC_FIELD, SENSOR_TYPE_ADDITIONAL_INFO}; runFilterTest(events); // Update setting to request Additional Info configureAdditionalInfo(true /* enable */); runFilterTest(events); // Update setting to stop requesting Additional Info configureAdditionalInfo(true /* enable */); runFilterTest(events); } } // namespace android Loading
include/android/sensor.h +24 −0 Original line number Diff line number Diff line Loading @@ -495,6 +495,7 @@ struct ASensorEventQueue; * - ASensorEventQueue_hasEvents() * - ASensorEventQueue_getEvents() * - ASensorEventQueue_setEventRate() * - ASensorEventQueue_requestAdditionalInfoEvents() */ typedef struct ASensorEventQueue ASensorEventQueue; Loading Loading @@ -779,6 +780,29 @@ int ASensorEventQueue_hasEvents(ASensorEventQueue* queue); */ ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count); #if __ANDROID_API__ >= __ANDROID_API_Q__ /** * Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on * the given {@link ASensorEventQueue}. * * Sensor data events are always delivered to the {@ASensorEventQueue}. * * The {@link ASENSOR_TYPE_ADDITIONAL_INFO} events will be returned through * {@link ASensorEventQueue_getEvents}. The client is responsible for checking * {@link ASensorEvent#type} to determine the event type prior to handling of * the event. * * The client must be tolerant of any value for * {@link AAdditionalInfoEvent#type}, as new values may be defined in the future * and may delivered to the client. * * \param queue {@link ASensorEventQueue} to configure * \param enable true to request {@link ASENSOR_TYPE_ADDITIONAL_INFO} events, * false to stop receiving events * \return 0 on success or a negative error code on failure */ int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable); #endif /* __ANDROID_API__ >= __ANDRDOID_API_Q__ */ /*****************************************************************************/ Loading
libs/sensor/SensorEventQueue.cpp +47 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <sensor/ISensorEventConnection.h> #include <android/sensor.h> #include <hardware/sensors-base.h> using std::min; Loading Loading @@ -188,6 +189,52 @@ void SensorEventQueue::sendAck(const ASensorEvent* events, int count) { return; } ssize_t SensorEventQueue::filterEvents(ASensorEvent* events, size_t count) const { // Check if this Sensor Event Queue is registered to receive each type of event. If it is not, // then do not copy the event into the final buffer. Minimize the number of copy operations by // finding consecutive sequences of events that the Sensor Event Queue should receive and only // copying the events once an unregistered event type is reached. bool intervalStartLocSet = false; size_t intervalStartLoc = 0; size_t eventsInInterval = 0; ssize_t eventsCopied = 0; for (size_t i = 0; i < count; i++) { bool includeEvent = (events[i].type != SENSOR_TYPE_ADDITIONAL_INFO || requestAdditionalInfo); if (includeEvent) { // Do not copy events yet since there may be more consecutive events that should be // copied together. Track the start location and number of events in the current // sequence. if (!intervalStartLocSet) { intervalStartLoc = i; intervalStartLocSet = true; eventsInInterval = 0; } eventsInInterval++; } // Shift the events from the already processed interval once an event that should not be // included is reached or if this is the final event to be processed. if (!includeEvent || (i + 1 == count)) { // Only shift the events if the interval did not start with the first event. If the // interval started with the first event, the events are already in their correct // location. if (intervalStartLoc > 0) { memmove(&events[eventsCopied], &events[intervalStartLoc], eventsInInterval * sizeof(ASensorEvent)); } eventsCopied += eventsInInterval; // Reset the interval information eventsInInterval = 0; intervalStartLocSet = false; } } return eventsCopied; } // ---------------------------------------------------------------------------- }; // namespace android
libs/sensor/include/sensor/SensorEventQueue.h +8 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ struct ASensorEvent; // Concrete types for the NDK struct ASensorEventQueue { ALooper* looper; bool requestAdditionalInfo; }; // ---------------------------------------------------------------------------- Loading Loading @@ -92,6 +93,13 @@ public: void sendAck(const ASensorEvent* events, int count); status_t injectSensorEvent(const ASensorEvent& event); // Filters the given sensor events in place and returns the new number of events. // // The filtering is controlled by ASensorEventQueue.requestAdditionalInfo, and if this value is // false, then all SENSOR_TYPE_ADDITIONAL_INFO sensor events will be removed. ssize_t filterEvents(ASensorEvent* events, size_t count) const; private: sp<Looper> getLooper() const; sp<ISensorEventConnection> mSensorEventConnection; Loading
libs/sensor/tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ cc_test { srcs: [ "Sensor_test.cpp", "SensorEventQueue_test.cpp", ], shared_libs: [ Loading
libs/sensor/tests/SensorEventQueue_test.cpp 0 → 100644 +172 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdint.h> #include <gtest/gtest.h> #include <utils/Errors.h> #include <android/sensor.h> #include <hardware/sensors-base.h> #include <sensor/SensorManager.h> #include <sensor/SensorEventQueue.h> namespace android { class SensorEventQueueTest : public ::testing::Test { protected: typedef std::vector<int32_t> Events; SensorEventQueueTest() {}; virtual void SetUp() override { SensorManager& manager = SensorManager::getInstanceForPackage(String16("SensorEventQueueTest")); mQueue = manager.createEventQueue(); } void configureAdditionalInfo(bool enable) { mQueue->requestAdditionalInfo = enable; } Events filterEvents(const Events &types) const { // Convert the events into SensorEvent array ASensorEvent* events = new ASensorEvent[types.size()]; for (size_t i = 0; i < types.size(); i++) { events[i].type = types[i]; } // Filter the events ssize_t filteredCount = mQueue->filterEvents(events, types.size()); // Copy the result into an output vector Events result; for (size_t i = 0; i < filteredCount; i++) { result.push_back(events[i].type); } delete[] events; return result; } Events getExpectedEvents(const Events &events) const { Events output; for (size_t i = 0; i != events.size(); i++) { // Copy events if the event queue is configured to receive them if (events[i] != SENSOR_TYPE_ADDITIONAL_INFO || mQueue->requestAdditionalInfo) { output.push_back(events[i]); } } return output; } void runFilterTest(const Events& events) { Events filtered = filterEvents(events); Events expected = getExpectedEvents(events); EXPECT_EQ(expected.size(), filtered.size()); EXPECT_EQ(expected, filtered); } private: sp<SensorEventQueue> mQueue; }; TEST_F(SensorEventQueueTest, FilterZeroEvents) { configureAdditionalInfo(false /* enable */); runFilterTest({}); } TEST_F(SensorEventQueueTest, FilterEvents_ReceiveAdditionalInfo) { configureAdditionalInfo(true /* enable */); runFilterTest({SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_MAGNETIC_FIELD}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveAll) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveFirst) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_MAGNETIC_FIELD}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveAllButOne) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_ADDITIONAL_INFO}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveLast) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_MAGNETIC_FIELD, SENSOR_TYPE_ADDITIONAL_INFO}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveConsecutive) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_MAGNETIC_FIELD, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER}); } TEST_F(SensorEventQueueTest, FilterEvents_RemoveInterleaved) { configureAdditionalInfo(false /* enable */); runFilterTest({SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_MAGNETIC_FIELD}); } TEST_F(SensorEventQueueTest, FilterEvents_ReconfigureAdditionalInfo) { configureAdditionalInfo(false /* enable */); const Events events = {SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_ADDITIONAL_INFO, SENSOR_TYPE_MAGNETIC_FIELD, SENSOR_TYPE_ADDITIONAL_INFO}; runFilterTest(events); // Update setting to request Additional Info configureAdditionalInfo(true /* enable */); runFilterTest(events); // Update setting to stop requesting Additional Info configureAdditionalInfo(true /* enable */); runFilterTest(events); } } // namespace android