1 // Copyright 2016 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 <SensorsApi.h>
6 #include <sensors.h>
7 #include <wrl/implements.h>
8 
9 #include "base/bind.h"
10 #include "base/numerics/math_constants.h"
11 #include "base/run_loop.h"
12 #include "base/test/task_environment.h"
13 #include "base/win/propvarutil.h"
14 #include "base/win/scoped_com_initializer.h"
15 #include "base/win/scoped_propvariant.h"
16 #include "services/device/generic_sensor/fake_platform_sensor_and_provider.h"
17 #include "services/device/generic_sensor/generic_sensor_consts.h"
18 #include "services/device/generic_sensor/platform_sensor_provider_win.h"
19 #include "services/device/generic_sensor/platform_sensor_util.h"
20 #include "services/device/public/mojom/sensor_provider.mojom.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gfx/geometry/angle_conversions.h"
24 
25 using ::testing::_;
26 using ::testing::Invoke;
27 using ::testing::IsNull;
28 using ::testing::NiceMock;
29 using ::testing::NotNull;
30 using ::testing::WithArgs;
31 
32 namespace device {
33 
34 using mojom::SensorType;
35 
36 // Mock class for ISensorManager COM interface.
37 class MockISensorManager
38     : public Microsoft::WRL::RuntimeClass<
39           Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
40           ISensorManager> {
41  public:
42   // ISensorManager interface
43   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
44                              GetSensorsByCategory,
45                              HRESULT(REFSENSOR_CATEGORY_ID category,
46                                      ISensorCollection** sensors_found));
47   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
48                              GetSensorsByType,
49                              HRESULT(REFSENSOR_TYPE_ID sensor_id,
50                                      ISensorCollection** sensors_found));
51   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
52                              GetSensorByID,
53                              HRESULT(REFSENSOR_ID sensor_id, ISensor** sensor));
54   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
55                              SetEventSink,
56                              HRESULT(ISensorManagerEvents* event_sink));
57   MOCK_METHOD3_WITH_CALLTYPE(STDMETHODCALLTYPE,
58                              RequestPermissions,
59                              HRESULT(HWND parent,
60                                      ISensorCollection* sensors,
61                                      BOOL is_modal));
62 
63  protected:
64   ~MockISensorManager() override = default;
65 };
66 
67 // Mock class for ISensorCollection COM interface.
68 class MockISensorCollection
69     : public Microsoft::WRL::RuntimeClass<
70           Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
71           ISensorCollection> {
72  public:
73   // ISensorCollection interface
74   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
75                              GetAt,
76                              HRESULT(ULONG index, ISensor** sensor));
77   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
78                              GetCount,
79                              HRESULT(ULONG* count));
80   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Add, HRESULT(ISensor* sensor));
81   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
82                              Remove,
83                              HRESULT(ISensor* sensor));
84   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
85                              RemoveByID,
86                              HRESULT(REFSENSOR_ID sensor_id));
87   MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Clear, HRESULT());
88 
89  protected:
90   ~MockISensorCollection() override = default;
91 };
92 
93 // Mock class for ISensor COM interface.
94 class MockISensor
95     : public Microsoft::WRL::RuntimeClass<
96           Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
97           ISensor> {
98  public:
99   // ISensor interface
100   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetID, HRESULT(SENSOR_ID* id));
101   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
102                              GetCategory,
103                              HRESULT(SENSOR_CATEGORY_ID* category));
104   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
105                              GetType,
106                              HRESULT(SENSOR_TYPE_ID* type));
107   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
108                              GetFriendlyName,
109                              HRESULT(BSTR* name));
110   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
111                              GetProperty,
112                              HRESULT(REFPROPERTYKEY key,
113                                      PROPVARIANT* property));
114   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
115                              GetProperties,
116                              HRESULT(IPortableDeviceKeyCollection* keys,
117                                      IPortableDeviceValues** properties));
118   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
119                              GetSupportedDataFields,
120                              HRESULT(IPortableDeviceKeyCollection** data));
121   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
122                              SetProperties,
123                              HRESULT(IPortableDeviceValues* properties,
124                                      IPortableDeviceValues** results));
125   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
126                              SupportsDataField,
127                              HRESULT(REFPROPERTYKEY key,
128                                      VARIANT_BOOL* is_supported));
129   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
130                              GetState,
131                              HRESULT(SensorState* state));
132   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
133                              GetData,
134                              HRESULT(ISensorDataReport** data_report));
135   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
136                              SupportsEvent,
137                              HRESULT(REFGUID event_guid,
138                                      VARIANT_BOOL* is_supported));
139   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
140                              GetEventInterest,
141                              HRESULT(GUID** values, ULONG* count));
142   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
143                              SetEventInterest,
144                              HRESULT(GUID* values, ULONG count));
145   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
146                              SetEventSink,
147                              HRESULT(ISensorEvents* pEvents));
148 
149  protected:
150   ~MockISensor() override = default;
151 };
152 
153 // Mock class for ISensorDataReport COM interface.
154 class MockISensorDataReport
155     : public Microsoft::WRL::RuntimeClass<
156           Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
157           ISensorDataReport> {
158  public:
159   // ISensorDataReport interface
160   MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
161                              GetTimestamp,
162                              HRESULT(SYSTEMTIME* timestamp));
163   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
164                              GetSensorValue,
165                              HRESULT(REFPROPERTYKEY key, PROPVARIANT* value));
166   MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
167                              GetSensorValues,
168                              HRESULT(IPortableDeviceKeyCollection* keys,
169                                      IPortableDeviceValues** values));
170 
171  protected:
172   ~MockISensorDataReport() override = default;
173 };
174 
175 // Class that provides test harness support for generic sensor adaptation for
176 // Windows platform. Testing is mainly done by mocking main COM interfaces that
177 // are used to communicate with Sensors API.
178 // MockISensorManager    - mocks ISensorManager and responsible for fetching
179 //                         list of supported sensors.
180 // MockISensorCollection - mocks collection of ISensor objects.
181 // MockISensor           - mocks ISensor intrface.
182 // MockISensorDataReport - mocks IDataReport interface that is used to deliver
183 //                         data in OnDataUpdated event.
184 class PlatformSensorAndProviderTestWin : public ::testing::Test {
185  public:
PlatformSensorAndProviderTestWin()186   PlatformSensorAndProviderTestWin()
187       : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
188 
SetUp()189   void SetUp() override {
190     sensor_ = Microsoft::WRL::Make<NiceMock<MockISensor>>();
191     sensor_collection_ =
192         Microsoft::WRL::Make<NiceMock<MockISensorCollection>>();
193     sensor_manager_ = Microsoft::WRL::Make<NiceMock<MockISensorManager>>();
194     Microsoft::WRL::ComPtr<ISensorManager> manager;
195     sensor_manager_->QueryInterface(IID_PPV_ARGS(&manager));
196 
197     // Overrides default ISensorManager with mocked interface.
198     provider_ = std::make_unique<PlatformSensorProviderWin>();
199     provider_->SetSensorManagerForTesting(std::move(manager));
200   }
201 
202  protected:
SensorCreated(scoped_refptr<PlatformSensor> sensor)203   void SensorCreated(scoped_refptr<PlatformSensor> sensor) {
204     platform_sensor_ = sensor;
205     run_loop_->Quit();
206   }
207 
208   // Sensor creation is asynchronous, therefore inner loop is used to wait for
209   // PlatformSensorProvider::CreateSensorCallback completion.
CreateSensor(mojom::SensorType type)210   scoped_refptr<PlatformSensor> CreateSensor(mojom::SensorType type) {
211     run_loop_ = std::make_unique<base::RunLoop>();
212     provider_->CreateSensor(
213         type, base::BindOnce(&PlatformSensorAndProviderTestWin::SensorCreated,
214                              base::Unretained(this)));
215     run_loop_->Run();
216     scoped_refptr<PlatformSensor> sensor;
217     sensor.swap(platform_sensor_);
218     run_loop_ = nullptr;
219     return sensor;
220   }
221 
222   // Listening the sensor is asynchronous, therefore inner loop is used to wait
223   // for SetEventSink to be called.
StartListening(scoped_refptr<PlatformSensor> sensor,PlatformSensor::Client * client,const PlatformSensorConfiguration & config)224   bool StartListening(scoped_refptr<PlatformSensor> sensor,
225                       PlatformSensor::Client* client,
226                       const PlatformSensorConfiguration& config) {
227     run_loop_ = std::make_unique<base::RunLoop>();
228     bool ret = sensor->StartListening(client, config);
229     if (ret)
230       run_loop_->Run();
231     run_loop_ = nullptr;
232     return ret;
233   }
234 
QuitInnerLoop()235   void QuitInnerLoop() { run_loop_->Quit(); }
236 
SetUnsupportedSensor(REFSENSOR_TYPE_ID sensor)237   void SetUnsupportedSensor(REFSENSOR_TYPE_ID sensor) {
238     EXPECT_CALL(*(sensor_manager_.Get()), GetSensorsByType(sensor, _))
239         .WillRepeatedly(
240             Invoke([](REFSENSOR_TYPE_ID type, ISensorCollection** collection) {
241               return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
242             }));
243   }
244 
245   // Sets sensor with REFSENSOR_TYPE_ID |sensor| to be supported by mocked
246   // ISensorMager and it will be present in ISensorCollection.
SetSupportedSensor(REFSENSOR_TYPE_ID sensor)247   void SetSupportedSensor(REFSENSOR_TYPE_ID sensor) {
248     // Returns mock ISensorCollection.
249     EXPECT_CALL(*(sensor_manager_.Get()), GetSensorsByType(sensor, _))
250         .WillOnce(Invoke(
251             [this](REFSENSOR_TYPE_ID type, ISensorCollection** collection) {
252               sensor_collection_->QueryInterface(
253                   __uuidof(ISensorCollection),
254                   reinterpret_cast<void**>(collection));
255               return S_OK;
256             }));
257 
258     // Returns number of ISensor objects in ISensorCollection, at the moment
259     // only one ISensor interface instance is suported.
260     EXPECT_CALL(*(sensor_collection_.Get()), GetCount(_))
261         .WillOnce(Invoke([](ULONG* count) {
262           *count = 1;
263           return S_OK;
264         }));
265 
266     // Returns ISensor interface instance at index 0.
267     EXPECT_CALL(*(sensor_collection_.Get()), GetAt(0, _))
268         .WillOnce(Invoke([this](ULONG index, ISensor** sensor) {
269           sensor_->QueryInterface(__uuidof(ISensor),
270                                   reinterpret_cast<void**>(sensor));
271           return S_OK;
272         }));
273 
274     // Handles |SetEventSink| call that is used to subscribe to sensor events
275     // through ISensorEvents interface. ISensorEvents is stored and attached to
276     // |sensor_events_| that is used later to generate fake error, state and
277     // data change events.
278     ON_CALL(*(sensor_.Get()), SetEventSink(NotNull()))
279         .WillByDefault(Invoke([this](ISensorEvents* events) {
280           events->AddRef();
281           sensor_events_.Attach(events);
282           if (this->run_loop_) {
283             task_environment_.GetMainThreadTaskRunner()->PostTask(
284                 FROM_HERE,
285                 base::BindOnce(&PlatformSensorAndProviderTestWin::QuitInnerLoop,
286                                base::Unretained(this)));
287           }
288           return S_OK;
289         }));
290 
291     // When |SetEventSink| is called with nullptr, it means that client is no
292     // longer interested in sensor events and ISensorEvents can be released.
293     ON_CALL(*(sensor_.Get()), SetEventSink(IsNull()))
294         .WillByDefault(Invoke([this](ISensorEvents* events) {
295           sensor_events_.Reset();
296           if (this->run_loop_) {
297             task_environment_.GetMainThreadTaskRunner()->PostTask(
298                 FROM_HERE,
299                 base::BindOnce(&PlatformSensorAndProviderTestWin::QuitInnerLoop,
300                                base::Unretained(this)));
301           }
302           return S_OK;
303         }));
304   }
305 
306   // Sets minimal reporting frequency for the mock sensor.
SetSupportedReportingFrequency(int frequency)307   void SetSupportedReportingFrequency(int frequency) {
308     ON_CALL(*(sensor_.Get()),
309             GetProperty(SENSOR_PROPERTY_MIN_REPORT_INTERVAL, _))
310         .WillByDefault(
311             Invoke([frequency](REFPROPERTYKEY key, PROPVARIANT* pProperty) {
312               pProperty->vt = VT_UI4;
313               pProperty->ulVal = 0;
314               if (frequency != 0) {
315                 pProperty->ulVal =
316                     (1.0 / frequency) * base::Time::kMillisecondsPerSecond;
317               }
318               return S_OK;
319             }));
320   }
321 
322   // Generates OnLeave event, e.g. when sensor is disconnected.
GenerateLeaveEvent()323   void GenerateLeaveEvent() {
324     if (!sensor_events_)
325       return;
326     sensor_events_->OnLeave(SENSOR_ID());
327   }
328 
329   // Generates OnStateChangedLeave event.
GenerateStateChangeEvent(SensorState state)330   void GenerateStateChangeEvent(SensorState state) {
331     if (!sensor_events_)
332       return;
333     sensor_events_->OnStateChanged(sensor_.Get(), state);
334   }
335 
336   struct PropertyKeyCompare {
operator ()device::PlatformSensorAndProviderTestWin::PropertyKeyCompare337     bool operator()(REFPROPERTYKEY a, REFPROPERTYKEY b) const {
338       if (a.fmtid == b.fmtid)
339         return a.pid < b.pid;
340       return false;
341     }
342   };
343 
344   using SensorData =
345       std::map<PROPERTYKEY, const PROPVARIANT*, PropertyKeyCompare>;
346 
347   // Generates OnDataUpdated event and creates ISensorDataReport with fake
348   // |value| for property with |key|.
GenerateDataUpdatedEvent(const SensorData & values)349   void GenerateDataUpdatedEvent(const SensorData& values) {
350     if (!sensor_events_)
351       return;
352 
353     auto mock_report = Microsoft::WRL::Make<NiceMock<MockISensorDataReport>>();
354     Microsoft::WRL::ComPtr<ISensorDataReport> data_report;
355     mock_report.As(&data_report);
356 
357     EXPECT_CALL(*(mock_report.Get()), GetTimestamp(_))
358         .WillOnce(Invoke([](SYSTEMTIME* timestamp) {
359           GetSystemTime(timestamp);
360           return S_OK;
361         }));
362 
363     EXPECT_CALL(*(mock_report.Get()), GetSensorValue(_, _))
364         .WillRepeatedly(WithArgs<0, 1>(
365             Invoke([&values](REFPROPERTYKEY key, PROPVARIANT* variant) {
366               auto it = values.find(key);
367               if (it == values.end())
368                 return E_FAIL;
369 
370               PropVariantCopy(variant, it->second);
371               return S_OK;
372             })));
373 
374     sensor_events_->OnDataUpdated(sensor_.Get(), data_report.Get());
375   }
376 
377   base::win::ScopedCOMInitializer com_initializer_;
378   base::test::TaskEnvironment task_environment_;
379   Microsoft::WRL::ComPtr<MockISensorManager> sensor_manager_;
380   Microsoft::WRL::ComPtr<MockISensorCollection> sensor_collection_;
381   Microsoft::WRL::ComPtr<MockISensor> sensor_;
382   std::unique_ptr<PlatformSensorProviderWin> provider_;
383   Microsoft::WRL::ComPtr<ISensorEvents> sensor_events_;
384   scoped_refptr<PlatformSensor> platform_sensor_;
385   // Inner run loop used to wait for async sensor creation callback.
386   std::unique_ptr<base::RunLoop> run_loop_;
387 };
388 
RoundAccelerometerValue(double value)389 double RoundAccelerometerValue(double value) {
390   return RoundToMultiple(value, kAccelerometerRoundingMultiple);
391 }
392 
RoundGyroscopeValue(double value)393 double RoundGyroscopeValue(double value) {
394   return RoundToMultiple(value, kGyroscopeRoundingMultiple);
395 }
396 
397 // Tests that PlatformSensorManager returns null sensor when sensor
398 // is not implemented.
TEST_F(PlatformSensorAndProviderTestWin,SensorIsNotImplemented)399 TEST_F(PlatformSensorAndProviderTestWin, SensorIsNotImplemented) {
400   EXPECT_CALL(*(sensor_manager_.Get()),
401               GetSensorsByType(SENSOR_TYPE_PRESSURE, _))
402       .Times(0);
403   EXPECT_FALSE(CreateSensor(SensorType::PRESSURE));
404 }
405 
406 // Tests that PlatformSensorManager returns null sensor when sensor
407 // is implemented, but not supported by the hardware.
TEST_F(PlatformSensorAndProviderTestWin,SensorIsNotSupported)408 TEST_F(PlatformSensorAndProviderTestWin, SensorIsNotSupported) {
409   EXPECT_CALL(*(sensor_manager_.Get()),
410               GetSensorsByType(SENSOR_TYPE_AMBIENT_LIGHT, _))
411       .WillOnce(Invoke([](REFSENSOR_TYPE_ID, ISensorCollection** result) {
412         *result = nullptr;
413         return E_FAIL;
414       }));
415 
416   EXPECT_FALSE(CreateSensor(SensorType::AMBIENT_LIGHT));
417 }
418 
419 // Tests that PlatformSensorManager returns correct sensor when sensor
420 // is supported by the hardware.
TEST_F(PlatformSensorAndProviderTestWin,SensorIsSupported)421 TEST_F(PlatformSensorAndProviderTestWin, SensorIsSupported) {
422   SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
423   auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
424   EXPECT_TRUE(sensor);
425   EXPECT_EQ(SensorType::AMBIENT_LIGHT, sensor->GetType());
426 }
427 
428 // Tests that PlatformSensor::StartListening fails when provided reporting
429 // frequency is above hardware capabilities.
TEST_F(PlatformSensorAndProviderTestWin,StartFails)430 TEST_F(PlatformSensorAndProviderTestWin, StartFails) {
431   SetSupportedReportingFrequency(1);
432   SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
433 
434   auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
435   EXPECT_TRUE(sensor);
436 
437   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
438   PlatformSensorConfiguration configuration(10);
439   EXPECT_FALSE(sensor->StartListening(client.get(), configuration));
440 }
441 
442 // Tests that PlatformSensor::StartListening succeeds and notification about
443 // modified sensor reading is sent to the PlatformSensor::Client interface.
TEST_F(PlatformSensorAndProviderTestWin,SensorStarted)444 TEST_F(PlatformSensorAndProviderTestWin, SensorStarted) {
445   SetSupportedReportingFrequency(10);
446   SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
447 
448   EXPECT_CALL(*(sensor_.Get()), SetEventSink(NotNull())).Times(1);
449   EXPECT_CALL(*(sensor_.Get()), SetEventSink(IsNull())).Times(1);
450   EXPECT_CALL(*(sensor_.Get()), SetProperties(NotNull(), _))
451       .WillRepeatedly(Invoke(
452           [](IPortableDeviceValues* props, IPortableDeviceValues** result) {
453             ULONG value = 0;
454             HRESULT hr = props->GetUnsignedIntegerValue(
455                 SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, &value);
456             EXPECT_TRUE(SUCCEEDED(hr));
457             // 10Hz is 100msec
458             EXPECT_THAT(value, 100);
459             return hr;
460           }));
461 
462   auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
463   EXPECT_TRUE(sensor);
464 
465   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
466   PlatformSensorConfiguration configuration(10);
467   EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
468 
469   EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
470   base::win::ScopedPropVariant pvLux;
471   InitPropVariantFromDouble(3.14, pvLux.Receive());
472   GenerateDataUpdatedEvent({{SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX, pvLux.ptr()}});
473   base::RunLoop().RunUntilIdle();
474   EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
475 }
476 
477 // Tests that OnSensorError is called when sensor is disconnected.
TEST_F(PlatformSensorAndProviderTestWin,SensorRemoved)478 TEST_F(PlatformSensorAndProviderTestWin, SensorRemoved) {
479   SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
480   auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
481   EXPECT_TRUE(sensor);
482 
483   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
484   PlatformSensorConfiguration configuration(10);
485   EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
486   EXPECT_CALL(*client, OnSensorError()).Times(1);
487 
488   GenerateLeaveEvent();
489   base::RunLoop().RunUntilIdle();
490 }
491 
492 // Tests that OnSensorError is called when sensor is in an error state.
TEST_F(PlatformSensorAndProviderTestWin,SensorStateChangedToError)493 TEST_F(PlatformSensorAndProviderTestWin, SensorStateChangedToError) {
494   SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
495   auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
496   EXPECT_TRUE(sensor);
497 
498   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
499   PlatformSensorConfiguration configuration(10);
500   EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
501   EXPECT_CALL(*client, OnSensorError()).Times(1);
502 
503   GenerateStateChangeEvent(SENSOR_STATE_ERROR);
504   base::RunLoop().RunUntilIdle();
505 }
506 
507 // Tests that OnSensorError is not called when sensor is in a ready state.
TEST_F(PlatformSensorAndProviderTestWin,SensorStateChangedToReady)508 TEST_F(PlatformSensorAndProviderTestWin, SensorStateChangedToReady) {
509   SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
510   auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
511   EXPECT_TRUE(sensor);
512 
513   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
514   PlatformSensorConfiguration configuration(10);
515   EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
516   EXPECT_CALL(*client, OnSensorError()).Times(0);
517 
518   GenerateStateChangeEvent(SENSOR_STATE_READY);
519   base::RunLoop().RunUntilIdle();
520 }
521 
522 // Tests that GetMaximumSupportedFrequency provides correct value.
TEST_F(PlatformSensorAndProviderTestWin,GetMaximumSupportedFrequency)523 TEST_F(PlatformSensorAndProviderTestWin, GetMaximumSupportedFrequency) {
524   SetSupportedReportingFrequency(20);
525   SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
526   auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
527   EXPECT_TRUE(sensor);
528   EXPECT_THAT(sensor->GetMaximumSupportedFrequency(), 20);
529 }
530 
531 // Tests that GetMaximumSupportedFrequency returns fallback value.
TEST_F(PlatformSensorAndProviderTestWin,GetMaximumSupportedFrequencyFallback)532 TEST_F(PlatformSensorAndProviderTestWin, GetMaximumSupportedFrequencyFallback) {
533   SetSupportedReportingFrequency(0);
534   SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
535   auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
536   EXPECT_TRUE(sensor);
537   EXPECT_THAT(sensor->GetMaximumSupportedFrequency(), 5);
538 }
539 
540 // Tests that Accelerometer readings are correctly converted.
TEST_F(PlatformSensorAndProviderTestWin,CheckAccelerometerReadingConversion)541 TEST_F(PlatformSensorAndProviderTestWin, CheckAccelerometerReadingConversion) {
542   mojo::ScopedSharedBufferHandle handle = provider_->CloneSharedBufferHandle();
543   mojo::ScopedSharedBufferMapping mapping = handle->MapAtOffset(
544       sizeof(SensorReadingSharedBuffer),
545       SensorReadingSharedBuffer::GetOffset(SensorType::ACCELEROMETER));
546 
547   SetSupportedSensor(SENSOR_TYPE_ACCELEROMETER_3D);
548   auto sensor = CreateSensor(SensorType::ACCELEROMETER);
549   EXPECT_TRUE(sensor);
550 
551   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
552   PlatformSensorConfiguration configuration(10);
553   EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
554   EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
555 
556   double x_accel = 0.25;
557   double y_accel = -0.25;
558   double z_accel = -0.5;
559 
560   base::win::ScopedPropVariant pvX, pvY, pvZ;
561   InitPropVariantFromDouble(x_accel, pvX.Receive());
562   InitPropVariantFromDouble(y_accel, pvY.Receive());
563   InitPropVariantFromDouble(z_accel, pvZ.Receive());
564 
565   GenerateDataUpdatedEvent({{SENSOR_DATA_TYPE_ACCELERATION_X_G, pvX.ptr()},
566                             {SENSOR_DATA_TYPE_ACCELERATION_Y_G, pvY.ptr()},
567                             {SENSOR_DATA_TYPE_ACCELERATION_Z_G, pvZ.ptr()}});
568 
569   base::RunLoop().RunUntilIdle();
570   SensorReadingSharedBuffer* buffer =
571       static_cast<SensorReadingSharedBuffer*>(mapping.get());
572   EXPECT_THAT(buffer->reading.accel.x,
573               RoundAccelerometerValue(-x_accel * base::kMeanGravityDouble));
574   EXPECT_THAT(buffer->reading.accel.y,
575               RoundAccelerometerValue(-y_accel * base::kMeanGravityDouble));
576   EXPECT_THAT(buffer->reading.accel.z,
577               RoundAccelerometerValue(-z_accel * base::kMeanGravityDouble));
578   EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
579 }
580 
581 // Tests that Gyroscope readings are correctly converted.
TEST_F(PlatformSensorAndProviderTestWin,CheckGyroscopeReadingConversion)582 TEST_F(PlatformSensorAndProviderTestWin, CheckGyroscopeReadingConversion) {
583   mojo::ScopedSharedBufferHandle handle = provider_->CloneSharedBufferHandle();
584   mojo::ScopedSharedBufferMapping mapping = handle->MapAtOffset(
585       sizeof(SensorReadingSharedBuffer),
586       SensorReadingSharedBuffer::GetOffset(SensorType::GYROSCOPE));
587 
588   SetSupportedSensor(SENSOR_TYPE_GYROMETER_3D);
589   auto sensor = CreateSensor(SensorType::GYROSCOPE);
590   EXPECT_TRUE(sensor);
591 
592   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
593   PlatformSensorConfiguration configuration(10);
594   EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
595   EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
596 
597   double x_ang_accel = 0.0;
598   double y_ang_accel = -1.8;
599   double z_ang_accel = -98.7;
600 
601   base::win::ScopedPropVariant pvX, pvY, pvZ;
602   InitPropVariantFromDouble(x_ang_accel, pvX.Receive());
603   InitPropVariantFromDouble(y_ang_accel, pvY.Receive());
604   InitPropVariantFromDouble(z_ang_accel, pvZ.Receive());
605 
606   GenerateDataUpdatedEvent(
607       {{SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND, pvX.ptr()},
608        {SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND, pvY.ptr()},
609        {SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND, pvZ.ptr()}});
610 
611   base::RunLoop().RunUntilIdle();
612   SensorReadingSharedBuffer* buffer =
613       static_cast<SensorReadingSharedBuffer*>(mapping.get());
614   EXPECT_THAT(buffer->reading.gyro.x,
615               RoundGyroscopeValue(gfx::DegToRad(x_ang_accel)));
616   EXPECT_THAT(buffer->reading.gyro.y,
617               RoundGyroscopeValue(gfx::DegToRad(y_ang_accel)));
618   EXPECT_THAT(buffer->reading.gyro.z,
619               RoundGyroscopeValue(gfx::DegToRad(z_ang_accel)));
620   EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
621 }
622 
623 // Tests that Magnetometer readings are correctly converted.
TEST_F(PlatformSensorAndProviderTestWin,CheckMagnetometerReadingConversion)624 TEST_F(PlatformSensorAndProviderTestWin, CheckMagnetometerReadingConversion) {
625   mojo::ScopedSharedBufferHandle handle = provider_->CloneSharedBufferHandle();
626   mojo::ScopedSharedBufferMapping mapping = handle->MapAtOffset(
627       sizeof(SensorReadingSharedBuffer),
628       SensorReadingSharedBuffer::GetOffset(SensorType::MAGNETOMETER));
629 
630   SetSupportedSensor(SENSOR_TYPE_COMPASS_3D);
631   auto sensor = CreateSensor(SensorType::MAGNETOMETER);
632   EXPECT_TRUE(sensor);
633 
634   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
635   PlatformSensorConfiguration configuration(10);
636   EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
637   EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
638 
639   double x_magn_field = 112.0;
640   double y_magn_field = -162.0;
641   double z_magn_field = 457.0;
642 
643   base::win::ScopedPropVariant pvX, pvY, pvZ;
644   InitPropVariantFromDouble(x_magn_field, pvX.Receive());
645   InitPropVariantFromDouble(y_magn_field, pvY.Receive());
646   InitPropVariantFromDouble(z_magn_field, pvZ.Receive());
647 
648   GenerateDataUpdatedEvent(
649       {{SENSOR_DATA_TYPE_MAGNETIC_FIELD_STRENGTH_X_MILLIGAUSS, pvX.ptr()},
650        {SENSOR_DATA_TYPE_MAGNETIC_FIELD_STRENGTH_Y_MILLIGAUSS, pvY.ptr()},
651        {SENSOR_DATA_TYPE_MAGNETIC_FIELD_STRENGTH_Z_MILLIGAUSS, pvZ.ptr()}});
652 
653   base::RunLoop().RunUntilIdle();
654   SensorReadingSharedBuffer* buffer =
655       static_cast<SensorReadingSharedBuffer*>(mapping.get());
656   EXPECT_THAT(buffer->reading.magn.x, x_magn_field * kMicroteslaInMilligauss);
657   EXPECT_THAT(buffer->reading.magn.y, y_magn_field * kMicroteslaInMilligauss);
658   EXPECT_THAT(buffer->reading.magn.z, z_magn_field * kMicroteslaInMilligauss);
659   EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
660 }
661 
662 // Tests that AbsoluteOrientationEulerAngles sensor readings are correctly
663 // provided.
TEST_F(PlatformSensorAndProviderTestWin,CheckDeviceOrientationEulerAnglesReadingConversion)664 TEST_F(PlatformSensorAndProviderTestWin,
665        CheckDeviceOrientationEulerAnglesReadingConversion) {
666   mojo::ScopedSharedBufferHandle handle = provider_->CloneSharedBufferHandle();
667   mojo::ScopedSharedBufferMapping mapping =
668       handle->MapAtOffset(sizeof(SensorReadingSharedBuffer),
669                           SensorReadingSharedBuffer::GetOffset(
670                               SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES));
671 
672   SetSupportedSensor(SENSOR_TYPE_INCLINOMETER_3D);
673   auto sensor = CreateSensor(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES);
674   EXPECT_TRUE(sensor);
675 
676   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
677   PlatformSensorConfiguration configuration(10);
678   EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
679   EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
680 
681   double x = 10;
682   double y = 20;
683   double z = 30;
684 
685   base::win::ScopedPropVariant pvX, pvY, pvZ;
686   InitPropVariantFromDouble(x, pvX.Receive());
687   InitPropVariantFromDouble(y, pvY.Receive());
688   InitPropVariantFromDouble(z, pvZ.Receive());
689 
690   GenerateDataUpdatedEvent({{SENSOR_DATA_TYPE_TILT_X_DEGREES, pvX.ptr()},
691                             {SENSOR_DATA_TYPE_TILT_Y_DEGREES, pvY.ptr()},
692                             {SENSOR_DATA_TYPE_TILT_Z_DEGREES, pvZ.ptr()}});
693 
694   base::RunLoop().RunUntilIdle();
695   SensorReadingSharedBuffer* buffer =
696       static_cast<SensorReadingSharedBuffer*>(mapping.get());
697 
698   EXPECT_THAT(buffer->reading.orientation_euler.x, x);
699   EXPECT_THAT(buffer->reading.orientation_euler.y, y);
700   EXPECT_THAT(buffer->reading.orientation_euler.z, z);
701   EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
702 }
703 
704 // Tests that AbsoluteOrientationQuaternion sensor readings are correctly
705 // provided.
TEST_F(PlatformSensorAndProviderTestWin,CheckDeviceOrientationQuaternionReadingConversion)706 TEST_F(PlatformSensorAndProviderTestWin,
707        CheckDeviceOrientationQuaternionReadingConversion) {
708   mojo::ScopedSharedBufferHandle handle = provider_->CloneSharedBufferHandle();
709   mojo::ScopedSharedBufferMapping mapping =
710       handle->MapAtOffset(sizeof(SensorReadingSharedBuffer),
711                           SensorReadingSharedBuffer::GetOffset(
712                               SensorType::ABSOLUTE_ORIENTATION_QUATERNION));
713 
714   SetSupportedSensor(SENSOR_TYPE_AGGREGATED_DEVICE_ORIENTATION);
715   auto sensor = CreateSensor(SensorType::ABSOLUTE_ORIENTATION_QUATERNION);
716   EXPECT_TRUE(sensor);
717 
718   auto client = std::make_unique<NiceMock<MockPlatformSensorClient>>(sensor);
719   PlatformSensorConfiguration configuration(10);
720   EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
721   EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
722 
723   // The axis (unit vector) around which to rotate.
724   const double axis[3] = {1.0 / std::sqrt(3), 1.0 / std::sqrt(3),
725                           -1.0 / std::sqrt(3)};
726 
727   // Create the unit quaternion manually.
728   const double theta = 2.0943951023931953;  // 120 degrees in radians.
729   const float quat_elements[4] = {
730       axis[0] * std::sin(theta / 2.0), axis[1] * std::sin(theta / 2.0),
731       axis[2] * std::sin(theta / 2.0), std::cos(theta / 2.0)};
732 
733   base::win::ScopedPropVariant pvQuat;
734 
735   // The SENSOR_DATA_TYPE_QUATERNION property has [VT_VECTOR | VT_UI1] type.
736   // https://msdn.microsoft.com/en-us/library/windows/hardware/dn265187(v=vs.85).aspx
737   // Helper functions e.g., InitVariantFromDoubleArray cannot be used for its
738   // intialization and the only way to initialize it, is to use
739   // InitPropVariantFromGUIDAsBuffer with quaternion format GUID.
740   InitPropVariantFromGUIDAsBuffer(SENSOR_DATA_TYPE_QUATERNION.fmtid,
741                                   pvQuat.Receive());
742   memcpy(pvQuat.get().caub.pElems, &quat_elements, sizeof(quat_elements));
743   GenerateDataUpdatedEvent({{SENSOR_DATA_TYPE_QUATERNION, pvQuat.ptr()}});
744 
745   base::RunLoop().RunUntilIdle();
746   SensorReadingSharedBuffer* buffer =
747       static_cast<SensorReadingSharedBuffer*>(mapping.get());
748 
749   const float epsilon = 1.0e-3;
750   EXPECT_NEAR(buffer->reading.orientation_quat.x, quat_elements[0], epsilon);
751   EXPECT_NEAR(buffer->reading.orientation_quat.y, quat_elements[1], epsilon);
752   EXPECT_NEAR(buffer->reading.orientation_quat.z, quat_elements[2], epsilon);
753   EXPECT_FLOAT_EQ(buffer->reading.orientation_quat.w, quat_elements[3]);
754   EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
755 }
756 
757 // Tests that when only the quaternion version of the absolute orientation
758 // sensor is available the provider falls back to using a fusion algorithm
759 // to provide the euler angles version.
TEST_F(PlatformSensorAndProviderTestWin,CheckDeviceOrientationEulerAnglesFallback)760 TEST_F(PlatformSensorAndProviderTestWin,
761        CheckDeviceOrientationEulerAnglesFallback) {
762   SetUnsupportedSensor(SENSOR_TYPE_INCLINOMETER_3D);
763   SetSupportedSensor(SENSOR_TYPE_AGGREGATED_DEVICE_ORIENTATION);
764 
765   auto sensor = CreateSensor(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES);
766   EXPECT_TRUE(sensor);
767 }
768 
769 // Tests that with neither absolute orientation sensor type available
770 // the fallback logic does not generate an infinite loop.
TEST_F(PlatformSensorAndProviderTestWin,CheckDeviceOrientationFallbackFailure)771 TEST_F(PlatformSensorAndProviderTestWin,
772        CheckDeviceOrientationFallbackFailure) {
773   SetUnsupportedSensor(SENSOR_TYPE_INCLINOMETER_3D);
774   SetUnsupportedSensor(SENSOR_TYPE_AGGREGATED_DEVICE_ORIENTATION);
775 
776   auto euler_angles_sensor =
777       CreateSensor(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES);
778   EXPECT_FALSE(euler_angles_sensor);
779   auto quaternion_sensor =
780       CreateSensor(SensorType::ABSOLUTE_ORIENTATION_QUATERNION);
781   EXPECT_FALSE(quaternion_sensor);
782 }
783 
784 }  // namespace device
785