unlock_manager_impl.cc 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  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/unlock_manager_impl.h"
  5. #include <memory>
  6. #include "ash/components/multidevice/logging/logging.h"
  7. #include "ash/components/multidevice/remote_device_ref.h"
  8. #include "ash/components/proximity_auth/messenger.h"
  9. #include "ash/components/proximity_auth/metrics.h"
  10. #include "ash/components/proximity_auth/proximity_auth_client.h"
  11. #include "ash/components/proximity_auth/proximity_monitor_impl.h"
  12. #include "ash/services/secure_channel/public/cpp/client/client_channel.h"
  13. #include "base/bind.h"
  14. #include "base/logging.h"
  15. #include "base/metrics/histogram_functions.h"
  16. #include "base/threading/thread_task_runner_handle.h"
  17. #include "base/time/default_clock.h"
  18. #include "base/time/time.h"
  19. #include "base/timer/timer.h"
  20. #include "device/bluetooth/bluetooth_adapter_factory.h"
  21. namespace proximity_auth {
  22. namespace {
  23. using SmartLockState = ash::SmartLockState;
  24. // This enum is tied directly to a UMA enum defined in
  25. // //tools/metrics/histograms/enums.xml, and should always reflect it (do not
  26. // change one without changing the other). Entries should be never modified
  27. // or deleted. Only additions possible.
  28. enum class FindAndConnectToHostResult {
  29. kFoundAndConnectedToHost = 0,
  30. kCanceledBluetoothDisabled = 1,
  31. kCanceledUserEnteredPassword = 2,
  32. kSecureChannelConnectionAttemptFailure = 3,
  33. kTimedOut = 4,
  34. kMaxValue = kTimedOut
  35. };
  36. // The maximum amount of time that the unlock manager can stay in the 'waking
  37. // up' state after resuming from sleep.
  38. constexpr base::TimeDelta kWakingUpDuration = base::Seconds(15);
  39. // The maximum amount of time that we wait for the BluetoothAdapter to be
  40. // fully initialized after resuming from sleep.
  41. // TODO(crbug.com/986896): This is necessary because the BluetoothAdapter
  42. // returns incorrect presence and power values directly after resume, and does
  43. // not return correct values until about 1-2 seconds later. Remove this once
  44. // the bug is fixed.
  45. constexpr base::TimeDelta kBluetoothAdapterResumeMaxDuration = base::Seconds(3);
  46. // The limit on the elapsed time for an auth attempt. If an auth attempt exceeds
  47. // this limit, it will time out and be rejected. This is provided as a failsafe,
  48. // in case something goes wrong.
  49. constexpr base::TimeDelta kAuthAttemptTimeout = base::Seconds(5);
  50. constexpr base::TimeDelta kMinExtendedDuration = base::Milliseconds(1);
  51. constexpr base::TimeDelta kMaxExtendedDuration = base::Seconds(15);
  52. const int kNumDurationMetricBuckets = 100;
  53. const char kGetRemoteStatusNone[] = "none";
  54. const char kGetRemoteStatusSuccess[] = "success";
  55. // The subset of SmartLockStates that represent the first non-trival status
  56. // shown to the user. Entries persisted to UMA histograms; do not reorder or
  57. // delete enum values.
  58. enum class FirstSmartLockStatus {
  59. kBluetoothDisabled = 0,
  60. kPhoneNotLockable = 1,
  61. kPhoneNotFound = 2,
  62. kPhoneNotAuthenticated = 3,
  63. kPhoneFoundLockedAndDistant = 4,
  64. kPhoneFoundLockedAndProximate = 5,
  65. kPhoneFoundUnlockedAndDistant = 6,
  66. kPhoneAuthenticated = 7,
  67. kPrimaryUserAbsent = 8,
  68. kMaxValue = kPrimaryUserAbsent
  69. };
  70. absl::optional<FirstSmartLockStatus> GetFirstSmartLockStatus(
  71. SmartLockState state) {
  72. switch (state) {
  73. case SmartLockState::kBluetoothDisabled:
  74. return FirstSmartLockStatus::kBluetoothDisabled;
  75. case SmartLockState::kPhoneNotLockable:
  76. return FirstSmartLockStatus::kPhoneNotLockable;
  77. case SmartLockState::kPhoneNotFound:
  78. return FirstSmartLockStatus::kPhoneNotFound;
  79. case SmartLockState::kPhoneNotAuthenticated:
  80. return FirstSmartLockStatus::kPhoneNotAuthenticated;
  81. case SmartLockState::kPhoneFoundLockedAndDistant:
  82. return FirstSmartLockStatus::kPhoneFoundLockedAndDistant;
  83. case SmartLockState::kPhoneFoundLockedAndProximate:
  84. return FirstSmartLockStatus::kPhoneFoundLockedAndProximate;
  85. case SmartLockState::kPhoneFoundUnlockedAndDistant:
  86. return FirstSmartLockStatus::kPhoneFoundUnlockedAndDistant;
  87. case SmartLockState::kPhoneAuthenticated:
  88. return FirstSmartLockStatus::kPhoneAuthenticated;
  89. case SmartLockState::kPrimaryUserAbsent:
  90. return FirstSmartLockStatus::kPrimaryUserAbsent;
  91. default:
  92. return absl::nullopt;
  93. }
  94. }
  95. // Returns the remote device's security settings state, for metrics,
  96. // corresponding to a remote status update.
  97. metrics::RemoteSecuritySettingsState GetRemoteSecuritySettingsState(
  98. const RemoteStatusUpdate& status_update) {
  99. switch (status_update.secure_screen_lock_state) {
  100. case SECURE_SCREEN_LOCK_STATE_UNKNOWN:
  101. return metrics::RemoteSecuritySettingsState::UNKNOWN;
  102. case SECURE_SCREEN_LOCK_DISABLED:
  103. switch (status_update.trust_agent_state) {
  104. case TRUST_AGENT_UNSUPPORTED:
  105. return metrics::RemoteSecuritySettingsState::
  106. SCREEN_LOCK_DISABLED_TRUST_AGENT_UNSUPPORTED;
  107. case TRUST_AGENT_DISABLED:
  108. return metrics::RemoteSecuritySettingsState::
  109. SCREEN_LOCK_DISABLED_TRUST_AGENT_DISABLED;
  110. case TRUST_AGENT_ENABLED:
  111. return metrics::RemoteSecuritySettingsState::
  112. SCREEN_LOCK_DISABLED_TRUST_AGENT_ENABLED;
  113. }
  114. case SECURE_SCREEN_LOCK_ENABLED:
  115. switch (status_update.trust_agent_state) {
  116. case TRUST_AGENT_UNSUPPORTED:
  117. return metrics::RemoteSecuritySettingsState::
  118. SCREEN_LOCK_ENABLED_TRUST_AGENT_UNSUPPORTED;
  119. case TRUST_AGENT_DISABLED:
  120. return metrics::RemoteSecuritySettingsState::
  121. SCREEN_LOCK_ENABLED_TRUST_AGENT_DISABLED;
  122. case TRUST_AGENT_ENABLED:
  123. return metrics::RemoteSecuritySettingsState::
  124. SCREEN_LOCK_ENABLED_TRUST_AGENT_ENABLED;
  125. }
  126. }
  127. NOTREACHED();
  128. return metrics::RemoteSecuritySettingsState::UNKNOWN;
  129. }
  130. std::string GetHistogramStatusSuffix(bool unlockable) {
  131. return unlockable ? "Unlockable" : "Other";
  132. }
  133. std::string GetHistogramScreenLockTypeName(
  134. ProximityAuthSystem::ScreenlockType screenlock_type) {
  135. return screenlock_type == ProximityAuthSystem::SESSION_LOCK ? "Unlock"
  136. : "SignIn";
  137. }
  138. void RecordFindAndConnectToHostResult(
  139. ProximityAuthSystem::ScreenlockType screenlock_type,
  140. FindAndConnectToHostResult result) {
  141. base::UmaHistogramEnumeration(
  142. "SmartLock.FindAndConnectToHostResult." +
  143. GetHistogramScreenLockTypeName(screenlock_type),
  144. result);
  145. }
  146. void RecordAuthResultFailure(
  147. ProximityAuthSystem::ScreenlockType screenlock_type,
  148. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason failure_reason) {
  149. if (screenlock_type == ProximityAuthSystem::SESSION_LOCK) {
  150. SmartLockMetricsRecorder::RecordAuthResultUnlockFailure(failure_reason);
  151. } else if (screenlock_type == ProximityAuthSystem::SIGN_IN) {
  152. SmartLockMetricsRecorder::RecordAuthResultSignInFailure(failure_reason);
  153. }
  154. }
  155. void RecordExtendedDurationTimerMetric(const std::string& histogram_name,
  156. base::TimeDelta duration) {
  157. // Use a custom |max| to account for Smart Lock's timeout (larger than the
  158. // default 10 seconds).
  159. base::UmaHistogramCustomTimes(
  160. histogram_name, duration, kMinExtendedDuration /* min */,
  161. kMaxExtendedDuration /* max */, kNumDurationMetricBuckets /* buckets */);
  162. }
  163. bool HasCommunicatedWithPhone(SmartLockState state) {
  164. switch (state) {
  165. case SmartLockState::kDisabled:
  166. [[fallthrough]];
  167. case SmartLockState::kInactive:
  168. [[fallthrough]];
  169. case SmartLockState::kBluetoothDisabled:
  170. [[fallthrough]];
  171. case SmartLockState::kPhoneNotFound:
  172. [[fallthrough]];
  173. case SmartLockState::kConnectingToPhone:
  174. [[fallthrough]];
  175. case SmartLockState::kPasswordReentryRequired:
  176. return false;
  177. case SmartLockState::kPhoneNotLockable:
  178. [[fallthrough]];
  179. case SmartLockState::kPhoneNotAuthenticated:
  180. [[fallthrough]];
  181. case SmartLockState::kPhoneFoundLockedAndDistant:
  182. [[fallthrough]];
  183. case SmartLockState::kPhoneFoundLockedAndProximate:
  184. [[fallthrough]];
  185. case SmartLockState::kPhoneFoundUnlockedAndDistant:
  186. [[fallthrough]];
  187. case SmartLockState::kPhoneAuthenticated:
  188. [[fallthrough]];
  189. case SmartLockState::kPrimaryUserAbsent:
  190. return true;
  191. }
  192. }
  193. } // namespace
  194. UnlockManagerImpl::UnlockManagerImpl(
  195. ProximityAuthSystem::ScreenlockType screenlock_type,
  196. ProximityAuthClient* proximity_auth_client)
  197. : screenlock_type_(screenlock_type),
  198. proximity_auth_client_(proximity_auth_client),
  199. bluetooth_suspension_recovery_timer_(
  200. std::make_unique<base::OneShotTimer>()) {
  201. chromeos::PowerManagerClient::Get()->AddObserver(this);
  202. if (device::BluetoothAdapterFactory::IsBluetoothSupported()) {
  203. device::BluetoothAdapterFactory::Get()->GetAdapter(
  204. base::BindOnce(&UnlockManagerImpl::OnBluetoothAdapterInitialized,
  205. weak_ptr_factory_.GetWeakPtr()));
  206. }
  207. }
  208. UnlockManagerImpl::~UnlockManagerImpl() {
  209. if (life_cycle_)
  210. life_cycle_->RemoveObserver(this);
  211. if (GetMessenger())
  212. GetMessenger()->RemoveObserver(this);
  213. if (proximity_monitor_)
  214. proximity_monitor_->RemoveObserver(this);
  215. chromeos::PowerManagerClient::Get()->RemoveObserver(this);
  216. if (bluetooth_adapter_)
  217. bluetooth_adapter_->RemoveObserver(this);
  218. }
  219. bool UnlockManagerImpl::IsUnlockAllowed() {
  220. return (remote_screenlock_state_ &&
  221. *remote_screenlock_state_ == RemoteScreenlockState::UNLOCKED &&
  222. is_bluetooth_connection_to_phone_active_ && proximity_monitor_ &&
  223. proximity_monitor_->IsUnlockAllowed() &&
  224. (screenlock_type_ != ProximityAuthSystem::SIGN_IN || GetMessenger()));
  225. }
  226. void UnlockManagerImpl::SetRemoteDeviceLifeCycle(
  227. RemoteDeviceLifeCycle* life_cycle) {
  228. PA_LOG(VERBOSE) << "Request received to change scan state to: "
  229. << (life_cycle == nullptr ? "inactive" : "active") << ".";
  230. if (life_cycle_)
  231. life_cycle_->RemoveObserver(this);
  232. if (GetMessenger())
  233. GetMessenger()->RemoveObserver(this);
  234. life_cycle_ = life_cycle;
  235. if (life_cycle_) {
  236. life_cycle_->AddObserver(this);
  237. is_bluetooth_connection_to_phone_active_ = false;
  238. show_lock_screen_time_ = base::DefaultClock::GetInstance()->Now();
  239. has_user_been_shown_first_status_ = false;
  240. if (IsBluetoothPresentAndPowered()) {
  241. SetIsPerformingInitialScan(true /* is_performing_initial_scan */);
  242. AttemptToStartRemoteDeviceLifecycle();
  243. } else {
  244. RecordFindAndConnectToHostResult(
  245. screenlock_type_,
  246. FindAndConnectToHostResult::kCanceledBluetoothDisabled);
  247. SetIsPerformingInitialScan(false /* is_performing_initial_scan */);
  248. }
  249. } else {
  250. ResetPerformanceMetricsTimestamps();
  251. if (proximity_monitor_)
  252. proximity_monitor_->RemoveObserver(this);
  253. proximity_monitor_.reset();
  254. UpdateLockScreen();
  255. }
  256. }
  257. void UnlockManagerImpl::OnLifeCycleStateChanged(
  258. RemoteDeviceLifeCycle::State old_state,
  259. RemoteDeviceLifeCycle::State new_state) {
  260. remote_screenlock_state_.reset();
  261. if (new_state == RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED) {
  262. DCHECK(life_cycle_->GetChannel());
  263. DCHECK(GetMessenger());
  264. if (!proximity_monitor_) {
  265. proximity_monitor_ = CreateProximityMonitor(life_cycle_);
  266. proximity_monitor_->AddObserver(this);
  267. proximity_monitor_->Start();
  268. }
  269. GetMessenger()->AddObserver(this);
  270. is_bluetooth_connection_to_phone_active_ = true;
  271. attempt_get_remote_status_start_time_ =
  272. base::DefaultClock::GetInstance()->Now();
  273. PA_LOG(VERBOSE) << "Successfully connected to host; waiting for remote "
  274. "status update.";
  275. if (is_performing_initial_scan_) {
  276. RecordFindAndConnectToHostResult(
  277. screenlock_type_,
  278. FindAndConnectToHostResult::kFoundAndConnectedToHost);
  279. }
  280. } else {
  281. is_bluetooth_connection_to_phone_active_ = false;
  282. if (proximity_monitor_) {
  283. proximity_monitor_->RemoveObserver(this);
  284. proximity_monitor_->Stop();
  285. proximity_monitor_.reset();
  286. }
  287. }
  288. // Note: though the name is AUTHENTICATION_FAILED, this state actually
  289. // encompasses any connection failure in
  290. // `ash::secure_channel::mojom::ConnectionAttemptFailureReason` beside
  291. // Bluetooth becoming disabled. See https://crbug.com/991644 for more.
  292. if (new_state == RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED) {
  293. PA_LOG(ERROR) << "Connection attempt to host failed.";
  294. if (is_performing_initial_scan_) {
  295. RecordFindAndConnectToHostResult(
  296. screenlock_type_,
  297. FindAndConnectToHostResult::kSecureChannelConnectionAttemptFailure);
  298. SetIsPerformingInitialScan(false /* is_performing_initial_scan */);
  299. }
  300. }
  301. if (new_state == RemoteDeviceLifeCycle::State::FINDING_CONNECTION &&
  302. old_state == RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED) {
  303. PA_LOG(ERROR) << "Secure channel dropped for unknown reason; potentially "
  304. "due to Bluetooth being disabled.";
  305. if (is_performing_initial_scan_) {
  306. OnDisconnected();
  307. SetIsPerformingInitialScan(false /* is_performing_initial_scan */);
  308. }
  309. }
  310. UpdateLockScreen();
  311. }
  312. void UnlockManagerImpl::OnUnlockEventSent(bool success) {
  313. if (!is_attempting_auth_) {
  314. PA_LOG(ERROR) << "Sent easy_unlock event, but no auth attempted.";
  315. FinalizeAuthAttempt(
  316. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason::
  317. kUnlockEventSentButNotAttemptingAuth);
  318. } else if (success) {
  319. FinalizeAuthAttempt(absl::nullopt /* failure_reason */);
  320. } else {
  321. FinalizeAuthAttempt(
  322. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason::
  323. kFailedtoNotifyHostDeviceThatSmartLockWasUsed);
  324. }
  325. }
  326. void UnlockManagerImpl::OnRemoteStatusUpdate(
  327. const RemoteStatusUpdate& status_update) {
  328. PA_LOG(VERBOSE) << "Status Update: ("
  329. << "user_present=" << status_update.user_presence << ", "
  330. << "secure_screen_lock="
  331. << status_update.secure_screen_lock_state << ", "
  332. << "trust_agent=" << status_update.trust_agent_state << ")";
  333. metrics::RecordRemoteSecuritySettingsState(
  334. GetRemoteSecuritySettingsState(status_update));
  335. remote_screenlock_state_ = std::make_unique<RemoteScreenlockState>(
  336. GetScreenlockStateFromRemoteUpdate(status_update));
  337. // Only record these metrics within the initial period of opening the laptop
  338. // displaying the lock screen.
  339. if (is_performing_initial_scan_) {
  340. RecordFirstRemoteStatusReceived(
  341. *remote_screenlock_state_ ==
  342. RemoteScreenlockState::UNLOCKED /* unlockable */);
  343. }
  344. // This also calls |UpdateLockScreen()|
  345. SetIsPerformingInitialScan(false /* is_performing_initial_scan */);
  346. }
  347. void UnlockManagerImpl::OnDecryptResponse(const std::string& decrypted_bytes) {
  348. if (!is_attempting_auth_) {
  349. PA_LOG(ERROR) << "Decrypt response received but not attempting auth.";
  350. return;
  351. }
  352. if (decrypted_bytes.empty()) {
  353. PA_LOG(WARNING) << "Failed to decrypt sign-in challenge.";
  354. FinalizeAuthAttempt(
  355. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason::
  356. kFailedToDecryptSignInChallenge);
  357. } else {
  358. sign_in_secret_ = std::make_unique<std::string>(decrypted_bytes);
  359. if (GetMessenger())
  360. GetMessenger()->DispatchUnlockEvent();
  361. }
  362. }
  363. void UnlockManagerImpl::OnUnlockResponse(bool success) {
  364. if (!is_attempting_auth_) {
  365. FinalizeAuthAttempt(
  366. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason::
  367. kUnlockRequestSentButNotAttemptingAuth);
  368. PA_LOG(ERROR) << "Unlock request sent but not attempting auth.";
  369. return;
  370. }
  371. PA_LOG(INFO) << "Received unlock response from device: "
  372. << (success ? "yes" : "no") << ".";
  373. if (success && GetMessenger()) {
  374. GetMessenger()->DispatchUnlockEvent();
  375. } else {
  376. FinalizeAuthAttempt(
  377. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason::
  378. kFailedToSendUnlockRequest);
  379. }
  380. }
  381. void UnlockManagerImpl::OnDisconnected() {
  382. if (is_attempting_auth_) {
  383. RecordAuthResultFailure(
  384. screenlock_type_,
  385. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason::
  386. kAuthenticatedChannelDropped);
  387. } else if (is_performing_initial_scan_) {
  388. RecordGetRemoteStatusResultFailure(
  389. screenlock_type_,
  390. GetRemoteStatusResultFailureReason::kAuthenticatedChannelDropped);
  391. }
  392. if (GetMessenger())
  393. GetMessenger()->RemoveObserver(this);
  394. }
  395. void UnlockManagerImpl::OnProximityStateChanged() {
  396. PA_LOG(VERBOSE) << "Proximity state changed.";
  397. UpdateLockScreen();
  398. }
  399. void UnlockManagerImpl::OnBluetoothAdapterInitialized(
  400. scoped_refptr<device::BluetoothAdapter> adapter) {
  401. bluetooth_adapter_ = adapter;
  402. bluetooth_adapter_->AddObserver(this);
  403. }
  404. void UnlockManagerImpl::AdapterPresentChanged(device::BluetoothAdapter* adapter,
  405. bool present) {
  406. if (!IsBluetoothAdapterRecoveringFromSuspend())
  407. OnBluetoothAdapterPresentAndPoweredChanged();
  408. }
  409. void UnlockManagerImpl::AdapterPoweredChanged(device::BluetoothAdapter* adapter,
  410. bool powered) {
  411. if (!IsBluetoothAdapterRecoveringFromSuspend())
  412. OnBluetoothAdapterPresentAndPoweredChanged();
  413. }
  414. void UnlockManagerImpl::SuspendImminent(
  415. power_manager::SuspendImminent::Reason reason) {
  416. // TODO(crbug.com/986896): For a short time window after resuming from
  417. // suspension, BluetoothAdapter returns incorrect presence and power values.
  418. // Cache the correct values now, in case we need to check those values during
  419. // that time window when the device resumes.
  420. was_bluetooth_present_and_powered_before_last_suspend_ =
  421. IsBluetoothPresentAndPowered();
  422. bluetooth_suspension_recovery_timer_->Stop();
  423. }
  424. void UnlockManagerImpl::SuspendDone(base::TimeDelta sleep_duration) {
  425. bluetooth_suspension_recovery_timer_->Start(
  426. FROM_HERE, kBluetoothAdapterResumeMaxDuration,
  427. base::BindOnce(
  428. &UnlockManagerImpl::OnBluetoothAdapterPresentAndPoweredChanged,
  429. weak_ptr_factory_.GetWeakPtr()));
  430. // The next scan after resuming is expected to be triggered by calling
  431. // SetRemoteDeviceLifeCycle().
  432. }
  433. bool UnlockManagerImpl::IsBluetoothPresentAndPowered() const {
  434. // TODO(crbug.com/986896): If the BluetoothAdapter is still "resuming after
  435. // suspension" at this time, it's prone to this bug, meaning we cannot trust
  436. // its returned presence and power values. If this is the case, depend on
  437. // the cached |was_bluetooth_present_and_powered_before_last_suspend_| to
  438. // signal if Bluetooth is enabled; otherwise, directly check request values
  439. // from BluetoothAdapter. Remove this check once the bug is fixed.
  440. if (IsBluetoothAdapterRecoveringFromSuspend())
  441. return was_bluetooth_present_and_powered_before_last_suspend_;
  442. return bluetooth_adapter_ && bluetooth_adapter_->IsPresent() &&
  443. bluetooth_adapter_->IsPowered();
  444. }
  445. void UnlockManagerImpl::OnBluetoothAdapterPresentAndPoweredChanged() {
  446. DCHECK(!IsBluetoothAdapterRecoveringFromSuspend());
  447. if (IsBluetoothPresentAndPowered()) {
  448. if (!is_performing_initial_scan_ &&
  449. !is_bluetooth_connection_to_phone_active_) {
  450. SetIsPerformingInitialScan(true /* is_performing_initial_scan */);
  451. }
  452. return;
  453. }
  454. if (is_performing_initial_scan_) {
  455. if (is_bluetooth_connection_to_phone_active_ &&
  456. !has_received_first_remote_status_) {
  457. RecordGetRemoteStatusResultFailure(
  458. screenlock_type_,
  459. GetRemoteStatusResultFailureReason::kCanceledBluetoothDisabled);
  460. } else {
  461. RecordFindAndConnectToHostResult(
  462. screenlock_type_,
  463. FindAndConnectToHostResult::kCanceledBluetoothDisabled);
  464. }
  465. SetIsPerformingInitialScan(false /* is_performing_initial_scan */);
  466. return;
  467. }
  468. // If Bluetooth is off but no initial scan is active, still ensure that the
  469. // lock screen UI reflects that Bluetooth is off.
  470. UpdateLockScreen();
  471. }
  472. bool UnlockManagerImpl::IsBluetoothAdapterRecoveringFromSuspend() const {
  473. return bluetooth_suspension_recovery_timer_->IsRunning();
  474. }
  475. void UnlockManagerImpl::AttemptToStartRemoteDeviceLifecycle() {
  476. if (IsBluetoothPresentAndPowered() && life_cycle_ &&
  477. life_cycle_->GetState() == RemoteDeviceLifeCycle::State::STOPPED) {
  478. // If Bluetooth is disabled after this, |life_cycle_| will be notified by
  479. // SecureChannel that the connection attempt failed. From that point on,
  480. // |life_cycle_| will wait to be started again by UnlockManager.
  481. life_cycle_->Start();
  482. }
  483. }
  484. void UnlockManagerImpl::OnAuthAttempted(mojom::AuthType auth_type) {
  485. if (is_attempting_auth_) {
  486. PA_LOG(VERBOSE) << "Already attempting auth.";
  487. return;
  488. }
  489. if (auth_type != mojom::AuthType::USER_CLICK)
  490. return;
  491. is_attempting_auth_ = true;
  492. if (!life_cycle_ || !GetMessenger()) {
  493. PA_LOG(ERROR) << "No life_cycle active when auth was attempted";
  494. FinalizeAuthAttempt(
  495. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason::
  496. kNoPendingOrActiveHost);
  497. UpdateLockScreen();
  498. return;
  499. }
  500. if (!IsUnlockAllowed()) {
  501. FinalizeAuthAttempt(
  502. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason::
  503. kUnlockNotAllowed);
  504. UpdateLockScreen();
  505. return;
  506. }
  507. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  508. FROM_HERE,
  509. base::BindOnce(
  510. &UnlockManagerImpl::FinalizeAuthAttempt,
  511. reject_auth_attempt_weak_ptr_factory_.GetWeakPtr(),
  512. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason::
  513. kAuthAttemptTimedOut),
  514. kAuthAttemptTimeout);
  515. if (screenlock_type_ == ProximityAuthSystem::SIGN_IN) {
  516. SendSignInChallenge();
  517. } else {
  518. GetMessenger()->RequestUnlock();
  519. }
  520. }
  521. void UnlockManagerImpl::CancelConnectionAttempt() {
  522. PA_LOG(VERBOSE) << "User entered password.";
  523. bluetooth_suspension_recovery_timer_->Stop();
  524. // Note: There is no need to record metrics here if Bluetooth isn't present
  525. // and powered; that has already been handled at this point in
  526. // OnBluetoothAdapterPresentAndPoweredChanged().
  527. if (!IsBluetoothPresentAndPowered())
  528. return;
  529. if (is_performing_initial_scan_) {
  530. if (is_bluetooth_connection_to_phone_active_ &&
  531. !has_received_first_remote_status_) {
  532. RecordGetRemoteStatusResultFailure(
  533. screenlock_type_,
  534. GetRemoteStatusResultFailureReason::kCanceledUserEnteredPassword);
  535. } else {
  536. RecordFindAndConnectToHostResult(
  537. screenlock_type_,
  538. FindAndConnectToHostResult::kCanceledUserEnteredPassword);
  539. }
  540. SetIsPerformingInitialScan(false /* is_performing_initial_scan */);
  541. }
  542. }
  543. std::unique_ptr<ProximityMonitor> UnlockManagerImpl::CreateProximityMonitor(
  544. RemoteDeviceLifeCycle* life_cycle) {
  545. return std::make_unique<ProximityMonitorImpl>(life_cycle->GetRemoteDevice(),
  546. life_cycle->GetChannel());
  547. }
  548. void UnlockManagerImpl::SendSignInChallenge() {
  549. if (!life_cycle_ || !GetMessenger()) {
  550. PA_LOG(ERROR) << "Not ready to send sign-in challenge";
  551. return;
  552. }
  553. if (!GetMessenger()->GetChannel()) {
  554. PA_LOG(ERROR) << "Channel is not ready to send sign-in challenge.";
  555. return;
  556. }
  557. GetMessenger()->GetChannel()->GetConnectionMetadata(
  558. base::BindOnce(&UnlockManagerImpl::OnGetConnectionMetadata,
  559. weak_ptr_factory_.GetWeakPtr()));
  560. }
  561. void UnlockManagerImpl::OnGetConnectionMetadata(
  562. ash::secure_channel::mojom::ConnectionMetadataPtr connection_metadata_ptr) {
  563. ash::multidevice::RemoteDeviceRef remote_device =
  564. life_cycle_->GetRemoteDevice();
  565. proximity_auth_client_->GetChallengeForUserAndDevice(
  566. remote_device.user_email(), remote_device.public_key(),
  567. connection_metadata_ptr->channel_binding_data,
  568. base::BindOnce(&UnlockManagerImpl::OnGotSignInChallenge,
  569. weak_ptr_factory_.GetWeakPtr()));
  570. }
  571. void UnlockManagerImpl::OnGotSignInChallenge(const std::string& challenge) {
  572. PA_LOG(VERBOSE) << "Got sign-in challenge, sending for decryption...";
  573. if (GetMessenger())
  574. GetMessenger()->RequestDecryption(challenge);
  575. }
  576. SmartLockState UnlockManagerImpl::GetSmartLockState() {
  577. if (!life_cycle_)
  578. return SmartLockState::kInactive;
  579. if (!IsBluetoothPresentAndPowered())
  580. return SmartLockState::kBluetoothDisabled;
  581. if (IsUnlockAllowed())
  582. return SmartLockState::kPhoneAuthenticated;
  583. RemoteDeviceLifeCycle::State life_cycle_state = life_cycle_->GetState();
  584. if (life_cycle_state == RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED)
  585. return SmartLockState::kPhoneNotAuthenticated;
  586. if (is_performing_initial_scan_)
  587. return SmartLockState::kConnectingToPhone;
  588. Messenger* messenger = GetMessenger();
  589. // Show a timeout state if we can not connect to the remote device in a
  590. // reasonable amount of time.
  591. if (!messenger)
  592. return SmartLockState::kPhoneNotFound;
  593. // If the RSSI is too low, then the remote device is nowhere near the local
  594. // device. This message should take priority over messages about Smart Lock
  595. // states.
  596. if (proximity_monitor_ && !proximity_monitor_->IsUnlockAllowed()) {
  597. if (remote_screenlock_state_ &&
  598. *remote_screenlock_state_ == RemoteScreenlockState::UNLOCKED) {
  599. return SmartLockState::kPhoneFoundUnlockedAndDistant;
  600. } else {
  601. return SmartLockState::kPhoneFoundLockedAndDistant;
  602. }
  603. }
  604. if (remote_screenlock_state_) {
  605. switch (*remote_screenlock_state_) {
  606. case RemoteScreenlockState::DISABLED:
  607. return SmartLockState::kPhoneNotLockable;
  608. case RemoteScreenlockState::LOCKED:
  609. return SmartLockState::kPhoneFoundLockedAndProximate;
  610. case RemoteScreenlockState::PRIMARY_USER_ABSENT:
  611. return SmartLockState::kPrimaryUserAbsent;
  612. case RemoteScreenlockState::UNKNOWN:
  613. case RemoteScreenlockState::UNLOCKED:
  614. // Handled by the code below.
  615. break;
  616. }
  617. }
  618. if (messenger) {
  619. PA_LOG(WARNING) << "Connection to host established, but remote screenlock "
  620. << "state was either malformed or not received.";
  621. }
  622. // TODO(crbug.com/1233587): Add more granular error states
  623. return SmartLockState::kPhoneNotFound;
  624. }
  625. void UnlockManagerImpl::UpdateLockScreen() {
  626. AttemptToStartRemoteDeviceLifecycle();
  627. SmartLockState new_state = GetSmartLockState();
  628. if (smartlock_state_ == new_state)
  629. return;
  630. PA_LOG(INFO) << "Updating Smart Lock state from " << smartlock_state_
  631. << " to " << new_state;
  632. RecordFirstStatusShownToUser(new_state);
  633. proximity_auth_client_->UpdateSmartLockState(new_state);
  634. smartlock_state_ = new_state;
  635. }
  636. void UnlockManagerImpl::SetIsPerformingInitialScan(
  637. bool is_performing_initial_scan) {
  638. PA_LOG(VERBOSE) << "Initial scan state is ["
  639. << (is_performing_initial_scan_ ? "active" : "inactive")
  640. << "]. Requesting state ["
  641. << (is_performing_initial_scan ? "active" : "inactive")
  642. << "].";
  643. is_performing_initial_scan_ = is_performing_initial_scan;
  644. // Clear the waking up state after a timeout.
  645. initial_scan_timeout_weak_ptr_factory_.InvalidateWeakPtrs();
  646. if (is_performing_initial_scan_) {
  647. initial_scan_start_time_ = base::DefaultClock::GetInstance()->Now();
  648. has_received_first_remote_status_ = false;
  649. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  650. FROM_HERE,
  651. base::BindOnce(&UnlockManagerImpl::OnInitialScanTimeout,
  652. initial_scan_timeout_weak_ptr_factory_.GetWeakPtr()),
  653. kWakingUpDuration);
  654. }
  655. UpdateLockScreen();
  656. }
  657. void UnlockManagerImpl::OnInitialScanTimeout() {
  658. // Note: There is no need to record metrics here if Bluetooth isn't present
  659. // and powered; that has already been handled at this point in
  660. // OnBluetoothAdapterPresentAndPoweredChanged().
  661. if (!IsBluetoothPresentAndPowered())
  662. return;
  663. if (is_bluetooth_connection_to_phone_active_) {
  664. PA_LOG(ERROR) << "Successfully connected to host, but it did not provide "
  665. "remote status update.";
  666. RecordGetRemoteStatusResultFailure(
  667. screenlock_type_, GetRemoteStatusResultFailureReason::
  668. kTimedOutDidNotReceiveRemoteStatusUpdate);
  669. } else {
  670. PA_LOG(INFO) << "Initial scan for host returned no result.";
  671. RecordFindAndConnectToHostResult(screenlock_type_,
  672. FindAndConnectToHostResult::kTimedOut);
  673. }
  674. SetIsPerformingInitialScan(false /* is_performing_initial_scan */);
  675. }
  676. void UnlockManagerImpl::FinalizeAuthAttempt(
  677. const absl::optional<
  678. SmartLockMetricsRecorder::SmartLockAuthResultFailureReason>& error) {
  679. if (error) {
  680. RecordAuthResultFailure(screenlock_type_, *error);
  681. }
  682. if (!is_attempting_auth_)
  683. return;
  684. // Cancel the pending task to time out the auth attempt.
  685. reject_auth_attempt_weak_ptr_factory_.InvalidateWeakPtrs();
  686. bool should_accept = !error;
  687. if (should_accept && proximity_monitor_)
  688. proximity_monitor_->RecordProximityMetricsOnAuthSuccess();
  689. is_attempting_auth_ = false;
  690. if (screenlock_type_ == ProximityAuthSystem::SIGN_IN) {
  691. PA_LOG(VERBOSE) << "Finalizing sign-in...";
  692. proximity_auth_client_->FinalizeSignin(
  693. should_accept && sign_in_secret_ ? *sign_in_secret_ : std::string());
  694. } else {
  695. PA_LOG(VERBOSE) << "Finalizing unlock...";
  696. proximity_auth_client_->FinalizeUnlock(should_accept);
  697. }
  698. }
  699. UnlockManagerImpl::RemoteScreenlockState
  700. UnlockManagerImpl::GetScreenlockStateFromRemoteUpdate(
  701. RemoteStatusUpdate update) {
  702. switch (update.secure_screen_lock_state) {
  703. case SECURE_SCREEN_LOCK_DISABLED:
  704. return RemoteScreenlockState::DISABLED;
  705. case SECURE_SCREEN_LOCK_ENABLED:
  706. if (update.user_presence == USER_PRESENCE_SECONDARY ||
  707. update.user_presence == USER_PRESENCE_BACKGROUND) {
  708. return RemoteScreenlockState::PRIMARY_USER_ABSENT;
  709. }
  710. if (update.user_presence == USER_PRESENT)
  711. return RemoteScreenlockState::UNLOCKED;
  712. return RemoteScreenlockState::LOCKED;
  713. case SECURE_SCREEN_LOCK_STATE_UNKNOWN:
  714. return RemoteScreenlockState::UNKNOWN;
  715. }
  716. NOTREACHED();
  717. return RemoteScreenlockState::UNKNOWN;
  718. }
  719. Messenger* UnlockManagerImpl::GetMessenger() {
  720. // TODO(tengs): We should use a weak pointer to hold the Messenger instance
  721. // instead.
  722. if (!life_cycle_)
  723. return nullptr;
  724. return life_cycle_->GetMessenger();
  725. }
  726. void UnlockManagerImpl::RecordFirstRemoteStatusReceived(bool unlockable) {
  727. if (has_received_first_remote_status_)
  728. return;
  729. has_received_first_remote_status_ = true;
  730. RecordGetRemoteStatusResultSuccess(screenlock_type_);
  731. if (initial_scan_start_time_.is_null() ||
  732. attempt_get_remote_status_start_time_.is_null()) {
  733. PA_LOG(WARNING) << "Attempted to RecordFirstRemoteStatusReceived() "
  734. "without initial timestamps recorded.";
  735. NOTREACHED();
  736. return;
  737. }
  738. const std::string histogram_status_suffix =
  739. GetHistogramStatusSuffix(unlockable);
  740. base::Time now = base::DefaultClock::GetInstance()->Now();
  741. base::TimeDelta start_scan_to_receive_first_remote_status_duration =
  742. now - initial_scan_start_time_;
  743. base::TimeDelta authentication_to_receive_first_remote_status_duration =
  744. now - attempt_get_remote_status_start_time_;
  745. if (screenlock_type_ == ProximityAuthSystem::SESSION_LOCK) {
  746. RecordExtendedDurationTimerMetric(
  747. "SmartLock.Performance.StartScanToReceiveFirstRemoteStatusDuration."
  748. "Unlock",
  749. start_scan_to_receive_first_remote_status_duration);
  750. RecordExtendedDurationTimerMetric(
  751. "SmartLock.Performance.StartScanToReceiveFirstRemoteStatusDuration."
  752. "Unlock." +
  753. histogram_status_suffix,
  754. start_scan_to_receive_first_remote_status_duration);
  755. // This should be much less than 10 seconds, so use UmaHistogramTimes.
  756. base::UmaHistogramTimes(
  757. "SmartLock.Performance."
  758. "AuthenticationToReceiveFirstRemoteStatusDuration.Unlock",
  759. authentication_to_receive_first_remote_status_duration);
  760. base::UmaHistogramTimes(
  761. "SmartLock.Performance."
  762. "AuthenticationToReceiveFirstRemoteStatusDuration.Unlock." +
  763. histogram_status_suffix,
  764. authentication_to_receive_first_remote_status_duration);
  765. }
  766. }
  767. void UnlockManagerImpl::RecordFirstStatusShownToUser(SmartLockState new_state) {
  768. absl::optional<FirstSmartLockStatus> first_status =
  769. GetFirstSmartLockStatus(new_state);
  770. if (!first_status.has_value()) {
  771. return;
  772. }
  773. if (has_user_been_shown_first_status_) {
  774. return;
  775. }
  776. has_user_been_shown_first_status_ = true;
  777. if (show_lock_screen_time_.is_null()) {
  778. PA_LOG(WARNING) << "Attempted to RecordFirstStatusShownToUser() "
  779. "without initial timestamp recorded.";
  780. NOTREACHED();
  781. return;
  782. }
  783. base::UmaHistogramEnumeration("SmartLock.FirstStatusToUser",
  784. first_status.value());
  785. base::Time now = base::DefaultClock::GetInstance()->Now();
  786. base::TimeDelta show_lock_screen_to_show_first_status_to_user_duration =
  787. now - show_lock_screen_time_;
  788. if (screenlock_type_ == ProximityAuthSystem::SESSION_LOCK) {
  789. RecordExtendedDurationTimerMetric(
  790. "SmartLock.Performance.ShowLockScreenToShowFirstStatusToUserDuration."
  791. "Unlock",
  792. show_lock_screen_to_show_first_status_to_user_duration);
  793. if (new_state == SmartLockState::kPhoneAuthenticated) {
  794. RecordExtendedDurationTimerMetric(
  795. "SmartLock.Performance.ShowLockScreenToShowFirstStatusToUserDuration."
  796. "Unlock.Unlockable",
  797. show_lock_screen_to_show_first_status_to_user_duration);
  798. } else if (HasCommunicatedWithPhone(new_state)) {
  799. // Only log to Unlock.Other if we aren't in an unlockable state since
  800. // that's covered by the other metric, and only if we are in a state that
  801. // indicates we were able to communicate with the phone over Bluetooth
  802. // since in all other cases the time to show the first status is highly
  803. // deterministic.
  804. RecordExtendedDurationTimerMetric(
  805. "SmartLock.Performance.ShowLockScreenToShowFirstStatusToUserDuration."
  806. "Unlock.Other",
  807. show_lock_screen_to_show_first_status_to_user_duration);
  808. }
  809. }
  810. }
  811. void UnlockManagerImpl::ResetPerformanceMetricsTimestamps() {
  812. show_lock_screen_time_ = base::Time();
  813. initial_scan_start_time_ = base::Time();
  814. attempt_get_remote_status_start_time_ = base::Time();
  815. }
  816. void UnlockManagerImpl::SetBluetoothSuspensionRecoveryTimerForTesting(
  817. std::unique_ptr<base::OneShotTimer> timer) {
  818. bluetooth_suspension_recovery_timer_ = std::move(timer);
  819. }
  820. void UnlockManagerImpl::RecordGetRemoteStatusResultSuccess(
  821. ProximityAuthSystem::ScreenlockType screenlock_type,
  822. bool success) {
  823. base::UmaHistogramBoolean("SmartLock.GetRemoteStatus." +
  824. GetHistogramScreenLockTypeName(screenlock_type),
  825. success);
  826. if (screenlock_type == ProximityAuthSystem::SESSION_LOCK) {
  827. get_remote_status_unlock_success_ = success;
  828. }
  829. }
  830. void UnlockManagerImpl::RecordGetRemoteStatusResultFailure(
  831. ProximityAuthSystem::ScreenlockType screenlock_type,
  832. GetRemoteStatusResultFailureReason failure_reason) {
  833. RecordGetRemoteStatusResultSuccess(screenlock_type, false /* success */);
  834. base::UmaHistogramEnumeration(
  835. "SmartLock.GetRemoteStatus." +
  836. GetHistogramScreenLockTypeName(screenlock_type) + ".Failure",
  837. failure_reason);
  838. if (screenlock_type == ProximityAuthSystem::SESSION_LOCK) {
  839. get_remote_status_unlock_failure_reason_ = failure_reason;
  840. }
  841. }
  842. std::string UnlockManagerImpl::GetRemoteStatusResultFailureReasonToString(
  843. GetRemoteStatusResultFailureReason reason) {
  844. switch (reason) {
  845. case GetRemoteStatusResultFailureReason::kCanceledBluetoothDisabled:
  846. return "CanceledBluetoothDisabled";
  847. case GetRemoteStatusResultFailureReason::
  848. kDeprecatedTimedOutCouldNotEstablishAuthenticatedChannel:
  849. return "DeprecatedTimedOutCouldNotEstablishAuthenticatedChannel";
  850. case GetRemoteStatusResultFailureReason::
  851. kTimedOutDidNotReceiveRemoteStatusUpdate:
  852. return "TimedOutDidNotReceiveRemoteStatusUpdate";
  853. case GetRemoteStatusResultFailureReason::
  854. kDeprecatedUserEnteredPasswordWhileBluetoothDisabled:
  855. return "DeprecatedUserEnteredPasswordWhileBluetoothDisabled";
  856. case GetRemoteStatusResultFailureReason::kCanceledUserEnteredPassword:
  857. return "CanceledUserEnteredPassword";
  858. case GetRemoteStatusResultFailureReason::kAuthenticatedChannelDropped:
  859. return "AuthenticatedChannelDropped";
  860. }
  861. }
  862. std::string UnlockManagerImpl::GetLastRemoteStatusUnlockForLogging() {
  863. if (!get_remote_status_unlock_success_.has_value()) {
  864. return kGetRemoteStatusNone;
  865. }
  866. if (*get_remote_status_unlock_success_) {
  867. return kGetRemoteStatusSuccess;
  868. }
  869. if (!get_remote_status_unlock_failure_reason_.has_value()) {
  870. return kGetRemoteStatusNone;
  871. }
  872. return GetRemoteStatusResultFailureReasonToString(
  873. *get_remote_status_unlock_failure_reason_);
  874. }
  875. } // namespace proximity_auth