Merge changes from topic "update_sensors_hal"

* changes:
  Add VTS tests for Sensors HAL 2.1
  Add Hinge Angle Sensor to default impl for HAL 2.1
  Add default impl of Sensors HAL 2.1
  Create wrapper for 2.0/2.1 sensor HALs
  Add Sensors HAL 2.1
This commit is contained in:
TreeHugger Robot
2020-02-19 04:13:50 +00:00
committed by Android (Google) Code Review
49 changed files with 3885 additions and 2635 deletions

View File

@@ -408,7 +408,7 @@
<hal format="hidl" optional="true">
<name>android.hardware.sensors</name>
<version>1.0</version>
<version>2.0</version>
<version>2.0-1</version>
<interface>
<name>ISensors</name>
<instance>default</instance>

View File

@@ -695,6 +695,9 @@ dcc8872337f0135e81970e1d8d5fd7139160dc80e9be76f0ae05290fa7e472b8 android.hardwar
a2977755bc5f1ef47f04b7f2400632efda6218e1515dba847da487145cfabc4f android.hardware.radio.config@1.3::IRadioConfig
742360c775313438b0f82256eac62fb5bbc76a6ae6f388573f3aa142fb2c1eea android.hardware.radio.config@1.3::IRadioConfigIndication
0006ab8e8b0910cbd3bbb08d5f17d5fac7d65a2bdad5f2334e4851db9d1e6fa8 android.hardware.radio.config@1.3::IRadioConfigResponse
3ca6616381080bdd6c08141ad12775a94ae868c58b02b1274ae3326f7de724ab android.hardware.sensors@2.1::ISensors
3d4141c6373cd9ca02fe221a7d12343840de2255d032c38248fe8e35816b58b2 android.hardware.sensors@2.1::ISensorsCallback
8051cc50fc90ed447f058a8b15d81f35a65f1bd9004b1de4f127edeb89b47978 android.hardware.sensors@2.1::types
4a6517ea4ad807855428b0101d8e1a486497bd88ab4300ba3b2be43d46d32580 android.hardware.soundtrigger@2.3::types
b37f78e3fdc79af8b32a545b2b426f1fd1355b359d9e7835f3bf1ed0aa4518d8 android.hardware.soundtrigger@2.3::ISoundTriggerHw
7746fda1fbf9c7c132bae701cc5a161309e4f5e7f3e8065811045975ee86196d android.hardware.usb.gadget@1.1::IUsbGadget

View File

@@ -20,7 +20,7 @@ cc_test {
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"SensorsHidlEnvironmentV1_0.cpp",
"VtsHalSensorsV1_0TargetTest.cpp"
"VtsHalSensorsV1_0TargetTest.cpp",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
@@ -31,6 +31,8 @@ cc_test {
"android.hardware.sensors@1.0",
"VtsHalSensorsTargetTestUtils",
],
test_suites: ["general-tests", "vts-core"],
test_suites: [
"general-tests",
"vts-core",
],
}

View File

@@ -29,8 +29,9 @@
using ::android::sp;
class SensorsHidlTest;
class SensorsHidlEnvironmentV1_0 : public SensorsHidlEnvironmentBase {
public:
class SensorsHidlEnvironmentV1_0
: public SensorsHidlEnvironmentBase<::android::hardware::sensors::V1_0::Event> {
public:
using Event = ::android::hardware::sensors::V1_0::Event;
SensorsHidlEnvironmentV1_0(const std::string& service_name)
: SensorsHidlEnvironmentBase(service_name) {}

View File

@@ -33,8 +33,7 @@ using ::android::sp;
using namespace ::android::hardware::sensors::V1_0;
// The main test class for SENSORS HIDL HAL.
class SensorsHidlTest : public SensorsHidlTestBase {
class SensorsHidlTest : public SensorsHidlTestBase<SensorType, Event, SensorInfo> {
public:
virtual void SetUp() override {
mEnvironment = new SensorsHidlEnvironmentV1_0(GetParam());
@@ -80,7 +79,7 @@ class SensorsHidlTest : public SensorsHidlTestBase {
inline sp<ISensors>& S() { return mEnvironment->sensors; }
SensorsHidlEnvironmentBase* getEnvironment() override { return mEnvironment; }
SensorsHidlEnvironmentBase<Event>* getEnvironment() override { return mEnvironment; }
private:
// Test environment for sensors HAL.
@@ -257,55 +256,55 @@ TEST_P(SensorsHidlTest, InjectSensorEventData) {
// Test if sensor hal can do UI speed accelerometer streaming properly
TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(200),
std::chrono::seconds(5), sAccelNormChecker);
std::chrono::seconds(5), mAccelNormChecker);
}
// Test if sensor hal can do normal speed accelerometer streaming properly
TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(20),
std::chrono::seconds(5), sAccelNormChecker);
std::chrono::seconds(5), mAccelNormChecker);
}
// Test if sensor hal can do game speed accelerometer streaming properly
TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) {
testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(5),
std::chrono::seconds(5), sAccelNormChecker);
std::chrono::seconds(5), mAccelNormChecker);
}
// Test if sensor hal can do UI speed gyroscope streaming properly
TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(200),
std::chrono::seconds(5), sGyroNormChecker);
std::chrono::seconds(5), mGyroNormChecker);
}
// Test if sensor hal can do normal speed gyroscope streaming properly
TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(20),
std::chrono::seconds(5), sGyroNormChecker);
std::chrono::seconds(5), mGyroNormChecker);
}
// Test if sensor hal can do game speed gyroscope streaming properly
TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) {
testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(5),
std::chrono::seconds(5), sGyroNormChecker);
std::chrono::seconds(5), mGyroNormChecker);
}
// Test if sensor hal can do UI speed magnetometer streaming properly
TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(200),
std::chrono::seconds(5), NullChecker());
std::chrono::seconds(5), NullChecker<Event>());
}
// Test if sensor hal can do normal speed magnetometer streaming properly
TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(20),
std::chrono::seconds(5), NullChecker());
std::chrono::seconds(5), NullChecker<Event>());
}
// Test if sensor hal can do game speed magnetometer streaming properly
TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) {
testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(5),
std::chrono::seconds(5), NullChecker());
std::chrono::seconds(5), NullChecker<Event>());
}
// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
@@ -344,109 +343,109 @@ TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) {
// Test sensor event direct report with ashmem for accel sensor at normal rate
TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
sAccelNormChecker);
mAccelNormChecker);
}
// Test sensor event direct report with ashmem for accel sensor at fast rate
TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::FAST,
sAccelNormChecker);
mAccelNormChecker);
}
// Test sensor event direct report with ashmem for accel sensor at very fast rate
TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM,
RateLevel::VERY_FAST, sAccelNormChecker);
RateLevel::VERY_FAST, mAccelNormChecker);
}
// Test sensor event direct report with ashmem for gyro sensor at normal rate
TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::NORMAL,
sGyroNormChecker);
mGyroNormChecker);
}
// Test sensor event direct report with ashmem for gyro sensor at fast rate
TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
sGyroNormChecker);
mGyroNormChecker);
}
// Test sensor event direct report with ashmem for gyro sensor at very fast rate
TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::VERY_FAST,
sGyroNormChecker);
mGyroNormChecker);
}
// Test sensor event direct report with ashmem for mag sensor at normal rate
TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::NORMAL,
NullChecker());
NullChecker<Event>());
}
// Test sensor event direct report with ashmem for mag sensor at fast rate
TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::FAST,
NullChecker());
NullChecker<Event>());
}
// Test sensor event direct report with ashmem for mag sensor at very fast rate
TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM,
RateLevel::VERY_FAST, NullChecker());
RateLevel::VERY_FAST, NullChecker<Event>());
}
// Test sensor event direct report with gralloc for accel sensor at normal rate
TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL,
sAccelNormChecker);
mAccelNormChecker);
}
// Test sensor event direct report with gralloc for accel sensor at fast rate
TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST,
sAccelNormChecker);
mAccelNormChecker);
}
// Test sensor event direct report with gralloc for accel sensor at very fast rate
TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC,
RateLevel::VERY_FAST, sAccelNormChecker);
RateLevel::VERY_FAST, mAccelNormChecker);
}
// Test sensor event direct report with gralloc for gyro sensor at normal rate
TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL,
sGyroNormChecker);
mGyroNormChecker);
}
// Test sensor event direct report with gralloc for gyro sensor at fast rate
TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
sGyroNormChecker);
mGyroNormChecker);
}
// Test sensor event direct report with gralloc for gyro sensor at very fast rate
TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
sGyroNormChecker);
mGyroNormChecker);
}
// Test sensor event direct report with gralloc for mag sensor at normal rate
TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL,
NullChecker());
NullChecker<Event>());
}
// Test sensor event direct report with gralloc for mag sensor at fast rate
TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST,
NullChecker());
NullChecker<Event>());
}
// Test sensor event direct report with gralloc for mag sensor at very fast rate
TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC,
RateLevel::VERY_FAST, NullChecker());
RateLevel::VERY_FAST, NullChecker<Event>());
}
INSTANTIATE_TEST_SUITE_P(

View File

@@ -20,13 +20,17 @@ cc_binary {
relative_install_path: "hw",
srcs: [
"service.cpp",
"Sensor.cpp",
"Sensors.cpp",
],
init_rc: ["android.hardware.sensors@2.0-service-mock.rc"],
header_libs: [
"android.hardware.sensors@2.X-shared-utils",
],
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
// Needed to compile some shared utilities for both 2.0/2.1 impls, but
// isn't normally needed for a HAL that only supports 2.0.
"android.hardware.sensors@2.1",
"libcutils",
"libfmq",
"libhidlbase",
@@ -34,5 +38,9 @@ cc_binary {
"libpower",
"libutils",
],
static_libs: [
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.X-shared-impl",
],
vintf_fragments: ["android.hardware.sensors@2.0.xml"],
}

View File

@@ -1,259 +0,0 @@
/*
* Copyright (C) 2018 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 "Sensors.h"
#include <android/hardware/sensors/2.0/types.h>
#include <log/log.h>
namespace android {
namespace hardware {
namespace sensors {
namespace V2_0 {
namespace implementation {
using ::android::hardware::sensors::V1_0::Event;
using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::RateLevel;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SharedMemInfo;
using ::android::hardware::sensors::V2_0::SensorTimeout;
using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";
Sensors::Sensors()
: mEventQueueFlag(nullptr),
mNextHandle(1),
mOutstandingWakeUpEvents(0),
mReadWakeLockQueueRun(false),
mAutoReleaseWakeLockTime(0),
mHasWakeLock(false) {
AddSensor<AccelSensor>();
AddSensor<GyroSensor>();
AddSensor<AmbientTempSensor>();
AddSensor<DeviceTempSensor>();
AddSensor<PressureSensor>();
AddSensor<MagnetometerSensor>();
AddSensor<LightSensor>();
AddSensor<ProximitySensor>();
AddSensor<RelativeHumiditySensor>();
}
Sensors::~Sensors() {
deleteEventFlag();
mReadWakeLockQueueRun = false;
mWakeLockThread.join();
}
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
Return<void> Sensors::getSensorsList(getSensorsList_cb _hidl_cb) {
std::vector<SensorInfo> sensors;
for (const auto& sensor : mSensors) {
sensors.push_back(sensor.second->getSensorInfo());
}
// Call the HIDL callback with the SensorInfo
_hidl_cb(sensors);
return Void();
}
Return<Result> Sensors::setOperationMode(OperationMode mode) {
for (auto sensor : mSensors) {
sensor.second->setOperationMode(mode);
}
return Result::OK;
}
Return<Result> Sensors::activate(int32_t sensorHandle, bool enabled) {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
sensor->second->activate(enabled);
return Result::OK;
}
return Result::BAD_VALUE;
}
Return<Result> Sensors::initialize(
const ::android::hardware::MQDescriptorSync<Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<ISensorsCallback>& sensorsCallback) {
Result result = Result::OK;
// Ensure that all sensors are disabled
for (auto sensor : mSensors) {
sensor.second->activate(false /* enable */);
}
// Stop the Wake Lock thread if it is currently running
if (mReadWakeLockQueueRun.load()) {
mReadWakeLockQueueRun = false;
mWakeLockThread.join();
}
// Save a reference to the callback
mCallback = sensorsCallback;
// Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
mEventQueue =
std::make_unique<EventMessageQueue>(eventQueueDescriptor, true /* resetPointers */);
// Ensure that any existing EventFlag is properly deleted
deleteEventFlag();
// Create the EventFlag that is used to signal to the framework that sensor events have been
// written to the Event FMQ
if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) {
result = Result::BAD_VALUE;
}
// Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP
// events have been successfully read and handled by the framework.
mWakeLockQueue =
std::make_unique<WakeLockMessageQueue>(wakeLockDescriptor, true /* resetPointers */);
if (!mCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) {
result = Result::BAD_VALUE;
}
// Start the thread to read events from the Wake Lock FMQ
mReadWakeLockQueueRun = true;
mWakeLockThread = std::thread(startReadWakeLockThread, this);
return result;
}
Return<Result> Sensors::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
int64_t /* maxReportLatencyNs */) {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
sensor->second->batch(samplingPeriodNs);
return Result::OK;
}
return Result::BAD_VALUE;
}
Return<Result> Sensors::flush(int32_t sensorHandle) {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
return sensor->second->flush();
}
return Result::BAD_VALUE;
}
Return<Result> Sensors::injectSensorData(const Event& event) {
auto sensor = mSensors.find(event.sensorHandle);
if (sensor != mSensors.end()) {
return sensor->second->injectEvent(event);
}
return Result::BAD_VALUE;
}
Return<void> Sensors::registerDirectChannel(const SharedMemInfo& /* mem */,
registerDirectChannel_cb _hidl_cb) {
_hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
return Return<void>();
}
Return<Result> Sensors::unregisterDirectChannel(int32_t /* channelHandle */) {
return Result::INVALID_OPERATION;
}
Return<void> Sensors::configDirectReport(int32_t /* sensorHandle */, int32_t /* channelHandle */,
RateLevel /* rate */, configDirectReport_cb _hidl_cb) {
_hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */);
return Return<void>();
}
void Sensors::postEvents(const std::vector<Event>& events, bool wakeup) {
std::lock_guard<std::mutex> lock(mWriteLock);
if (mEventQueue->write(events.data(), events.size())) {
mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));
if (wakeup) {
// Keep track of the number of outstanding WAKE_UP events in order to properly hold
// a wake lock until the framework has secured a wake lock
updateWakeLock(events.size(), 0 /* eventsHandled */);
}
}
}
void Sensors::updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) {
std::lock_guard<std::mutex> lock(mWakeLockLock);
int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled;
if (newVal < 0) {
mOutstandingWakeUpEvents = 0;
} else {
mOutstandingWakeUpEvents = newVal;
}
if (eventsWritten > 0) {
// Update the time at which the last WAKE_UP event was sent
mAutoReleaseWakeLockTime = ::android::uptimeMillis() +
static_cast<uint32_t>(SensorTimeout::WAKE_LOCK_SECONDS) * 1000;
}
if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 &&
acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) {
mHasWakeLock = true;
} else if (mHasWakeLock) {
// Check if the wake lock should be released automatically if
// SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written to
// the Wake Lock FMQ.
if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) {
ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock",
SensorTimeout::WAKE_LOCK_SECONDS);
mOutstandingWakeUpEvents = 0;
}
if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) {
mHasWakeLock = false;
}
}
}
void Sensors::readWakeLockFMQ() {
while (mReadWakeLockQueueRun.load()) {
constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000; // 500 ms
uint32_t eventsHandled = 0;
// Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to ensure
// that any held wake lock is able to be released if it is held for too long.
mWakeLockQueue->readBlocking(&eventsHandled, 1 /* count */, 0 /* readNotification */,
static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN),
kReadTimeoutNs);
updateWakeLock(0 /* eventsWritten */, eventsHandled);
}
}
void Sensors::startReadWakeLockThread(Sensors* sensors) {
sensors->readWakeLockFMQ();
}
void Sensors::deleteEventFlag() {
status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag);
if (status != OK) {
ALOGI("Failed to delete event flag: %d", status);
}
}
} // namespace implementation
} // namespace V2_0
} // namespace sensors
} // namespace hardware
} // namespace android

View File

@@ -1,191 +0,0 @@
/*
* Copyright (C) 2018 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.
*/
#ifndef ANDROID_HARDWARE_SENSORS_V2_0_SENSORS_H
#define ANDROID_HARDWARE_SENSORS_V2_0_SENSORS_H
#include "Sensor.h"
#include <android/hardware/sensors/2.0/ISensors.h>
#include <fmq/MessageQueue.h>
#include <hardware_legacy/power.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <atomic>
#include <memory>
#include <thread>
namespace android {
namespace hardware {
namespace sensors {
namespace V2_0 {
namespace implementation {
using ::android::sp;
using ::android::hardware::EventFlag;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::MessageQueue;
using ::android::hardware::MQDescriptor;
using ::android::hardware::Return;
using ::android::hardware::Void;
struct Sensors : public ISensors, public ISensorsEventCallback {
using Event = ::android::hardware::sensors::V1_0::Event;
using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
using Result = ::android::hardware::sensors::V1_0::Result;
using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
Sensors();
virtual ~Sensors();
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
Return<Result> setOperationMode(OperationMode mode) override;
Return<Result> activate(int32_t sensorHandle, bool enabled) override;
Return<Result> initialize(
const ::android::hardware::MQDescriptorSync<Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<ISensorsCallback>& sensorsCallback) override;
Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
int64_t maxReportLatencyNs) override;
Return<Result> flush(int32_t sensorHandle) override;
Return<Result> injectSensorData(const Event& event) override;
Return<void> registerDirectChannel(const SharedMemInfo& mem,
registerDirectChannel_cb _hidl_cb) override;
Return<Result> unregisterDirectChannel(int32_t channelHandle) override;
Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
configDirectReport_cb _hidl_cb) override;
void postEvents(const std::vector<Event>& events, bool wakeup) override;
private:
/**
* Add a new sensor
*/
template <class SensorType>
void AddSensor() {
std::shared_ptr<SensorType> sensor =
std::make_shared<SensorType>(mNextHandle++ /* sensorHandle */, this /* callback */);
mSensors[sensor->getSensorInfo().sensorHandle] = sensor;
}
/**
* Utility function to delete the Event Flag
*/
void deleteEventFlag();
/**
* Function to read the Wake Lock FMQ and release the wake lock when appropriate
*/
void readWakeLockFMQ();
static void startReadWakeLockThread(Sensors* sensors);
/**
* Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events
*/
void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled);
using EventMessageQueue = MessageQueue<Event, kSynchronizedReadWrite>;
using WakeLockMessageQueue = MessageQueue<uint32_t, kSynchronizedReadWrite>;
/**
* The Event FMQ where sensor events are written
*/
std::unique_ptr<EventMessageQueue> mEventQueue;
/**
* The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events
*/
std::unique_ptr<WakeLockMessageQueue> mWakeLockQueue;
/**
* Event Flag to signal to the framework when sensor events are available to be read
*/
EventFlag* mEventQueueFlag;
/**
* Callback for asynchronous events, such as dynamic sensor connections.
*/
sp<ISensorsCallback> mCallback;
/**
* A map of the available sensors
*/
std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
/**
* The next available sensor handle
*/
int32_t mNextHandle;
/**
* Lock to protect writes to the FMQs
*/
std::mutex mWriteLock;
/**
* Lock to protect acquiring and releasing the wake lock
*/
std::mutex mWakeLockLock;
/**
* Track the number of WAKE_UP events that have not been handled by the framework
*/
uint32_t mOutstandingWakeUpEvents;
/**
* A thread to read the Wake Lock FMQ
*/
std::thread mWakeLockThread;
/**
* Flag to indicate that the Wake Lock Thread should continue to run
*/
std::atomic_bool mReadWakeLockQueueRun;
/**
* Track the time when the wake lock should automatically be released
*/
int64_t mAutoReleaseWakeLockTime;
/**
* Flag to indicate if a wake lock has been acquired
*/
bool mHasWakeLock;
};
} // namespace implementation
} // namespace V2_0
} // namespace sensors
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_SENSORS_V2_0_SENSORS_H

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2020 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.
*/
#ifndef ANDROID_HARDWARE_SENSORS_V2_0_H
#define ANDROID_HARDWARE_SENSORS_V2_0_H
#include "Sensors.h"
#include <android/hardware/sensors/2.0/ISensors.h>
namespace android {
namespace hardware {
namespace sensors {
namespace V2_0 {
namespace implementation {
struct SensorsV2_0 : public ::android::hardware::sensors::V2_X::implementation::Sensors<ISensors> {
};
} // namespace implementation
} // namespace V2_0
} // namespace sensors
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_SENSORS_V2_0_H

View File

@@ -20,17 +20,17 @@
#include <hidl/HidlTransportSupport.h>
#include <log/log.h>
#include <utils/StrongPointer.h>
#include "Sensors.h"
#include "SensorsV2_0.h"
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::sensors::V2_0::ISensors;
using android::hardware::sensors::V2_0::implementation::Sensors;
using android::hardware::sensors::V2_0::implementation::SensorsV2_0;
int main(int /* argc */, char** /* argv */) {
configureRpcThreadpool(1, true);
android::sp<ISensors> sensors = new Sensors();
android::sp<ISensors> sensors = new SensorsV2_0();
if (sensors->registerAsService() != ::android::OK) {
ALOGE("Failed to register Sensors HAL instance");
return -1;

View File

@@ -19,8 +19,10 @@ cc_test {
cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"SensorsHidlEnvironmentV2_0.cpp",
"VtsHalSensorsV2_0TargetTest.cpp"
"VtsHalSensorsV2_0TargetTest.cpp",
],
header_libs: [
"android.hardware.sensors@2.X-shared-utils",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
@@ -29,9 +31,15 @@ cc_test {
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
"libfmq",
"VtsHalSensorsTargetTestUtils",
"VtsHalSensorsV2_XTargetTest",
],
test_suites: [
"general-tests",
"vts-core",
],
}

File diff suppressed because it is too large Load Diff

21
sensors/2.1/Android.bp Normal file
View File

@@ -0,0 +1,21 @@
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "android.hardware.sensors@2.1",
root: "android.hardware",
vndk: {
enabled: true,
},
srcs: [
"types.hal",
"ISensors.hal",
"ISensorsCallback.hal",
],
interfaces: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
"android.hidl.base@1.0",
],
gen_java: false,
gen_java_constants: true,
}

148
sensors/2.1/ISensors.hal Normal file
View File

@@ -0,0 +1,148 @@
/*
* Copyright (C) 2020 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.
*/
package android.hardware.sensors@2.1;
import @1.0::Result;
import @2.0::ISensors;
import @2.1::ISensorsCallback;
interface ISensors extends @2.0::ISensors {
/**
* Enumerate all available (static) sensors.
*
* The SensorInfo for each sensor returned by getSensorsList must be stable
* from the initial call to getSensorsList after a device boot until the
* entire system restarts. The SensorInfo for each sensor must not change
* between subsequent calls to getSensorsList, even across restarts of the
* HAL and its dependencies (for example, the sensor handle for a given
* sensor must not change across HAL restarts).
*/
getSensorsList_2_1() generates (vec<SensorInfo> list);
/**
* Initialize the Sensors HAL's Fast Message Queues (FMQ) and callback.
*
* The Fast Message Queues (FMQ) that are used to send data between the
* framework and the HAL. The callback is used by the HAL to notify the
* framework of asynchronous events, such as a dynamic sensor connection.
*
* The Event FMQ is used to transport sensor events from the HAL to the
* framework. The Event FMQ is created using the eventQueueDescriptor.
* Data may only be written to the Event FMQ. Data must not be read from
* the Event FMQ since the framework is the only reader. Upon receiving
* sensor events, the HAL writes the sensor events to the Event FMQ.
*
* Once the HAL is finished writing sensor events to the Event FMQ, the HAL
* must notify the framework that sensor events are available to be read and
* processed. This is accomplished by either:
* 1) Calling the Event FMQs EventFlag::wake() function with
EventQueueFlagBits::READ_AND_PROCESS
* 2) Setting the write notification in the Event FMQs writeBlocking()
* function to EventQueueFlagBits::READ_AND_PROCESS.
*
* If the Event FMQs writeBlocking() function is used, the read
* notification must be set to EventQueueFlagBits::EVENTS_READ in order to
* be notified and unblocked when the framework has successfully read events
* from the Event FMQ.
*
* The Wake Lock FMQ is used by the framework to notify the HAL when it is
* safe to release its wake_lock. When the framework receives WAKE_UP events
* from the Event FMQ and the framework has acquired a wake_lock, the
* framework must write the number of WAKE_UP events processed to the Wake
* Lock FMQ. When the HAL reads the data from the Wake Lock FMQ, the HAL
* decrements its current count of unprocessed WAKE_UP events and releases
* its wake_lock if the current count of unprocessed WAKE_UP events is
* zero. It is important to note that the HAL must acquire the wake lock and
* update its internal state regarding the number of outstanding WAKE_UP
* events _before_ posting the event to the Wake Lock FMQ, in order to avoid
* a race condition that can lead to loss of wake lock synchronization with
* the framework.
*
* The framework must use the WakeLockQueueFlagBits::DATA_WRITTEN value to
* notify the HAL that data has been written to the Wake Lock FMQ and must
* be read by HAL.
*
* The ISensorsCallback is used by the HAL to notify the framework of
* asynchronous events, such as a dynamic sensor connection.
*
* The name of any wake_lock acquired by the Sensors HAL for WAKE_UP events
* must begin with "SensorsHAL_WAKEUP".
*
* If WAKE_LOCK_TIMEOUT_SECONDS has elapsed since the most recent WAKE_UP
* event was written to the Event FMQ without receiving a message on the
* Wake Lock FMQ, then any held wake_lock for WAKE_UP events must be
* released.
*
* If either the Event FMQ or the Wake Lock FMQ is already initialized when
* initialize is invoked, then both existing FMQs must be discarded and the
* new descriptors must be used to create new FMQs within the HAL. The
* number of outstanding WAKE_UP events should also be reset to zero, and
* any outstanding wake_locks held as a result of WAKE_UP events should be
* released.
*
* All active sensor requests and direct channels must be closed and
* properly cleaned up when initialize is called in order to ensure that the
* HAL and framework's state is consistent (e.g. after a runtime restart).
*
* initialize must be thread safe and prevent concurrent calls
* to initialize from simultaneously modifying state.
*
* @param eventQueueDescriptor Fast Message Queue descriptor that is used to
* create the Event FMQ which is where sensor events are written. The
* descriptor is obtained from the framework's FMQ that is used to read
* sensor events.
* @param wakeLockDescriptor Fast Message Queue descriptor that is used to
* create the Wake Lock FMQ which is where wake_lock events are read
* from. The descriptor is obtained from the framework's FMQ that is
* used to write wake_lock events.
* @param sensorsCallback sensors callback that receives asynchronous data
* from the Sensors HAL.
* @return result OK on success; BAD_VALUE if descriptor is invalid (such
* as null)
*/
@entry
@callflow(next = {"getSensorsList"})
initialize_2_1(fmq_sync<Event> eventQueueDescriptor,
fmq_sync<uint32_t> wakeLockDescriptor,
ISensorsCallback sensorsCallback)
generates
(Result result);
/**
* Inject a single sensor event or push operation environment parameters to
* device.
*
* When device is in NORMAL mode, this function is called to push operation
* environment data to device. In this operation, Event is always of
* SensorType::AdditionalInfo type. See operation evironment parameters
* section in AdditionalInfoType.
*
* When device is in DATA_INJECTION mode, this function is also used for
* injecting sensor events.
*
* Regardless of OperationMode, injected SensorType::ADDITIONAL_INFO
* type events should not be routed back to the sensor event queue.
*
* @see AdditionalInfoType
* @see OperationMode
* @param event sensor event to be injected
* @return result OK on success; PERMISSION_DENIED if operation is not
* allowed; INVALID_OPERATION, if this functionality is unsupported;
* BAD_VALUE if sensor event cannot be injected.
*/
injectSensorData_2_1(Event event) generates (Result result);
};

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2020 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.
*/
package android.hardware.sensors@2.1;
import @2.0::ISensorsCallback;
import @2.1::SensorInfo;
interface ISensorsCallback extends @2.0::ISensorsCallback {
/**
* Notify the framework that new dynamic sensors have been connected.
*
* If a dynamic sensor was previously connected and has not been
* disconnected, then that sensor must not be included in sensorInfos.
*
* @param sensorInfos vector of SensorInfo for each dynamic sensor that
* was connected.
*/
oneway onDynamicSensorsConnected_2_1(vec<SensorInfo> sensorInfos);
};

View File

@@ -0,0 +1,45 @@
//
// Copyright (C) 2018 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.
cc_binary {
name: "android.hardware.sensors@2.1-service.mock",
defaults: ["hidl_defaults"],
vendor: true,
relative_install_path: "hw",
srcs: [
"SensorsV2_1.cpp",
"service.cpp",
],
init_rc: ["android.hardware.sensors@2.1-service-mock.rc"],
header_libs: [
"android.hardware.sensors@2.X-shared-utils",
],
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
"libcutils",
"libfmq",
"libhidlbase",
"liblog",
"libpower",
"libutils",
],
static_libs: [
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.X-shared-impl",
],
vintf_fragments: ["android.hardware.sensors@2.1.xml"],
}

View File

@@ -0,0 +1,3 @@
arthuri@google.com
bduddie@google.com
stange@google.com

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2020 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 "SensorsV2_1.h"
#include "Sensor.h"
namespace android {
namespace hardware {
namespace sensors {
namespace V2_1 {
namespace implementation {
using V2_X::implementation::ISensorsEventCallback;
using V2_X::implementation::OnChangeSensor;
class HingeAngleSensor : public OnChangeSensor {
public:
HingeAngleSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
: OnChangeSensor(callback) {
mSensorInfo.sensorHandle = sensorHandle;
mSensorInfo.name = "Hinge Angle Sensor";
mSensorInfo.vendor = "Vendor String";
mSensorInfo.version = 1;
mSensorInfo.type = SensorType::HINGE_ANGLE;
mSensorInfo.typeAsString = "";
mSensorInfo.maxRange = 360.0f;
mSensorInfo.resolution = 1.0f;
mSensorInfo.power = 0.001f;
mSensorInfo.minDelay = 40 * 1000; // microseconds
mSensorInfo.maxDelay = V2_X::implementation::kDefaultMaxDelayUs;
mSensorInfo.fifoReservedEventCount = 0;
mSensorInfo.fifoMaxEventCount = 0;
mSensorInfo.requiredPermission = "";
mSensorInfo.flags = static_cast<uint32_t>(V1_0::SensorFlagBits::ON_CHANGE_MODE);
}
};
SensorsV2_1::SensorsV2_1() {
AddSensor<HingeAngleSensor>();
}
// Methods from ::android::hardware::sensors::V2_1::ISensors follow.
Return<void> SensorsV2_1::getSensorsList_2_1(ISensors::getSensorsList_2_1_cb _hidl_cb) {
std::vector<SensorInfo> sensors;
for (const auto& sensor : mSensors) {
sensors.push_back(sensor.second->getSensorInfo());
}
// Call the HIDL callback with the SensorInfo
_hidl_cb(sensors);
return Void();
}
Return<Result> SensorsV2_1::initialize_2_1(
const ::android::hardware::MQDescriptorSync<V2_1::Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<V2_1::ISensorsCallback>& sensorsCallback) {
auto eventQueue = std::make_unique<MessageQueue<V2_1::Event, kSynchronizedReadWrite>>(
eventQueueDescriptor, true /* resetPointers */);
std::unique_ptr<EventMessageQueueWrapperBase> wrapper =
std::make_unique<EventMessageQueueWrapperV2_1>(eventQueue);
mCallbackWrapper = new ISensorsCallbackWrapper(sensorsCallback);
return initializeBase(wrapper, wakeLockDescriptor, mCallbackWrapper);
}
Return<Result> SensorsV2_1::injectSensorData_2_1(const V2_1::Event& event) {
return injectSensorData(convertToOldEvent(event));
}
} // namespace implementation
} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2020 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.
*/
#ifndef ANDROID_HARDWARE_SENSORS_V2_1_H
#define ANDROID_HARDWARE_SENSORS_V2_1_H
#include "Sensors.h"
#include "EventMessageQueueWrapper.h"
#include <android/hardware/sensors/2.1/ISensors.h>
namespace android {
namespace hardware {
namespace sensors {
namespace V2_1 {
namespace implementation {
using Result = ::android::hardware::sensors::V1_0::Result;
using Sensors = ::android::hardware::sensors::V2_X::implementation::Sensors<ISensors>;
class ISensorsCallbackWrapper : public V2_0::ISensorsCallback {
public:
ISensorsCallbackWrapper(const sp<V2_1::ISensorsCallback>& callback) : mCallback(callback) {}
Return<void> onDynamicSensorsConnected(const hidl_vec<V1_0::SensorInfo>& sensorInfos) override {
return mCallback->onDynamicSensorsConnected_2_1(convertToNewSensorInfos(sensorInfos));
}
Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& sensorHandles) override {
return mCallback->onDynamicSensorsDisconnected(sensorHandles);
}
private:
sp<V2_1::ISensorsCallback> mCallback;
};
struct SensorsV2_1 : public Sensors {
SensorsV2_1();
// Methods from ::android::hardware::sensors::V2_1::ISensors follow.
Return<void> getSensorsList_2_1(ISensors::getSensorsList_2_1_cb _hidl_cb) override;
Return<Result> initialize_2_1(
const ::android::hardware::MQDescriptorSync<V2_1::Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<V2_1::ISensorsCallback>& sensorsCallback) override;
Return<Result> injectSensorData_2_1(const V2_1::Event& event) override;
private:
sp<ISensorsCallbackWrapper> mCallbackWrapper;
};
} // namespace implementation
} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_SENSORS_V2_1_H

View File

@@ -0,0 +1,7 @@
service vendor.sensors-hal-2-1-mock /vendor/bin/hw/android.hardware.sensors@2.1-service.mock
interface android.hardware.sensors@2.0::ISensors default
interface android.hardware.sensors@2.1::ISensors default
class hal
user system
group system
rlimit rtprio 10 10

View File

@@ -0,0 +1,11 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.sensors</name>
<transport>hwbinder</transport>
<version>2.1</version>
<interface>
<name>ISensors</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2018 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.
*/
#define LOG_TAG "android.hardware.sensors@2.1-service"
#include <android/hardware/sensors/2.1/ISensors.h>
#include <hidl/HidlTransportSupport.h>
#include <log/log.h>
#include <utils/StrongPointer.h>
#include "SensorsV2_1.h"
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::sensors::V2_1::ISensors;
using android::hardware::sensors::V2_1::implementation::SensorsV2_1;
int main(int /* argc */, char** /* argv */) {
configureRpcThreadpool(1, true);
android::sp<ISensors> sensors = new SensorsV2_1();
if (sensors->registerAsService() != ::android::OK) {
ALOGE("Failed to register Sensors HAL instance");
return -1;
}
joinRpcThreadpool();
return 1; // joinRpcThreadpool shouldn't exit
}

160
sensors/2.1/types.hal Normal file
View File

@@ -0,0 +1,160 @@
/*
* Copyright (C) 2020 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.
*/
package android.hardware.sensors@2.1;
import @1.0::EventPayload;
import @1.0::SensorType;
import @1.0::SensorFlagBits;
@export(name="", value_prefix="SENSOR_TYPE_")
enum SensorType : @1.0::SensorType {
/**
* HINGE_ANGLE
* reporting-mode: on-change
* wake-up sensor: yes
*
* A sensor of this type measures the angle, in degrees, between two
* integral parts of the device. Movement of a hinge measured by this sensor
* type is expected to alter the ways in which the user may interact with
* the device, for example by unfolding or revealing a display.
*
* Sensor data is output using @1.0::EventPayload.scalar.
*
* Implement wake-up proximity sensor before implementing a non wake-up
* proximity sensor.
*/
HINGE_ANGLE = 36,
};
struct Event {
/** Time measured in nanoseconds, in "elapsedRealtimeNano()'s" timebase. */
int64_t timestamp;
/** sensor identifier */
int32_t sensorHandle;
@2.1::SensorType sensorType;
/** Union discriminated on sensorType */
EventPayload u;
};
struct SensorInfo {
/**
* handle that identifies this sensors. This handle is used to reference
* this sensor throughout the HAL API.
*/
int32_t sensorHandle;
/**
* Name of this sensor.
* All sensors of the same "type" must have a different "name".
*/
string name;
/** vendor of the hardware part */
string vendor;
/**
* version of the hardware part + driver. The value of this field
* must increase when the driver is updated in a way that changes the
* output of this sensor. This is important for fused sensors when the
* fusion algorithm is updated.
*/
int32_t version;
/** this sensor's type. */
@2.1::SensorType type;
/**
* type of this sensor as a string.
*
* When defining an OEM specific sensor or sensor manufacturer specific
* sensor, use your reserve domain name as a prefix.
* e.g. com.google.glass.onheaddetector
*
* For sensors of known type defined in SensorType (value <
* SensorType::DEVICE_PRIVATE_BASE), this can be an empty string.
*/
string typeAsString;
/** maximum range of this sensor's value in SI units */
float maxRange;
/** smallest difference between two values reported by this sensor */
float resolution;
/** rough estimate of this sensor's power consumption in mA */
float power;
/**
* this value depends on the reporting mode:
*
* continuous: minimum sample period allowed in microseconds
* on-change : 0
* one-shot :-1
* special : 0, unless otherwise noted
*/
int32_t minDelay;
/**
* number of events reserved for this sensor in the batch mode FIFO.
* If there is a dedicated FIFO for this sensor, then this is the
* size of this FIFO. If the FIFO is shared with other sensors,
* this is the size reserved for that sensor and it can be zero.
*/
uint32_t fifoReservedEventCount;
/**
* maximum number of events of this sensor that could be batched.
* This is especially relevant when the FIFO is shared between
* several sensors; this value is then set to the size of that FIFO.
*/
uint32_t fifoMaxEventCount;
/**
* permission required to see this sensor, register to it and receive data.
* Set to "" if no permission is required. Some sensor types like the
* heart rate monitor have a mandatory require_permission.
* For sensors that always require a specific permission, like the heart
* rate monitor, the android framework might overwrite this string
* automatically.
*/
string requiredPermission;
/**
* This value is defined only for continuous mode and on-change sensors.
* It is the delay between two sensor events corresponding to the lowest
* frequency that this sensor supports. When lower frequencies are requested
* through batch()/setDelay() the events will be generated at this frequency
* instead.
* It can be used by the framework or applications to estimate when the
* batch FIFO may be full.
*
* NOTE: periodNs is in nanoseconds where as maxDelay/minDelay are in
* microseconds.
*
* continuous, on-change: maximum sampling period allowed in
* microseconds.
*
* one-shot, special : 0
*/
int32_t maxDelay;
/** Bitmask of SensorFlagBits */
bitfield<SensorFlagBits> flags;
};

View File

@@ -0,0 +1,48 @@
//
// Copyright (C) 2018 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.
//
cc_test {
name: "VtsHalSensorsV2_1TargetTest",
cflags: [
"-DLOG_TAG=\"sensors_hidl_hal_test\"",
"-DSENSORS_HAL_2_1",
],
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"VtsHalSensorsV2_1TargetTest.cpp",
],
header_libs: [
"android.hardware.sensors@2.X-shared-utils",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
"libfmq",
"VtsHalSensorsTargetTestUtils",
"VtsHalSensorsV2_XTargetTest",
],
test_suites: [
"general-tests",
"vts-core",
],
}

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<configuration description="Runs VtsHalSensorsV2_1TargetTest.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="stop"/>
<option name="teardown-command" value="start"/>
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="VtsHalSensorsV2_1TargetTest->/data/local/tmp/VtsHalSensorsV2_1TargetTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-timeout" value="900000" />
<option name="runtime-hint" value="300000"/>
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalSensorsV2_1TargetTest" />
</test>
</configuration>

View File

@@ -0,0 +1,8 @@
# Sensors team
arthuri@google.com
bduddie@google.com
stange@google.com
# VTS team
trong@google.com
yim@google.com

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2020 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 "VtsHalSensorsV2_XTargetTest.h"
INSTANTIATE_TEST_SUITE_P(PerInstance, SensorsHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
android::hardware::sensors::V2_1::ISensors::descriptor)),
android::hardware::PrintInstanceNameToString);

View File

@@ -0,0 +1,37 @@
//
// Copyright (C) 2020 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.
cc_library_static {
name: "android.hardware.sensors@2.X-shared-impl",
vendor: true,
export_include_dirs: ["."],
srcs: [
"Sensor.cpp",
],
header_libs: [
"android.hardware.sensors@2.X-shared-utils",
],
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
"libcutils",
"libfmq",
"libhidlbase",
"liblog",
"libpower",
"libutils",
],
}

View File

@@ -0,0 +1,3 @@
arthuri@google.com
bduddie@google.com
stange@google.com

View File

@@ -23,14 +23,17 @@
namespace android {
namespace hardware {
namespace sensors {
namespace V2_0 {
namespace V2_X {
namespace implementation {
using ::android::hardware::sensors::V1_0::MetaDataEventType;
using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SensorFlagBits;
using ::android::hardware::sensors::V1_0::SensorStatus;
static constexpr float kDefaultMaxDelayUs = 10 * 1000 * 1000;
using ::android::hardware::sensors::V2_1::Event;
using ::android::hardware::sensors::V2_1::SensorInfo;
using ::android::hardware::sensors::V2_1::SensorType;
Sensor::Sensor(ISensorsEventCallback* callback)
: mIsEnabled(false),
@@ -204,8 +207,8 @@ AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
mSensorInfo.typeAsString = "";
mSensorInfo.maxRange = 78.4f; // +/- 8g
mSensorInfo.resolution = 1.52e-5;
mSensorInfo.power = 0.001f; // mA
mSensorInfo.minDelay = 20 * 1000; // microseconds
mSensorInfo.power = 0.001f; // mA
mSensorInfo.minDelay = 20 * 1000; // microseconds
mSensorInfo.maxDelay = kDefaultMaxDelayUs;
mSensorInfo.fifoReservedEventCount = 0;
mSensorInfo.fifoMaxEventCount = 0;
@@ -221,9 +224,9 @@ PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* call
mSensorInfo.version = 1;
mSensorInfo.type = SensorType::PRESSURE;
mSensorInfo.typeAsString = "";
mSensorInfo.maxRange = 1100.0f; // hPa
mSensorInfo.resolution = 0.005f; // hPa
mSensorInfo.power = 0.001f; // mA
mSensorInfo.maxRange = 1100.0f; // hPa
mSensorInfo.resolution = 0.005f; // hPa
mSensorInfo.power = 0.001f; // mA
mSensorInfo.minDelay = 100 * 1000; // microseconds
mSensorInfo.maxDelay = kDefaultMaxDelayUs;
mSensorInfo.fifoReservedEventCount = 0;
@@ -242,7 +245,7 @@ MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallba
mSensorInfo.typeAsString = "";
mSensorInfo.maxRange = 1300.0f;
mSensorInfo.resolution = 0.01f;
mSensorInfo.power = 0.001f; // mA
mSensorInfo.power = 0.001f; // mA
mSensorInfo.minDelay = 20 * 1000; // microseconds
mSensorInfo.maxDelay = kDefaultMaxDelayUs;
mSensorInfo.fifoReservedEventCount = 0;
@@ -261,8 +264,8 @@ LightSensor::LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
mSensorInfo.typeAsString = "";
mSensorInfo.maxRange = 43000.0f;
mSensorInfo.resolution = 10.0f;
mSensorInfo.power = 0.001f; // mA
mSensorInfo.minDelay = 200 * 1000; // microseconds
mSensorInfo.power = 0.001f; // mA
mSensorInfo.minDelay = 200 * 1000; // microseconds
mSensorInfo.maxDelay = kDefaultMaxDelayUs;
mSensorInfo.fifoReservedEventCount = 0;
mSensorInfo.fifoMaxEventCount = 0;
@@ -280,7 +283,7 @@ ProximitySensor::ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* ca
mSensorInfo.typeAsString = "";
mSensorInfo.maxRange = 5.0f;
mSensorInfo.resolution = 1.0f;
mSensorInfo.power = 0.012f; // mA
mSensorInfo.power = 0.012f; // mA
mSensorInfo.minDelay = 200 * 1000; // microseconds
mSensorInfo.maxDelay = kDefaultMaxDelayUs;
mSensorInfo.fifoReservedEventCount = 0;
@@ -367,7 +370,7 @@ RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle,
}
} // namespace implementation
} // namespace V2_0
} // namespace V2_X
} // namespace sensors
} // namespace hardware
} // namespace android

View File

@@ -14,10 +14,11 @@
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_SENSORS_V2_0_SENSOR_H
#define ANDROID_HARDWARE_SENSORS_V2_0_SENSOR_H
#ifndef ANDROID_HARDWARE_SENSORS_V2_X_SENSOR_H
#define ANDROID_HARDWARE_SENSORS_V2_X_SENSOR_H
#include <android/hardware/sensors/1.0/types.h>
#include <android/hardware/sensors/2.1/types.h>
#include <condition_variable>
#include <memory>
@@ -25,26 +26,30 @@
#include <thread>
#include <vector>
using ::android::hardware::sensors::V1_0::Event;
using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SensorInfo;
using ::android::hardware::sensors::V1_0::SensorType;
namespace android {
namespace hardware {
namespace sensors {
namespace V2_0 {
namespace V2_X {
namespace implementation {
static constexpr float kDefaultMaxDelayUs = 10 * 1000 * 1000;
class ISensorsEventCallback {
public:
public:
using Event = ::android::hardware::sensors::V2_1::Event;
virtual ~ISensorsEventCallback(){};
virtual void postEvents(const std::vector<Event>& events, bool wakeup) = 0;
};
class Sensor {
public:
public:
using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
using Result = ::android::hardware::sensors::V1_0::Result;
using Event = ::android::hardware::sensors::V2_1::Event;
using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
using SensorType = ::android::hardware::sensors::V2_1::SensorType;
Sensor(ISensorsEventCallback* callback);
virtual ~Sensor();
@@ -57,7 +62,7 @@ class Sensor {
bool supportsDataInjection() const;
Result injectEvent(const Event& event);
protected:
protected:
void run();
virtual std::vector<Event> readEvents();
static void startThread(Sensor* sensor);
@@ -80,68 +85,68 @@ class Sensor {
};
class OnChangeSensor : public Sensor {
public:
public:
OnChangeSensor(ISensorsEventCallback* callback);
virtual void activate(bool enable) override;
protected:
protected:
virtual std::vector<Event> readEvents() override;
protected:
protected:
Event mPreviousEvent;
bool mPreviousEventSet;
};
class AccelSensor : public Sensor {
public:
public:
AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
class GyroSensor : public Sensor {
public:
public:
GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
class AmbientTempSensor : public OnChangeSensor {
public:
public:
AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
class DeviceTempSensor : public OnChangeSensor {
public:
public:
DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
class PressureSensor : public Sensor {
public:
public:
PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
class MagnetometerSensor : public Sensor {
public:
public:
MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
class LightSensor : public OnChangeSensor {
public:
public:
LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
class ProximitySensor : public OnChangeSensor {
public:
public:
ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
class RelativeHumiditySensor : public OnChangeSensor {
public:
public:
RelativeHumiditySensor(int32_t sensorHandle, ISensorsEventCallback* callback);
};
} // namespace implementation
} // namespace V2_0
} // namespace V2_X
} // namespace sensors
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_SENSORS_V2_0_SENSOR_H
#endif // ANDROID_HARDWARE_SENSORS_V2_X_SENSOR_H

View File

@@ -0,0 +1,377 @@
/*
* Copyright (C) 2018 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.
*/
#ifndef ANDROID_HARDWARE_SENSORS_V2_X_SENSORS_H
#define ANDROID_HARDWARE_SENSORS_V2_X_SENSORS_H
#include "EventMessageQueueWrapper.h"
#include "Sensor.h"
#include <android/hardware/sensors/2.0/ISensors.h>
#include <android/hardware/sensors/2.0/types.h>
#include <fmq/MessageQueue.h>
#include <hardware_legacy/power.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <log/log.h>
#include <atomic>
#include <memory>
#include <thread>
namespace android {
namespace hardware {
namespace sensors {
namespace V2_X {
namespace implementation {
template <class ISensorsInterface>
struct Sensors : public ISensorsInterface, public ISensorsEventCallback {
using Event = ::android::hardware::sensors::V1_0::Event;
using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
using Result = ::android::hardware::sensors::V1_0::Result;
using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
using EventQueueFlagBits = ::android::hardware::sensors::V2_0::EventQueueFlagBits;
using SensorTimeout = ::android::hardware::sensors::V2_0::SensorTimeout;
using WakeLockQueueFlagBits = ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
using ISensorsCallback = ::android::hardware::sensors::V2_0::ISensorsCallback;
using EventMessageQueue = MessageQueue<Event, kSynchronizedReadWrite>;
using WakeLockMessageQueue = MessageQueue<uint32_t, kSynchronizedReadWrite>;
static constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";
Sensors()
: mEventQueueFlag(nullptr),
mNextHandle(1),
mOutstandingWakeUpEvents(0),
mReadWakeLockQueueRun(false),
mAutoReleaseWakeLockTime(0),
mHasWakeLock(false) {
AddSensor<AccelSensor>();
AddSensor<GyroSensor>();
AddSensor<AmbientTempSensor>();
AddSensor<DeviceTempSensor>();
AddSensor<PressureSensor>();
AddSensor<MagnetometerSensor>();
AddSensor<LightSensor>();
AddSensor<ProximitySensor>();
AddSensor<RelativeHumiditySensor>();
}
virtual ~Sensors() {
deleteEventFlag();
mReadWakeLockQueueRun = false;
mWakeLockThread.join();
}
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
Return<void> getSensorsList(V2_0::ISensors::getSensorsList_cb _hidl_cb) override {
std::vector<V1_0::SensorInfo> sensors;
for (const auto& sensor : mSensors) {
sensors.push_back(
V2_1::implementation::convertToOldSensorInfo(sensor.second->getSensorInfo()));
}
// Call the HIDL callback with the SensorInfo
_hidl_cb(sensors);
return Void();
}
Return<Result> setOperationMode(OperationMode mode) override {
for (auto sensor : mSensors) {
sensor.second->setOperationMode(mode);
}
return Result::OK;
}
Return<Result> activate(int32_t sensorHandle, bool enabled) override {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
sensor->second->activate(enabled);
return Result::OK;
}
return Result::BAD_VALUE;
}
Return<Result> initialize(
const ::android::hardware::MQDescriptorSync<Event>& eventQueueDescriptor,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<ISensorsCallback>& sensorsCallback) override {
auto eventQueue =
std::make_unique<EventMessageQueue>(eventQueueDescriptor, true /* resetPointers */);
std::unique_ptr<V2_1::implementation::EventMessageQueueWrapperBase> wrapper =
std::make_unique<V2_1::implementation::EventMessageQueueWrapperV1_0>(eventQueue);
return initializeBase(wrapper, wakeLockDescriptor, sensorsCallback);
}
Return<Result> initializeBase(
std::unique_ptr<V2_1::implementation::EventMessageQueueWrapperBase>& eventQueue,
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<ISensorsCallback>& sensorsCallback) {
Result result = Result::OK;
// Ensure that all sensors are disabled
for (auto sensor : mSensors) {
sensor.second->activate(false /* enable */);
}
// Stop the Wake Lock thread if it is currently running
if (mReadWakeLockQueueRun.load()) {
mReadWakeLockQueueRun = false;
mWakeLockThread.join();
}
// Save a reference to the callback
mCallback = sensorsCallback;
// Save the event queue.
mEventQueue = std::move(eventQueue);
// Ensure that any existing EventFlag is properly deleted
deleteEventFlag();
// Create the EventFlag that is used to signal to the framework that sensor events have been
// written to the Event FMQ
if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) {
result = Result::BAD_VALUE;
}
// Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP
// events have been successfully read and handled by the framework.
mWakeLockQueue = std::make_unique<WakeLockMessageQueue>(wakeLockDescriptor,
true /* resetPointers */);
if (!mCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) {
result = Result::BAD_VALUE;
}
// Start the thread to read events from the Wake Lock FMQ
mReadWakeLockQueueRun = true;
mWakeLockThread = std::thread(startReadWakeLockThread, this);
return result;
}
Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
int64_t /* maxReportLatencyNs */) override {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
sensor->second->batch(samplingPeriodNs);
return Result::OK;
}
return Result::BAD_VALUE;
}
Return<Result> flush(int32_t sensorHandle) override {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
return sensor->second->flush();
}
return Result::BAD_VALUE;
}
Return<Result> injectSensorData(const Event& event) override {
auto sensor = mSensors.find(event.sensorHandle);
if (sensor != mSensors.end()) {
return sensor->second->injectEvent(V2_1::implementation::convertToNewEvent(event));
}
return Result::BAD_VALUE;
}
Return<void> registerDirectChannel(const SharedMemInfo& /* mem */,
V2_0::ISensors::registerDirectChannel_cb _hidl_cb) override {
_hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
return Return<void>();
}
Return<Result> unregisterDirectChannel(int32_t /* channelHandle */) override {
return Result::INVALID_OPERATION;
}
Return<void> configDirectReport(int32_t /* sensorHandle */, int32_t /* channelHandle */,
RateLevel /* rate */,
V2_0::ISensors::configDirectReport_cb _hidl_cb) override {
_hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */);
return Return<void>();
}
void postEvents(const std::vector<V2_1::Event>& events, bool wakeup) override {
std::lock_guard<std::mutex> lock(mWriteLock);
if (mEventQueue->write(events)) {
mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));
if (wakeup) {
// Keep track of the number of outstanding WAKE_UP events in order to properly hold
// a wake lock until the framework has secured a wake lock
updateWakeLock(events.size(), 0 /* eventsHandled */);
}
}
}
protected:
/**
* Add a new sensor
*/
template <class SensorType>
void AddSensor() {
std::shared_ptr<SensorType> sensor =
std::make_shared<SensorType>(mNextHandle++ /* sensorHandle */, this /* callback */);
mSensors[sensor->getSensorInfo().sensorHandle] = sensor;
}
/**
* Utility function to delete the Event Flag
*/
void deleteEventFlag() {
status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag);
if (status != OK) {
ALOGI("Failed to delete event flag: %d", status);
}
}
static void startReadWakeLockThread(Sensors* sensors) { sensors->readWakeLockFMQ(); }
/**
* Function to read the Wake Lock FMQ and release the wake lock when appropriate
*/
void readWakeLockFMQ() {
while (mReadWakeLockQueueRun.load()) {
constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000; // 500 ms
uint32_t eventsHandled = 0;
// Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to
// ensure that any held wake lock is able to be released if it is held for too long.
mWakeLockQueue->readBlocking(&eventsHandled, 1 /* count */, 0 /* readNotification */,
static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN),
kReadTimeoutNs);
updateWakeLock(0 /* eventsWritten */, eventsHandled);
}
}
/**
* Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events
*/
void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) {
std::lock_guard<std::mutex> lock(mWakeLockLock);
int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled;
if (newVal < 0) {
mOutstandingWakeUpEvents = 0;
} else {
mOutstandingWakeUpEvents = newVal;
}
if (eventsWritten > 0) {
// Update the time at which the last WAKE_UP event was sent
mAutoReleaseWakeLockTime =
::android::uptimeMillis() +
static_cast<uint32_t>(SensorTimeout::WAKE_LOCK_SECONDS) * 1000;
}
if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 &&
acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) {
mHasWakeLock = true;
} else if (mHasWakeLock) {
// Check if the wake lock should be released automatically if
// SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written
// to the Wake Lock FMQ.
if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) {
ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock",
SensorTimeout::WAKE_LOCK_SECONDS);
mOutstandingWakeUpEvents = 0;
}
if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) {
mHasWakeLock = false;
}
}
}
/**
* The Event FMQ where sensor events are written
*/
std::unique_ptr<V2_1::implementation::EventMessageQueueWrapperBase> mEventQueue;
/**
* The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events
*/
std::unique_ptr<WakeLockMessageQueue> mWakeLockQueue;
/**
* Event Flag to signal to the framework when sensor events are available to be read
*/
EventFlag* mEventQueueFlag;
/**
* Callback for asynchronous events, such as dynamic sensor connections.
*/
sp<ISensorsCallback> mCallback;
/**
* A map of the available sensors
*/
std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
/**
* The next available sensor handle
*/
int32_t mNextHandle;
/**
* Lock to protect writes to the FMQs
*/
std::mutex mWriteLock;
/**
* Lock to protect acquiring and releasing the wake lock
*/
std::mutex mWakeLockLock;
/**
* Track the number of WAKE_UP events that have not been handled by the framework
*/
uint32_t mOutstandingWakeUpEvents;
/**
* A thread to read the Wake Lock FMQ
*/
std::thread mWakeLockThread;
/**
* Flag to indicate that the Wake Lock Thread should continue to run
*/
std::atomic_bool mReadWakeLockQueueRun;
/**
* Track the time when the wake lock should automatically be released
*/
int64_t mAutoReleaseWakeLockTime;
/**
* Flag to indicate if a wake lock has been acquired
*/
bool mHasWakeLock;
};
} // namespace implementation
} // namespace V2_X
} // namespace sensors
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_SENSORS_V2_X_SENSORS_H

View File

@@ -0,0 +1,36 @@
//
// Copyright (C) 2020 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.
cc_library_headers {
name: "android.hardware.sensors@2.X-shared-utils",
vendor_available: true,
defaults: ["hidl_defaults"],
export_include_dirs: ["."],
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
"libbinder",
"libcutils",
"libfmq",
"libhidlbase",
"liblog",
"libpower",
"libutils",
],
static_libs: [
"android.hardware.sensors@1.0-convert",
],
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2020 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.
*/
#ifndef ANDROID_HARDWARE_SENSORS_V2_1_EVENTMESSAGEQUEUEWRAPPER_H
#define ANDROID_HARDWARE_SENSORS_V2_1_EVENTMESSAGEQUEUEWRAPPER_H
#include "convertV2_1.h"
#include <android/hardware/sensors/2.1/types.h>
#include <fmq/MessageQueue.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <log/log.h>
#include <atomic>
namespace android {
namespace hardware {
namespace sensors {
namespace V2_1 {
namespace implementation {
class EventMessageQueueWrapperBase : public RefBase {
public:
virtual ~EventMessageQueueWrapperBase() {}
virtual std::atomic<uint32_t>* getEventFlagWord() = 0;
virtual size_t availableToRead() = 0;
virtual bool read(V2_1::Event* events, size_t numToRead) = 0;
virtual bool write(const std::vector<V2_1::Event>& events) = 0;
};
class EventMessageQueueWrapperV1_0 : public EventMessageQueueWrapperBase {
public:
using EventMessageQueue = MessageQueue<V1_0::Event, kSynchronizedReadWrite>;
EventMessageQueueWrapperV1_0(std::unique_ptr<EventMessageQueue>& queue)
: mQueue(std::move(queue)) {}
const ::android::hardware::MQDescriptorSync<V1_0::Event>* getDesc() {
return mQueue->getDesc();
}
virtual std::atomic<uint32_t>* getEventFlagWord() override {
return mQueue->getEventFlagWord();
}
virtual size_t availableToRead() override { return mQueue->availableToRead(); }
virtual bool read(V2_1::Event* events, size_t numToRead) override {
return mQueue->read(reinterpret_cast<V1_0::Event*>(events), numToRead);
}
virtual bool write(const std::vector<V2_1::Event>& events) override {
const std::vector<V1_0::Event>& oldEvents = convertToOldEvents(events);
return mQueue->write(oldEvents.data(), oldEvents.size());
}
private:
std::unique_ptr<EventMessageQueue> mQueue;
};
class EventMessageQueueWrapperV2_1 : public EventMessageQueueWrapperBase {
public:
using EventMessageQueue = MessageQueue<V2_1::Event, kSynchronizedReadWrite>;
EventMessageQueueWrapperV2_1(std::unique_ptr<EventMessageQueue>& queue)
: mQueue(std::move(queue)) {}
const ::android::hardware::MQDescriptorSync<V2_1::Event>* getDesc() {
return mQueue->getDesc();
}
std::atomic<uint32_t>* getEventFlagWord() override { return mQueue->getEventFlagWord(); }
virtual size_t availableToRead() override { return mQueue->availableToRead(); }
virtual bool read(V2_1::Event* events, size_t numToRead) override {
return mQueue->read(events, numToRead);
}
bool write(const std::vector<V2_1::Event>& events) override {
return mQueue->write(events.data(), events.size());
}
private:
std::unique_ptr<EventMessageQueue> mQueue;
};
} // namespace implementation
} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_SENSORS_V2_1_EVENTMESSAGEQUEUEWRAPPER_H

View File

@@ -0,0 +1,209 @@
/*
* Copyright (C) 2020 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.
*/
#ifndef ANDROID_HARDWARE_SENSORS_V2_1_ISENSORSWRAPPER_H
#define ANDROID_HARDWARE_SENSORS_V2_1_ISENSORSWRAPPER_H
#include "EventMessageQueueWrapper.h"
#include "convertV2_1.h"
#include <android/hardware/sensors/2.1/ISensors.h>
#include <android/hardware/sensors/2.1/types.h>
#include <binder/IBinder.h>
#include <fmq/MessageQueue.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <log/log.h>
#include <atomic>
/**
* ISensorsWrapperBase wraps around the V2_1::ISensors APIs to make any HAL 2.0/2.1 interface
* appear as a HAL 2.1 implementation. This ensures the maximum amount of code can be shared
* between VTS, default implementations, and the sensors framework.
*/
namespace android {
namespace hardware {
namespace sensors {
namespace V2_1 {
namespace implementation {
using ::android::sp;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::RateLevel;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SharedMemInfo;
// TODO: Look into providing this as a param if it needs to be a different value
// than the framework.
static constexpr size_t MAX_RECEIVE_BUFFER_EVENT_COUNT = 256;
class ISensorsWrapperBase : public RefBase {
public:
virtual ~ISensorsWrapperBase() {}
virtual EventMessageQueueWrapperBase& getEventQueue() = 0;
virtual Return<void> getSensorsList(V2_1::ISensors::getSensorsList_2_1_cb _hidl_cb) = 0;
virtual Return<Result> injectSensorData(const V2_1::Event& event) = 0;
virtual Return<Result> initialize(
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<V2_1::ISensorsCallback>& sensorsCallback) = 0;
// V2_0::ISensors implementation
void linkToDeath(android::sp<android::hardware::hidl_death_recipient> deathRecipient,
uint64_t cookie) {
getSensors()->linkToDeath(deathRecipient, cookie);
}
Return<Result> activate(int32_t sensorHandle, bool enabled) {
return getSensors()->activate(sensorHandle, enabled);
}
Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
int64_t maxReportLatencyNs) {
return getSensors()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
}
Return<Result> flush(int32_t sensorHandle) { return getSensors()->flush(sensorHandle); }
Return<void> registerDirectChannel(const SharedMemInfo& mem,
V2_0::ISensors::registerDirectChannel_cb _hidl_cb) {
return getSensors()->registerDirectChannel(mem, _hidl_cb);
}
Return<Result> unregisterDirectChannel(int32_t channelHandle) {
return getSensors()->unregisterDirectChannel(channelHandle);
}
Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
V2_0::ISensors::configDirectReport_cb _hidl_cb) {
return getSensors()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
}
Return<Result> setOperationMode(OperationMode mode) {
return getSensors()->setOperationMode(mode);
}
private:
virtual V2_0::ISensors* getSensors() = 0;
};
class ISensorsWrapperV2_0 : public ISensorsWrapperBase {
public:
typedef MessageQueue<V1_0::Event, ::android::hardware::kSynchronizedReadWrite>
EventMessageQueue;
ISensorsWrapperV2_0(sp<V2_0::ISensors>& sensors) : mSensors(sensors) {
auto eventQueue = std::make_unique<EventMessageQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
true /* configureEventFlagWord */);
mEventQueue = std::make_unique<EventMessageQueueWrapperV1_0>(eventQueue);
}
EventMessageQueueWrapperBase& getEventQueue() override { return *mEventQueue; }
Return<Result> initialize(
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<V2_1::ISensorsCallback>& sensorsCallback) override {
return mSensors->initialize(*mEventQueue->getDesc(), wakeLockDescriptor, sensorsCallback);
}
Return<void> getSensorsList(V2_1::ISensors::getSensorsList_2_1_cb _hidl_cb) override {
return getSensors()->getSensorsList(
[&](const auto& list) { _hidl_cb(convertToNewSensorInfos(list)); });
}
Return<Result> injectSensorData(const V2_1::Event& event) override {
return mSensors->injectSensorData(convertToOldEvent(event));
}
private:
V2_0::ISensors* getSensors() override { return mSensors.get(); }
sp<V2_0::ISensors> mSensors;
std::unique_ptr<EventMessageQueueWrapperV1_0> mEventQueue;
};
class ISensorsWrapperV2_1 : public ISensorsWrapperBase {
public:
typedef MessageQueue<V2_1::Event, ::android::hardware::kSynchronizedReadWrite>
EventMessageQueue;
ISensorsWrapperV2_1(sp<V2_1::ISensors>& sensors) : mSensors(sensors) {
auto eventQueue = std::make_unique<EventMessageQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
true /* configureEventFlagWord */);
mEventQueue = std::make_unique<EventMessageQueueWrapperV2_1>(eventQueue);
}
EventMessageQueueWrapperBase& getEventQueue() override { return *mEventQueue; }
Return<Result> initialize(
const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
const sp<V2_1::ISensorsCallback>& sensorsCallback) override {
return mSensors->initialize_2_1(*mEventQueue->getDesc(), wakeLockDescriptor,
sensorsCallback);
}
Return<void> getSensorsList(V2_1::ISensors::getSensorsList_2_1_cb _hidl_cb) override {
return mSensors->getSensorsList_2_1(_hidl_cb);
}
Return<Result> injectSensorData(const V2_1::Event& event) override {
return mSensors->injectSensorData_2_1(event);
}
private:
V2_0::ISensors* getSensors() override { return mSensors.get(); }
sp<V2_1::ISensors> mSensors;
std::unique_ptr<EventMessageQueueWrapperV2_1> mEventQueue;
};
inline sp<ISensorsWrapperV2_0> wrapISensors(sp<V2_0::ISensors> sensors) {
return new ISensorsWrapperV2_0(sensors);
}
inline sp<ISensorsWrapperV2_1> wrapISensors(sp<V2_1::ISensors> sensors) {
return new ISensorsWrapperV2_1(sensors);
}
class NoOpSensorsCallback : public ISensorsCallback {
public:
Return<void> onDynamicSensorsConnected(
const hidl_vec<V1_0::SensorInfo>& /* sensorInfos */) override {
return Return<void>();
}
Return<void> onDynamicSensorsDisconnected(
const hidl_vec<int32_t>& /* sensorHandles */) override {
return Return<void>();
}
Return<void> onDynamicSensorsConnected_2_1(
const hidl_vec<SensorInfo>& /* sensorInfos */) override {
return Return<void>();
}
};
} // namespace implementation
} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_SENSORS_V2_1_ISENSORSWRAPPER_H

View File

@@ -0,0 +1,3 @@
arthuri@google.com
bduddie@google.com
stange@google.com

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2020 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.
*/
#ifndef ANDROID_HARDWARE_SENSORS_V2_1_CONVERT_H
#define ANDROID_HARDWARE_SENSORS_V2_1_CONVERT_H
#include <android/hardware/sensors/2.1/types.h>
#include <hardware/sensors.h>
#include <sensors/convert.h>
namespace android {
namespace hardware {
namespace sensors {
namespace V2_1 {
namespace implementation {
static_assert(sizeof(V1_0::Event) == sizeof(V2_1::Event),
"New and old Event types must have the same size");
static_assert(sizeof(V1_0::SensorInfo) == sizeof(V2_1::SensorInfo),
"New and old SensorInfo types must have the same size");
// The following conversion methods are safe as the only difference between
// V1_0 and V2_1 for these types is an added enum value to SensorType which doesn't
// change the memory layout of the types.
inline const V1_0::Event& convertToOldEvent(const V2_1::Event& event) {
return reinterpret_cast<const V1_0::Event&>(event);
}
inline const std::vector<V1_0::Event>& convertToOldEvents(const std::vector<V2_1::Event>& events) {
return reinterpret_cast<const std::vector<V1_0::Event>&>(events);
}
inline V1_0::Event* convertToOldEvent(V2_1::Event* event) {
return reinterpret_cast<V1_0::Event*>(event);
}
inline const V2_1::SensorInfo& convertToNewSensorInfo(const V1_0::SensorInfo& info) {
return reinterpret_cast<const V2_1::SensorInfo&>(info);
}
inline const V1_0::SensorInfo& convertToOldSensorInfo(const V2_1::SensorInfo& info) {
return reinterpret_cast<const V1_0::SensorInfo&>(info);
}
inline const V2_1::Event& convertToNewEvent(const V1_0::Event& event) {
return reinterpret_cast<const V2_1::Event&>(event);
}
inline const std::vector<V2_1::Event>& convertToNewEvents(const std::vector<V1_0::Event>& events) {
return reinterpret_cast<const std::vector<V2_1::Event>&>(events);
}
inline const hidl_vec<V2_1::Event>& convertToNewEvents(const hidl_vec<V1_0::Event>& events) {
return reinterpret_cast<const hidl_vec<V2_1::Event>&>(events);
}
inline const hidl_vec<V2_1::SensorInfo>& convertToNewSensorInfos(
const hidl_vec<V1_0::SensorInfo>& infos) {
return reinterpret_cast<const hidl_vec<V2_1::SensorInfo>&>(infos);
}
inline const hidl_vec<V1_0::SensorInfo>& convertToOldSensorInfos(
const hidl_vec<V2_1::SensorInfo>& infos) {
return reinterpret_cast<const hidl_vec<V1_0::SensorInfo>&>(infos);
}
inline void convertFromSensorEvent(const sensors_event_t& src, V2_1::Event* dst) {
switch ((SensorType)src.type) {
case SensorType::HINGE_ANGLE:
// Only fill in values for hinge angle as other sensors
// will have it filled in by legacy code.
*dst = {
.timestamp = src.timestamp,
.sensorHandle = src.sensor,
.sensorType = (SensorType)src.type,
};
dst->u.scalar = src.data[0];
break;
default:
V1_0::implementation::convertFromSensorEvent(src, convertToOldEvent(dst));
break;
}
}
inline void convertToSensorEvent(const V2_1::Event& src, sensors_event_t* dst) {
switch (src.sensorType) {
case SensorType::HINGE_ANGLE:
// Only fill in values for hinge angle as other sensors
// will have it filled in by legacy code.
*dst = {.version = sizeof(sensors_event_t),
.sensor = src.sensorHandle,
.type = (int32_t)src.sensorType,
.reserved0 = 0,
.timestamp = src.timestamp};
dst->data[0] = src.u.scalar;
break;
default:
V1_0::implementation::convertToSensorEvent(convertToOldEvent(src), dst);
break;
}
}
} // namespace implementation
} // namespace V2_1
} // namespace sensors
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_SENSORS_V2_1_CONVERT_H

View File

@@ -0,0 +1,44 @@
//
// Copyright (C) 2018 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.
//
cc_test_library {
name: "VtsHalSensorsV2_XTargetTest",
cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"SensorsHidlEnvironmentV2_X.cpp",
],
export_include_dirs: ["."],
header_libs: [
"android.hardware.sensors@2.X-shared-utils",
],
shared_libs: [
"libbinder",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
"libfmq",
"VtsHalSensorsTargetTestUtils",
],
}

View File

@@ -14,9 +14,11 @@
* limitations under the License.
*/
#include "SensorsHidlEnvironmentV2_0.h"
#include "SensorsHidlEnvironmentV2_X.h"
#include <android/hardware/sensors/2.0/types.h>
#include <android/hardware/sensors/2.1/types.h>
#include <log/log.h>
#include <algorithm>
@@ -26,18 +28,20 @@ using ::android::hardware::EventFlag;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SensorInfo;
using ::android::hardware::sensors::V2_0::EventQueueFlagBits;
using ::android::hardware::sensors::V2_1::SensorInfo;
#ifdef SENSORS_HAL_2_1
using ::android::hardware::sensors::V2_1::ISensors;
#else
using ::android::hardware::sensors::V2_0::ISensors;
using ::android::hardware::sensors::V2_0::ISensorsCallback;
#endif
using ::android::hardware::sensors::V2_1::ISensorsCallback;
template <typename EnumType>
constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
return static_cast<typename std::underlying_type<EnumType>::type>(value);
}
constexpr size_t SensorsHidlEnvironmentV2_0::MAX_RECEIVE_BUFFER_EVENT_COUNT;
void SensorsHalDeathRecipient::serviceDied(
uint64_t /* cookie */,
const ::android::wp<::android::hidl::base::V1_0::IBase>& /* service */) {
@@ -45,48 +49,34 @@ void SensorsHalDeathRecipient::serviceDied(
FAIL() << "Sensors HAL died during test";
}
struct SensorsCallback : ISensorsCallback {
Return<void> onDynamicSensorsConnected(const hidl_vec<SensorInfo>& /* sensorInfos */) {
return Return<void>();
}
Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& /* sensorHandles */) {
return Return<void>();
}
};
bool SensorsHidlEnvironmentV2_0::resetHal() {
bool SensorsHidlEnvironmentV2_X::resetHal() {
bool succeed = false;
do {
mSensors = ISensors::getService(mServiceName);
mSensors = wrapISensors(ISensors::getService(mServiceName));
if (mSensors == nullptr) {
break;
}
mSensors->linkToDeath(mDeathRecipient, 0 /* cookie */);
// Initialize FMQs
mEventQueue = std::make_unique<EventMessageQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
true /* configureEventFlagWord */);
mWakeLockQueue = std::make_unique<WakeLockQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
true /* configureEventFlagWord */);
if (mEventQueue == nullptr || mWakeLockQueue == nullptr) {
if (mWakeLockQueue == nullptr) {
break;
}
EventFlag::deleteEventFlag(&mEventQueueFlag);
EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag);
EventFlag::createEventFlag(mSensors->getEventQueue().getEventFlagWord(), &mEventQueueFlag);
if (mEventQueueFlag == nullptr) {
break;
}
mSensors->initialize(*mEventQueue->getDesc(), *mWakeLockQueue->getDesc(),
new SensorsCallback());
mSensors->initialize(*mWakeLockQueue->getDesc(), new NoOpSensorsCallback());
std::vector<SensorInfo> sensorList;
if (!mSensors->getSensorsList([&](const hidl_vec<SensorInfo>& list) { sensorList = list; })
.isOk()) {
.isOk()) {
break;
}
@@ -113,7 +103,7 @@ bool SensorsHidlEnvironmentV2_0::resetHal() {
return succeed;
}
void SensorsHidlEnvironmentV2_0::HidlTearDown() {
void SensorsHidlEnvironmentV2_X::HidlTearDown() {
mStopThread = true;
if (mEventQueueFlag != nullptr) {
@@ -127,25 +117,25 @@ void SensorsHidlEnvironmentV2_0::HidlTearDown() {
}
}
void SensorsHidlEnvironmentV2_0::startPollingThread() {
void SensorsHidlEnvironmentV2_X::startPollingThread() {
mStopThread = false;
mEvents.reserve(MAX_RECEIVE_BUFFER_EVENT_COUNT);
mPollThread = std::thread(pollingThread, this);
}
void SensorsHidlEnvironmentV2_0::readEvents() {
size_t availableEvents = mEventQueue->availableToRead();
void SensorsHidlEnvironmentV2_X::readEvents() {
size_t availableEvents = mSensors->getEventQueue().availableToRead();
if (availableEvents == 0) {
uint32_t eventFlagState = 0;
mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS), &eventFlagState);
availableEvents = mEventQueue->availableToRead();
availableEvents = mSensors->getEventQueue().availableToRead();
}
size_t eventsToRead = std::min(availableEvents, mEventBuffer.size());
if (eventsToRead > 0) {
if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) {
if (mSensors->getEventQueue().read(mEventBuffer.data(), eventsToRead)) {
mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::EVENTS_READ));
for (size_t i = 0; i < eventsToRead; i++) {
addEvent(mEventBuffer[i]);
@@ -154,7 +144,7 @@ void SensorsHidlEnvironmentV2_0::readEvents() {
}
}
void SensorsHidlEnvironmentV2_0::pollingThread(SensorsHidlEnvironmentV2_0* env) {
void SensorsHidlEnvironmentV2_X::pollingThread(SensorsHidlEnvironmentV2_X* env) {
ALOGD("polling thread start");
while (!env->mStopThread.load()) {

View File

@@ -14,13 +14,15 @@
* limitations under the License.
*/
#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H
#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H
#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_X_H
#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_X_H
#include "ISensorsWrapper.h"
#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
#include <android/hardware/sensors/1.0/types.h>
#include <android/hardware/sensors/2.0/ISensors.h>
#include <android/hardware/sensors/2.1/ISensors.h>
#include <android/hardware/sensors/2.1/types.h>
#include <fmq/MessageQueue.h>
#include <utils/StrongPointer.h>
@@ -30,6 +32,10 @@
using ::android::sp;
using ::android::hardware::MessageQueue;
using ::android::hardware::sensors::V2_1::implementation::ISensorsWrapperBase;
using ::android::hardware::sensors::V2_1::implementation::MAX_RECEIVE_BUFFER_EVENT_COUNT;
using ::android::hardware::sensors::V2_1::implementation::NoOpSensorsCallback;
using ::android::hardware::sensors::V2_1::implementation::wrapISensors;
class SensorsHidlTest;
@@ -39,14 +45,14 @@ class SensorsHalDeathRecipient : public ::android::hardware::hidl_death_recipien
const ::android::wp<::android::hidl::base::V1_0::IBase>& service) override;
};
class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase {
public:
using Event = ::android::hardware::sensors::V1_0::Event;
class SensorsHidlEnvironmentV2_X
: public SensorsHidlEnvironmentBase<::android::hardware::sensors::V2_1::Event> {
public:
virtual void HidlTearDown() override;
protected:
protected:
friend SensorsHidlTest;
SensorsHidlEnvironmentV2_0(const std::string& service_name)
SensorsHidlEnvironmentV2_X(const std::string& service_name)
: SensorsHidlEnvironmentBase(service_name), mEventQueueFlag(nullptr) {}
/**
@@ -66,41 +72,30 @@ class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase {
*
* @param env SensorEnvironment to being polling for events on
*/
static void pollingThread(SensorsHidlEnvironmentV2_0* env);
static void pollingThread(SensorsHidlEnvironmentV2_X* env);
/**
* Reads and saves sensor events from the Event FMQ
*/
void readEvents();
GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV2_0);
GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV2_X);
/**
* Pointer to the Sensors HAL Interface that allows the test to call HAL functions.
*/
sp<android::hardware::sensors::V2_0::ISensors> mSensors;
sp<ISensorsWrapperBase> mSensors;
/**
* Monitors the HAL for crashes, triggering test failure if seen
*/
sp<SensorsHalDeathRecipient> mDeathRecipient = new SensorsHalDeathRecipient();
/**
* Type used to simplify the creation of the Event FMQ
*/
typedef MessageQueue<Event, ::android::hardware::kSynchronizedReadWrite> EventMessageQueue;
/**
* Type used to simplify the creation of the Wake Lock FMQ
*/
typedef MessageQueue<uint32_t, ::android::hardware::kSynchronizedReadWrite> WakeLockQueue;
/**
* The Event FMQ where the test framework is able to read sensor events that the Sensors HAL
* has written.
*/
std::unique_ptr<EventMessageQueue> mEventQueue;
/**
* The Wake Lock FMQ is used by the test to notify the Sensors HAL whenever it has processed
* WAKE_UP sensor events.
@@ -113,15 +108,11 @@ class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase {
*/
::android::hardware::EventFlag* mEventQueueFlag;
/**
* The maximum number of sensor events that can be read from the Event FMQ at one time.
*/
static constexpr size_t MAX_RECEIVE_BUFFER_EVENT_COUNT = 128;
/**
* An array that is used to store sensor events read from the Event FMQ
*/
std::array<Event, MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
std::array<::android::hardware::sensors::V2_1::Event, MAX_RECEIVE_BUFFER_EVENT_COUNT>
mEventBuffer;
};
#endif // ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H
#endif // ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_X_H

File diff suppressed because it is too large Load Diff

View File

@@ -20,9 +20,6 @@ cc_library_static {
cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
srcs: [
"GrallocWrapper.cpp",
"SensorsHidlEnvironmentBase.cpp",
"SensorsHidlTestBase.cpp",
"SensorsTestSharedMemory.cpp",
],
export_include_dirs: [
"include",
@@ -30,6 +27,9 @@ cc_library_static {
local_include_dirs: [
"include/sensors-vts-utils",
],
shared_libs: [
"libutils",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
@@ -37,5 +37,7 @@ cc_library_static {
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
],
}

View File

@@ -1,69 +0,0 @@
/*
* Copyright (C) 2018 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 "SensorsHidlEnvironmentBase.h"
void SensorsHidlEnvironmentBase::HidlSetUp() {
ASSERT_TRUE(resetHal()) << "could not get hidl service";
mCollectionEnabled = false;
startPollingThread();
// In case framework just stopped for test and there is sensor events in the pipe,
// wait some time for those events to be cleared to avoid them messing up the test.
std::this_thread::sleep_for(std::chrono::seconds(3));
}
void SensorsHidlEnvironmentBase::HidlTearDown() {
mStopThread = true;
if (mPollThread.joinable()) {
mPollThread.detach();
}
}
void SensorsHidlEnvironmentBase::catEvents(std::vector<Event>* output) {
std::lock_guard<std::mutex> lock(mEventsMutex);
if (output) {
output->insert(output->end(), mEvents.begin(), mEvents.end());
}
mEvents.clear();
}
void SensorsHidlEnvironmentBase::setCollection(bool enable) {
std::lock_guard<std::mutex> lock(mEventsMutex);
mCollectionEnabled = enable;
}
void SensorsHidlEnvironmentBase::addEvent(const Event& ev) {
std::lock_guard<std::mutex> lock(mEventsMutex);
if (mCollectionEnabled) {
mEvents.push_back(ev);
}
if (mCallback != nullptr) {
mCallback->onEvent(ev);
}
}
void SensorsHidlEnvironmentBase::registerCallback(IEventCallback* callback) {
std::lock_guard<std::mutex> lock(mEventsMutex);
mCallback = callback;
}
void SensorsHidlEnvironmentBase::unregisterCallback() {
std::lock_guard<std::mutex> lock(mEventsMutex);
mCallback = nullptr;
}

View File

@@ -1,584 +0,0 @@
/*
* Copyright (C) 2018 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 "SensorsHidlTestBase.h"
#include "sensors-vts-utils/GrallocWrapper.h"
#include "sensors-vts-utils/SensorsTestSharedMemory.h"
#include <hardware/sensors.h> // for sensor type strings
#include <log/log.h>
#include <utils/SystemClock.h>
#include <cinttypes>
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::sensors::V1_0::SensorFlagShift;
using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
const Vec3NormChecker SensorsHidlTestBase::sAccelNormChecker(
Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f /*m/s^2*/));
const Vec3NormChecker SensorsHidlTestBase::sGyroNormChecker(
Vec3NormChecker::byNominal(0.f, 0.1f /*rad/s*/));
std::vector<Event> SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
bool clearBeforeStart,
bool changeCollection) {
return collectEvents(timeLimitUs, nEventLimit, getEnvironment(), clearBeforeStart,
changeCollection);
}
std::vector<Event> SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
SensorsHidlEnvironmentBase* environment,
bool clearBeforeStart,
bool changeCollection) {
std::vector<Event> events;
constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000; // granularity 100 ms
ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs,
clearBeforeStart);
if (changeCollection) {
environment->setCollection(true);
}
if (clearBeforeStart) {
environment->catEvents(nullptr);
}
while (timeLimitUs > 0) {
useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
usleep(duration);
timeLimitUs -= duration;
environment->catEvents(&events);
if (events.size() >= nEventLimit) {
break;
}
ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs,
(int)(nEventLimit - events.size()));
}
if (changeCollection) {
environment->setCollection(false);
}
return events;
}
void SensorsHidlTestBase::assertTypeMatchStringType(SensorType type,
const hidl_string& stringType) {
if (type >= SensorType::DEVICE_PRIVATE_BASE) {
return;
}
switch (type) {
#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
case SensorType::type: \
ASSERT_STREQ(SENSOR_STRING_TYPE_##type, stringType.c_str()); \
break;
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
default:
FAIL() << "Type " << static_cast<int>(type)
<< " in android defined range is not checked, "
<< "stringType = " << stringType;
#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
}
}
void SensorsHidlTestBase::assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode) {
if (type >= SensorType::DEVICE_PRIVATE_BASE) {
return;
}
SensorFlagBits expected = expectedReportModeForType(type);
ASSERT_TRUE(expected == (SensorFlagBits)-1 || expected == reportMode)
<< "reportMode=" << static_cast<int>(reportMode)
<< "expected=" << static_cast<int>(expected);
}
void SensorsHidlTestBase::assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay,
SensorFlagBits reportMode) {
switch (reportMode) {
case SensorFlagBits::CONTINUOUS_MODE:
ASSERT_LT(0, minDelay);
ASSERT_LE(0, maxDelay);
break;
case SensorFlagBits::ON_CHANGE_MODE:
ASSERT_LE(0, minDelay);
ASSERT_LE(0, maxDelay);
break;
case SensorFlagBits::ONE_SHOT_MODE:
ASSERT_EQ(-1, minDelay);
ASSERT_EQ(0, maxDelay);
break;
case SensorFlagBits::SPECIAL_REPORTING_MODE:
// do not enforce anything for special reporting mode
break;
default:
FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked";
}
}
// return -1 means no expectation for this type
SensorFlagBits SensorsHidlTestBase::expectedReportModeForType(SensorType type) {
switch (type) {
case SensorType::ACCELEROMETER:
case SensorType::ACCELEROMETER_UNCALIBRATED:
case SensorType::GYROSCOPE:
case SensorType::MAGNETIC_FIELD:
case SensorType::ORIENTATION:
case SensorType::PRESSURE:
case SensorType::TEMPERATURE:
case SensorType::GRAVITY:
case SensorType::LINEAR_ACCELERATION:
case SensorType::ROTATION_VECTOR:
case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
case SensorType::GAME_ROTATION_VECTOR:
case SensorType::GYROSCOPE_UNCALIBRATED:
case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
case SensorType::POSE_6DOF:
case SensorType::HEART_BEAT:
return SensorFlagBits::CONTINUOUS_MODE;
case SensorType::LIGHT:
case SensorType::PROXIMITY:
case SensorType::RELATIVE_HUMIDITY:
case SensorType::AMBIENT_TEMPERATURE:
case SensorType::HEART_RATE:
case SensorType::DEVICE_ORIENTATION:
case SensorType::STEP_COUNTER:
case SensorType::LOW_LATENCY_OFFBODY_DETECT:
return SensorFlagBits::ON_CHANGE_MODE;
case SensorType::SIGNIFICANT_MOTION:
case SensorType::WAKE_GESTURE:
case SensorType::GLANCE_GESTURE:
case SensorType::PICK_UP_GESTURE:
case SensorType::MOTION_DETECT:
case SensorType::STATIONARY_DETECT:
return SensorFlagBits::ONE_SHOT_MODE;
case SensorType::STEP_DETECTOR:
case SensorType::TILT_DETECTOR:
case SensorType::WRIST_TILT_GESTURE:
case SensorType::DYNAMIC_SENSOR_META:
return SensorFlagBits::SPECIAL_REPORTING_MODE;
default:
ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type);
return (SensorFlagBits)-1;
}
}
bool SensorsHidlTestBase::isDirectReportRateSupported(SensorInfo sensor, RateLevel rate) {
unsigned int r = static_cast<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT) >>
static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT);
return r >= static_cast<unsigned int>(rate);
}
bool SensorsHidlTestBase::isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type) {
switch (type) {
case SharedMemType::ASHMEM:
return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0;
case SharedMemType::GRALLOC:
return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0;
default:
return false;
}
}
void SensorsHidlTestBase::testDirectReportOperation(SensorType type, SharedMemType memType,
RateLevel rate,
const SensorEventsChecker& checker) {
constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
constexpr size_t kNEvent = 4096;
constexpr size_t kMemSize = kEventSize * kNEvent;
constexpr float kNormalNominal = 50;
constexpr float kFastNominal = 200;
constexpr float kVeryFastNominal = 800;
constexpr float kNominalTestTimeSec = 1.f;
constexpr float kMaxTestTimeSec = kNominalTestTimeSec + 0.5f; // 0.5 second for initialization
SensorInfo sensor = defaultSensorByType(type);
if (!isValidType(sensor.type)) {
// no default sensor of this type
return;
}
if (!isDirectReportRateSupported(sensor, rate)) {
return;
}
if (!isDirectChannelTypeSupported(sensor, memType)) {
return;
}
std::unique_ptr<SensorsTestSharedMemory> mem(
SensorsTestSharedMemory::create(memType, kMemSize));
ASSERT_NE(mem, nullptr);
char* buffer = mem->getBuffer();
// fill memory with data
for (size_t i = 0; i < kMemSize; ++i) {
buffer[i] = '\xcc';
}
int32_t channelHandle;
registerDirectChannel(mem->getSharedMemInfo(),
[&channelHandle](auto result, auto channelHandle_) {
ASSERT_EQ(result, Result::OK);
channelHandle = channelHandle_;
});
// check memory is zeroed
for (size_t i = 0; i < kMemSize; ++i) {
ASSERT_EQ(buffer[i], '\0');
}
int32_t eventToken;
configDirectReport(sensor.sensorHandle, channelHandle, rate,
[&eventToken](auto result, auto token) {
ASSERT_EQ(result, Result::OK);
eventToken = token;
});
usleep(static_cast<useconds_t>(kMaxTestTimeSec * 1e6f));
auto events = mem->parseEvents();
// find norminal rate
float nominalFreq = 0.f;
switch (rate) {
case RateLevel::NORMAL:
nominalFreq = kNormalNominal;
break;
case RateLevel::FAST:
nominalFreq = kFastNominal;
break;
case RateLevel::VERY_FAST:
nominalFreq = kVeryFastNominal;
break;
case RateLevel::STOP:
FAIL();
}
// allowed to be between 55% and 220% of nominal freq
ASSERT_GT(events.size(), static_cast<size_t>(nominalFreq * 0.55f * kNominalTestTimeSec));
ASSERT_LT(events.size(), static_cast<size_t>(nominalFreq * 2.2f * kMaxTestTimeSec));
int64_t lastTimestamp = 0;
bool typeErrorReported = false;
bool tokenErrorReported = false;
bool timestampErrorReported = false;
std::vector<Event> sensorEvents;
for (auto& e : events) {
if (!tokenErrorReported) {
EXPECT_EQ(eventToken, e.sensorHandle)
<< (tokenErrorReported = true,
"Event token does not match that retured from configDirectReport");
}
if (isMetaSensorType(e.sensorType)) {
continue;
}
sensorEvents.push_back(e);
if (!typeErrorReported) {
EXPECT_EQ(type, e.sensorType)
<< (typeErrorReported = true,
"Type in event does not match type of sensor registered.");
}
if (!timestampErrorReported) {
EXPECT_GT(e.timestamp, lastTimestamp)
<< (timestampErrorReported = true, "Timestamp not monotonically increasing");
}
lastTimestamp = e.timestamp;
}
std::string s;
EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
// stop sensor and unregister channel
configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP,
[](auto result, auto) { EXPECT_EQ(result, Result::OK); });
EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK);
}
void SensorsHidlTestBase::testStreamingOperation(SensorType type,
std::chrono::nanoseconds samplingPeriod,
std::chrono::seconds duration,
const SensorEventsChecker& checker) {
std::vector<Event> events;
std::vector<Event> sensorEvents;
const int64_t samplingPeriodInNs = samplingPeriod.count();
const int64_t batchingPeriodInNs = 0; // no batching
const useconds_t minTimeUs = std::chrono::microseconds(duration).count();
const size_t minNEvent = duration / samplingPeriod;
SensorInfo sensor = defaultSensorByType(type);
if (!isValidType(sensor.type)) {
// no default sensor of this type
return;
}
if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) {
// rate not supported
return;
}
int32_t handle = sensor.sensorHandle;
ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK);
ASSERT_EQ(activate(handle, 1), Result::OK);
events = collectEvents(minTimeUs, minNEvent, true /*clearBeforeStart*/);
ASSERT_EQ(activate(handle, 0), Result::OK);
ALOGI("Collected %zu samples", events.size());
ASSERT_GT(events.size(), 0u);
bool handleMismatchReported = false;
bool metaSensorTypeErrorReported = false;
for (auto& e : events) {
if (e.sensorType == type) {
// avoid generating hundreds of error
if (!handleMismatchReported) {
EXPECT_EQ(e.sensorHandle, handle)
<< (handleMismatchReported = true,
"Event of the same type must come from the sensor registered");
}
sensorEvents.push_back(e);
} else {
// avoid generating hundreds of error
if (!metaSensorTypeErrorReported) {
EXPECT_TRUE(isMetaSensorType(e.sensorType))
<< (metaSensorTypeErrorReported = true,
"Only meta types are allowed besides the type registered");
}
}
}
std::string s;
EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
EXPECT_GE(sensorEvents.size(),
minNEvent / 2); // make sure returned events are not all meta
}
void SensorsHidlTestBase::testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow) {
std::vector<Event> events1, events2;
constexpr int64_t batchingPeriodInNs = 0; // no batching
constexpr int64_t collectionTimeoutUs = 60000000; // 60s
constexpr size_t minNEvent = 50;
SensorInfo sensor = defaultSensorByType(type);
if (!isValidType(sensor.type)) {
// no default sensor of this type
return;
}
int32_t handle = sensor.sensorHandle;
int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
int64_t maxSamplingPeriodInNs = sensor.maxDelay * 1000ll;
if (minSamplingPeriodInNs == maxSamplingPeriodInNs) {
// only support single rate
return;
}
int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
int64_t secondCollectionPeriod = !fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
// first collection
ASSERT_EQ(batch(handle, firstCollectionPeriod, batchingPeriodInNs), Result::OK);
ASSERT_EQ(activate(handle, 1), Result::OK);
usleep(500000); // sleep 0.5 sec to wait for change rate to happen
events1 = collectEvents(collectionTimeoutUs, minNEvent);
// second collection, without stop sensor
ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
usleep(500000); // sleep 0.5 sec to wait for change rate to happen
events2 = collectEvents(collectionTimeoutUs, minNEvent);
// end of collection, stop sensor
ASSERT_EQ(activate(handle, 0), Result::OK);
ALOGI("Collected %zu fast samples and %zu slow samples", events1.size(), events2.size());
ASSERT_GT(events1.size(), 0u);
ASSERT_GT(events2.size(), 0u);
int64_t minDelayAverageInterval, maxDelayAverageInterval;
std::vector<Event>& minDelayEvents(fastToSlow ? events1 : events2);
std::vector<Event>& maxDelayEvents(fastToSlow ? events2 : events1);
size_t nEvent = 0;
int64_t prevTimestamp = -1;
int64_t timestampInterval = 0;
for (auto& e : minDelayEvents) {
if (e.sensorType == type) {
ASSERT_EQ(e.sensorHandle, handle);
if (prevTimestamp > 0) {
timestampInterval += e.timestamp - prevTimestamp;
}
prevTimestamp = e.timestamp;
++nEvent;
}
}
ASSERT_GT(nEvent, 2u);
minDelayAverageInterval = timestampInterval / (nEvent - 1);
nEvent = 0;
prevTimestamp = -1;
timestampInterval = 0;
for (auto& e : maxDelayEvents) {
if (e.sensorType == type) {
ASSERT_EQ(e.sensorHandle, handle);
if (prevTimestamp > 0) {
timestampInterval += e.timestamp - prevTimestamp;
}
prevTimestamp = e.timestamp;
++nEvent;
}
}
ASSERT_GT(nEvent, 2u);
maxDelayAverageInterval = timestampInterval / (nEvent - 1);
// change of rate is significant.
ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64, minDelayAverageInterval,
maxDelayAverageInterval);
EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval), minDelayAverageInterval / 10);
// fastest rate sampling time is close to spec
EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
minSamplingPeriodInNs / 10);
// slowest rate sampling time is close to spec
EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
maxSamplingPeriodInNs / 10);
}
void SensorsHidlTestBase::testBatchingOperation(SensorType type) {
std::vector<Event> events;
constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000;
constexpr int64_t oneSecondInNs = 1ull * 1000 * 1000 * 1000;
SensorInfo sensor = defaultSensorByType(type);
if (!isValidType(sensor.type)) {
// no default sensor of this type
return;
}
int32_t handle = sensor.sensorHandle;
int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
uint32_t minFifoCount = sensor.fifoReservedEventCount;
int64_t batchingPeriodInNs = minFifoCount * minSamplingPeriodInNs;
if (batchingPeriodInNs < oneSecondInNs) {
// batching size too small to test reliably
return;
}
batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs);
ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000));
int64_t allowedBatchDeliverTimeNs = std::max(oneSecondInNs, batchingPeriodInNs / 10);
ASSERT_EQ(batch(handle, minSamplingPeriodInNs, INT64_MAX), Result::OK);
ASSERT_EQ(activate(handle, 1), Result::OK);
usleep(500000); // sleep 0.5 sec to wait for initialization
ASSERT_EQ(flush(handle), Result::OK);
// wait for 80% of the reserved batching period
// there should not be any significant amount of events
// since collection is not enabled all events will go down the drain
usleep(batchingPeriodInNs / 1000 * 8 / 10);
getEnvironment()->setCollection(true);
// clean existing collections
collectEvents(0 /*timeLimitUs*/, 0 /*nEventLimit*/, true /*clearBeforeStart*/,
false /*change collection*/);
// 0.8 + 0.2 times the batching period
usleep(batchingPeriodInNs / 1000 * 8 / 10);
ASSERT_EQ(flush(handle), Result::OK);
// plus some time for the event to deliver
events = collectEvents(allowedBatchDeliverTimeNs / 1000, minFifoCount,
false /*clearBeforeStart*/, false /*change collection*/);
getEnvironment()->setCollection(false);
ASSERT_EQ(activate(handle, 0), Result::OK);
size_t nEvent = 0;
for (auto& e : events) {
if (e.sensorType == type && e.sensorHandle == handle) {
++nEvent;
}
}
// at least reach 90% of advertised capacity
ASSERT_GT(nEvent, (size_t)(minFifoCount * 9 / 10));
}

View File

@@ -1,189 +0,0 @@
/*
* Copyright (C) 2018 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 "SensorsTestSharedMemory.h"
#include <log/log.h>
#include <sys/mman.h>
#include <cinttypes>
using namespace ::android::hardware::sensors::V1_0;
SharedMemInfo SensorsTestSharedMemory::getSharedMemInfo() const {
SharedMemInfo mem = {.type = mType,
.format = SharedMemFormat::SENSORS_EVENT,
.size = static_cast<uint32_t>(mSize),
.memoryHandle = mNativeHandle};
return mem;
}
char* SensorsTestSharedMemory::getBuffer() const {
return mBuffer;
}
size_t SensorsTestSharedMemory::getSize() const {
return mSize;
}
std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const {
constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN);
constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE);
constexpr size_t kOffsetAtomicCounter =
static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER);
constexpr size_t kOffsetTimestamp = static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP);
constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA);
std::vector<Event> events;
std::vector<float> data(16);
while (offset + kEventSize <= mSize) {
int64_t atomicCounter =
*reinterpret_cast<uint32_t*>(mBuffer + offset + kOffsetAtomicCounter);
if (atomicCounter <= lastCounter) {
ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter,
lastCounter);
break;
}
int32_t size = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetSize);
if (size != kEventSize) {
// unknown error, events parsed may be wrong, remove all
events.clear();
break;
}
int32_t token = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetToken);
int32_t type = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetType);
int64_t timestamp = *reinterpret_cast<int64_t*>(mBuffer + offset + kOffsetTimestamp);
ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32
", timestamp %" PRId64,
offset, atomicCounter, token, type, timestamp);
Event event = {
.timestamp = timestamp,
.sensorHandle = token,
.sensorType = static_cast<SensorType>(type),
};
event.u.data = android::hardware::hidl_array<float, 16>(
reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
events.push_back(event);
lastCounter = atomicCounter;
offset += kEventSize;
}
return events;
}
SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size)
: mType(type), mSize(0), mBuffer(nullptr) {
native_handle_t* handle = nullptr;
char* buffer = nullptr;
switch (type) {
case SharedMemType::ASHMEM: {
int fd;
handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/);
if (handle != nullptr) {
handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size);
if (handle->data[0] > 0) {
// memory is pinned by default
buffer = static_cast<char*>(
::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
break;
}
::native_handle_close(handle);
}
::native_handle_delete(handle);
handle = nullptr;
}
break;
}
case SharedMemType::GRALLOC: {
mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
if (!mGrallocWrapper->isInitialized()) {
break;
}
std::pair<native_handle_t*, void*> buf = mGrallocWrapper->allocate(size);
handle = buf.first;
buffer = static_cast<char*>(buf.second);
break;
}
default:
break;
}
if (buffer != nullptr) {
mNativeHandle = handle;
mSize = size;
mBuffer = buffer;
}
}
SensorsTestSharedMemory::~SensorsTestSharedMemory() {
switch (mType) {
case SharedMemType::ASHMEM: {
if (mSize != 0) {
::munmap(mBuffer, mSize);
mBuffer = nullptr;
::native_handle_close(mNativeHandle);
::native_handle_delete(mNativeHandle);
mNativeHandle = nullptr;
mSize = 0;
}
break;
}
case SharedMemType::GRALLOC: {
if (mSize != 0) {
mGrallocWrapper->freeBuffer(mNativeHandle);
mNativeHandle = nullptr;
mSize = 0;
}
break;
}
default: {
if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
ALOGE(
"SensorsTestSharedMemory %p not properly destructed: "
"type %d, native handle %p, size %zu, buffer %p",
this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
}
break;
}
}
}
SensorsTestSharedMemory* SensorsTestSharedMemory::create(SharedMemType type, size_t size) {
constexpr size_t kMaxSize = 128 * 1024 * 1024; // sensor test should not need more than 128M
if (size == 0 || size >= kMaxSize) {
return nullptr;
}
auto m = new SensorsTestSharedMemory(type, size);
if (m->mSize != size || m->mBuffer == nullptr) {
delete m;
m = nullptr;
}
return m;
}

View File

@@ -17,26 +17,26 @@
#ifndef ANDROID_SENSOR_EVENTS_CHECKER_H
#define ANDROID_SENSOR_EVENTS_CHECKER_H
#include <android/hardware/sensors/1.0/types.h>
#include <cmath>
template <class EventType>
class SensorEventsChecker {
public:
using Event = ::android::hardware::sensors::V1_0::Event;
virtual bool check(const std::vector<Event>& events, std::string* out) const = 0;
public:
virtual bool check(const std::vector<EventType>& events, std::string* out) const = 0;
virtual ~SensorEventsChecker() {}
};
class NullChecker : public SensorEventsChecker {
public:
virtual bool check(const std::vector<Event>&, std::string*) const { return true; }
template <class EventType>
class NullChecker : public SensorEventsChecker<EventType> {
public:
virtual bool check(const std::vector<EventType>&, std::string*) const { return true; }
};
class SensorEventPerEventChecker : public SensorEventsChecker {
public:
virtual bool checkEvent(const Event& event, std::string* out) const = 0;
virtual bool check(const std::vector<Event>& events, std::string* out) const {
template <class EventType>
class SensorEventPerEventChecker : public SensorEventsChecker<EventType> {
public:
virtual bool checkEvent(const EventType& event, std::string* out) const = 0;
virtual bool check(const std::vector<EventType>& events, std::string* out) const {
for (const auto& e : events) {
if (!checkEvent(e, out)) {
return false;
@@ -46,14 +46,15 @@ class SensorEventPerEventChecker : public SensorEventsChecker {
}
};
class Vec3NormChecker : public SensorEventPerEventChecker {
public:
template <class EventType>
class Vec3NormChecker : public SensorEventPerEventChecker<EventType> {
public:
Vec3NormChecker(float min, float max) : mLowerLimit(min), mUpperLimit(max) {}
static Vec3NormChecker byNominal(float nominal, float allowedError) {
return Vec3NormChecker(nominal - allowedError, nominal + allowedError);
static Vec3NormChecker<EventType> byNominal(float nominal, float allowedError) {
return Vec3NormChecker<EventType>(nominal - allowedError, nominal + allowedError);
}
virtual bool checkEvent(const Event& event, std::string* out) const {
virtual bool checkEvent(const EventType& event, std::string* out) const {
android::hardware::sensors::V1_0::Vec3 v = event.u.vec3;
float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
if (norm < mLowerLimit || norm > mUpperLimit) {

View File

@@ -17,7 +17,6 @@
#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
#define ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
#include <android/hardware/sensors/1.0/types.h>
#include <gtest/gtest.h>
#include <atomic>
@@ -26,27 +25,59 @@
#include <thread>
#include <vector>
template <class Event>
class IEventCallback {
public:
public:
virtual ~IEventCallback() = default;
virtual void onEvent(const ::android::hardware::sensors::V1_0::Event& event) = 0;
virtual void onEvent(const Event& event) = 0;
};
template <class Event>
class SensorsHidlEnvironmentBase {
public:
using Event = ::android::hardware::sensors::V1_0::Event;
virtual void HidlSetUp();
virtual void HidlTearDown();
virtual void HidlSetUp() {
ASSERT_TRUE(resetHal()) << "could not get hidl service";
mCollectionEnabled = false;
startPollingThread();
// In case framework just stopped for test and there is sensor events in the pipe,
// wait some time for those events to be cleared to avoid them messing up the test.
std::this_thread::sleep_for(std::chrono::seconds(3));
}
virtual void HidlTearDown() {
mStopThread = true;
if (mPollThread.joinable()) {
mPollThread.join();
}
}
// Get and clear all events collected so far (like "cat" shell command).
// If output is nullptr, it clears all collected events.
void catEvents(std::vector<Event>* output);
void catEvents(std::vector<Event>* output) {
std::lock_guard<std::mutex> lock(mEventsMutex);
if (output) {
output->insert(output->end(), mEvents.begin(), mEvents.end());
}
mEvents.clear();
}
// set sensor event collection status
void setCollection(bool enable);
void setCollection(bool enable) {
std::lock_guard<std::mutex> lock(mEventsMutex);
mCollectionEnabled = enable;
}
void registerCallback(IEventCallback* callback);
void unregisterCallback();
void registerCallback(IEventCallback<Event>* callback) {
std::lock_guard<std::mutex> lock(mEventsMutex);
mCallback = callback;
}
void unregisterCallback() {
std::lock_guard<std::mutex> lock(mEventsMutex);
mCallback = nullptr;
}
protected:
SensorsHidlEnvironmentBase(const std::string& service_name)
@@ -55,7 +86,16 @@ class SensorsHidlEnvironmentBase {
}
virtual ~SensorsHidlEnvironmentBase(){};
void addEvent(const Event& ev);
void addEvent(const Event& ev) {
std::lock_guard<std::mutex> lock(mEventsMutex);
if (mCollectionEnabled) {
mEvents.push_back(ev);
}
if (mCallback != nullptr) {
mCallback->onEvent(ev);
}
}
virtual void startPollingThread() = 0;
virtual bool resetHal() = 0;
@@ -67,9 +107,9 @@ class SensorsHidlEnvironmentBase {
std::vector<Event> mEvents;
std::mutex mEventsMutex;
IEventCallback* mCallback;
IEventCallback<Event>* mCallback;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase);
GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase<Event>);
};
#endif // ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H

View File

@@ -19,11 +19,15 @@
#include "sensors-vts-utils/SensorEventsChecker.h"
#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
#include "sensors-vts-utils/SensorsTestSharedMemory.h"
#include <android/hardware/sensors/1.0/ISensors.h>
#include <android/hardware/sensors/1.0/types.h>
#include <gtest/gtest.h>
#include <hardware/sensors.h>
#include <log/log.h>
#include <cinttypes>
#include <unordered_set>
#include <vector>
@@ -34,19 +38,130 @@ using ::android::hardware::Void;
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::sensors::V1_0::Event;
using ::android::hardware::sensors::V1_0::ISensors;
using ::android::hardware::sensors::V1_0::RateLevel;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SensorFlagBits;
using ::android::hardware::sensors::V1_0::SensorInfo;
using ::android::hardware::sensors::V1_0::SensorType;
using ::android::hardware::sensors::V1_0::SensorFlagShift;
using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
using ::android::hardware::sensors::V1_0::SharedMemInfo;
using ::android::hardware::sensors::V1_0::SharedMemType;
template <class SensorTypeT>
static void assertTypeMatchStringType(SensorTypeT type, const hidl_string& stringType) {
if (type >= SensorTypeT::DEVICE_PRIVATE_BASE) {
return;
}
switch (type) {
#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
case SensorTypeT::type: \
ASSERT_STREQ(SENSOR_STRING_TYPE_##type, stringType.c_str()); \
break;
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
default:
FAIL() << "Type " << static_cast<int>(type)
<< " in android defined range is not checked, "
<< "stringType = " << stringType;
#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
}
}
template <class SensorTypeT>
static SensorFlagBits expectedReportModeForType(SensorTypeT type) {
switch (type) {
case SensorTypeT::ACCELEROMETER:
case SensorTypeT::ACCELEROMETER_UNCALIBRATED:
case SensorTypeT::GYROSCOPE:
case SensorTypeT::MAGNETIC_FIELD:
case SensorTypeT::ORIENTATION:
case SensorTypeT::PRESSURE:
case SensorTypeT::TEMPERATURE:
case SensorTypeT::GRAVITY:
case SensorTypeT::LINEAR_ACCELERATION:
case SensorTypeT::ROTATION_VECTOR:
case SensorTypeT::MAGNETIC_FIELD_UNCALIBRATED:
case SensorTypeT::GAME_ROTATION_VECTOR:
case SensorTypeT::GYROSCOPE_UNCALIBRATED:
case SensorTypeT::GEOMAGNETIC_ROTATION_VECTOR:
case SensorTypeT::POSE_6DOF:
case SensorTypeT::HEART_BEAT:
return SensorFlagBits::CONTINUOUS_MODE;
case SensorTypeT::LIGHT:
case SensorTypeT::PROXIMITY:
case SensorTypeT::RELATIVE_HUMIDITY:
case SensorTypeT::AMBIENT_TEMPERATURE:
case SensorTypeT::HEART_RATE:
case SensorTypeT::DEVICE_ORIENTATION:
case SensorTypeT::STEP_COUNTER:
case SensorTypeT::LOW_LATENCY_OFFBODY_DETECT:
return SensorFlagBits::ON_CHANGE_MODE;
case SensorTypeT::SIGNIFICANT_MOTION:
case SensorTypeT::WAKE_GESTURE:
case SensorTypeT::GLANCE_GESTURE:
case SensorTypeT::PICK_UP_GESTURE:
case SensorTypeT::MOTION_DETECT:
case SensorTypeT::STATIONARY_DETECT:
return SensorFlagBits::ONE_SHOT_MODE;
case SensorTypeT::STEP_DETECTOR:
case SensorTypeT::TILT_DETECTOR:
case SensorTypeT::WRIST_TILT_GESTURE:
case SensorTypeT::DYNAMIC_SENSOR_META:
return SensorFlagBits::SPECIAL_REPORTING_MODE;
default:
ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type);
return (SensorFlagBits)-1;
}
}
template <class SensorTypeVersion, class EventType, class SensorInfoType>
class SensorsHidlTestBase : public testing::TestWithParam<std::string> {
public:
virtual SensorsHidlEnvironmentBase* getEnvironment() = 0;
using ISensors = ::android::hardware::sensors::V1_0::ISensors;
SensorsHidlTestBase()
: mAccelNormChecker(Vec3NormChecker<EventType>::byNominal(GRAVITY_EARTH, 1.0f /*m/s^2*/)),
mGyroNormChecker(Vec3NormChecker<EventType>::byNominal(0.f, 0.1f /*rad/s*/)) {}
virtual SensorsHidlEnvironmentBase<EventType>* getEnvironment() = 0;
virtual void SetUp() override {}
virtual void TearDown() override {
@@ -66,16 +181,13 @@ class SensorsHidlTestBase : public testing::TestWithParam<std::string> {
}
// implementation wrapper
virtual SensorInfo defaultSensorByType(SensorType type) = 0;
virtual SensorInfoType defaultSensorByType(SensorTypeVersion type) = 0;
virtual Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) = 0;
virtual Return<Result> injectSensorData(const EventType& event) = 0;
virtual Return<Result> activate(int32_t sensorHandle, bool enabled) = 0;
virtual Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
int64_t maxReportLatencyNs) = 0;
virtual Return<Result> flush(int32_t sensorHandle) = 0;
virtual Return<Result> injectSensorData(const Event& event) = 0;
virtual Return<void> registerDirectChannel(const SharedMemInfo& mem,
ISensors::registerDirectChannel_cb _hidl_cb) = 0;
virtual Return<Result> unregisterDirectChannel(int32_t channelHandle) = 0;
@@ -83,12 +195,395 @@ class SensorsHidlTestBase : public testing::TestWithParam<std::string> {
RateLevel rate,
ISensors::configDirectReport_cb _hidl_cb) = 0;
std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
bool clearBeforeStart = true, bool changeCollection = true);
static std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
SensorsHidlEnvironmentBase* environment,
bool clearBeforeStart = true,
bool changeCollection = true);
std::vector<EventType> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
bool clearBeforeStart = true,
bool changeCollection = true) {
return collectEvents(timeLimitUs, nEventLimit, getEnvironment(), clearBeforeStart,
changeCollection);
}
std::vector<EventType> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
SensorsHidlEnvironmentBase<EventType>* environment,
bool clearBeforeStart = true,
bool changeCollection = true) {
std::vector<EventType> events;
constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000; // granularity 100 ms
ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs,
clearBeforeStart);
if (changeCollection) {
environment->setCollection(true);
}
if (clearBeforeStart) {
environment->catEvents(nullptr);
}
while (timeLimitUs > 0) {
useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
usleep(duration);
timeLimitUs -= duration;
environment->catEvents(&events);
if (events.size() >= nEventLimit) {
break;
}
ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs,
(int)(nEventLimit - events.size()));
}
if (changeCollection) {
environment->setCollection(false);
}
return events;
}
void testStreamingOperation(SensorTypeVersion type, std::chrono::nanoseconds samplingPeriod,
std::chrono::seconds duration,
const SensorEventsChecker<EventType>& checker) {
std::vector<EventType> events;
std::vector<EventType> sensorEvents;
const int64_t samplingPeriodInNs = samplingPeriod.count();
const int64_t batchingPeriodInNs = 0; // no batching
const useconds_t minTimeUs = std::chrono::microseconds(duration).count();
const size_t minNEvent = duration / samplingPeriod;
SensorInfoType sensor = defaultSensorByType(type);
if (!isValidType(sensor.type)) {
// no default sensor of this type
return;
}
if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) {
// rate not supported
return;
}
int32_t handle = sensor.sensorHandle;
ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK);
ASSERT_EQ(activate(handle, 1), Result::OK);
events = collectEvents(minTimeUs, minNEvent, getEnvironment(), true /*clearBeforeStart*/);
ASSERT_EQ(activate(handle, 0), Result::OK);
ALOGI("Collected %zu samples", events.size());
ASSERT_GT(events.size(), 0u);
bool handleMismatchReported = false;
bool metaSensorTypeErrorReported = false;
for (auto& e : events) {
if (e.sensorType == type) {
// avoid generating hundreds of error
if (!handleMismatchReported) {
EXPECT_EQ(e.sensorHandle, handle)
<< (handleMismatchReported = true,
"Event of the same type must come from the sensor registered");
}
sensorEvents.push_back(e);
} else {
// avoid generating hundreds of error
if (!metaSensorTypeErrorReported) {
EXPECT_TRUE(isMetaSensorType(e.sensorType))
<< (metaSensorTypeErrorReported = true,
"Only meta types are allowed besides the type registered");
}
}
}
std::string s;
EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
EXPECT_GE(sensorEvents.size(),
minNEvent / 2); // make sure returned events are not all meta
}
void testSamplingRateHotSwitchOperation(SensorTypeVersion type, bool fastToSlow = true) {
std::vector<EventType> events1, events2;
constexpr int64_t batchingPeriodInNs = 0; // no batching
constexpr int64_t collectionTimeoutUs = 60000000; // 60s
constexpr size_t minNEvent = 50;
SensorInfoType sensor = defaultSensorByType(type);
if (!isValidType(sensor.type)) {
// no default sensor of this type
return;
}
int32_t handle = sensor.sensorHandle;
int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
int64_t maxSamplingPeriodInNs = sensor.maxDelay * 1000ll;
if (minSamplingPeriodInNs == maxSamplingPeriodInNs) {
// only support single rate
return;
}
int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
int64_t secondCollectionPeriod =
!fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
// first collection
ASSERT_EQ(batch(handle, firstCollectionPeriod, batchingPeriodInNs), Result::OK);
ASSERT_EQ(activate(handle, 1), Result::OK);
usleep(500000); // sleep 0.5 sec to wait for change rate to happen
events1 = collectEvents(collectionTimeoutUs, minNEvent, getEnvironment());
// second collection, without stop sensor
ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
usleep(500000); // sleep 0.5 sec to wait for change rate to happen
events2 = collectEvents(collectionTimeoutUs, minNEvent, getEnvironment());
// end of collection, stop sensor
ASSERT_EQ(activate(handle, 0), Result::OK);
ALOGI("Collected %zu fast samples and %zu slow samples", events1.size(), events2.size());
ASSERT_GT(events1.size(), 0u);
ASSERT_GT(events2.size(), 0u);
int64_t minDelayAverageInterval, maxDelayAverageInterval;
std::vector<EventType>& minDelayEvents(fastToSlow ? events1 : events2);
std::vector<EventType>& maxDelayEvents(fastToSlow ? events2 : events1);
size_t nEvent = 0;
int64_t prevTimestamp = -1;
int64_t timestampInterval = 0;
for (auto& e : minDelayEvents) {
if (e.sensorType == type) {
ASSERT_EQ(e.sensorHandle, handle);
if (prevTimestamp > 0) {
timestampInterval += e.timestamp - prevTimestamp;
}
prevTimestamp = e.timestamp;
++nEvent;
}
}
ASSERT_GT(nEvent, 2u);
minDelayAverageInterval = timestampInterval / (nEvent - 1);
nEvent = 0;
prevTimestamp = -1;
timestampInterval = 0;
for (auto& e : maxDelayEvents) {
if (e.sensorType == type) {
ASSERT_EQ(e.sensorHandle, handle);
if (prevTimestamp > 0) {
timestampInterval += e.timestamp - prevTimestamp;
}
prevTimestamp = e.timestamp;
++nEvent;
}
}
ASSERT_GT(nEvent, 2u);
maxDelayAverageInterval = timestampInterval / (nEvent - 1);
// change of rate is significant.
ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64, minDelayAverageInterval,
maxDelayAverageInterval);
EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval),
minDelayAverageInterval / 10);
// fastest rate sampling time is close to spec
EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
minSamplingPeriodInNs / 10);
// slowest rate sampling time is close to spec
EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
maxSamplingPeriodInNs / 10);
}
void testBatchingOperation(SensorTypeVersion type) {
std::vector<EventType> events;
constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000;
constexpr int64_t oneSecondInNs = 1ull * 1000 * 1000 * 1000;
SensorInfoType sensor = defaultSensorByType(type);
if (!isValidType(sensor.type)) {
// no default sensor of this type
return;
}
int32_t handle = sensor.sensorHandle;
int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
uint32_t minFifoCount = sensor.fifoReservedEventCount;
int64_t batchingPeriodInNs = minFifoCount * minSamplingPeriodInNs;
if (batchingPeriodInNs < oneSecondInNs) {
// batching size too small to test reliably
return;
}
batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs);
ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000));
int64_t allowedBatchDeliverTimeNs = std::max(oneSecondInNs, batchingPeriodInNs / 10);
ASSERT_EQ(batch(handle, minSamplingPeriodInNs, INT64_MAX), Result::OK);
ASSERT_EQ(activate(handle, 1), Result::OK);
usleep(500000); // sleep 0.5 sec to wait for initialization
ASSERT_EQ(flush(handle), Result::OK);
// wait for 80% of the reserved batching period
// there should not be any significant amount of events
// since collection is not enabled all events will go down the drain
usleep(batchingPeriodInNs / 1000 * 8 / 10);
getEnvironment()->setCollection(true);
// clean existing collections
collectEvents(0 /*timeLimitUs*/, 0 /*nEventLimit*/, true /*clearBeforeStart*/,
false /*change collection*/);
// 0.8 + 0.2 times the batching period
usleep(batchingPeriodInNs / 1000 * 8 / 10);
ASSERT_EQ(flush(handle), Result::OK);
// plus some time for the event to deliver
events = collectEvents(allowedBatchDeliverTimeNs / 1000, minFifoCount,
false /*clearBeforeStart*/, false /*change collection*/);
getEnvironment()->setCollection(false);
ASSERT_EQ(activate(handle, 0), Result::OK);
size_t nEvent = 0;
for (auto& e : events) {
if (e.sensorType == type && e.sensorHandle == handle) {
++nEvent;
}
}
// at least reach 90% of advertised capacity
ASSERT_GT(nEvent, (size_t)(minFifoCount * 9 / 10));
}
void testDirectReportOperation(SensorTypeVersion type, SharedMemType memType, RateLevel rate,
const SensorEventsChecker<EventType>& checker) {
constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
constexpr size_t kNEvent = 4096;
constexpr size_t kMemSize = kEventSize * kNEvent;
constexpr float kNormalNominal = 50;
constexpr float kFastNominal = 200;
constexpr float kVeryFastNominal = 800;
constexpr float kNominalTestTimeSec = 1.f;
constexpr float kMaxTestTimeSec =
kNominalTestTimeSec + 0.5f; // 0.5 second for initialization
SensorInfoType sensor = defaultSensorByType(type);
if (!isValidType(sensor.type)) {
// no default sensor of this type
return;
}
if (!isDirectReportRateSupported(sensor, rate)) {
return;
}
if (!isDirectChannelTypeSupported(sensor, memType)) {
return;
}
std::unique_ptr<SensorsTestSharedMemory<SensorTypeVersion, EventType>> mem(
SensorsTestSharedMemory<SensorTypeVersion, EventType>::create(memType, kMemSize));
ASSERT_NE(mem, nullptr);
char* buffer = mem->getBuffer();
// fill memory with data
for (size_t i = 0; i < kMemSize; ++i) {
buffer[i] = '\xcc';
}
int32_t channelHandle;
registerDirectChannel(mem->getSharedMemInfo(),
[&channelHandle](auto result, auto channelHandle_) {
ASSERT_EQ(result, Result::OK);
channelHandle = channelHandle_;
});
// check memory is zeroed
for (size_t i = 0; i < kMemSize; ++i) {
ASSERT_EQ(buffer[i], '\0');
}
int32_t eventToken;
configDirectReport(sensor.sensorHandle, channelHandle, rate,
[&eventToken](auto result, auto token) {
ASSERT_EQ(result, Result::OK);
eventToken = token;
});
usleep(static_cast<useconds_t>(kMaxTestTimeSec * 1e6f));
auto events = mem->parseEvents();
// find norminal rate
float nominalFreq = 0.f;
switch (rate) {
case RateLevel::NORMAL:
nominalFreq = kNormalNominal;
break;
case RateLevel::FAST:
nominalFreq = kFastNominal;
break;
case RateLevel::VERY_FAST:
nominalFreq = kVeryFastNominal;
break;
case RateLevel::STOP:
FAIL();
}
// allowed to be between 55% and 220% of nominal freq
ASSERT_GT(events.size(), static_cast<size_t>(nominalFreq * 0.55f * kNominalTestTimeSec));
ASSERT_LT(events.size(), static_cast<size_t>(nominalFreq * 2.2f * kMaxTestTimeSec));
int64_t lastTimestamp = 0;
bool typeErrorReported = false;
bool tokenErrorReported = false;
bool timestampErrorReported = false;
std::vector<EventType> sensorEvents;
for (auto& e : events) {
if (!tokenErrorReported) {
EXPECT_EQ(eventToken, e.sensorHandle)
<< (tokenErrorReported = true,
"Event token does not match that retured from configDirectReport");
}
if (isMetaSensorType(e.sensorType)) {
continue;
}
sensorEvents.push_back(e);
if (!typeErrorReported) {
EXPECT_EQ(type, e.sensorType)
<< (typeErrorReported = true,
"Type in event does not match type of sensor registered.");
}
if (!timestampErrorReported) {
EXPECT_GT(e.timestamp, lastTimestamp) << (timestampErrorReported = true,
"Timestamp not monotonically increasing");
}
lastTimestamp = e.timestamp;
}
std::string s;
EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
// stop sensor and unregister channel
configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP,
[](auto result, auto) { EXPECT_EQ(result, Result::OK); });
EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK);
}
inline static SensorFlagBits extractReportMode(uint64_t flag) {
return (SensorFlagBits)(flag & ((uint64_t)SensorFlagBits::CONTINUOUS_MODE |
@@ -97,32 +592,71 @@ class SensorsHidlTestBase : public testing::TestWithParam<std::string> {
(uint64_t)SensorFlagBits::SPECIAL_REPORTING_MODE));
}
inline static bool isMetaSensorType(SensorType type) {
return (type == SensorType::META_DATA || type == SensorType::DYNAMIC_SENSOR_META ||
type == SensorType::ADDITIONAL_INFO);
inline static bool isMetaSensorType(SensorTypeVersion type) {
return (type == SensorTypeVersion::META_DATA ||
type == SensorTypeVersion::DYNAMIC_SENSOR_META ||
type == SensorTypeVersion::ADDITIONAL_INFO);
}
inline static bool isValidType(SensorType type) { return (int32_t)type > 0; }
inline static bool isValidType(SensorTypeVersion type) { return (int32_t)type > 0; }
void testStreamingOperation(SensorType type, std::chrono::nanoseconds samplingPeriod,
std::chrono::seconds duration, const SensorEventsChecker& checker);
void testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow = true);
void testBatchingOperation(SensorType type);
void testDirectReportOperation(SensorType type, SharedMemType memType, RateLevel rate,
const SensorEventsChecker& checker);
static void assertTypeMatchStringType(SensorType type, const hidl_string& stringType);
static void assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode);
static void assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay,
SensorFlagBits reportMode);
static SensorFlagBits expectedReportModeForType(SensorType type);
static bool isDirectReportRateSupported(SensorInfo sensor, RateLevel rate);
static bool isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type);
SensorFlagBits reportMode) {
switch (reportMode) {
case SensorFlagBits::CONTINUOUS_MODE:
ASSERT_LT(0, minDelay);
ASSERT_LE(0, maxDelay);
break;
case SensorFlagBits::ON_CHANGE_MODE:
ASSERT_LE(0, minDelay);
ASSERT_LE(0, maxDelay);
break;
case SensorFlagBits::ONE_SHOT_MODE:
ASSERT_EQ(-1, minDelay);
ASSERT_EQ(0, maxDelay);
break;
case SensorFlagBits::SPECIAL_REPORTING_MODE:
// do not enforce anything for special reporting mode
break;
default:
FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked";
}
}
protected:
// checkers
static const Vec3NormChecker sAccelNormChecker;
static const Vec3NormChecker sGyroNormChecker;
protected:
static void assertTypeMatchReportMode(SensorTypeVersion type, SensorFlagBits reportMode) {
if (type >= SensorTypeVersion::DEVICE_PRIVATE_BASE) {
return;
}
SensorFlagBits expected = expectedReportModeForType(type);
ASSERT_TRUE(expected == (SensorFlagBits)-1 || expected == reportMode)
<< "reportMode=" << static_cast<int>(reportMode)
<< "expected=" << static_cast<int>(expected);
}
static bool isDirectReportRateSupported(SensorInfoType sensor, RateLevel rate) {
unsigned int r =
static_cast<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT) >>
static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT);
return r >= static_cast<unsigned int>(rate);
}
static bool isDirectChannelTypeSupported(SensorInfoType sensor, SharedMemType type) {
switch (type) {
case SharedMemType::ASHMEM:
return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0;
case SharedMemType::GRALLOC:
return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0;
default:
return false;
}
}
// Checkers
Vec3NormChecker<EventType> mAccelNormChecker;
Vec3NormChecker<EventType> mGyroNormChecker;
// all sensors and direct channnels used
std::unordered_set<int32_t> mSensorHandles;

View File

@@ -20,25 +20,177 @@
#include "GrallocWrapper.h"
#include <android-base/macros.h>
#include <android/hardware/sensors/1.0/types.h>
#include <log/log.h>
#include <sys/mman.h>
#include <cinttypes>
#include <cutils/ashmem.h>
using namespace ::android::hardware::sensors::V1_0;
template <class SensorTypeVersion, class EventType>
class SensorsTestSharedMemory {
using SharedMemType = ::android::hardware::sensors::V1_0::SharedMemType;
using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
using Event = ::android::hardware::sensors::V1_0::Event;
public:
static SensorsTestSharedMemory* create(SharedMemType type, size_t size) {
constexpr size_t kMaxSize =
128 * 1024 * 1024; // sensor test should not need more than 128M
if (size == 0 || size >= kMaxSize) {
return nullptr;
}
public:
static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
SharedMemInfo getSharedMemInfo() const;
char* getBuffer() const;
size_t getSize() const;
std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const;
virtual ~SensorsTestSharedMemory();
auto m = new SensorsTestSharedMemory<SensorTypeVersion, EventType>(type, size);
if (m->mSize != size || m->mBuffer == nullptr) {
delete m;
m = nullptr;
}
return m;
}
private:
SensorsTestSharedMemory(SharedMemType type, size_t size);
SharedMemInfo getSharedMemInfo() const {
SharedMemInfo mem = {.type = mType,
.format = SharedMemFormat::SENSORS_EVENT,
.size = static_cast<uint32_t>(mSize),
.memoryHandle = mNativeHandle};
return mem;
}
char* getBuffer() const { return mBuffer; }
size_t getSize() const { return mSize; }
std::vector<EventType> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const {
constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN);
constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE);
constexpr size_t kOffsetAtomicCounter =
static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER);
constexpr size_t kOffsetTimestamp =
static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP);
constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA);
std::vector<EventType> events;
std::vector<float> data(16);
while (offset + kEventSize <= mSize) {
int64_t atomicCounter =
*reinterpret_cast<uint32_t*>(mBuffer + offset + kOffsetAtomicCounter);
if (atomicCounter <= lastCounter) {
ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter,
lastCounter);
break;
}
int32_t size = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetSize);
if (size != kEventSize) {
// unknown error, events parsed may be wrong, remove all
events.clear();
break;
}
int32_t token = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetToken);
int32_t type = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetType);
int64_t timestamp = *reinterpret_cast<int64_t*>(mBuffer + offset + kOffsetTimestamp);
ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32
", timestamp %" PRId64,
offset, atomicCounter, token, type, timestamp);
EventType event = {
.timestamp = timestamp,
.sensorHandle = token,
.sensorType = static_cast<SensorTypeVersion>(type),
};
event.u.data = android::hardware::hidl_array<float, 16>(
reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
events.push_back(event);
lastCounter = atomicCounter;
offset += kEventSize;
}
return events;
}
virtual ~SensorsTestSharedMemory() {
switch (mType) {
case SharedMemType::ASHMEM: {
if (mSize != 0) {
::munmap(mBuffer, mSize);
mBuffer = nullptr;
::native_handle_close(mNativeHandle);
::native_handle_delete(mNativeHandle);
mNativeHandle = nullptr;
mSize = 0;
}
break;
}
case SharedMemType::GRALLOC: {
if (mSize != 0) {
mGrallocWrapper->freeBuffer(mNativeHandle);
mNativeHandle = nullptr;
mSize = 0;
}
break;
}
default: {
if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
ALOGE("SensorsTestSharedMemory %p not properly destructed: "
"type %d, native handle %p, size %zu, buffer %p",
this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
}
break;
}
}
}
private:
SensorsTestSharedMemory(SharedMemType type, size_t size)
: mType(type), mSize(0), mBuffer(nullptr) {
native_handle_t* handle = nullptr;
char* buffer = nullptr;
switch (type) {
case SharedMemType::ASHMEM: {
int fd;
handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/);
if (handle != nullptr) {
handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size);
if (handle->data[0] > 0) {
// memory is pinned by default
buffer = static_cast<char*>(
::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
break;
}
::native_handle_close(handle);
}
::native_handle_delete(handle);
handle = nullptr;
}
break;
}
case SharedMemType::GRALLOC: {
mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
if (!mGrallocWrapper->isInitialized()) {
break;
}
std::pair<native_handle_t*, void*> buf = mGrallocWrapper->allocate(size);
handle = buf.first;
buffer = static_cast<char*>(buf.second);
break;
}
default:
break;
}
if (buffer != nullptr) {
mNativeHandle = handle;
mSize = size;
mBuffer = buffer;
}
}
SharedMemType mType;
native_handle_t* mNativeHandle;