/*
* Copyright (C) 2016 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 "sensors_hidl_hal_test"
#include "SensorsHidlEnvironmentV1_0.h"
#include "sensors-vts-utils/SensorsHidlTestBase.h"
#include <android/hardware/sensors/1.0/ISensors.h>
#include <android/hardware/sensors/1.0/types.h>
#include <log/log.h>
#include <utils/SystemClock.h>
#include <cinttypes>
#include <vector>
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
using namespace ::android::hardware::sensors::V1_0;
// The main test class for SENSORS HIDL HAL.
class SensorsHidlTest : public SensorsHidlTestBase {
protected:
SensorInfo defaultSensorByType(SensorType type) override;
std::vector<SensorInfo> getSensorsList();
// implementation wrapper
Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) override {
return S()->getSensorsList(_hidl_cb);
}
Return<Result> activate(int32_t sensorHandle, bool enabled) override;
Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
int64_t maxReportLatencyNs) override {
return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
}
Return<Result> flush(int32_t sensorHandle) override { return S()->flush(sensorHandle); }
Return<Result> injectSensorData(const Event& event) override {
return S()->injectSensorData(event);
}
Return<void> registerDirectChannel(const SharedMemInfo& mem,
ISensors::registerDirectChannel_cb _hidl_cb) override;
Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
return S()->unregisterDirectChannel(channelHandle);
}
Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
ISensors::configDirectReport_cb _hidl_cb) override {
return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
}
inline sp<ISensors>& S() { return SensorsHidlEnvironmentV1_0::Instance()->sensors; }
SensorsHidlEnvironmentBase* getEnvironment() override {
return SensorsHidlEnvironmentV1_0::Instance();
}
};
Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
// If activating a sensor, add the handle in a set so that when test fails it can be turned off.
// The handle is not removed when it is deactivating on purpose so that it is not necessary to
// check the return value of deactivation. Deactivating a sensor more than once does not have
// negative effect.
if (enabled) {
mSensorHandles.insert(sensorHandle);
}
return S()->activate(sensorHandle, enabled);
}
Return<void> SensorsHidlTest::registerDirectChannel(
const SharedMemInfo& mem, ISensors::registerDirectChannel_cb cb) {
// If registeration of a channel succeeds, add the handle of channel to a set so that it can be
// unregistered when test fails. Unregister a channel does not remove the handle on purpose.
// Unregistering a channel more than once should not have negative effect.
S()->registerDirectChannel(mem,
[&] (auto result, auto channelHandle) {
if (result == Result::OK) {
mDirectChannelHandles.insert(channelHandle);
}
cb(result, channelHandle);
});
return Void();
}
SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) {
SensorInfo ret;
ret.type = (SensorType) -1;
S()->getSensorsList(
[&] (const auto &list) {
const size_t count = list.size();
for (size_t i = 0; i < count; ++i) {
if (list[i].type == type) {
ret = list[i];
return;
}
}
});
return ret;
}
std::vector<SensorInfo> SensorsHidlTest::getSensorsList() {
std::vector<SensorInfo> ret;
S()->getSensorsList(
[&] (const auto &list) {
const size_t count = list.size();
ret.reserve(list.size());
for (size_t i = 0; i < count; ++i) {
ret.push_back(list[i]);
}
});
return ret;
}
// Test if sensor list returned is valid
TEST_F(SensorsHidlTest, SensorListValid) {
S()->getSensorsList(
[&] (const auto &list) {
const size_t count = list.size();
for (size_t i = 0; i < count; ++i) {
const auto &s = list[i];
SCOPED_TRACE(::testing::Message() << i << "/" << count << ": "
<< " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
<< s.sensorHandle << std::dec
<< " type=" << static_cast<int>(s.type)
<< " name=" << s.name);
// Test non-empty type string
EXPECT_FALSE(s.typeAsString.empty());
// Test defined type matches defined string type
EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(s.type, s.typeAsString));
// Test if all sensor has name and vendor
EXPECT_FALSE(s.name.empty());
EXPECT_FALSE(s.vendor.empty());
// Test power > 0, maxRange > 0
EXPECT_LE(0, s.power);
EXPECT_LT(0, s.maxRange);
// Info type, should have no sensor
EXPECT_FALSE(
s.type == SensorType::ADDITIONAL_INFO
|| s.type == SensorType::META_DATA);
// Test fifoMax >= fifoReserved
EXPECT_GE(s.fifoMaxEventCount, s.fifoReservedEventCount)
<< "max=" << s.fifoMaxEventCount << " reserved=" << s.fifoReservedEventCount;
// Test Reporting mode valid
EXPECT_NO_FATAL_FAILURE(assertTypeMatchReportMode(s.type, extractReportMode(s.flags)));
// Test min max are in the right order
EXPECT_LE(s.minDelay, s.maxDelay);
// Test min/max delay matches reporting mode
EXPECT_NO_FATAL_FAILURE(
assertDelayMatchReportMode(s.minDelay, s.maxDelay, extractReportMode(s.flags)));
}
});
}
// Test if sensor list returned is valid
TEST_F(SensorsHidlTest, SetOperationMode) {
std::vector<SensorInfo> sensorList = getSensorsList();
bool needOperationModeSupport =
std::any_of(sensorList.begin(), sensorList.end(),
[] (const auto& s) {
return (s.flags & SensorFlagBits::DATA_INJECTION) != 0;
});
if (!needOperationModeSupport) {
return;
}
ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::DATA_INJECTION));
ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
}
// Test if sensor list returned is valid
TEST_F(SensorsHidlTest, InjectSensorEventData) {
std::vector<SensorInfo> sensorList = getSensorsList();
std::vector<SensorInfo> sensorSupportInjection;
bool needOperationModeSupport =
std::any_of(sensorList.begin(), sensorList.end(),
[&sensorSupportInjection] (const auto& s) {
bool ret = (s.flags & SensorFlagBits::DATA_INJECTION) != 0;
if (ret) {
sensorSupportInjection.push_back(s);
}
return ret;
});
if (!needOperationModeSupport) {
return;
}
ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::DATA_INJECTION));
for (const auto &s : sensorSupportInjection) {
switch (s.type) {
case SensorType::ACCELEROMETER:
case SensorType::GYROSCOPE:
case SensorType::MAGNETIC_FIELD: {
usleep(100000); // sleep 100ms
Event dummy;
dummy.timestamp = android::elapsedRealtimeNano();
dummy.sensorType = s.type;
dummy.sensorHandle = s.sensorHandle;
Vec3 v = {1, 2, 3, SensorStatus::ACCURACY_HIGH};
dummy.u.vec3 = v;
EXPECT_EQ(Result::OK, S()->injectSensorData(dummy));
break;
}
default:
break;
}
}
ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
}
// Test if sensor hal can do UI speed accelerometer streaming properly
TEST_F(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
testStreamingOperation(SensorType::ACCELEROMETER,
std::chrono::milliseconds(200),
std::chrono::seconds(5),
sAccelNormChecker);
}
// Test if sensor hal can do normal speed accelerometer streaming properly
TEST_F(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
testStreamingOperation(SensorType::ACCELEROMETER,
std::chrono::milliseconds(20),
std::chrono::seconds(5),
sAccelNormChecker);
}
// Test if sensor hal can do game speed accelerometer streaming properly
TEST_F(SensorsHidlTest, AccelerometerStreamingOperationFast) {
testStreamingOperation(SensorType::ACCELEROMETER,
std::chrono::milliseconds(5),
std::chrono::seconds(5),
sAccelNormChecker);
}
// Test if sensor hal can do UI speed gyroscope streaming properly
TEST_F(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
testStreamingOperation(SensorType::GYROSCOPE,
std::chrono::milliseconds(200),
std::chrono::seconds(5),
sGyroNormChecker);
}
// Test if sensor hal can do normal speed gyroscope streaming properly
TEST_F(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
testStreamingOperation(SensorType::GYROSCOPE,
std::chrono::milliseconds(20),
std::chrono::seconds(5),
sGyroNormChecker);
}
// Test if sensor hal can do game speed gyroscope streaming properly
TEST_F(SensorsHidlTest, GyroscopeStreamingOperationFast) {
testStreamingOperation(SensorType::GYROSCOPE,
std::chrono::milliseconds(5),
std::chrono::seconds(5),
sGyroNormChecker);
}
// Test if sensor hal can do UI speed magnetometer streaming properly
TEST_F(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
testStreamingOperation(SensorType::MAGNETIC_FIELD,
std::chrono::milliseconds(200),
std::chrono::seconds(5),
NullChecker());
}
// Test if sensor hal can do normal speed magnetometer streaming properly
TEST_F(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
testStreamingOperation(SensorType::MAGNETIC_FIELD,
std::chrono::milliseconds(20),
std::chrono::seconds(5),
NullChecker());
}
// Test if sensor hal can do game speed magnetometer streaming properly
TEST_F(SensorsHidlTest, MagnetometerStreamingOperationFast) {
testStreamingOperation(SensorType::MAGNETIC_FIELD,
std::chrono::milliseconds(5),
std::chrono::seconds(5),
NullChecker());
}
// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER);
testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER, false /*fastToSlow*/);
}
// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
TEST_F(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE);
testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE, false /*fastToSlow*/);
}
// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
TEST_F(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD);
testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/);
}
// Test if sensor hal can do accelerometer batching properly
TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) {
testBatchingOperation(SensorType::ACCELEROMETER);
}
// Test if sensor hal can do gyroscope batching properly
TEST_F(SensorsHidlTest, GyroscopeBatchingOperation) {
testBatchingOperation(SensorType::GYROSCOPE);
}
// Test if sensor hal can do magnetometer batching properly
TEST_F(SensorsHidlTest, MagnetometerBatchingOperation) {
testBatchingOperation(SensorType::MAGNETIC_FIELD);
}
// Test sensor event direct report with ashmem for accel sensor at normal rate
TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
sAccelNormChecker);
}
// Test sensor event direct report with ashmem for accel sensor at fast rate
TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::FAST,
sAccelNormChecker);
}
// Test sensor event direct report with ashmem for accel sensor at very fast rate
TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::VERY_FAST,
sAccelNormChecker);
}
// Test sensor event direct report with ashmem for gyro sensor at normal rate
TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::NORMAL,
sGyroNormChecker);
}
// Test sensor event direct report with ashmem for gyro sensor at fast rate
TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
sGyroNormChecker);
}
// Test sensor event direct report with ashmem for gyro sensor at very fast rate
TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::VERY_FAST,
sGyroNormChecker);
}
// Test sensor event direct report with ashmem for mag sensor at normal rate
TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::NORMAL,
NullChecker());
}
// Test sensor event direct report with ashmem for mag sensor at fast rate
TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::FAST,
NullChecker());
}
// Test sensor event direct report with ashmem for mag sensor at very fast rate
TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
testDirectReportOperation(
SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::VERY_FAST, NullChecker());
}
// Test sensor event direct report with gralloc for accel sensor at normal rate
TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL,
sAccelNormChecker);
}
// Test sensor event direct report with gralloc for accel sensor at fast rate
TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST,
sAccelNormChecker);
}
// Test sensor event direct report with gralloc for accel sensor at very fast rate
TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
sAccelNormChecker);
}
// Test sensor event direct report with gralloc for gyro sensor at normal rate
TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL,
sGyroNormChecker);
}
// Test sensor event direct report with gralloc for gyro sensor at fast rate
TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
sGyroNormChecker);
}
// Test sensor event direct report with gralloc for gyro sensor at very fast rate
TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
sGyroNormChecker);
}
// Test sensor event direct report with gralloc for mag sensor at normal rate
TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL,
NullChecker());
}
// Test sensor event direct report with gralloc for mag sensor at fast rate
TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST,
NullChecker());
}
// Test sensor event direct report with gralloc for mag sensor at very fast rate
TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
testDirectReportOperation(
SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::VERY_FAST, NullChecker());
}
int main(int argc, char **argv) {
::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV1_0::Instance());
::testing::InitGoogleTest(&argc, argv);
SensorsHidlEnvironmentV1_0::Instance()->init(&argc, argv);
int status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
return status;
}
// vim: set ts=2 sw=2