platform_sensor_chromeos_unittest.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. // Copyright 2020 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 "services/device/generic_sensor/platform_sensor_chromeos.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/memory/scoped_refptr.h"
  8. #include "base/run_loop.h"
  9. #include "base/test/gmock_callback_support.h"
  10. #include "base/test/task_environment.h"
  11. #include "base/time/time.h"
  12. #include "chromeos/components/sensors/fake_sensor_device.h"
  13. #include "services/device/generic_sensor/fake_platform_sensor_and_provider.h"
  14. #include "services/device/generic_sensor/platform_sensor_util.h"
  15. #include "services/device/public/cpp/generic_sensor/sensor_traits.h"
  16. #include "testing/gmock/include/gmock/gmock.h"
  17. #include "testing/gtest/include/gtest/gtest.h"
  18. namespace device {
  19. namespace {
  20. constexpr int kFakeDeviceId = 1;
  21. constexpr char kAccelerometerChannels[][10] = {"accel_x", "accel_y", "accel_z"};
  22. constexpr char kGyroscopeChannels[][10] = {"anglvel_x", "anglvel_y",
  23. "anglvel_z"};
  24. constexpr char kMagnetometerChannels[][10] = {"magn_x", "magn_y", "magn_z"};
  25. constexpr char kGravityChannels[][10] = {"gravity_x", "gravity_y", "gravity_z"};
  26. constexpr double kScaleValue = 10.0;
  27. // The number of axes for which there are accelerometer readings.
  28. constexpr uint32_t kNumberOfAxes = 3u;
  29. constexpr int64_t kFakeSampleData = 1;
  30. constexpr int64_t kFakeAxesSampleData[] = {1, 2, 3};
  31. constexpr int64_t kFakeTimestampData = 163176689212344ll;
  32. } // namespace
  33. class PlatformSensorChromeOSTestBase {
  34. protected:
  35. void SetUpBase() {
  36. provider_ = std::make_unique<FakePlatformSensorProvider>();
  37. pending_receiver_ = sensor_device_remote_.BindNewPipeAndPassReceiver();
  38. }
  39. void InitSensorDevice(
  40. std::vector<chromeos::sensors::FakeSensorDevice::ChannelData>
  41. channels_data) {
  42. sensor_device_ = std::make_unique<chromeos::sensors::FakeSensorDevice>(
  43. std::move(channels_data));
  44. receiver_id_ = sensor_device_->AddReceiver(std::move(pending_receiver_));
  45. }
  46. void DisableFirstChannel() {
  47. DCHECK(sensor_device_.get());
  48. sensor_device_->SetChannelsEnabledWithId(receiver_id_, {0}, false);
  49. }
  50. void OnSensorDeviceDisconnect(uint32_t custom_reason_code,
  51. const std::string& description) {
  52. custom_reason_code_ = custom_reason_code;
  53. }
  54. std::unique_ptr<chromeos::sensors::FakeSensorDevice> sensor_device_;
  55. std::unique_ptr<FakePlatformSensorProvider> provider_;
  56. scoped_refptr<PlatformSensorChromeOS> sensor_;
  57. mojo::ReceiverId receiver_id_;
  58. mojo::Remote<chromeos::sensors::mojom::SensorDevice> sensor_device_remote_;
  59. mojo::PendingReceiver<chromeos::sensors::mojom::SensorDevice>
  60. pending_receiver_;
  61. absl::optional<uint32_t> custom_reason_code_;
  62. base::test::SingleThreadTaskEnvironment task_environment;
  63. };
  64. class PlatformSensorChromeOSOneChannelTest
  65. : public PlatformSensorChromeOSTestBase,
  66. public ::testing::TestWithParam<
  67. std::pair<mojom::SensorType, const char*>> {
  68. protected:
  69. void SetUp() override {
  70. SetUpBase();
  71. auto type = GetParam().first;
  72. sensor_ = base::MakeRefCounted<PlatformSensorChromeOS>(
  73. kFakeDeviceId, type, provider_->GetSensorReadingBuffer(type),
  74. provider_.get(),
  75. base::BindOnce(
  76. &PlatformSensorChromeOSOneChannelTest::OnSensorDeviceDisconnect,
  77. base::Unretained(this)),
  78. kScaleValue, std::move(sensor_device_remote_));
  79. EXPECT_EQ(sensor_->GetReportingMode(),
  80. type == mojom::SensorType::AMBIENT_LIGHT
  81. ? mojom::ReportingMode::ON_CHANGE
  82. : mojom::ReportingMode::CONTINUOUS);
  83. EXPECT_EQ(sensor_->GetDefaultConfiguration().frequency(),
  84. GetSensorMaxAllowedFrequency(type));
  85. }
  86. void SetChannels(const char channel[], bool set_first_channel) {
  87. std::vector<chromeos::sensors::FakeSensorDevice::ChannelData> channels_data(
  88. set_first_channel ? 2 : 1);
  89. if (set_first_channel) {
  90. channels_data.front().id = channel;
  91. channels_data.front().sample_data = kFakeSampleData;
  92. }
  93. channels_data.back().id = chromeos::sensors::mojom::kTimestampChannel;
  94. channels_data.back().sample_data = kFakeTimestampData;
  95. InitSensorDevice(std::move(channels_data));
  96. }
  97. SensorReadingSingle& GetSensorReadingSingle(SensorReading& reading) {
  98. switch (GetParam().first) {
  99. case mojom::SensorType::AMBIENT_LIGHT:
  100. return reading.als;
  101. default:
  102. LOG(FATAL) << "Invalid type: " << GetParam().first;
  103. return reading.als;
  104. }
  105. }
  106. void GetRoundedSensorReadingSingle(SensorReadingSingle* reading_single) {
  107. reading_single->value = kFakeSampleData * kScaleValue;
  108. reading_single->timestamp =
  109. base::Nanoseconds(kFakeTimestampData).InSecondsF();
  110. // No need to do rounding for these types of sensors.
  111. }
  112. void WaitForAndCheckReading(
  113. testing::NiceMock<MockPlatformSensorClient>* client) {
  114. base::RunLoop loop;
  115. // Wait until a sample is received.
  116. EXPECT_CALL(*client, OnSensorReadingChanged(GetParam().first))
  117. .WillOnce(base::test::RunOnceClosure(loop.QuitClosure()));
  118. loop.Run();
  119. SensorReading reading;
  120. EXPECT_TRUE(sensor_->GetLatestReading(&reading));
  121. const auto& reading_single = GetSensorReadingSingle(reading);
  122. SensorReadingSingle rounded_reading_single;
  123. GetRoundedSensorReadingSingle(&rounded_reading_single);
  124. EXPECT_EQ(reading_single.value, rounded_reading_single.value);
  125. EXPECT_EQ(reading_single.timestamp, rounded_reading_single.timestamp);
  126. }
  127. };
  128. TEST_P(PlatformSensorChromeOSOneChannelTest, MissingChannels) {
  129. SetChannels(GetParam().second, /*set_first_channel=*/false);
  130. auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>();
  131. sensor_->AddClient(client.get());
  132. sensor_->StartListening(client.get(),
  133. PlatformSensorConfiguration(
  134. GetSensorMaxAllowedFrequency(GetParam().first)));
  135. EXPECT_TRUE(sensor_->IsActiveForTesting());
  136. EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0);
  137. // Wait until all tasks done and no samples updated.
  138. base::RunLoop().RunUntilIdle();
  139. sensor_->RemoveClient(client.get());
  140. }
  141. TEST_P(PlatformSensorChromeOSOneChannelTest, GetSamples) {
  142. SetChannels(GetParam().second, /*set_first_channel=*/true);
  143. auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>();
  144. sensor_->AddClient(client.get());
  145. double frequency = GetSensorMaxAllowedFrequency(GetParam().first);
  146. sensor_->StartListening(client.get(), PlatformSensorConfiguration(frequency));
  147. EXPECT_TRUE(sensor_->IsActiveForTesting());
  148. WaitForAndCheckReading(client.get());
  149. sensor_->StopListening(client.get(), PlatformSensorConfiguration(frequency));
  150. sensor_->StartListening(client.get(), PlatformSensorConfiguration(frequency));
  151. WaitForAndCheckReading(client.get());
  152. DisableFirstChannel();
  153. EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0);
  154. // Wait until a sample without the first channel is received.
  155. base::RunLoop().RunUntilIdle();
  156. // No reading updated.
  157. sensor_device_->ResetObserverRemoteWithReason(
  158. receiver_id_,
  159. chromeos::sensors::mojom::SensorDeviceDisconnectReason::DEVICE_REMOVED,
  160. "Device was removed");
  161. base::RunLoop loop;
  162. // Wait until the disconnect arrives at |sensor_|.
  163. EXPECT_CALL(*client.get(), OnSensorError())
  164. .WillOnce(base::test::RunOnceClosure(loop.QuitClosure()));
  165. loop.Run();
  166. EXPECT_EQ(
  167. custom_reason_code_,
  168. static_cast<uint32_t>(chromeos::sensors::mojom::
  169. SensorDeviceDisconnectReason::DEVICE_REMOVED));
  170. sensor_->RemoveClient(client.get());
  171. }
  172. TEST_P(PlatformSensorChromeOSOneChannelTest, ResetOnTooManyFailures) {
  173. SetChannels(GetParam().second, /*set_first_channel=*/true);
  174. auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>();
  175. sensor_->AddClient(client.get());
  176. sensor_->StartListening(client.get(),
  177. PlatformSensorConfiguration(
  178. GetSensorMaxAllowedFrequency(GetParam().first)));
  179. EXPECT_TRUE(sensor_->IsActiveForTesting());
  180. WaitForAndCheckReading(client.get());
  181. EXPECT_CALL(*client.get(), OnSensorError()).Times(0);
  182. for (size_t i = 0;
  183. i < PlatformSensorChromeOS::kNumFailedReadsBeforeGivingUp - 1; ++i) {
  184. sensor_->OnErrorOccurred(
  185. chromeos::sensors::mojom::ObserverErrorType::READ_FAILED);
  186. }
  187. base::flat_map<int32_t, int64_t> sample;
  188. sample[0] = kFakeSampleData;
  189. sample[1] = kFakeTimestampData;
  190. for (size_t i = 0; i < PlatformSensorChromeOS::kNumRecoveryReads; ++i)
  191. sensor_->OnSampleUpdated(sample);
  192. // |num_failed_reads_| is recovered by 1.
  193. sensor_->OnErrorOccurred(
  194. chromeos::sensors::mojom::ObserverErrorType::READ_FAILED);
  195. EXPECT_CALL(*client.get(), OnSensorError()).Times(1);
  196. sensor_->OnErrorOccurred(
  197. chromeos::sensors::mojom::ObserverErrorType::READ_FAILED);
  198. sensor_->RemoveClient(client.get());
  199. }
  200. INSTANTIATE_TEST_SUITE_P(
  201. PlatformSensorChromeOSOneChannelTestRun,
  202. PlatformSensorChromeOSOneChannelTest,
  203. ::testing::Values(std::make_pair(mojom::SensorType::AMBIENT_LIGHT,
  204. chromeos::sensors::mojom::kLightChannel)));
  205. class PlatformSensorChromeOSAxesTest
  206. : public PlatformSensorChromeOSTestBase,
  207. public ::testing::TestWithParam<
  208. std::pair<mojom::SensorType, const char (*)[10]>> {
  209. protected:
  210. void SetUp() override {
  211. SetUpBase();
  212. auto type = GetParam().first;
  213. sensor_ = base::MakeRefCounted<PlatformSensorChromeOS>(
  214. kFakeDeviceId, type, provider_->GetSensorReadingBuffer(type), nullptr,
  215. base::BindOnce(
  216. &PlatformSensorChromeOSAxesTest::OnSensorDeviceDisconnect,
  217. base::Unretained(this)),
  218. kScaleValue, std::move(sensor_device_remote_));
  219. EXPECT_EQ(sensor_->GetReportingMode(), mojom::ReportingMode::CONTINUOUS);
  220. EXPECT_EQ(sensor_->GetDefaultConfiguration().frequency(),
  221. GetSensorMaxAllowedFrequency(type));
  222. }
  223. void SetChannelsWithAxes(const char channels[][10], uint32_t num_of_axes) {
  224. CHECK_LE(num_of_axes, kNumberOfAxes);
  225. std::vector<chromeos::sensors::FakeSensorDevice::ChannelData> channels_data(
  226. num_of_axes + 1);
  227. for (uint32_t i = 0; i < num_of_axes; ++i) {
  228. channels_data[i].id = channels[i];
  229. channels_data[i].sample_data = kFakeAxesSampleData[i];
  230. }
  231. channels_data.back().id = chromeos::sensors::mojom::kTimestampChannel;
  232. channels_data.back().sample_data = kFakeTimestampData;
  233. InitSensorDevice(std::move(channels_data));
  234. }
  235. SensorReadingXYZ& GetSensorReadingXYZ(SensorReading& reading) {
  236. switch (GetParam().first) {
  237. case mojom::SensorType::ACCELEROMETER:
  238. case mojom::SensorType::GRAVITY:
  239. return reading.accel;
  240. case mojom::SensorType::GYROSCOPE:
  241. return reading.gyro;
  242. case mojom::SensorType::MAGNETOMETER:
  243. return reading.magn;
  244. default:
  245. LOG(FATAL) << "Invalid type: " << GetParam().first;
  246. return reading.accel;
  247. }
  248. }
  249. void GetRoundedSensorReadingXYZ(SensorReadingXYZ* reading_xyz) {
  250. reading_xyz->x = kFakeAxesSampleData[0] * kScaleValue;
  251. reading_xyz->y = kFakeAxesSampleData[1] * kScaleValue;
  252. reading_xyz->z = kFakeAxesSampleData[2] * kScaleValue;
  253. reading_xyz->timestamp = base::Nanoseconds(kFakeTimestampData).InSecondsF();
  254. switch (GetParam().first) {
  255. case mojom::SensorType::ACCELEROMETER:
  256. case mojom::SensorType::GRAVITY:
  257. RoundAccelerometerReading(reading_xyz);
  258. break;
  259. case mojom::SensorType::GYROSCOPE:
  260. RoundGyroscopeReading(reading_xyz);
  261. break;
  262. case mojom::SensorType::MAGNETOMETER:
  263. break;
  264. default:
  265. LOG(FATAL) << "Invalid type: " << GetParam().first;
  266. break;
  267. }
  268. }
  269. void WaitForAndCheckReading(
  270. testing::NiceMock<MockPlatformSensorClient>* client) {
  271. base::RunLoop loop;
  272. // Wait until a sample is received.
  273. EXPECT_CALL(*client, OnSensorReadingChanged(GetParam().first))
  274. .WillOnce(base::test::RunOnceClosure(loop.QuitClosure()));
  275. loop.Run();
  276. SensorReading reading;
  277. EXPECT_TRUE(sensor_->GetLatestReading(&reading));
  278. const auto& reading_xyz = GetSensorReadingXYZ(reading);
  279. SensorReadingXYZ rounded_reading_xyz;
  280. GetRoundedSensorReadingXYZ(&rounded_reading_xyz);
  281. EXPECT_EQ(reading_xyz.x, rounded_reading_xyz.x);
  282. EXPECT_EQ(reading_xyz.y, rounded_reading_xyz.y);
  283. EXPECT_EQ(reading_xyz.z, rounded_reading_xyz.z);
  284. EXPECT_EQ(reading_xyz.timestamp, rounded_reading_xyz.timestamp);
  285. }
  286. };
  287. TEST_P(PlatformSensorChromeOSAxesTest, MissingChannels) {
  288. SetChannelsWithAxes(GetParam().second, kNumberOfAxes - 1);
  289. auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>();
  290. sensor_->AddClient(client.get());
  291. sensor_->StartListening(client.get(),
  292. PlatformSensorConfiguration(
  293. GetSensorMaxAllowedFrequency(GetParam().first)));
  294. EXPECT_TRUE(sensor_->IsActiveForTesting());
  295. EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0);
  296. // Wait until all tasks done and no samples updated.
  297. base::RunLoop().RunUntilIdle();
  298. sensor_->RemoveClient(client.get());
  299. }
  300. TEST_P(PlatformSensorChromeOSAxesTest, GetSamples) {
  301. SetChannelsWithAxes(GetParam().second, kNumberOfAxes);
  302. auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>();
  303. sensor_->AddClient(client.get());
  304. double frequency = GetSensorMaxAllowedFrequency(GetParam().first);
  305. sensor_->StartListening(client.get(), PlatformSensorConfiguration(frequency));
  306. EXPECT_TRUE(sensor_->IsActiveForTesting());
  307. WaitForAndCheckReading(client.get());
  308. sensor_->StopListening(client.get(), PlatformSensorConfiguration(frequency));
  309. sensor_->StartListening(client.get(), PlatformSensorConfiguration(frequency));
  310. WaitForAndCheckReading(client.get());
  311. DisableFirstChannel();
  312. EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0);
  313. // Wait until a sample without the first channel is received.
  314. base::RunLoop().RunUntilIdle();
  315. // No reading updated.
  316. sensor_device_->RemoveReceiver(receiver_id_);
  317. base::RunLoop loop;
  318. // Wait until the disconnect arrives at |sensor_|.
  319. EXPECT_CALL(*client.get(), OnSensorError())
  320. .WillOnce(base::test::RunOnceClosure(loop.QuitClosure()));
  321. loop.Run();
  322. sensor_->RemoveClient(client.get());
  323. }
  324. INSTANTIATE_TEST_SUITE_P(
  325. PlatformSensorChromeOSAxesTestRun,
  326. PlatformSensorChromeOSAxesTest,
  327. ::testing::Values(
  328. std::make_pair(mojom::SensorType::ACCELEROMETER,
  329. kAccelerometerChannels),
  330. std::make_pair(mojom::SensorType::GYROSCOPE, kGyroscopeChannels),
  331. std::make_pair(mojom::SensorType::MAGNETOMETER, kMagnetometerChannels),
  332. std::make_pair(mojom::SensorType::GRAVITY, kGravityChannels)));
  333. } // namespace device