proximity_monitor_impl_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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.
  4. #include "ash/components/proximity_auth/proximity_monitor_impl.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "ash/components/multidevice/logging/logging.h"
  8. #include "ash/components/multidevice/remote_device_ref.h"
  9. #include "ash/components/multidevice/remote_device_test_util.h"
  10. #include "ash/components/multidevice/software_feature_state.h"
  11. #include "ash/components/proximity_auth/proximity_monitor_observer.h"
  12. #include "ash/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
  13. #include "ash/services/secure_channel/fake_connection.h"
  14. #include "ash/services/secure_channel/public/cpp/client/fake_client_channel.h"
  15. #include "base/memory/ptr_util.h"
  16. #include "base/memory/ref_counted.h"
  17. #include "base/test/gmock_move_support.h"
  18. #include "base/test/metrics/histogram_tester.h"
  19. #include "base/test/scoped_feature_list.h"
  20. #include "base/test/simple_test_tick_clock.h"
  21. #include "base/test/test_simple_task_runner.h"
  22. #include "base/threading/thread_task_runner_handle.h"
  23. #include "base/time/time.h"
  24. #include "device/bluetooth/bluetooth_adapter_factory.h"
  25. #include "device/bluetooth/test/mock_bluetooth_adapter.h"
  26. #include "testing/gmock/include/gmock/gmock.h"
  27. #include "testing/gtest/include/gtest/gtest.h"
  28. using device::BluetoothDevice;
  29. using testing::_;
  30. using testing::NiceMock;
  31. using testing::Return;
  32. namespace proximity_auth {
  33. namespace {
  34. const char kRemoteDeviceUserEmail[] = "example@gmail.com";
  35. const char kRemoteDeviceName[] = "LGE Nexus 5";
  36. const int kRssiThreshold = -70;
  37. class MockProximityMonitorObserver : public ProximityMonitorObserver {
  38. public:
  39. MockProximityMonitorObserver() {}
  40. MockProximityMonitorObserver(const MockProximityMonitorObserver&) = delete;
  41. MockProximityMonitorObserver& operator=(const MockProximityMonitorObserver&) =
  42. delete;
  43. ~MockProximityMonitorObserver() override {}
  44. MOCK_METHOD0(OnProximityStateChanged, void());
  45. };
  46. // Creates a mock Bluetooth adapter and sets it as the global adapter for
  47. // testing.
  48. scoped_refptr<device::MockBluetoothAdapter>
  49. CreateAndRegisterMockBluetoothAdapter() {
  50. scoped_refptr<device::MockBluetoothAdapter> adapter =
  51. new NiceMock<device::MockBluetoothAdapter>();
  52. device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
  53. return adapter;
  54. }
  55. } // namespace
  56. class ProximityAuthProximityMonitorImplTest : public testing::Test {
  57. public:
  58. ProximityAuthProximityMonitorImplTest()
  59. : bluetooth_adapter_(CreateAndRegisterMockBluetoothAdapter()),
  60. remote_bluetooth_device_(&*bluetooth_adapter_,
  61. 0,
  62. kRemoteDeviceName,
  63. "",
  64. false /* paired */,
  65. true /* connected */),
  66. fake_client_channel_(
  67. std::make_unique<ash::secure_channel::FakeClientChannel>()),
  68. remote_device_(ash::multidevice::RemoteDeviceRefBuilder()
  69. .SetUserEmail(kRemoteDeviceUserEmail)
  70. .SetName(kRemoteDeviceName)
  71. .Build()),
  72. task_runner_(new base::TestSimpleTaskRunner()),
  73. thread_task_runner_handle_(task_runner_) {}
  74. ~ProximityAuthProximityMonitorImplTest() override {}
  75. void InitializeTest(bool multidevice_flags_enabled) {
  76. fake_multidevice_setup_client_ =
  77. std::make_unique<ash::multidevice_setup::FakeMultiDeviceSetupClient>();
  78. monitor_ = std::make_unique<ProximityMonitorImpl>(
  79. remote_device_, fake_client_channel_.get());
  80. ON_CALL(*bluetooth_adapter_, GetDevice(std::string()))
  81. .WillByDefault(Return(&remote_bluetooth_device_));
  82. ON_CALL(remote_bluetooth_device_, GetConnectionInfo(_))
  83. .WillByDefault(MoveArg<0>(&connection_info_callback_));
  84. monitor_->AddObserver(&observer_);
  85. }
  86. void RunPendingTasks() { task_runner_->RunPendingTasks(); }
  87. void ProvideRssi(absl::optional<int32_t> rssi) {
  88. RunPendingTasks();
  89. std::vector<ash::secure_channel::mojom::ConnectionCreationDetail>
  90. creation_details{ash::secure_channel::mojom::ConnectionCreationDetail::
  91. REMOTE_DEVICE_USED_BACKGROUND_BLE_ADVERTISING};
  92. ash::secure_channel::mojom::BluetoothConnectionMetadataPtr
  93. bluetooth_connection_metadata_ptr;
  94. if (rssi) {
  95. bluetooth_connection_metadata_ptr =
  96. ash::secure_channel::mojom::BluetoothConnectionMetadata::New(*rssi);
  97. }
  98. ash::secure_channel::mojom::ConnectionMetadataPtr connection_metadata_ptr =
  99. ash::secure_channel::mojom::ConnectionMetadata::New(
  100. creation_details, std::move(bluetooth_connection_metadata_ptr),
  101. "channel_binding_data");
  102. fake_client_channel_->InvokePendingGetConnectionMetadataCallback(
  103. std::move(connection_metadata_ptr));
  104. }
  105. protected:
  106. // Mock for verifying interactions with the proximity monitor's observer.
  107. NiceMock<MockProximityMonitorObserver> observer_;
  108. // Mocks used for verifying interactions with the Bluetooth subsystem.
  109. scoped_refptr<device::MockBluetoothAdapter> bluetooth_adapter_;
  110. NiceMock<device::MockBluetoothDevice> remote_bluetooth_device_;
  111. std::unique_ptr<ash::secure_channel::FakeClientChannel> fake_client_channel_;
  112. ash::multidevice::RemoteDeviceRef remote_device_;
  113. std::unique_ptr<ash::multidevice_setup::FakeMultiDeviceSetupClient>
  114. fake_multidevice_setup_client_;
  115. // The proximity monitor under test.
  116. std::unique_ptr<ProximityMonitorImpl> monitor_;
  117. private:
  118. scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
  119. base::ThreadTaskRunnerHandle thread_task_runner_handle_;
  120. BluetoothDevice::ConnectionInfoCallback connection_info_callback_;
  121. ash::multidevice::ScopedDisableLoggingForTesting disable_logging_;
  122. base::test::ScopedFeatureList scoped_feature_list_;
  123. };
  124. TEST_F(ProximityAuthProximityMonitorImplTest, IsUnlockAllowed_NeverStarted) {
  125. InitializeTest(true /* multidevice_flags_enabled */);
  126. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  127. }
  128. TEST_F(ProximityAuthProximityMonitorImplTest,
  129. IsUnlockAllowed_Started_NoRssiReceivedYet) {
  130. InitializeTest(true /* multidevice_flags_enabled */);
  131. monitor_->Start();
  132. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  133. }
  134. TEST_F(ProximityAuthProximityMonitorImplTest, IsUnlockAllowed_RssiInRange) {
  135. InitializeTest(true /* multidevice_flags_enabled */);
  136. monitor_->Start();
  137. ProvideRssi(4);
  138. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  139. }
  140. TEST_F(ProximityAuthProximityMonitorImplTest, IsUnlockAllowed_UnknownRssi) {
  141. InitializeTest(true /* multidevice_flags_enabled */);
  142. monitor_->Start();
  143. ProvideRssi(0);
  144. ProvideRssi(absl::nullopt);
  145. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  146. }
  147. TEST_F(ProximityAuthProximityMonitorImplTest,
  148. IsUnlockAllowed_InformsObserverOfChanges) {
  149. InitializeTest(true /* multidevice_flags_enabled */);
  150. // Initially, the device is not in proximity.
  151. monitor_->Start();
  152. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  153. // Simulate receiving an RSSI reading in proximity.
  154. EXPECT_CALL(observer_, OnProximityStateChanged()).Times(1);
  155. ProvideRssi(kRssiThreshold / 2);
  156. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  157. // Simulate a reading indicating non-proximity.
  158. EXPECT_CALL(observer_, OnProximityStateChanged()).Times(1);
  159. ProvideRssi(kRssiThreshold * 2);
  160. ProvideRssi(kRssiThreshold * 2);
  161. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  162. }
  163. TEST_F(ProximityAuthProximityMonitorImplTest, IsUnlockAllowed_StartThenStop) {
  164. InitializeTest(true /* multidevice_flags_enabled */);
  165. monitor_->Start();
  166. ProvideRssi(0);
  167. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  168. monitor_->Stop();
  169. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  170. }
  171. TEST_F(ProximityAuthProximityMonitorImplTest,
  172. IsUnlockAllowed_StartThenStopThenStartAgain) {
  173. InitializeTest(true /* multidevice_flags_enabled */);
  174. monitor_->Start();
  175. ProvideRssi(kRssiThreshold / 2);
  176. ProvideRssi(kRssiThreshold / 2);
  177. ProvideRssi(kRssiThreshold / 2);
  178. ProvideRssi(kRssiThreshold / 2);
  179. ProvideRssi(kRssiThreshold / 2);
  180. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  181. monitor_->Stop();
  182. // Restarting the monitor should immediately reset the proximity state, rather
  183. // than building on the previous rolling average.
  184. monitor_->Start();
  185. ProvideRssi(kRssiThreshold - 1);
  186. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  187. }
  188. TEST_F(ProximityAuthProximityMonitorImplTest,
  189. IsUnlockAllowed_RemoteDeviceRemainsInProximity) {
  190. InitializeTest(true /* multidevice_flags_enabled */);
  191. monitor_->Start();
  192. ProvideRssi(kRssiThreshold / 2 + 1);
  193. ProvideRssi(kRssiThreshold / 2 - 1);
  194. ProvideRssi(kRssiThreshold / 2 + 2);
  195. ProvideRssi(kRssiThreshold / 2 - 3);
  196. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  197. // Brief drops in RSSI should be handled by weighted averaging.
  198. ProvideRssi(kRssiThreshold - 5);
  199. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  200. }
  201. TEST_F(ProximityAuthProximityMonitorImplTest,
  202. IsUnlockAllowed_RemoteDeviceLeavesProximity) {
  203. InitializeTest(true /* multidevice_flags_enabled */);
  204. monitor_->Start();
  205. // Start with a device in proximity.
  206. ProvideRssi(0);
  207. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  208. // Simulate readings for the remote device leaving proximity.
  209. ProvideRssi(-1);
  210. ProvideRssi(-4);
  211. ProvideRssi(0);
  212. ProvideRssi(-10);
  213. ProvideRssi(-15);
  214. ProvideRssi(-20);
  215. ProvideRssi(kRssiThreshold);
  216. ProvideRssi(kRssiThreshold - 10);
  217. ProvideRssi(kRssiThreshold - 20);
  218. ProvideRssi(kRssiThreshold - 20);
  219. ProvideRssi(kRssiThreshold - 20);
  220. ProvideRssi(kRssiThreshold - 20);
  221. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  222. }
  223. TEST_F(ProximityAuthProximityMonitorImplTest,
  224. IsUnlockAllowed_RemoteDeviceEntersProximity) {
  225. InitializeTest(true /* multidevice_flags_enabled */);
  226. monitor_->Start();
  227. // Start with a device out of proximity.
  228. ProvideRssi(kRssiThreshold * 2);
  229. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  230. // Simulate readings for the remote device entering proximity.
  231. ProvideRssi(-15);
  232. ProvideRssi(-8);
  233. ProvideRssi(-12);
  234. ProvideRssi(-18);
  235. ProvideRssi(-7);
  236. ProvideRssi(-3);
  237. ProvideRssi(-2);
  238. ProvideRssi(0);
  239. ProvideRssi(0);
  240. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  241. }
  242. // TODO(jhawkins): Fix this test.
  243. TEST_F(ProximityAuthProximityMonitorImplTest,
  244. DISABLED_IsUnlockAllowed_DeviceNotKnownToAdapter) {
  245. InitializeTest(true /* multidevice_flags_enabled */);
  246. monitor_->Start();
  247. // Start with the device known to the adapter and in proximity.
  248. ProvideRssi(0);
  249. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  250. // Simulate it being forgotten.
  251. ON_CALL(*bluetooth_adapter_, GetDevice(std::string()))
  252. .WillByDefault(Return(nullptr));
  253. EXPECT_CALL(observer_, OnProximityStateChanged());
  254. RunPendingTasks();
  255. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  256. }
  257. TEST_F(ProximityAuthProximityMonitorImplTest,
  258. IsUnlockAllowed_DeviceNotConnected) {
  259. InitializeTest(true /* multidevice_flags_enabled */);
  260. monitor_->Start();
  261. // Start with the device connected and in proximity.
  262. ProvideRssi(0);
  263. EXPECT_TRUE(monitor_->IsUnlockAllowed());
  264. // Simulate it disconnecting.
  265. fake_client_channel_->NotifyDisconnected();
  266. EXPECT_CALL(observer_, OnProximityStateChanged());
  267. RunPendingTasks();
  268. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  269. }
  270. TEST_F(ProximityAuthProximityMonitorImplTest,
  271. IsUnlockAllowed_ConnectionInfoReceivedAfterStopping) {
  272. InitializeTest(true /* multidevice_flags_enabled */);
  273. monitor_->Start();
  274. monitor_->Stop();
  275. ProvideRssi(0);
  276. EXPECT_FALSE(monitor_->IsUnlockAllowed());
  277. }
  278. TEST_F(ProximityAuthProximityMonitorImplTest,
  279. RecordProximityMetricsOnAuthSuccess_NormalValues) {
  280. InitializeTest(true /* multidevice_flags_enabled */);
  281. monitor_->Start();
  282. ProvideRssi(0);
  283. ProvideRssi(-20);
  284. base::HistogramTester histogram_tester;
  285. monitor_->RecordProximityMetricsOnAuthSuccess();
  286. histogram_tester.ExpectUniqueSample("EasyUnlock.AuthProximity.RollingRssi",
  287. -6, 1);
  288. histogram_tester.ExpectUniqueSample(
  289. "EasyUnlock.AuthProximity.RemoteDeviceModelHash",
  290. 1881443083 /* hash of "LGE Nexus 5" */, 1);
  291. }
  292. TEST_F(ProximityAuthProximityMonitorImplTest,
  293. RecordProximityMetricsOnAuthSuccess_ClampedValues) {
  294. InitializeTest(true /* multidevice_flags_enabled */);
  295. monitor_->Start();
  296. ProvideRssi(-99999);
  297. base::HistogramTester histogram_tester;
  298. monitor_->RecordProximityMetricsOnAuthSuccess();
  299. histogram_tester.ExpectUniqueSample("EasyUnlock.AuthProximity.RollingRssi",
  300. -100, 1);
  301. }
  302. TEST_F(ProximityAuthProximityMonitorImplTest,
  303. RecordProximityMetricsOnAuthSuccess_UnknownValues) {
  304. InitializeTest(true /* multidevice_flags_enabled */);
  305. // Note: A device without a recorded name will have "Unknown" as its name.
  306. ash::multidevice::RemoteDeviceRef remote_device =
  307. ash::multidevice::RemoteDeviceRefBuilder()
  308. .SetUserEmail(kRemoteDeviceUserEmail)
  309. .SetName(std::string())
  310. .Build();
  311. ProximityMonitorImpl monitor(remote_device, fake_client_channel_.get());
  312. monitor.AddObserver(&observer_);
  313. monitor.Start();
  314. ProvideRssi(127);
  315. base::HistogramTester histogram_tester;
  316. monitor.RecordProximityMetricsOnAuthSuccess();
  317. histogram_tester.ExpectUniqueSample("EasyUnlock.AuthProximity.RollingRssi",
  318. 127, 1);
  319. histogram_tester.ExpectUniqueSample(
  320. "EasyUnlock.AuthProximity.RemoteDeviceModelHash",
  321. -1808066424 /* hash of "Unknown" */, 1);
  322. }
  323. } // namespace proximity_auth