1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.car.trust; 18 19 import static android.car.Car.PERMISSION_CAR_ENROLL_TRUST; 20 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.RequiresPermission; 25 import android.annotation.SystemApi; 26 import android.bluetooth.BluetoothDevice; 27 import android.car.Car; 28 import android.car.CarManagerBase; 29 import android.os.Bundle; 30 import android.os.Handler; 31 import android.os.IBinder; 32 import android.os.Looper; 33 import android.os.Message; 34 import android.os.RemoteException; 35 import android.util.Log; 36 37 import com.android.internal.annotations.GuardedBy; 38 39 import java.lang.annotation.Retention; 40 import java.lang.annotation.RetentionPolicy; 41 import java.lang.ref.WeakReference; 42 import java.util.Collections; 43 import java.util.List; 44 45 46 /** 47 * APIs to help enroll a remote device as a trusted device that can be used to authenticate a user 48 * in the head unit. 49 * <p> 50 * The call sequence to add a new trusted device from the client should be as follows: 51 * <ol> 52 * <li> setEnrollmentCallback() 53 * <li> setBleCallback(bleCallback) 54 * <li> startEnrollmentAdvertising() 55 * <li> wait for onEnrollmentAdvertisingStarted() or 56 * <li> wait for onBleEnrollmentDeviceConnected() and check if the device connected is the right 57 * one. 58 * <li> initiateEnrollmentHandshake() 59 * <li> wait for onAuthStringAvailable() to get the pairing code to display to the user 60 * <li> enrollmentHandshakeAccepted() after user confirms the pairing code 61 * <li> wait for onEscrowTokenAdded() 62 * <li> Authenticate user's credentials by showing the lock screen 63 * <li> activateToken() 64 * <li> wait for onEscrowTokenActiveStateChanged() to add the device as a trusted device and show 65 * in the list 66 * </ol> 67 * 68 * @hide 69 * 70 * @deprecated Enrollment of a trusted device is no longer a supported feature and these APIs will 71 * be removed in the next Android release. 72 */ 73 @Deprecated 74 @SystemApi 75 public final class CarTrustAgentEnrollmentManager extends CarManagerBase { 76 private static final String TAG = "CarTrustEnrollMgr"; 77 private static final String KEY_HANDLE = "handle"; 78 private static final String KEY_ACTIVE = "active"; 79 private static final int MSG_ENROLL_ADVERTISING_STARTED = 0; 80 private static final int MSG_ENROLL_ADVERTISING_FAILED = 1; 81 private static final int MSG_ENROLL_DEVICE_CONNECTED = 2; 82 private static final int MSG_ENROLL_DEVICE_DISCONNECTED = 3; 83 private static final int MSG_ENROLL_HANDSHAKE_FAILURE = 4; 84 private static final int MSG_ENROLL_AUTH_STRING_AVAILABLE = 5; 85 private static final int MSG_ENROLL_TOKEN_ADDED = 6; 86 private static final int MSG_ENROLL_TOKEN_STATE_CHANGED = 7; 87 private static final int MSG_ENROLL_TOKEN_REMOVED = 8; 88 89 private final ICarTrustAgentEnrollment mEnrollmentService; 90 private Object mListenerLock = new Object(); 91 @GuardedBy("mListenerLock") 92 private CarTrustAgentEnrollmentCallback mEnrollmentCallback; 93 @GuardedBy("mListenerLock") 94 private CarTrustAgentBleCallback mBleCallback; 95 @GuardedBy("mListenerLock") 96 private final ListenerToEnrollmentService mListenerToEnrollmentService = 97 new ListenerToEnrollmentService(this); 98 private final ListenerToBleService mListenerToBleService = new ListenerToBleService(this); 99 private final EventCallbackHandler mEventCallbackHandler; 100 101 /** 102 * Enrollment Handshake failed. 103 */ 104 public static final int ENROLLMENT_HANDSHAKE_FAILURE = 1; 105 /** 106 * Enrollment of a new device is not allowed. This happens when either the whole feature is 107 * disabled or just the enrollment is disabled. Useful when feature needs to be disabled 108 * in a lost/stolen phone scenario. 109 */ 110 public static final int ENROLLMENT_NOT_ALLOWED = 2; 111 112 /** @hide */ 113 @Retention(RetentionPolicy.SOURCE) 114 @IntDef({ENROLLMENT_HANDSHAKE_FAILURE, 115 ENROLLMENT_NOT_ALLOWED}) 116 public @interface TrustedDeviceEnrollmentError { 117 } 118 119 120 /** @hide */ CarTrustAgentEnrollmentManager(Car car, IBinder service)121 public CarTrustAgentEnrollmentManager(Car car, IBinder service) { 122 super(car); 123 mEnrollmentService = ICarTrustAgentEnrollment.Stub.asInterface(service); 124 mEventCallbackHandler = new EventCallbackHandler(this, getEventHandler().getLooper()); 125 } 126 127 /** @hide */ 128 @Override onCarDisconnected()129 public synchronized void onCarDisconnected() { 130 } 131 132 /** 133 * Starts broadcasting enrollment UUID on BLE. 134 * Phones can scan and connect for the enrollment process to begin. 135 */ 136 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) startEnrollmentAdvertising()137 public void startEnrollmentAdvertising() { 138 try { 139 mEnrollmentService.startEnrollmentAdvertising(); 140 } catch (RemoteException e) { 141 handleRemoteExceptionFromCarService(e); 142 } 143 } 144 145 /** 146 * Stops Enrollment advertising. 147 */ 148 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) stopEnrollmentAdvertising()149 public void stopEnrollmentAdvertising() { 150 try { 151 mEnrollmentService.stopEnrollmentAdvertising(); 152 } catch (RemoteException e) { 153 handleRemoteExceptionFromCarService(e); 154 } 155 } 156 157 /** 158 * Confirms that the enrollment handshake has been accepted by the user. This should be called 159 * after the user has confirmed the verification code displayed on the UI. 160 * 161 * @param device the remote Bluetooth device that will receive the signal. 162 */ 163 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) enrollmentHandshakeAccepted(BluetoothDevice device)164 public void enrollmentHandshakeAccepted(BluetoothDevice device) { 165 try { 166 mEnrollmentService.enrollmentHandshakeAccepted(device); 167 } catch (RemoteException e) { 168 handleRemoteExceptionFromCarService(e); 169 } 170 } 171 172 /** 173 * Provides an option to quit enrollment if the pairing code doesn't match for example. 174 */ 175 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) terminateEnrollmentHandshake()176 public void terminateEnrollmentHandshake() { 177 try { 178 mEnrollmentService.terminateEnrollmentHandshake(); 179 } catch (RemoteException e) { 180 handleRemoteExceptionFromCarService(e); 181 } 182 } 183 184 /** 185 * Returns {@code true} if the escrow token associated with the given handle is active. 186 * <p> 187 * When a new escrow token has been added as part of the Trusted device enrollment, the client 188 * will receive {@link CarTrustAgentEnrollmentCallback#onEscrowTokenAdded(long)} and 189 * {@link CarTrustAgentEnrollmentCallback#onEscrowTokenActiveStateChanged(long, boolean)} 190 * callbacks. This method provides a way to query for the token state at a later point of time. 191 * 192 * @param handle the handle corresponding to the escrow token 193 * @param uid user id associated with the token 194 * @return true if the token is active, false if not 195 */ 196 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) isEscrowTokenActive(long handle, int uid)197 public boolean isEscrowTokenActive(long handle, int uid) { 198 try { 199 return mEnrollmentService.isEscrowTokenActive(handle, uid); 200 } catch (RemoteException e) { 201 return handleRemoteExceptionFromCarService(e, false); 202 } 203 } 204 205 /** 206 * Remove the escrow token that is associated with the given handle and uid. 207 * 208 * @param handle the handle associated with the escrow token 209 * @param uid user id associated with the token 210 */ 211 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) removeEscrowToken(long handle, int uid)212 public void removeEscrowToken(long handle, int uid) { 213 try { 214 mEnrollmentService.removeEscrowToken(handle, uid); 215 } catch (RemoteException e) { 216 handleRemoteExceptionFromCarService(e); 217 } 218 } 219 220 /** 221 * Remove all of the trusted devices associated with the given user. 222 * 223 * @param uid User id to remove the devices for 224 */ 225 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) removeAllTrustedDevices(int uid)226 public void removeAllTrustedDevices(int uid) { 227 try { 228 mEnrollmentService.removeAllTrustedDevices(uid); 229 } catch (RemoteException e) { 230 handleRemoteExceptionFromCarService(e); 231 } 232 } 233 234 /** 235 * Enable or Disable Trusted device enrollment. Once disabled, head unit will not broadcast 236 * for enrollment until enabled back. 237 * 238 * @param isEnabled {@code true} enables enrollment. 239 */ 240 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) setTrustedDeviceEnrollmentEnabled(boolean isEnabled)241 public void setTrustedDeviceEnrollmentEnabled(boolean isEnabled) { 242 try { 243 mEnrollmentService.setTrustedDeviceEnrollmentEnabled(isEnabled); 244 } catch (RemoteException e) { 245 handleRemoteExceptionFromCarService(e); 246 } 247 } 248 249 /** 250 * Enable or disable Unlocking with a trusted device. Once disabled, head unit will not 251 * broadcast until enabled back. 252 * 253 * @param isEnabled {@code true} enables unlock. 254 */ 255 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) setTrustedDeviceUnlockEnabled(boolean isEnabled)256 public void setTrustedDeviceUnlockEnabled(boolean isEnabled) { 257 try { 258 mEnrollmentService.setTrustedDeviceUnlockEnabled(isEnabled); 259 } catch (RemoteException e) { 260 handleRemoteExceptionFromCarService(e); 261 } 262 } 263 264 /** 265 * Register for enrollment event callbacks. 266 * 267 * @param callback The callback methods to call, null to unregister 268 */ 269 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) setEnrollmentCallback(@ullable CarTrustAgentEnrollmentCallback callback)270 public void setEnrollmentCallback(@Nullable CarTrustAgentEnrollmentCallback callback) { 271 if (callback == null) { 272 unregisterEnrollmentCallback(); 273 } else { 274 registerEnrollmentCallback(callback); 275 } 276 } 277 registerEnrollmentCallback(CarTrustAgentEnrollmentCallback callback)278 private void registerEnrollmentCallback(CarTrustAgentEnrollmentCallback callback) { 279 synchronized (mListenerLock) { 280 if (callback != null && mEnrollmentCallback == null) { 281 try { 282 mEnrollmentService.registerEnrollmentCallback(mListenerToEnrollmentService); 283 mEnrollmentCallback = callback; 284 } catch (RemoteException e) { 285 handleRemoteExceptionFromCarService(e); 286 } 287 } 288 } 289 } 290 unregisterEnrollmentCallback()291 private void unregisterEnrollmentCallback() { 292 synchronized (mListenerLock) { 293 if (mEnrollmentCallback != null) { 294 try { 295 mEnrollmentService.unregisterEnrollmentCallback(mListenerToEnrollmentService); 296 } catch (RemoteException e) { 297 handleRemoteExceptionFromCarService(e); 298 } 299 mEnrollmentCallback = null; 300 } 301 } 302 } 303 304 /** 305 * Register for general BLE callbacks 306 * 307 * @param callback The callback methods to call, null to unregister 308 */ 309 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) setBleCallback(@ullable CarTrustAgentBleCallback callback)310 public void setBleCallback(@Nullable CarTrustAgentBleCallback callback) { 311 if (callback == null) { 312 unregisterBleCallback(); 313 } else { 314 registerBleCallback(callback); 315 } 316 } 317 registerBleCallback(CarTrustAgentBleCallback callback)318 private void registerBleCallback(CarTrustAgentBleCallback callback) { 319 synchronized (mListenerLock) { 320 if (callback != null && mBleCallback == null) { 321 try { 322 mEnrollmentService.registerBleCallback(mListenerToBleService); 323 mBleCallback = callback; 324 } catch (RemoteException e) { 325 handleRemoteExceptionFromCarService(e); 326 } 327 } 328 } 329 } 330 unregisterBleCallback()331 private void unregisterBleCallback() { 332 synchronized (mListenerLock) { 333 if (mBleCallback != null) { 334 try { 335 mEnrollmentService.unregisterBleCallback(mListenerToBleService); 336 } catch (RemoteException e) { 337 handleRemoteExceptionFromCarService(e); 338 } 339 mBleCallback = null; 340 } 341 } 342 } 343 344 /** 345 * Provides a list that contains information about the enrolled devices for the given user id. 346 * <p> 347 * Each enrollment handle corresponds to a trusted device for the given user. 348 * 349 * @param uid user id. 350 * @return list of the Enrollment handles and user names for the user id. 351 */ 352 @RequiresPermission(PERMISSION_CAR_ENROLL_TRUST) 353 @NonNull getEnrolledDeviceInfoForUser(int uid)354 public List<TrustedDeviceInfo> getEnrolledDeviceInfoForUser(int uid) { 355 try { 356 return mEnrollmentService.getEnrolledDeviceInfosForUser(uid); 357 } catch (RemoteException e) { 358 return handleRemoteExceptionFromCarService(e, Collections.emptyList()); 359 } 360 } 361 getEventCallbackHandler()362 private Handler getEventCallbackHandler() { 363 return mEventCallbackHandler; 364 } 365 366 /** 367 * Callback interface for Trusted device enrollment applications to implement. The applications 368 * get notified on various enrollment state change events. 369 */ 370 public interface CarTrustAgentEnrollmentCallback { 371 /** 372 * Communicate about failure/timeouts in the handshake process. BluetoothDevice will be 373 * null when the returned error code is {@link #ENROLLMENT_NOT_ALLOWED}. 374 * 375 * @param device the remote device trying to enroll 376 * @param errorCode information on what failed. 377 */ onEnrollmentHandshakeFailure(@ullable BluetoothDevice device, @TrustedDeviceEnrollmentError int errorCode)378 void onEnrollmentHandshakeFailure(@Nullable BluetoothDevice device, 379 @TrustedDeviceEnrollmentError int errorCode); 380 381 /** 382 * Present the pairing/authentication string to the user. 383 * 384 * @param device the remote device trying to enroll 385 * @param authString the authentication string to show to the user to confirm across 386 * both devices 387 */ onAuthStringAvailable(BluetoothDevice device, String authString)388 void onAuthStringAvailable(BluetoothDevice device, String authString); 389 390 /** 391 * Escrow token was received and the Trust Agent framework has generated a corresponding 392 * handle. 393 * 394 * @param handle the handle associated with the escrow token. 395 */ onEscrowTokenAdded(long handle)396 void onEscrowTokenAdded(long handle); 397 398 /** 399 * Escrow token was removed as a result of a call to {@link #removeEscrowToken(long handle, 400 * int uid)}. The peer device associated with this token is not trusted for authentication 401 * anymore. 402 * 403 * @param handle the handle associated with the escrow token. 404 */ onEscrowTokenRemoved(long handle)405 void onEscrowTokenRemoved(long handle); 406 407 408 /** 409 * Escrow token's active state changed. 410 * 411 * @param handle the handle associated with the escrow token 412 * @param active True if token has been activated, false if not. 413 */ onEscrowTokenActiveStateChanged(long handle, boolean active)414 void onEscrowTokenActiveStateChanged(long handle, boolean active); 415 } 416 417 /** 418 * Callback interface for Trusted device enrollment applications to implement. The applications 419 * get notified on various BLE state change events that happen during trusted device enrollment. 420 */ 421 public interface CarTrustAgentBleCallback { 422 /** 423 * Indicates a remote device connected on BLE. 424 */ onBleEnrollmentDeviceConnected(BluetoothDevice device)425 void onBleEnrollmentDeviceConnected(BluetoothDevice device); 426 427 /** 428 * Indicates a remote device disconnected on BLE. 429 */ onBleEnrollmentDeviceDisconnected(BluetoothDevice device)430 void onBleEnrollmentDeviceDisconnected(BluetoothDevice device); 431 432 /** 433 * Indicates that the device is broadcasting for trusted device enrollment on BLE. 434 */ onEnrollmentAdvertisingStarted()435 void onEnrollmentAdvertisingStarted(); 436 437 /** 438 * Indicates a failure in BLE broadcasting for enrollment. 439 */ onEnrollmentAdvertisingFailed()440 void onEnrollmentAdvertisingFailed(); 441 } 442 443 private static final class ListenerToEnrollmentService extends 444 ICarTrustAgentEnrollmentCallback.Stub { 445 private final WeakReference<CarTrustAgentEnrollmentManager> mMgr; 446 ListenerToEnrollmentService(CarTrustAgentEnrollmentManager mgr)447 ListenerToEnrollmentService(CarTrustAgentEnrollmentManager mgr) { 448 mMgr = new WeakReference<>(mgr); 449 } 450 451 /** 452 * Communicate about failure/timeouts in the handshake process. 453 */ 454 @Override onEnrollmentHandshakeFailure(BluetoothDevice device, @TrustedDeviceEnrollmentError int errorCode)455 public void onEnrollmentHandshakeFailure(BluetoothDevice device, 456 @TrustedDeviceEnrollmentError int errorCode) { 457 CarTrustAgentEnrollmentManager enrollmentManager = mMgr.get(); 458 if (enrollmentManager == null) { 459 return; 460 } 461 enrollmentManager.getEventCallbackHandler().sendMessage( 462 enrollmentManager.getEventCallbackHandler().obtainMessage( 463 MSG_ENROLL_HANDSHAKE_FAILURE, new AuthInfo(device, null, errorCode))); 464 } 465 466 /** 467 * Present the pairing/authentication string to the user. 468 */ 469 @Override onAuthStringAvailable(BluetoothDevice device, String authString)470 public void onAuthStringAvailable(BluetoothDevice device, String authString) { 471 CarTrustAgentEnrollmentManager enrollmentManager = mMgr.get(); 472 if (enrollmentManager == null) { 473 return; 474 } 475 enrollmentManager.getEventCallbackHandler().sendMessage( 476 enrollmentManager.getEventCallbackHandler().obtainMessage( 477 MSG_ENROLL_AUTH_STRING_AVAILABLE, new AuthInfo(device, authString, 0))); 478 } 479 480 /** 481 * Escrow token was received and the Trust Agent framework has generated a corresponding 482 * handle. 483 */ 484 @Override onEscrowTokenAdded(long handle)485 public void onEscrowTokenAdded(long handle) { 486 CarTrustAgentEnrollmentManager enrollmentManager = mMgr.get(); 487 if (enrollmentManager == null) { 488 return; 489 } 490 Message message = enrollmentManager.getEventCallbackHandler().obtainMessage( 491 MSG_ENROLL_TOKEN_ADDED); 492 Bundle data = new Bundle(); 493 data.putLong(KEY_HANDLE, handle); 494 message.setData(data); 495 enrollmentManager.getEventCallbackHandler().sendMessage(message); 496 } 497 498 /** 499 * Escrow token was removed. 500 */ 501 @Override onEscrowTokenRemoved(long handle)502 public void onEscrowTokenRemoved(long handle) { 503 CarTrustAgentEnrollmentManager enrollmentManager = mMgr.get(); 504 if (enrollmentManager == null) { 505 return; 506 } 507 Message message = enrollmentManager.getEventCallbackHandler().obtainMessage( 508 MSG_ENROLL_TOKEN_REMOVED); 509 Bundle data = new Bundle(); 510 data.putLong(KEY_HANDLE, handle); 511 message.setData(data); 512 enrollmentManager.getEventCallbackHandler().sendMessage(message); 513 } 514 515 /** 516 * Escrow token's active state changed. 517 */ 518 @Override onEscrowTokenActiveStateChanged(long handle, boolean active)519 public void onEscrowTokenActiveStateChanged(long handle, boolean active) { 520 CarTrustAgentEnrollmentManager enrollmentManager = mMgr.get(); 521 if (enrollmentManager == null) { 522 return; 523 } 524 Message message = enrollmentManager.getEventCallbackHandler().obtainMessage( 525 MSG_ENROLL_TOKEN_STATE_CHANGED); 526 Bundle data = new Bundle(); 527 data.putLong(KEY_HANDLE, handle); 528 data.putBoolean(KEY_ACTIVE, active); 529 message.setData(data); 530 enrollmentManager.getEventCallbackHandler().sendMessage(message); 531 } 532 } 533 534 private static final class ListenerToBleService extends ICarTrustAgentBleCallback.Stub { 535 private final WeakReference<CarTrustAgentEnrollmentManager> mMgr; 536 ListenerToBleService(CarTrustAgentEnrollmentManager mgr)537 ListenerToBleService(CarTrustAgentEnrollmentManager mgr) { 538 mMgr = new WeakReference<>(mgr); 539 } 540 541 /** 542 * Called when the GATT server is started and BLE is successfully advertising for 543 * enrollment. 544 */ onEnrollmentAdvertisingStarted()545 public void onEnrollmentAdvertisingStarted() { 546 CarTrustAgentEnrollmentManager enrollmentManager = mMgr.get(); 547 if (enrollmentManager == null) { 548 return; 549 } 550 enrollmentManager.getEventCallbackHandler().sendMessage( 551 enrollmentManager.getEventCallbackHandler().obtainMessage( 552 MSG_ENROLL_ADVERTISING_STARTED)); 553 } 554 555 /** 556 * Called when the BLE enrollment advertisement fails to start. 557 * see AdvertiseCallback#ADVERTISE_FAILED_* for possible error codes. 558 */ onEnrollmentAdvertisingFailed()559 public void onEnrollmentAdvertisingFailed() { 560 CarTrustAgentEnrollmentManager enrollmentManager = mMgr.get(); 561 if (enrollmentManager == null) { 562 return; 563 } 564 enrollmentManager.getEventCallbackHandler().sendMessage( 565 enrollmentManager.getEventCallbackHandler().obtainMessage( 566 MSG_ENROLL_ADVERTISING_FAILED)); 567 } 568 569 /** 570 * Called when a remote device is connected on BLE. 571 */ onBleEnrollmentDeviceConnected(BluetoothDevice device)572 public void onBleEnrollmentDeviceConnected(BluetoothDevice device) { 573 CarTrustAgentEnrollmentManager enrollmentManager = mMgr.get(); 574 if (enrollmentManager == null) { 575 return; 576 } 577 enrollmentManager.getEventCallbackHandler().sendMessage( 578 enrollmentManager.getEventCallbackHandler().obtainMessage( 579 MSG_ENROLL_DEVICE_CONNECTED, device)); 580 } 581 582 /** 583 * Called when a remote device is disconnected on BLE. 584 */ onBleEnrollmentDeviceDisconnected(BluetoothDevice device)585 public void onBleEnrollmentDeviceDisconnected(BluetoothDevice device) { 586 CarTrustAgentEnrollmentManager enrollmentManager = mMgr.get(); 587 if (enrollmentManager == null) { 588 return; 589 } 590 enrollmentManager.getEventCallbackHandler().sendMessage( 591 enrollmentManager.getEventCallbackHandler().obtainMessage( 592 MSG_ENROLL_DEVICE_DISCONNECTED, device)); 593 } 594 } 595 596 /** 597 * Callback Handler to handle dispatching the enrollment state changes to the corresponding 598 * listeners 599 */ 600 private static final class EventCallbackHandler extends Handler { 601 private final WeakReference<CarTrustAgentEnrollmentManager> mEnrollmentManager; 602 EventCallbackHandler(CarTrustAgentEnrollmentManager manager, Looper looper)603 EventCallbackHandler(CarTrustAgentEnrollmentManager manager, Looper looper) { 604 super(looper); 605 mEnrollmentManager = new WeakReference<>(manager); 606 } 607 608 @Override handleMessage(Message message)609 public void handleMessage(Message message) { 610 CarTrustAgentEnrollmentManager enrollmentManager = mEnrollmentManager.get(); 611 if (enrollmentManager == null) { 612 return; 613 } 614 switch (message.what) { 615 case MSG_ENROLL_ADVERTISING_STARTED: 616 case MSG_ENROLL_ADVERTISING_FAILED: 617 case MSG_ENROLL_DEVICE_CONNECTED: 618 case MSG_ENROLL_DEVICE_DISCONNECTED: 619 enrollmentManager.dispatchBleCallback(message); 620 break; 621 case MSG_ENROLL_HANDSHAKE_FAILURE: 622 case MSG_ENROLL_AUTH_STRING_AVAILABLE: 623 case MSG_ENROLL_TOKEN_ADDED: 624 case MSG_ENROLL_TOKEN_STATE_CHANGED: 625 case MSG_ENROLL_TOKEN_REMOVED: 626 enrollmentManager.dispatchEnrollmentCallback(message); 627 break; 628 default: 629 Log.e(TAG, "Unknown message:" + message.what); 630 break; 631 } 632 } 633 } 634 635 /** 636 * Dispatch BLE related state change callbacks 637 * 638 * @param message Message to handle and dispatch 639 */ dispatchBleCallback(Message message)640 private void dispatchBleCallback(Message message) { 641 CarTrustAgentBleCallback bleCallback; 642 synchronized (mListenerLock) { 643 bleCallback = mBleCallback; 644 } 645 if (bleCallback == null) { 646 return; 647 } 648 switch (message.what) { 649 case MSG_ENROLL_ADVERTISING_STARTED: 650 bleCallback.onEnrollmentAdvertisingStarted(); 651 break; 652 case MSG_ENROLL_ADVERTISING_FAILED: 653 bleCallback.onEnrollmentAdvertisingFailed(); 654 break; 655 case MSG_ENROLL_DEVICE_CONNECTED: 656 bleCallback.onBleEnrollmentDeviceConnected((BluetoothDevice) message.obj); 657 break; 658 case MSG_ENROLL_DEVICE_DISCONNECTED: 659 bleCallback.onBleEnrollmentDeviceDisconnected((BluetoothDevice) message.obj); 660 break; 661 default: 662 break; 663 } 664 } 665 666 /** 667 * Dispatch Enrollment related state changes to the listener. 668 * 669 * @param message Message to handle and dispatch 670 */ dispatchEnrollmentCallback(Message message)671 private void dispatchEnrollmentCallback(Message message) { 672 CarTrustAgentEnrollmentCallback enrollmentCallback; 673 synchronized (mListenerLock) { 674 enrollmentCallback = mEnrollmentCallback; 675 } 676 if (enrollmentCallback == null) { 677 return; 678 } 679 AuthInfo auth; 680 Bundle data; 681 switch (message.what) { 682 case MSG_ENROLL_HANDSHAKE_FAILURE: 683 auth = (AuthInfo) message.obj; 684 enrollmentCallback.onEnrollmentHandshakeFailure(auth.mDevice, auth.mErrorCode); 685 break; 686 case MSG_ENROLL_AUTH_STRING_AVAILABLE: 687 auth = (AuthInfo) message.obj; 688 if (auth.mDevice != null && auth.mAuthString != null) { 689 enrollmentCallback.onAuthStringAvailable(auth.mDevice, auth.mAuthString); 690 } 691 break; 692 case MSG_ENROLL_TOKEN_ADDED: 693 data = message.getData(); 694 if (data == null) { 695 break; 696 } 697 enrollmentCallback.onEscrowTokenAdded(data.getLong(KEY_HANDLE)); 698 break; 699 case MSG_ENROLL_TOKEN_STATE_CHANGED: 700 data = message.getData(); 701 if (data == null) { 702 break; 703 } 704 enrollmentCallback.onEscrowTokenActiveStateChanged(data.getLong(KEY_HANDLE), 705 data.getBoolean(KEY_ACTIVE)); 706 break; 707 case MSG_ENROLL_TOKEN_REMOVED: 708 data = message.getData(); 709 if (data == null) { 710 break; 711 } 712 enrollmentCallback.onEscrowTokenRemoved(data.getLong(KEY_HANDLE)); 713 break; 714 default: 715 break; 716 } 717 } 718 719 /** 720 * Container class to pass information through a Message to the handler. 721 */ 722 private static class AuthInfo { 723 final BluetoothDevice mDevice; 724 @Nullable 725 final String mAuthString; 726 final int mErrorCode; 727 AuthInfo(BluetoothDevice device, @Nullable String authString, @TrustedDeviceEnrollmentError int errorCode)728 AuthInfo(BluetoothDevice device, @Nullable String authString, 729 @TrustedDeviceEnrollmentError int errorCode) { 730 mDevice = device; 731 mAuthString = authString; 732 mErrorCode = errorCode; 733 } 734 } 735 } 736