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