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 
5 #include "services/device/generic_sensor/platform_sensor_provider_chromeos.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/optional.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/test/bind.h"
14 #include "base/test/task_environment.h"
15 #include "chromeos/components/sensors/fake_sensor_device.h"
16 #include "chromeos/components/sensors/fake_sensor_hal_server.h"
17 #include "chromeos/components/sensors/sensor_hal_dispatcher.h"
18 #include "services/device/public/cpp/generic_sensor/sensor_traits.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 
21 namespace device {
22 
23 namespace {
24 
25 constexpr int kFakeDeviceId = 1;
26 
27 constexpr double kScaleValue = 10.0;
28 constexpr char kWrongScale[] = "10..0";
29 
30 constexpr char kWrongLocation[] = "basee";
31 
32 }  // namespace
33 
34 class PlatformSensorProviderChromeOSTest : public ::testing::Test {
35  protected:
SetUp()36   void SetUp() override {
37     chromeos::sensors::SensorHalDispatcher::Initialize();
38 
39     sensor_hal_server_ =
40         std::make_unique<chromeos::sensors::FakeSensorHalServer>();
41     provider_ = std::make_unique<PlatformSensorProviderChromeOS>();
42   }
43 
TearDown()44   void TearDown() override {
45     chromeos::sensors::SensorHalDispatcher::Shutdown();
46   }
47 
AddDevice(int32_t iio_device_id,chromeos::sensors::mojom::DeviceType type,const base::Optional<std::string> & scale,const base::Optional<std::string> & location)48   void AddDevice(int32_t iio_device_id,
49                  chromeos::sensors::mojom::DeviceType type,
50                  const base::Optional<std::string>& scale,
51                  const base::Optional<std::string>& location) {
52     AddDevice(iio_device_id,
53               std::set<chromeos::sensors::mojom::DeviceType>{type},
54               std::move(scale), std::move(location));
55   }
56 
AddDevice(int32_t iio_device_id,std::set<chromeos::sensors::mojom::DeviceType> types,const base::Optional<std::string> & scale,const base::Optional<std::string> & location)57   void AddDevice(int32_t iio_device_id,
58                  std::set<chromeos::sensors::mojom::DeviceType> types,
59                  const base::Optional<std::string>& scale,
60                  const base::Optional<std::string>& location) {
61     auto sensor_device = std::make_unique<chromeos::sensors::FakeSensorDevice>(
62         std::vector<chromeos::sensors::FakeSensorDevice::ChannelData>{});
63 
64     if (scale.has_value()) {
65       sensor_device->SetAttribute(chromeos::sensors::mojom::kScale,
66                                   scale.value());
67     }
68     if (location.has_value()) {
69       sensor_device->SetAttribute(chromeos::sensors::mojom::kLocation,
70                                   location.value());
71     }
72 
73     sensor_devices_.push_back(sensor_device.get());
74 
75     sensor_hal_server_->GetSensorService()->SetDevice(
76         iio_device_id, std::move(types), std::move(sensor_device));
77   }
78 
79   // Sensor creation is asynchronous, therefore inner loop is used to wait for
80   // PlatformSensorProvider::CreateSensorCallback completion.
CreateSensor(mojom::SensorType type)81   scoped_refptr<PlatformSensor> CreateSensor(mojom::SensorType type) {
82     scoped_refptr<PlatformSensor> sensor;
83     base::RunLoop run_loop;
84     provider_->CreateSensor(type,
85                             base::BindLambdaForTesting(
86                                 [&](scoped_refptr<PlatformSensor> new_sensor) {
87                                   if (new_sensor)
88                                     EXPECT_EQ(type, new_sensor->GetType());
89 
90                                   sensor = std::move(new_sensor);
91                                   run_loop.Quit();
92                                 }));
93     run_loop.Run();
94     return sensor;
95   }
96 
StartConnection()97   void StartConnection() {
98     chromeos::sensors::SensorHalDispatcher::GetInstance()->RegisterServer(
99         sensor_hal_server_->PassRemote());
100   }
101 
ResetClient()102   void ResetClient() {
103     // Similar to provider_->OnSensorHalClientFailure, but without the delay.
104     provider_->ResetSensorService();
105     provider_->sensor_hal_client_.reset();
106     provider_->RegisterSensorClient();
107   }
108 
109   std::unique_ptr<chromeos::sensors::FakeSensorHalServer> sensor_hal_server_;
110   std::vector<chromeos::sensors::FakeSensorDevice*> sensor_devices_;
111 
112   std::unique_ptr<PlatformSensorProviderChromeOS> provider_;
113 
114   base::test::SingleThreadTaskEnvironment task_environment_;
115 };
116 
TEST_F(PlatformSensorProviderChromeOSTest,CheckUnsupportedTypes)117 TEST_F(PlatformSensorProviderChromeOSTest, CheckUnsupportedTypes) {
118   int fake_id = 1;
119   // Containing at least one supported device type.
120   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL,
121             base::NumberToString(kScaleValue),
122             chromeos::sensors::mojom::kLocationBase);
123   AddDevice(fake_id++,
124             std::set<chromeos::sensors::mojom::DeviceType>{
125                 chromeos::sensors::mojom::DeviceType::ANGLVEL,
126                 chromeos::sensors::mojom::DeviceType::COUNT},
127             base::NumberToString(kScaleValue),
128             chromeos::sensors::mojom::kLocationBase);
129 
130   // All device types are unsupported.
131   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::COUNT,
132             base::NumberToString(kScaleValue),
133             chromeos::sensors::mojom::kLocationBase);
134   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGL,
135             base::NumberToString(kScaleValue),
136             chromeos::sensors::mojom::kLocationBase);
137   AddDevice(fake_id++,
138             std::set<chromeos::sensors::mojom::DeviceType>{
139                 chromeos::sensors::mojom::DeviceType::ANGL,
140                 chromeos::sensors::mojom::DeviceType::BARO},
141             base::NumberToString(kScaleValue),
142             chromeos::sensors::mojom::kLocationBase);
143 
144   StartConnection();
145 
146   EXPECT_TRUE(CreateSensor(mojom::SensorType::ACCELEROMETER));
147 
148   EXPECT_FALSE(provider_->sensors_[1].ignored);
149   EXPECT_FALSE(provider_->sensors_[2].ignored);
150   EXPECT_TRUE(provider_->sensors_[3].ignored);
151   EXPECT_TRUE(provider_->sensors_[4].ignored);
152   EXPECT_TRUE(provider_->sensors_[5].ignored);
153 }
154 
TEST_F(PlatformSensorProviderChromeOSTest,MissingScale)155 TEST_F(PlatformSensorProviderChromeOSTest, MissingScale) {
156   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL,
157             /*scale=*/base::nullopt, chromeos::sensors::mojom::kLocationBase);
158 
159   StartConnection();
160 
161   EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER));
162 }
163 
TEST_F(PlatformSensorProviderChromeOSTest,MissingLocation)164 TEST_F(PlatformSensorProviderChromeOSTest, MissingLocation) {
165   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL,
166             base::NumberToString(kScaleValue),
167             /*location=*/base::nullopt);
168 
169   StartConnection();
170 
171   EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER));
172 }
173 
TEST_F(PlatformSensorProviderChromeOSTest,WrongScale)174 TEST_F(PlatformSensorProviderChromeOSTest, WrongScale) {
175   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL,
176             kWrongScale, chromeos::sensors::mojom::kLocationBase);
177 
178   StartConnection();
179 
180   EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER));
181 }
182 
TEST_F(PlatformSensorProviderChromeOSTest,WrongLocation)183 TEST_F(PlatformSensorProviderChromeOSTest, WrongLocation) {
184   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL,
185             base::NumberToString(kScaleValue), kWrongLocation);
186 
187   StartConnection();
188 
189   EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER));
190 }
191 
TEST_F(PlatformSensorProviderChromeOSTest,CheckMainLocationBase)192 TEST_F(PlatformSensorProviderChromeOSTest, CheckMainLocationBase) {
193   int fake_id = 1;
194   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL,
195             base::NumberToString(kScaleValue),
196             chromeos::sensors::mojom::kLocationBase);
197 
198   // Will not be used.
199   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL,
200             base::NumberToString(kScaleValue),
201             chromeos::sensors::mojom::kLocationLid);
202 
203   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL,
204             base::NumberToString(kScaleValue),
205             chromeos::sensors::mojom::kLocationBase);
206 
207   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::MAGN,
208             base::NumberToString(kScaleValue),
209             chromeos::sensors::mojom::kLocationBase);
210 
211   StartConnection();
212 
213   EXPECT_TRUE(CreateSensor(mojom::SensorType::GYROSCOPE));
214 
215   // Wait until the disconnect of the gyroscope arrives at FakeSensorDevice.
216   base::RunLoop().RunUntilIdle();
217 
218   // Remote stored in |provider_|.
219   EXPECT_TRUE(sensor_devices_[0]->HasReceivers());
220   EXPECT_TRUE(sensor_devices_[3]->HasReceivers());
221   // Removed in |provider_| as it'll never be used.
222   EXPECT_FALSE(sensor_devices_[1]->HasReceivers());
223 }
224 
TEST_F(PlatformSensorProviderChromeOSTest,CheckMainLocationLid)225 TEST_F(PlatformSensorProviderChromeOSTest, CheckMainLocationLid) {
226   int fake_id = 1;
227   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL,
228             base::NumberToString(kScaleValue),
229             chromeos::sensors::mojom::kLocationBase);
230   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL,
231             base::NumberToString(kScaleValue),
232             chromeos::sensors::mojom::kLocationLid);
233 
234   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL,
235             base::NumberToString(kScaleValue),
236             chromeos::sensors::mojom::kLocationBase);
237   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL,
238             base::NumberToString(kScaleValue),
239             chromeos::sensors::mojom::kLocationLid);
240 
241   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::MAGN,
242             base::NumberToString(kScaleValue),
243             chromeos::sensors::mojom::kLocationCamera);
244 
245   StartConnection();
246 
247   // Wait until the disconnect of the first gyroscope arrives at
248   // FakeSensorDevice.
249   base::RunLoop().RunUntilIdle();
250 
251   // Removed in |provider_| as they'll never be used.
252   EXPECT_FALSE(sensor_devices_[0]->HasReceivers());
253   EXPECT_FALSE(sensor_devices_[2]->HasReceivers());
254   EXPECT_FALSE(sensor_devices_[4]->HasReceivers());
255   // Remote stored in |provider_|.
256   EXPECT_TRUE(sensor_devices_[1]->HasReceivers());
257   EXPECT_TRUE(sensor_devices_[3]->HasReceivers());
258 }
259 
TEST_F(PlatformSensorProviderChromeOSTest,CheckMainLocationLidWithMultitypeSensor)260 TEST_F(PlatformSensorProviderChromeOSTest,
261        CheckMainLocationLidWithMultitypeSensor) {
262   int fake_id = 1;
263   AddDevice(fake_id++,
264             std::set<chromeos::sensors::mojom::DeviceType>{
265                 chromeos::sensors::mojom::DeviceType::ACCEL,
266                 chromeos::sensors::mojom::DeviceType::ANGLVEL},
267             base::NumberToString(kScaleValue),
268             chromeos::sensors::mojom::kLocationLid);
269 
270   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL,
271             base::NumberToString(kScaleValue),
272             chromeos::sensors::mojom::kLocationBase);
273 
274   StartConnection();
275 
276   // Wait until the disconnect of the gyroscope arrives at FakeSensorDevice.
277   base::RunLoop().RunUntilIdle();
278 
279   // Remote stored in |provider_|.
280   EXPECT_TRUE(sensor_devices_[0]->HasReceivers());
281   // Removed in |provider_| as it'll never be used.
282   EXPECT_FALSE(sensor_devices_[1]->HasReceivers());
283 
284   EXPECT_TRUE(CreateSensor(mojom::SensorType::ACCELEROMETER));
285   EXPECT_TRUE(CreateSensor(mojom::SensorType::GYROSCOPE));
286 }
287 
TEST_F(PlatformSensorProviderChromeOSTest,CheckAmbientLightSensorLocationLid)288 TEST_F(PlatformSensorProviderChromeOSTest, CheckAmbientLightSensorLocationLid) {
289   int fake_id = 1;
290   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::LIGHT,
291             base::NumberToString(kScaleValue),
292             chromeos::sensors::mojom::kLocationBase);
293   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::LIGHT,
294             base::NumberToString(kScaleValue),
295             chromeos::sensors::mojom::kLocationLid);
296 
297   StartConnection();
298 
299   // Wait until the disconnect of the first ambient light sensor arrives at
300   // FakeSensorDevice.
301   base::RunLoop().RunUntilIdle();
302 
303   // Removed in |provider_| as it'll never be used.
304   EXPECT_FALSE(sensor_devices_[0]->HasReceivers());
305   // Remote stored in |provider_|.
306   EXPECT_TRUE(sensor_devices_[1]->HasReceivers());
307 }
308 
TEST_F(PlatformSensorProviderChromeOSTest,CheckAmbientLightSensorLocationBase)309 TEST_F(PlatformSensorProviderChromeOSTest,
310        CheckAmbientLightSensorLocationBase) {
311   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::LIGHT,
312             base::NumberToString(kScaleValue),
313             chromeos::sensors::mojom::kLocationBase);
314 
315   StartConnection();
316 
317   EXPECT_TRUE(CreateSensor(mojom::SensorType::AMBIENT_LIGHT));
318 }
319 
TEST_F(PlatformSensorProviderChromeOSTest,Reconnect)320 TEST_F(PlatformSensorProviderChromeOSTest, Reconnect) {
321   int fake_id = 1;
322 
323   // Will not be used.
324   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL,
325             base::NumberToString(kScaleValue),
326             chromeos::sensors::mojom::kLocationBase);
327 
328   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL,
329             base::NumberToString(kScaleValue),
330             chromeos::sensors::mojom::kLocationLid);
331 
332   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::LIGHT,
333             base::NumberToString(kScaleValue),
334             chromeos::sensors::mojom::kLocationBase);
335 
336   StartConnection();
337 
338   EXPECT_FALSE(CreateSensor(mojom::SensorType::ACCELEROMETER));
339 
340   // Simulate a disconnection between |provider_| and the dispatcher.
341   ResetClient();
342 
343   EXPECT_TRUE(CreateSensor(mojom::SensorType::GYROSCOPE));
344 
345   // Simulate a disconnection of IIO Service.
346   sensor_hal_server_->GetSensorService()->OnServiceDisconnect();
347   sensor_hal_server_->OnServerDisconnect();
348   // Remove the stored Mojo remote of the ambient light sensor.
349   sensor_devices_.back()->ClearReceivers();
350 
351   // Wait until the disconnect arrives at the dispatcher.
352   base::RunLoop().RunUntilIdle();
353 
354   StartConnection();
355 
356   EXPECT_TRUE(CreateSensor(mojom::SensorType::AMBIENT_LIGHT));
357 }
358 
TEST_F(PlatformSensorProviderChromeOSTest,CheckLinearAccelerationSensorNotCreatedIfNoAccelerometer)359 TEST_F(PlatformSensorProviderChromeOSTest,
360        CheckLinearAccelerationSensorNotCreatedIfNoAccelerometer) {
361   StartConnection();
362 
363   EXPECT_FALSE(CreateSensor(mojom::SensorType::LINEAR_ACCELERATION));
364 }
365 
TEST_F(PlatformSensorProviderChromeOSTest,CheckLinearAcceleration)366 TEST_F(PlatformSensorProviderChromeOSTest, CheckLinearAcceleration) {
367   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL,
368             base::NumberToString(kScaleValue),
369             chromeos::sensors::mojom::kLocationBase);
370 
371   StartConnection();
372 
373   EXPECT_TRUE(CreateSensor(mojom::SensorType::LINEAR_ACCELERATION));
374 }
375 
TEST_F(PlatformSensorProviderChromeOSTest,CheckAbsoluteOrientationSensorNotCreatedIfNoAccelerometerAndNoMagnetometer)376 TEST_F(
377     PlatformSensorProviderChromeOSTest,
378     CheckAbsoluteOrientationSensorNotCreatedIfNoAccelerometerAndNoMagnetometer) {
379   StartConnection();
380 
381   EXPECT_FALSE(
382       CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES));
383   EXPECT_FALSE(
384       CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION));
385 }
386 
TEST_F(PlatformSensorProviderChromeOSTest,CheckAbsoluteOrientationSensorNotCreatedIfNoAccelerometer)387 TEST_F(PlatformSensorProviderChromeOSTest,
388        CheckAbsoluteOrientationSensorNotCreatedIfNoAccelerometer) {
389   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::MAGN,
390             base::NumberToString(kScaleValue),
391             chromeos::sensors::mojom::kLocationBase);
392 
393   StartConnection();
394 
395   EXPECT_FALSE(
396       CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES));
397   EXPECT_FALSE(
398       CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION));
399 }
400 
TEST_F(PlatformSensorProviderChromeOSTest,CheckAbsoluteOrientationSensorNotCreatedIfNoMagnetometer)401 TEST_F(PlatformSensorProviderChromeOSTest,
402        CheckAbsoluteOrientationSensorNotCreatedIfNoMagnetometer) {
403   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL,
404             base::NumberToString(kScaleValue),
405             chromeos::sensors::mojom::kLocationBase);
406 
407   StartConnection();
408 
409   EXPECT_FALSE(
410       CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES));
411   EXPECT_FALSE(
412       CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION));
413 }
414 
TEST_F(PlatformSensorProviderChromeOSTest,CheckAbsoluteOrientationSensors)415 TEST_F(PlatformSensorProviderChromeOSTest, CheckAbsoluteOrientationSensors) {
416   int fake_id = 1;
417 
418   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL,
419             base::NumberToString(kScaleValue),
420             chromeos::sensors::mojom::kLocationBase);
421   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::MAGN,
422             base::NumberToString(kScaleValue),
423             chromeos::sensors::mojom::kLocationBase);
424 
425   StartConnection();
426 
427   EXPECT_TRUE(
428       CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES));
429   EXPECT_TRUE(CreateSensor(mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION));
430 }
431 
TEST_F(PlatformSensorProviderChromeOSTest,CheckRelativeOrientationSensorNotCreatedIfNoAccelerometerAndNoGyroscope)432 TEST_F(
433     PlatformSensorProviderChromeOSTest,
434     CheckRelativeOrientationSensorNotCreatedIfNoAccelerometerAndNoGyroscope) {
435   StartConnection();
436 
437   EXPECT_FALSE(
438       CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES));
439   EXPECT_FALSE(
440       CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION));
441 }
442 
TEST_F(PlatformSensorProviderChromeOSTest,CheckRelativeOrientationSensorNotCreatedIfNoAccelerometer)443 TEST_F(PlatformSensorProviderChromeOSTest,
444        CheckRelativeOrientationSensorNotCreatedIfNoAccelerometer) {
445   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ANGLVEL,
446             base::NumberToString(kScaleValue),
447             chromeos::sensors::mojom::kLocationBase);
448 
449   StartConnection();
450 
451   EXPECT_FALSE(
452       CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES));
453   EXPECT_FALSE(
454       CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION));
455 }
456 
TEST_F(PlatformSensorProviderChromeOSTest,CheckRelativeOrientationSensorUsingAccelerometer)457 TEST_F(PlatformSensorProviderChromeOSTest,
458        CheckRelativeOrientationSensorUsingAccelerometer) {
459   AddDevice(kFakeDeviceId, chromeos::sensors::mojom::DeviceType::ACCEL,
460             base::NumberToString(kScaleValue),
461             chromeos::sensors::mojom::kLocationBase);
462 
463   StartConnection();
464 
465   EXPECT_TRUE(
466       CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES));
467   EXPECT_TRUE(CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION));
468 }
469 
TEST_F(PlatformSensorProviderChromeOSTest,CheckRelativeOrientationSensorUsingAccelerometerAndGyroscope)470 TEST_F(PlatformSensorProviderChromeOSTest,
471        CheckRelativeOrientationSensorUsingAccelerometerAndGyroscope) {
472   int fake_id = 1;
473   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ANGLVEL,
474             base::NumberToString(kScaleValue),
475             chromeos::sensors::mojom::kLocationBase);
476   AddDevice(fake_id++, chromeos::sensors::mojom::DeviceType::ACCEL,
477             base::NumberToString(kScaleValue),
478             chromeos::sensors::mojom::kLocationBase);
479 
480   StartConnection();
481 
482   EXPECT_TRUE(
483       CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES));
484   EXPECT_TRUE(CreateSensor(mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION));
485 }
486 
487 }  // namespace device
488