platform_sensor_fusion_unittest.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <memory>
  5. #include "base/bind.h"
  6. #include "base/callback_helpers.h"
  7. #include "base/memory/ref_counted.h"
  8. #include "base/run_loop.h"
  9. #include "base/test/task_environment.h"
  10. #include "base/test/test_future.h"
  11. #include "services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h"
  12. #include "services/device/generic_sensor/fake_platform_sensor_and_provider.h"
  13. #include "services/device/generic_sensor/generic_sensor_consts.h"
  14. #include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h"
  15. #include "services/device/generic_sensor/platform_sensor.h"
  16. #include "services/device/generic_sensor/platform_sensor_fusion.h"
  17. #include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
  18. #include "services/device/generic_sensor/platform_sensor_provider.h"
  19. #include "testing/gtest/include/gtest/gtest.h"
  20. using ::testing::_;
  21. using ::testing::Invoke;
  22. using ::testing::Return;
  23. namespace device {
  24. using mojom::SensorType;
  25. namespace {
  26. void ExpectNoReadingChangedEvent(MockPlatformSensorClient* sensor_client,
  27. mojom::SensorType sensor_type) {
  28. base::RunLoop run_loop;
  29. EXPECT_CALL(*sensor_client, OnSensorReadingChanged(sensor_type)).Times(0);
  30. run_loop.RunUntilIdle();
  31. }
  32. void ExpectReadingChangedEvent(MockPlatformSensorClient* sensor_client,
  33. mojom::SensorType sensor_type) {
  34. base::RunLoop run_loop;
  35. EXPECT_CALL(*sensor_client, OnSensorReadingChanged(sensor_type))
  36. .WillOnce(Invoke([&](SensorType) { run_loop.Quit(); }));
  37. run_loop.Run();
  38. }
  39. // Attempts to add a new reading to the sensor owned by |sensor_client|, and
  40. // asserts that it does not lead to OnSensorReadingChanged() being called (i.e.
  41. // PlatformSensor's significance check has failed).
  42. void AddNewReadingAndExpectNoReadingChangedEvent(
  43. MockPlatformSensorClient* sensor_client,
  44. const SensorReading& new_reading,
  45. mojom::SensorType sensor_type) {
  46. scoped_refptr<FakePlatformSensor> fake_sensor =
  47. static_cast<FakePlatformSensor*>(sensor_client->sensor().get());
  48. fake_sensor->AddNewReading(new_reading);
  49. ExpectNoReadingChangedEvent(sensor_client, sensor_type);
  50. }
  51. // Add a new reading to the sensor owned by |sensor_client|, and expect reading
  52. // change event.
  53. void AddNewReadingAndExpectReadingChangedEvent(
  54. MockPlatformSensorClient* sensor_client,
  55. const SensorReading& new_reading,
  56. mojom::SensorType sensor_type) {
  57. scoped_refptr<FakePlatformSensor> fake_sensor =
  58. static_cast<FakePlatformSensor*>(sensor_client->sensor().get());
  59. fake_sensor->AddNewReading(new_reading);
  60. ExpectReadingChangedEvent(sensor_client, sensor_type);
  61. }
  62. void FusionAlgorithmCopyLowLevelValues(const SensorReading& low_level_reading,
  63. SensorReading* fused_reading) {
  64. fused_reading->raw.values[0] = low_level_reading.raw.values[0];
  65. fused_reading->raw.values[1] = low_level_reading.raw.values[1];
  66. fused_reading->raw.values[2] = low_level_reading.raw.values[2];
  67. }
  68. void FusionAlgorithmSubtractEpsilonFromX(const SensorReading& low_level_reading,
  69. SensorReading* fused_reading) {
  70. fused_reading->raw.values[0] = low_level_reading.raw.values[0] - kEpsilon;
  71. fused_reading->raw.values[1] = low_level_reading.raw.values[1];
  72. fused_reading->raw.values[2] = low_level_reading.raw.values[2];
  73. }
  74. // A PlatformSensorFusionAlgorithm whose fusion algorithm can be customized
  75. // at runtime via set_fusion_function().
  76. class CustomizableFusionAlgorithm : public PlatformSensorFusionAlgorithm {
  77. public:
  78. using FusionFunction =
  79. base::RepeatingCallback<void(const SensorReading& low_level_reading,
  80. SensorReading* fused_reading)>;
  81. static constexpr mojom::SensorType kLowLevelSensorType =
  82. SensorType::ACCELEROMETER;
  83. static constexpr mojom::SensorType kFusionSensorType = SensorType::GRAVITY;
  84. CustomizableFusionAlgorithm()
  85. : PlatformSensorFusionAlgorithm(kFusionSensorType,
  86. {kLowLevelSensorType}) {}
  87. ~CustomizableFusionAlgorithm() override = default;
  88. bool GetFusedDataInternal(mojom::SensorType which_sensor_changed,
  89. SensorReading* fused_reading) override {
  90. EXPECT_EQ(which_sensor_changed, kLowLevelSensorType);
  91. SensorReading low_level_reading;
  92. EXPECT_TRUE(fusion_sensor_->GetSourceReading(kLowLevelSensorType,
  93. &low_level_reading));
  94. fusion_function_.Run(low_level_reading, fused_reading);
  95. return true;
  96. }
  97. void set_fusion_function(FusionFunction fusion_function) {
  98. fusion_function_ = std::move(fusion_function);
  99. }
  100. private:
  101. FusionFunction fusion_function_;
  102. };
  103. } // namespace
  104. class PlatformSensorFusionTest : public testing::Test {
  105. public:
  106. PlatformSensorFusionTest() {
  107. provider_ = std::make_unique<FakePlatformSensorProvider>();
  108. }
  109. PlatformSensorFusionTest(const PlatformSensorFusionTest&) = delete;
  110. PlatformSensorFusionTest& operator=(const PlatformSensorFusionTest&) = delete;
  111. protected:
  112. void CreateAccelerometer() {
  113. base::test::TestFuture<scoped_refptr<PlatformSensor>> future;
  114. provider_->CreateSensor(SensorType::ACCELEROMETER, future.GetCallback());
  115. accelerometer_ = static_cast<FakePlatformSensor*>(future.Get().get());
  116. EXPECT_TRUE(accelerometer_);
  117. EXPECT_EQ(SensorType::ACCELEROMETER, accelerometer_->GetType());
  118. }
  119. void CreateMagnetometer() {
  120. base::test::TestFuture<scoped_refptr<PlatformSensor>> future;
  121. provider_->CreateSensor(SensorType::MAGNETOMETER, future.GetCallback());
  122. magnetometer_ = static_cast<FakePlatformSensor*>(future.Get().get());
  123. EXPECT_TRUE(magnetometer_);
  124. EXPECT_EQ(SensorType::MAGNETOMETER, magnetometer_->GetType());
  125. }
  126. void CreateLinearAccelerationFusionSensor() {
  127. auto fusion_algorithm =
  128. std::make_unique<LinearAccelerationFusionAlgorithmUsingAccelerometer>();
  129. CreateFusionSensor(std::move(fusion_algorithm));
  130. }
  131. void CreateAbsoluteOrientationEulerAnglesFusionSensor() {
  132. auto fusion_algorithm = std::make_unique<
  133. AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer>();
  134. CreateFusionSensor(std::move(fusion_algorithm));
  135. }
  136. void CreateFusionSensor(
  137. std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm) {
  138. base::test::TestFuture<scoped_refptr<PlatformSensor>> future;
  139. const SensorType type = fusion_algorithm->fused_type();
  140. PlatformSensorFusion::Create(provider_->GetSensorReadingBuffer(type),
  141. provider_.get(), std::move(fusion_algorithm),
  142. future.GetCallback());
  143. fusion_sensor_ = static_cast<PlatformSensorFusion*>(future.Get().get());
  144. }
  145. base::test::TaskEnvironment task_environment_;
  146. std::unique_ptr<FakePlatformSensorProvider> provider_;
  147. scoped_refptr<FakePlatformSensor> accelerometer_;
  148. scoped_refptr<FakePlatformSensor> magnetometer_;
  149. scoped_refptr<PlatformSensorFusion> fusion_sensor_;
  150. };
  151. // The following code tests creating a fusion sensor that needs one source
  152. // sensor.
  153. TEST_F(PlatformSensorFusionTest, SourceSensorAlreadyExists) {
  154. EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  155. CreateAccelerometer();
  156. // Now the source sensor already exists.
  157. EXPECT_TRUE(provider_->GetSensor(SensorType::ACCELEROMETER));
  158. CreateLinearAccelerationFusionSensor();
  159. EXPECT_TRUE(fusion_sensor_);
  160. EXPECT_EQ(SensorType::LINEAR_ACCELERATION, fusion_sensor_->GetType());
  161. }
  162. TEST_F(PlatformSensorFusionTest, SourceSensorWorksSeparately) {
  163. CreateAccelerometer();
  164. EXPECT_TRUE(accelerometer_);
  165. EXPECT_FALSE(accelerometer_->IsActiveForTesting());
  166. auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>();
  167. accelerometer_->AddClient(client.get());
  168. accelerometer_->StartListening(client.get(), PlatformSensorConfiguration(10));
  169. EXPECT_TRUE(accelerometer_->IsActiveForTesting());
  170. CreateLinearAccelerationFusionSensor();
  171. EXPECT_TRUE(fusion_sensor_);
  172. EXPECT_EQ(SensorType::LINEAR_ACCELERATION, fusion_sensor_->GetType());
  173. EXPECT_FALSE(fusion_sensor_->IsActiveForTesting());
  174. fusion_sensor_->AddClient(client.get());
  175. fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(10));
  176. EXPECT_TRUE(fusion_sensor_->IsActiveForTesting());
  177. fusion_sensor_->StopListening(client.get(), PlatformSensorConfiguration(10));
  178. EXPECT_FALSE(fusion_sensor_->IsActiveForTesting());
  179. EXPECT_TRUE(accelerometer_->IsActiveForTesting());
  180. accelerometer_->RemoveClient(client.get());
  181. EXPECT_FALSE(accelerometer_->IsActiveForTesting());
  182. fusion_sensor_->RemoveClient(client.get());
  183. }
  184. namespace {
  185. void CheckConfigsCountForClient(const scoped_refptr<PlatformSensor>& sensor,
  186. PlatformSensor::Client* client,
  187. size_t expected_count) {
  188. auto client_entry = sensor->GetConfigMapForTesting().find(client);
  189. if (sensor->GetConfigMapForTesting().end() == client_entry) {
  190. EXPECT_EQ(0u, expected_count);
  191. return;
  192. }
  193. EXPECT_EQ(expected_count, client_entry->second.size());
  194. }
  195. } // namespace
  196. TEST_F(PlatformSensorFusionTest, SourceSensorDoesNotKeepOutdatedConfigs) {
  197. CreateAccelerometer();
  198. EXPECT_TRUE(accelerometer_);
  199. CreateLinearAccelerationFusionSensor();
  200. EXPECT_TRUE(fusion_sensor_);
  201. EXPECT_EQ(SensorType::LINEAR_ACCELERATION, fusion_sensor_->GetType());
  202. auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(
  203. fusion_sensor_);
  204. fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(10));
  205. fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(20));
  206. fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(30));
  207. EXPECT_EQ(1u, fusion_sensor_->GetConfigMapForTesting().size());
  208. EXPECT_EQ(1u, accelerometer_->GetConfigMapForTesting().size());
  209. CheckConfigsCountForClient(fusion_sensor_, client.get(), 3u);
  210. // Fusion sensor is a client for its sources, however it must keep only
  211. // one active configuration for them at a time.
  212. CheckConfigsCountForClient(accelerometer_, fusion_sensor_.get(), 1u);
  213. fusion_sensor_->StopListening(client.get(), PlatformSensorConfiguration(30));
  214. fusion_sensor_->StopListening(client.get(), PlatformSensorConfiguration(20));
  215. CheckConfigsCountForClient(fusion_sensor_, client.get(), 1u);
  216. CheckConfigsCountForClient(accelerometer_, fusion_sensor_.get(), 1u);
  217. fusion_sensor_->StopListening(client.get(), PlatformSensorConfiguration(10));
  218. CheckConfigsCountForClient(fusion_sensor_, client.get(), 0u);
  219. CheckConfigsCountForClient(accelerometer_, fusion_sensor_.get(), 0u);
  220. }
  221. TEST_F(PlatformSensorFusionTest, AllSourceSensorsStoppedOnSingleSourceFailure) {
  222. CreateAccelerometer();
  223. EXPECT_TRUE(accelerometer_);
  224. CreateMagnetometer();
  225. EXPECT_TRUE(magnetometer_);
  226. // Magnetometer will be started after Accelerometer for the given
  227. // sensor fusion algorithm.
  228. ON_CALL(*magnetometer_, StartSensor(_)).WillByDefault(Return(false));
  229. CreateAbsoluteOrientationEulerAnglesFusionSensor();
  230. EXPECT_TRUE(fusion_sensor_);
  231. EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES,
  232. fusion_sensor_->GetType());
  233. auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(
  234. fusion_sensor_);
  235. fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(10));
  236. EXPECT_FALSE(fusion_sensor_->IsActiveForTesting());
  237. EXPECT_FALSE(accelerometer_->IsActiveForTesting());
  238. EXPECT_FALSE(magnetometer_->IsActiveForTesting());
  239. }
  240. TEST_F(PlatformSensorFusionTest, SourceSensorNeedsToBeCreated) {
  241. EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  242. CreateLinearAccelerationFusionSensor();
  243. EXPECT_TRUE(fusion_sensor_);
  244. EXPECT_EQ(SensorType::LINEAR_ACCELERATION, fusion_sensor_->GetType());
  245. }
  246. TEST_F(PlatformSensorFusionTest, SourceSensorIsNotAvailable) {
  247. // Accelerometer is not available.
  248. ON_CALL(*provider_, DoCreateSensorInternal(SensorType::ACCELEROMETER, _, _))
  249. .WillByDefault(
  250. Invoke([](mojom::SensorType, scoped_refptr<PlatformSensor>,
  251. FakePlatformSensorProvider::CreateSensorCallback callback) {
  252. std::move(callback).Run(nullptr);
  253. }));
  254. CreateLinearAccelerationFusionSensor();
  255. EXPECT_FALSE(fusion_sensor_);
  256. }
  257. // The following code tests creating a fusion sensor that needs two source
  258. // sensors.
  259. TEST_F(PlatformSensorFusionTest, BothSourceSensorsAlreadyExist) {
  260. EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  261. CreateAccelerometer();
  262. EXPECT_TRUE(provider_->GetSensor(SensorType::ACCELEROMETER));
  263. EXPECT_FALSE(provider_->GetSensor(SensorType::MAGNETOMETER));
  264. CreateMagnetometer();
  265. EXPECT_TRUE(provider_->GetSensor(SensorType::MAGNETOMETER));
  266. CreateAbsoluteOrientationEulerAnglesFusionSensor();
  267. EXPECT_TRUE(fusion_sensor_);
  268. EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES,
  269. fusion_sensor_->GetType());
  270. }
  271. TEST_F(PlatformSensorFusionTest, BothSourceSensorsNeedToBeCreated) {
  272. EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  273. EXPECT_FALSE(provider_->GetSensor(SensorType::MAGNETOMETER));
  274. CreateAbsoluteOrientationEulerAnglesFusionSensor();
  275. EXPECT_TRUE(fusion_sensor_);
  276. EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES,
  277. fusion_sensor_->GetType());
  278. }
  279. TEST_F(PlatformSensorFusionTest, BothSourceSensorsAreNotAvailable) {
  280. // Failure.
  281. ON_CALL(*provider_, DoCreateSensorInternal(_, _, _))
  282. .WillByDefault(
  283. Invoke([](mojom::SensorType, scoped_refptr<PlatformSensor>,
  284. FakePlatformSensorProvider::CreateSensorCallback callback) {
  285. std::move(callback).Run(nullptr);
  286. }));
  287. CreateAbsoluteOrientationEulerAnglesFusionSensor();
  288. EXPECT_FALSE(fusion_sensor_);
  289. }
  290. TEST_F(PlatformSensorFusionTest,
  291. OneSourceSensorAlreadyExistsTheOtherSourceSensorNeedsToBeCreated) {
  292. EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  293. CreateAccelerometer();
  294. EXPECT_TRUE(provider_->GetSensor(SensorType::ACCELEROMETER));
  295. EXPECT_FALSE(provider_->GetSensor(SensorType::MAGNETOMETER));
  296. CreateAbsoluteOrientationEulerAnglesFusionSensor();
  297. EXPECT_TRUE(fusion_sensor_);
  298. EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES,
  299. fusion_sensor_->GetType());
  300. }
  301. TEST_F(PlatformSensorFusionTest,
  302. OneSourceSensorAlreadyExistsTheOtherSourceSensorIsNotAvailable) {
  303. EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  304. CreateAccelerometer();
  305. EXPECT_TRUE(provider_->GetSensor(SensorType::ACCELEROMETER));
  306. // Magnetometer is not available.
  307. ON_CALL(*provider_, DoCreateSensorInternal(SensorType::MAGNETOMETER, _, _))
  308. .WillByDefault(
  309. Invoke([](mojom::SensorType, scoped_refptr<PlatformSensor>,
  310. FakePlatformSensorProvider::CreateSensorCallback callback) {
  311. std::move(callback).Run(nullptr);
  312. }));
  313. CreateAbsoluteOrientationEulerAnglesFusionSensor();
  314. EXPECT_FALSE(fusion_sensor_);
  315. }
  316. TEST_F(PlatformSensorFusionTest,
  317. OneSourceSensorNeedsToBeCreatedTheOtherSourceSensorIsNotAvailable) {
  318. EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  319. // Magnetometer is not available.
  320. ON_CALL(*provider_, DoCreateSensorInternal(SensorType::MAGNETOMETER, _, _))
  321. .WillByDefault(
  322. Invoke([](mojom::SensorType, scoped_refptr<PlatformSensor>,
  323. FakePlatformSensorProvider::CreateSensorCallback callback) {
  324. std::move(callback).Run(nullptr);
  325. }));
  326. CreateAbsoluteOrientationEulerAnglesFusionSensor();
  327. EXPECT_FALSE(fusion_sensor_);
  328. }
  329. TEST_F(PlatformSensorFusionTest,
  330. FusionSensorMaximumSupportedFrequencyIsTheMaximumOfItsSourceSensors) {
  331. EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  332. CreateAccelerometer();
  333. scoped_refptr<PlatformSensor> accelerometer =
  334. provider_->GetSensor(SensorType::ACCELEROMETER);
  335. EXPECT_TRUE(accelerometer);
  336. static_cast<FakePlatformSensor*>(accelerometer.get())
  337. ->set_maximum_supported_frequency(30.0);
  338. EXPECT_FALSE(provider_->GetSensor(SensorType::MAGNETOMETER));
  339. CreateMagnetometer();
  340. scoped_refptr<PlatformSensor> magnetometer =
  341. provider_->GetSensor(SensorType::MAGNETOMETER);
  342. EXPECT_TRUE(magnetometer);
  343. static_cast<FakePlatformSensor*>(magnetometer.get())
  344. ->set_maximum_supported_frequency(20.0);
  345. CreateAbsoluteOrientationEulerAnglesFusionSensor();
  346. EXPECT_TRUE(fusion_sensor_);
  347. EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES,
  348. fusion_sensor_->GetType());
  349. EXPECT_EQ(30.0, fusion_sensor_->GetMaximumSupportedFrequency());
  350. auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(
  351. fusion_sensor_);
  352. EXPECT_TRUE(fusion_sensor_->StartListening(
  353. client.get(), PlatformSensorConfiguration(30.0)));
  354. }
  355. TEST_F(PlatformSensorFusionTest, FusionIsSignificantlyDifferent) {
  356. // Due to inaccuracy of calculations between doubles, difference between two
  357. // input values has to be bigger than the threshold value used in
  358. // significantly different check.
  359. CreateLinearAccelerationFusionSensor();
  360. const auto* const fusion_algorithm = fusion_sensor_->fusion_algorithm();
  361. const double kValueToFlipThreshold = fusion_algorithm->threshold() + kEpsilon;
  362. const double kValueNotToFlipThreshold =
  363. fusion_algorithm->threshold() - kEpsilon;
  364. SensorReading reading1;
  365. SensorReading reading2;
  366. // Made up test values.
  367. reading1.accel.x = reading2.accel.x = 0.1;
  368. reading1.accel.y = reading2.accel.y = 0.5;
  369. reading1.accel.z = reading2.accel.z = 10.0;
  370. // Compared values are same.
  371. // reading1: 0.1, 0.5, 10.0
  372. // reading2: 0.1, 0.5, 10.0
  373. EXPECT_FALSE(fusion_sensor_->IsSignificantlyDifferent(
  374. reading1, reading2, fusion_sensor_->GetType()));
  375. // Compared values do not significantly differ from each other.
  376. // reading1: 0.1, 0.5, 10.0
  377. // reading2: 0.1, 0.5, 10.00001
  378. reading2.accel.z = reading2.accel.z + kValueNotToFlipThreshold;
  379. EXPECT_FALSE(fusion_sensor_->IsSignificantlyDifferent(
  380. reading1, reading2, fusion_sensor_->GetType()));
  381. // Compared values significantly differ from each other.
  382. // reading1: 0.1, 0.5, 10.0
  383. // reading2: 0.1, 0.5, 10.11001
  384. reading2.accel.z = reading2.accel.z + kValueToFlipThreshold;
  385. EXPECT_TRUE(fusion_sensor_->IsSignificantlyDifferent(
  386. reading1, reading2, fusion_sensor_->GetType()));
  387. }
  388. TEST_F(PlatformSensorFusionTest, OnSensorReadingChanged) {
  389. // Accelerometer is selected as low-level sensor.
  390. CreateAccelerometer();
  391. EXPECT_TRUE(accelerometer_);
  392. auto client_low_level_ =
  393. std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(
  394. accelerometer_);
  395. CreateFusionSensor(std::make_unique<CustomizableFusionAlgorithm>());
  396. ASSERT_TRUE(fusion_sensor_);
  397. auto* fusion_algorithm = static_cast<CustomizableFusionAlgorithm*>(
  398. fusion_sensor_->fusion_algorithm());
  399. EXPECT_EQ(CustomizableFusionAlgorithm::kFusionSensorType,
  400. fusion_sensor_->GetType());
  401. auto client_fusion =
  402. std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(
  403. fusion_sensor_);
  404. fusion_sensor_->StartListening(client_fusion.get(),
  405. PlatformSensorConfiguration(10));
  406. // Made up test values.
  407. const double kTestValueX = 0.6;
  408. const double kTestValueY = 0.9;
  409. const double kTestValueZ = 1.1;
  410. const double kValueToFlipThreshold = fusion_algorithm->threshold() + kEpsilon;
  411. const double kValueToFlipThresholdRounded = fusion_algorithm->threshold();
  412. struct TestSensorReading {
  413. const struct {
  414. double x;
  415. double y;
  416. double z;
  417. } input, expected;
  418. const bool expect_reading_changed_event;
  419. };
  420. const struct {
  421. TestSensorReading low_level;
  422. TestSensorReading fusion;
  423. CustomizableFusionAlgorithm::FusionFunction fusion_function;
  424. } kTestSteps[] = {
  425. // Test set 1
  426. // Triggers low-level and fusion reading as initial sensor
  427. // values are zero.
  428. {// Low-level sensor
  429. {{kTestValueX, kTestValueY, kTestValueZ},
  430. {kTestValueX, kTestValueY, kTestValueZ},
  431. true},
  432. // Fusion sensor
  433. {{kTestValueX, kTestValueY, kTestValueZ},
  434. {kTestValueX, kTestValueY, kTestValueZ},
  435. true},
  436. base::BindRepeating(&FusionAlgorithmCopyLowLevelValues)},
  437. // Test set 2
  438. // Doesn't trigger low-level reading event as rounded value is same as
  439. // earlier. Because of that fusion sensor event is not either triggered.
  440. {// Low-level sensor
  441. {{kTestValueX + kEpsilon, kTestValueY, kTestValueZ},
  442. {kTestValueX, kTestValueY, kTestValueZ},
  443. false},
  444. // Fusion sensor
  445. {{kTestValueX, kTestValueY, kTestValueZ},
  446. {kTestValueX, kTestValueY, kTestValueZ},
  447. false},
  448. base::BindRepeating(&FusionAlgorithmSubtractEpsilonFromX)},
  449. // Test set 3
  450. // In current code as fusion sensor values are rounded before
  451. // PlatformSensorFusionAlgorithm::IsReadingSignificantlyDifferent() call
  452. // the difference between values must much bigger than threshold value.
  453. {// Low-level sensor
  454. {{kTestValueX + kValueToFlipThreshold, kTestValueY, kTestValueZ},
  455. {kTestValueX + kValueToFlipThresholdRounded, kTestValueY, kTestValueZ},
  456. true},
  457. // Fusion sensor
  458. {{kTestValueX + kValueToFlipThreshold, kTestValueY, kTestValueZ},
  459. {kTestValueX + kValueToFlipThresholdRounded, kTestValueY, kTestValueZ},
  460. true},
  461. base::BindRepeating(&FusionAlgorithmCopyLowLevelValues)},
  462. };
  463. for (const auto& test_step : kTestSteps) {
  464. fusion_algorithm->set_fusion_function(test_step.fusion_function);
  465. // First add low-level sensor readings.
  466. SensorReading reading;
  467. reading.accel.x = test_step.low_level.input.x;
  468. reading.accel.y = test_step.low_level.input.y;
  469. reading.accel.z = test_step.low_level.input.z;
  470. // Code checks if PlatformSensor::OnSensorReadingChanged() is called
  471. // or not called as expected.
  472. if (test_step.low_level.expect_reading_changed_event) {
  473. AddNewReadingAndExpectReadingChangedEvent(
  474. client_low_level_.get(), reading,
  475. CustomizableFusionAlgorithm::kLowLevelSensorType);
  476. } else {
  477. AddNewReadingAndExpectNoReadingChangedEvent(
  478. client_low_level_.get(), reading,
  479. CustomizableFusionAlgorithm::kLowLevelSensorType);
  480. }
  481. if (test_step.fusion.expect_reading_changed_event) {
  482. ExpectReadingChangedEvent(client_fusion.get(),
  483. CustomizableFusionAlgorithm::kFusionSensorType);
  484. } else {
  485. ExpectNoReadingChangedEvent(
  486. client_fusion.get(), CustomizableFusionAlgorithm::kFusionSensorType);
  487. }
  488. // Once new values are added, we can check that low-level sensors and
  489. // fusion sensor have correct values.
  490. // Check rounded low-level sensor values.
  491. EXPECT_TRUE(accelerometer_->GetLatestReading(&reading));
  492. EXPECT_DOUBLE_EQ(test_step.low_level.expected.x, reading.accel.x);
  493. EXPECT_DOUBLE_EQ(test_step.low_level.expected.y, reading.accel.y);
  494. EXPECT_DOUBLE_EQ(test_step.low_level.expected.z, reading.accel.z);
  495. // Check raw low-level sensor values.
  496. EXPECT_TRUE(accelerometer_->GetLatestRawReading(&reading));
  497. EXPECT_DOUBLE_EQ(test_step.low_level.input.x, reading.accel.x);
  498. EXPECT_DOUBLE_EQ(test_step.low_level.input.y, reading.accel.y);
  499. EXPECT_DOUBLE_EQ(test_step.low_level.input.z, reading.accel.z);
  500. // Check rounded fusion sensor values.
  501. EXPECT_TRUE(fusion_sensor_->GetLatestReading(&reading));
  502. EXPECT_DOUBLE_EQ(test_step.fusion.expected.x, reading.accel.x);
  503. EXPECT_DOUBLE_EQ(test_step.fusion.expected.y, reading.accel.y);
  504. EXPECT_DOUBLE_EQ(test_step.fusion.expected.z, reading.accel.z);
  505. // Check raw fusion sensor values.
  506. EXPECT_TRUE(fusion_sensor_->GetLatestRawReading(&reading));
  507. EXPECT_DOUBLE_EQ(test_step.fusion.input.x, reading.accel.x);
  508. EXPECT_DOUBLE_EQ(test_step.fusion.input.y, reading.accel.y);
  509. EXPECT_DOUBLE_EQ(test_step.fusion.input.z, reading.accel.z);
  510. }
  511. }
  512. } // namespace device