1 // Copyright 2015 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.
5 #include "components/proximity_auth/proximity_monitor_impl.h"
7 #include "base/macros.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/test/histogram_tester.h"
12 #include "base/test/simple_test_tick_clock.h"
13 #include "base/test/test_simple_task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/time/time.h"
16 #include "components/proximity_auth/logging/logging.h"
17 #include "components/proximity_auth/proximity_monitor_observer.h"
18 #include "components/proximity_auth/remote_device.h"
19 #include "device/bluetooth/bluetooth_adapter_factory.h"
20 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using device::BluetoothDevice
;
26 using testing::NiceMock
;
27 using testing::Return
;
28 using testing::SaveArg
;
30 namespace proximity_auth
{
33 const char kBluetoothAddress
[] = "AA:BB:CC:DD:EE:FF";
34 const char kRemoteDevicePublicKey
[] = "Remote Public Key";
35 const char kRemoteDeviceName
[] = "LGE Nexus 5";
36 const char kPersistentSymmetricKey
[] = "PSK";
38 class TestProximityMonitorImpl
: public ProximityMonitorImpl
{
40 explicit TestProximityMonitorImpl(const RemoteDevice
& remote_device
,
41 scoped_ptr
<base::TickClock
> clock
,
42 ProximityMonitorObserver
* observer
)
43 : ProximityMonitorImpl(remote_device
, clock
.Pass(), observer
) {}
44 ~TestProximityMonitorImpl() override
{}
46 using ProximityMonitorImpl::SetStrategy
;
49 DISALLOW_COPY_AND_ASSIGN(TestProximityMonitorImpl
);
52 class MockProximityMonitorObserver
: public ProximityMonitorObserver
{
54 MockProximityMonitorObserver() {}
55 ~MockProximityMonitorObserver() override
{}
57 MOCK_METHOD0(OnProximityStateChanged
, void());
60 DISALLOW_COPY_AND_ASSIGN(MockProximityMonitorObserver
);
63 // Creates a mock Bluetooth adapter and sets it as the global adapter for
65 scoped_refptr
<device::MockBluetoothAdapter
>
66 CreateAndRegisterMockBluetoothAdapter() {
67 scoped_refptr
<device::MockBluetoothAdapter
> adapter
=
68 new NiceMock
<device::MockBluetoothAdapter
>();
69 device::BluetoothAdapterFactory::SetAdapterForTesting(adapter
);
75 class ProximityAuthProximityMonitorImplTest
: public testing::Test
{
77 ProximityAuthProximityMonitorImplTest()
78 : clock_(new base::SimpleTestTickClock()),
79 bluetooth_adapter_(CreateAndRegisterMockBluetoothAdapter()),
80 remote_bluetooth_device_(&*bluetooth_adapter_
,
85 true /* connected */),
86 monitor_(RemoteDevice(kRemoteDeviceName
,
87 kRemoteDevicePublicKey
,
89 kPersistentSymmetricKey
),
90 make_scoped_ptr(clock_
),
92 task_runner_(new base::TestSimpleTaskRunner()),
93 thread_task_runner_handle_(task_runner_
) {
94 ON_CALL(*bluetooth_adapter_
, GetDevice(kBluetoothAddress
))
95 .WillByDefault(Return(&remote_bluetooth_device_
));
96 ON_CALL(remote_bluetooth_device_
, GetConnectionInfo(_
))
97 .WillByDefault(SaveArg
<0>(&connection_info_callback_
));
99 ~ProximityAuthProximityMonitorImplTest() override
{}
101 void RunPendingTasks() { task_runner_
->RunPendingTasks(); }
103 void ProvideConnectionInfo(
104 const BluetoothDevice::ConnectionInfo
& connection_info
) {
106 connection_info_callback_
.Run(connection_info
);
108 // Reset the callback to ensure that tests correctly only respond at most
109 // once per call to GetConnectionInfo().
110 connection_info_callback_
= BluetoothDevice::ConnectionInfoCallback();
114 // Mock for verifying interactions with the proximity monitor's observer.
115 NiceMock
<MockProximityMonitorObserver
> observer_
;
117 // Clock used for verifying time calculations. Owned by the monitor_.
118 base::SimpleTestTickClock
* clock_
;
120 // Mocks used for verifying interactions with the Bluetooth subsystem.
121 scoped_refptr
<device::MockBluetoothAdapter
> bluetooth_adapter_
;
122 NiceMock
<device::MockBluetoothDevice
> remote_bluetooth_device_
;
124 // The proximity monitor under test.
125 TestProximityMonitorImpl monitor_
;
128 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
129 base::ThreadTaskRunnerHandle thread_task_runner_handle_
;
130 BluetoothDevice::ConnectionInfoCallback connection_info_callback_
;
131 ScopedDisableLoggingForTesting disable_logging_
;
134 TEST_F(ProximityAuthProximityMonitorImplTest
, GetStrategy
) {
135 EXPECT_EQ(ProximityMonitor::Strategy::NONE
, monitor_
.GetStrategy());
137 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
);
138 EXPECT_EQ(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
,
139 monitor_
.GetStrategy());
142 TEST_F(ProximityAuthProximityMonitorImplTest
, ProximityState_StrategyIsNone
) {
143 monitor_
.SetStrategy(ProximityMonitor::Strategy::NONE
);
145 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
146 EXPECT_FALSE(monitor_
.IsInRssiRange());
149 TEST_F(ProximityAuthProximityMonitorImplTest
, ProximityState_NeverStarted
) {
150 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
152 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
153 EXPECT_FALSE(monitor_
.IsInRssiRange());
156 TEST_F(ProximityAuthProximityMonitorImplTest
,
157 ProximityState_Started_NoConnectionInfoReceivedYet
) {
158 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
161 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
162 EXPECT_FALSE(monitor_
.IsInRssiRange());
165 TEST_F(ProximityAuthProximityMonitorImplTest
,
166 ProximityState_InformsObserverOfChanges
) {
167 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
);
169 // Initially, the device is not in proximity.
171 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
173 // Simulate a reading indicating proximity.
174 EXPECT_CALL(observer_
, OnProximityStateChanged()).Times(1);
175 ProvideConnectionInfo({0, 0, 4});
176 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
178 // Simulate a reading indicating non-proximity.
179 EXPECT_CALL(observer_
, OnProximityStateChanged()).Times(1);
180 ProvideConnectionInfo({0, 4, 4});
181 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
184 TEST_F(ProximityAuthProximityMonitorImplTest
,
185 ProximityState_CheckRssi_RssiIndicatesProximity_TxPowerDoesNot
) {
186 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
189 ProvideConnectionInfo({0, 4, 4});
191 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
192 EXPECT_TRUE(monitor_
.IsInRssiRange());
195 TEST_F(ProximityAuthProximityMonitorImplTest
,
196 ProximityState_CheckRssi_TxPowerIndicatesProximity_RssiDoesNot
) {
197 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
200 ProvideConnectionInfo({-10, 0, 4});
202 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
203 EXPECT_FALSE(monitor_
.IsInRssiRange());
206 TEST_F(ProximityAuthProximityMonitorImplTest
,
207 ProximityState_CheckRssi_NeitherRssiNorTxPowerIndicatesProximity
) {
208 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
211 ProvideConnectionInfo({-10, 4, 4});
213 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
214 EXPECT_FALSE(monitor_
.IsInRssiRange());
217 TEST_F(ProximityAuthProximityMonitorImplTest
,
218 ProximityState_CheckRssi_BothRssiAndTxPowerIndicateProximity
) {
219 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
222 ProvideConnectionInfo({0, 0, 4});
224 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
225 EXPECT_TRUE(monitor_
.IsInRssiRange());
228 TEST_F(ProximityAuthProximityMonitorImplTest
,
229 ProximityState_CheckRssi_UnknownRssi
) {
230 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
233 ProvideConnectionInfo({0, 0, 4});
234 ProvideConnectionInfo({BluetoothDevice::kUnknownPower
, 0, 4});
236 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
237 EXPECT_FALSE(monitor_
.IsInRssiRange());
240 TEST_F(ProximityAuthProximityMonitorImplTest
,
241 ProximityState_CheckRssi_UnknownTxPower
) {
242 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
245 ProvideConnectionInfo({0, 0, 4});
246 ProvideConnectionInfo({0, BluetoothDevice::kUnknownPower
, 4});
248 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
249 EXPECT_FALSE(monitor_
.IsInRssiRange());
252 TEST_F(ProximityAuthProximityMonitorImplTest
,
253 ProximityState_CheckRssi_UnknownMaxTxPower
) {
254 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
257 ProvideConnectionInfo({0, 0, 4});
258 ProvideConnectionInfo({0, 0, BluetoothDevice::kUnknownPower
});
260 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
261 EXPECT_FALSE(monitor_
.IsInRssiRange());
264 TEST_F(ProximityAuthProximityMonitorImplTest
,
265 ProximityState_CheckTxPower_RssiIndicatesProximity_TxPowerDoesNot
) {
266 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
);
269 ProvideConnectionInfo({0, 4, 4});
271 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
272 EXPECT_TRUE(monitor_
.IsInRssiRange());
275 TEST_F(ProximityAuthProximityMonitorImplTest
,
276 ProximityState_CheckTxPower_TxPowerIndicatesProximity_RssiDoesNot
) {
277 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
);
280 ProvideConnectionInfo({-10, 0, 4});
282 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
283 EXPECT_FALSE(monitor_
.IsInRssiRange());
286 TEST_F(ProximityAuthProximityMonitorImplTest
,
287 ProximityState_CheckTxPower_NeitherRssiNorTxPowerIndicatesProximity
) {
288 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
);
291 ProvideConnectionInfo({-10, 4, 4});
293 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
294 EXPECT_FALSE(monitor_
.IsInRssiRange());
297 TEST_F(ProximityAuthProximityMonitorImplTest
,
298 ProximityState_CheckTxPower_BothRssiAndTxPowerIndicateProximity
) {
299 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
);
302 ProvideConnectionInfo({0, 0, 4});
304 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
305 EXPECT_TRUE(monitor_
.IsInRssiRange());
308 TEST_F(ProximityAuthProximityMonitorImplTest
,
309 ProximityState_CheckTxPower_UnknownRssi
) {
310 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
);
313 ProvideConnectionInfo({0, 0, 4});
314 ProvideConnectionInfo({BluetoothDevice::kUnknownPower
, 0, 4});
316 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
317 EXPECT_FALSE(monitor_
.IsInRssiRange());
320 TEST_F(ProximityAuthProximityMonitorImplTest
,
321 ProximityState_CheckTxPower_UnknownTxPower
) {
322 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
);
325 ProvideConnectionInfo({0, 0, 4});
326 ProvideConnectionInfo({0, BluetoothDevice::kUnknownPower
, 4});
328 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
329 EXPECT_FALSE(monitor_
.IsInRssiRange());
332 TEST_F(ProximityAuthProximityMonitorImplTest
,
333 ProximityState_CheckTxPower_UnknownMaxTxPower
) {
334 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_TRANSMIT_POWER
);
337 ProvideConnectionInfo({0, 0, 4});
338 ProvideConnectionInfo({0, 0, BluetoothDevice::kUnknownPower
});
340 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
341 EXPECT_FALSE(monitor_
.IsInRssiRange());
344 TEST_F(ProximityAuthProximityMonitorImplTest
, ProximityState_StartThenStop
) {
345 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
348 ProvideConnectionInfo({0, 0, 4});
351 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
352 EXPECT_FALSE(monitor_
.IsInRssiRange());
355 TEST_F(ProximityAuthProximityMonitorImplTest
,
356 ProximityState_StartThenStopThenStartAgain
) {
357 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
360 ProvideConnectionInfo({-10, 4, 4});
361 ProvideConnectionInfo({-10, 4, 4});
362 ProvideConnectionInfo({-10, 4, 4});
363 ProvideConnectionInfo({-10, 4, 4});
364 ProvideConnectionInfo({-10, 4, 4});
367 // Restarting the monitor should immediately reset the proximity state, rather
368 // than building on the previous rolling average.
370 ProvideConnectionInfo({0, 4, 4});
372 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
373 EXPECT_TRUE(monitor_
.IsInRssiRange());
376 TEST_F(ProximityAuthProximityMonitorImplTest
,
377 ProximityState_RemoteDeviceRemainsInProximity
) {
378 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
381 ProvideConnectionInfo({0, 4, 4});
382 ProvideConnectionInfo({-1, 4, 4});
383 ProvideConnectionInfo({0, 4, 4});
384 ProvideConnectionInfo({-2, 4, 4});
385 ProvideConnectionInfo({-1, 4, 4});
387 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
388 EXPECT_TRUE(monitor_
.IsInRssiRange());
390 // Brief drops in RSSI should be handled by weighted averaging.
391 ProvideConnectionInfo({-10, 4, 4});
393 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
394 EXPECT_TRUE(monitor_
.IsInRssiRange());
397 TEST_F(ProximityAuthProximityMonitorImplTest
,
398 ProximityState_RemoteDeviceLeavesProximity
) {
399 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
402 // Start with a device in proximity.
403 ProvideConnectionInfo({0, 4, 4});
404 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
405 EXPECT_TRUE(monitor_
.IsInRssiRange());
407 // Simulate readings for the remote device leaving proximity.
408 ProvideConnectionInfo({-1, 4, 4});
409 ProvideConnectionInfo({-4, 4, 4});
410 ProvideConnectionInfo({0, 4, 4});
411 ProvideConnectionInfo({-10, 4, 4});
412 ProvideConnectionInfo({-8, 4, 4});
413 ProvideConnectionInfo({-15, 4, 4});
414 ProvideConnectionInfo({-10, 4, 4});
415 ProvideConnectionInfo({-10, 4, 4});
416 ProvideConnectionInfo({-10, 4, 4});
417 ProvideConnectionInfo({-10, 4, 4});
419 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
420 EXPECT_FALSE(monitor_
.IsInRssiRange());
423 TEST_F(ProximityAuthProximityMonitorImplTest
,
424 ProximityState_RemoteDeviceEntersProximity
) {
425 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
428 // Start with a device in proximity.
429 ProvideConnectionInfo({-20, 4, 4});
430 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
431 EXPECT_FALSE(monitor_
.IsInRssiRange());
433 // Simulate readings for the remote device entering proximity.
434 ProvideConnectionInfo({-15, 4, 4});
435 ProvideConnectionInfo({-8, 4, 4});
436 ProvideConnectionInfo({-12, 4, 4});
437 ProvideConnectionInfo({-18, 4, 4});
438 ProvideConnectionInfo({-7, 4, 4});
439 ProvideConnectionInfo({-3, 4, 4});
440 ProvideConnectionInfo({-2, 4, 4});
441 ProvideConnectionInfo({0, 4, 4});
442 ProvideConnectionInfo({0, 4, 4});
444 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
445 EXPECT_TRUE(monitor_
.IsInRssiRange());
448 TEST_F(ProximityAuthProximityMonitorImplTest
,
449 ProximityState_DeviceNotKnownToAdapter
) {
450 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
453 // Start with the device known to the adapter and in proximity.
454 ProvideConnectionInfo({0, 4, 4});
455 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
456 EXPECT_TRUE(monitor_
.IsInRssiRange());
458 // Simulate it being forgotten.
459 ON_CALL(*bluetooth_adapter_
, GetDevice(kBluetoothAddress
))
460 .WillByDefault(Return(nullptr));
461 EXPECT_CALL(observer_
, OnProximityStateChanged());
464 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
465 EXPECT_FALSE(monitor_
.IsInRssiRange());
468 TEST_F(ProximityAuthProximityMonitorImplTest
,
469 ProximityState_DeviceNotConnected
) {
470 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
473 // Start with the device connected and in proximity.
474 ProvideConnectionInfo({0, 4, 4});
475 EXPECT_TRUE(monitor_
.IsUnlockAllowed());
476 EXPECT_TRUE(monitor_
.IsInRssiRange());
478 // Simulate it disconnecting.
479 ON_CALL(remote_bluetooth_device_
, IsConnected()).WillByDefault(Return(false));
480 EXPECT_CALL(observer_
, OnProximityStateChanged());
483 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
484 EXPECT_FALSE(monitor_
.IsInRssiRange());
487 TEST_F(ProximityAuthProximityMonitorImplTest
,
488 ProximityState_ConnectionInfoReceivedAfterStopping
) {
489 monitor_
.SetStrategy(ProximityMonitor::Strategy::CHECK_RSSI
);
493 ProvideConnectionInfo({0, 4, 4});
495 EXPECT_FALSE(monitor_
.IsUnlockAllowed());
496 EXPECT_FALSE(monitor_
.IsInRssiRange());
499 TEST_F(ProximityAuthProximityMonitorImplTest
,
500 RecordProximityMetricsOnAuthSuccess_NormalValues
) {
502 ProvideConnectionInfo({0, 0, 4});
504 clock_
->Advance(base::TimeDelta::FromMilliseconds(101));
505 ProvideConnectionInfo({-20, 3, 4});
507 clock_
->Advance(base::TimeDelta::FromMilliseconds(203));
508 base::HistogramTester histogram_tester
;
509 monitor_
.RecordProximityMetricsOnAuthSuccess();
510 histogram_tester
.ExpectUniqueSample("EasyUnlock.AuthProximity.RollingRssi",
512 histogram_tester
.ExpectUniqueSample(
513 "EasyUnlock.AuthProximity.TransmitPowerDelta", -1, 1);
514 histogram_tester
.ExpectUniqueSample(
515 "EasyUnlock.AuthProximity.TimeSinceLastZeroRssi", 304, 1);
516 histogram_tester
.ExpectUniqueSample(
517 "EasyUnlock.AuthProximity.RemoteDeviceModelHash",
518 1881443083 /* hash of "LGE Nexus 5" */, 1);
521 TEST_F(ProximityAuthProximityMonitorImplTest
,
522 RecordProximityMetricsOnAuthSuccess_ClampedValues
) {
524 ProvideConnectionInfo({-99999, 99999, 12345});
526 base::HistogramTester histogram_tester
;
527 monitor_
.RecordProximityMetricsOnAuthSuccess();
528 histogram_tester
.ExpectUniqueSample("EasyUnlock.AuthProximity.RollingRssi",
530 histogram_tester
.ExpectUniqueSample(
531 "EasyUnlock.AuthProximity.TransmitPowerDelta", 50, 1);
534 TEST_F(ProximityAuthProximityMonitorImplTest
,
535 RecordProximityMetricsOnAuthSuccess_UnknownValues
) {
536 // Note: A device without a recorded name will have its Bluetooth address as
538 RemoteDevice
unnamed_remote_device(kBluetoothAddress
, kRemoteDevicePublicKey
,
540 kPersistentSymmetricKey
);
542 scoped_ptr
<base::TickClock
> clock(new base::SimpleTestTickClock());
543 ProximityMonitorImpl
monitor(unnamed_remote_device
, clock
.Pass(), &observer_
);
545 ProvideConnectionInfo({127, 127, 127});
547 base::HistogramTester histogram_tester
;
548 monitor
.RecordProximityMetricsOnAuthSuccess();
549 histogram_tester
.ExpectUniqueSample("EasyUnlock.AuthProximity.RollingRssi",
551 histogram_tester
.ExpectUniqueSample(
552 "EasyUnlock.AuthProximity.TransmitPowerDelta", 127, 1);
553 histogram_tester
.ExpectUniqueSample(
554 "EasyUnlock.AuthProximity.TimeSinceLastZeroRssi",
555 base::TimeDelta::FromSeconds(10).InMilliseconds(), 1);
556 histogram_tester
.ExpectUniqueSample(
557 "EasyUnlock.AuthProximity.RemoteDeviceModelHash",
558 -1808066424 /* hash of "Unknown" */, 1);
561 } // namespace proximity_auth