CarUnlockService.java revision 77e5e49cf9dcceb69b07510c380ae2a9285ebfee
1/* 2 * Copyright (C) 2017 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 */ 16package com.android.car.trust; 17 18import android.bluetooth.BluetoothDevice; 19import android.bluetooth.BluetoothGattCharacteristic; 20import android.bluetooth.BluetoothGattService; 21import android.content.Intent; 22import android.os.Binder; 23import android.os.IBinder; 24import android.os.ParcelUuid; 25import android.util.Log; 26import com.android.car.trust.comms.SimpleBleServer; 27 28import java.util.UUID; 29 30/** 31 * A service that receives unlock requests from remote devices. 32 */ 33public class CarUnlockService extends SimpleBleServer { 34 /** 35 * A callback to receives callback 36 */ 37 public interface UnlockServiceCallback { 38 void unlockDevice(byte[] token, long handle); 39 } 40 41 private static final String TAG = "CarUnlockService"; 42 43 private BluetoothGattService mUnlockService; 44 private BluetoothGattCharacteristic mUnlockEscrowToken; 45 private BluetoothGattCharacteristic mUnlockTokenHandle; 46 47 private UnlockServiceCallback mCallback; 48 49 private byte[] mCurrentToken; 50 private Long mCurrentHandle; 51 52 private final IBinder mBinder = new UnlockServiceBinder(); 53 54 public class UnlockServiceBinder extends Binder { 55 public CarUnlockService getService() { 56 return CarUnlockService.this; 57 } 58 } 59 60 @Override 61 public void onCreate() { 62 super.onCreate(); 63 Log.d(TAG, "CarUnlockService starting up, creating BLE service"); 64 setupUnlockService(); 65 } 66 67 /** 68 * Start advertising the BLE unlock service 69 */ 70 public void start() { 71 ParcelUuid uuid = new ParcelUuid( 72 UUID.fromString(getString(R.string.unlock_service_uuid))); 73 start(uuid, mUnlockService); 74 } 75 76 public void addUnlockServiceCallback(UnlockServiceCallback callback) { 77 mCallback = callback; 78 } 79 80 @Override 81 public IBinder onBind(Intent intent) { 82 return mBinder; 83 } 84 85 @Override 86 public void onCharacteristicWrite(BluetoothDevice device, 87 int requestId, BluetoothGattCharacteristic characteristic, 88 boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { 89 UUID uuid = characteristic.getUuid(); 90 91 if (uuid.equals(mUnlockTokenHandle.getUuid())) { 92 Log.d(TAG, "Unlock handle received, value: " + Utils.getLong(value)); 93 mCurrentHandle = Utils.getLong(value); 94 unlockDataReceived(); 95 } else if (uuid.equals(mUnlockEscrowToken.getUuid())) { 96 Log.d(TAG, "Unlock escrow token received, value: " + Utils.getLong(value)); 97 mCurrentToken = value; 98 unlockDataReceived(); 99 } 100 } 101 102 @Override 103 public void onCharacteristicRead(BluetoothDevice device, 104 int requestId, int offset, BluetoothGattCharacteristic characteristic) { 105 // The BLE unlock service should not receive any read requests. 106 } 107 108 private synchronized void unlockDataReceived() { 109 // If any piece of the unlocking data is not received, then do not unlock. 110 if (mCurrentHandle == null || mCurrentToken == null) { 111 return; 112 } 113 Log.d(TAG, "Handle and token both received, requesting unlock. Time: " 114 + System.currentTimeMillis()); 115 // Both the handle and token has been received, try to unlock the device. 116 117 118 mCallback.unlockDevice(mCurrentToken, mCurrentHandle); 119 120 // Once we've notified the client of the unlocking data, clear it out. 121 mCurrentToken = null; 122 mCurrentHandle = null; 123 } 124 125 126 // Create services and characteristics to receive tokens and handles for unlocking the device. 127 private void setupUnlockService() { 128 mUnlockService = new BluetoothGattService( 129 UUID.fromString(getString(R.string.unlock_service_uuid)), 130 BluetoothGattService.SERVICE_TYPE_PRIMARY); 131 132 // Characteristic to describe the escrow token being used for unlock 133 mUnlockEscrowToken = new BluetoothGattCharacteristic( 134 UUID.fromString(getString(R.string.unlock_escrow_token_uiid)), 135 BluetoothGattCharacteristic.PROPERTY_WRITE, 136 BluetoothGattCharacteristic.PERMISSION_WRITE); 137 138 // Characteristic to describe the handle being used for this escrow token 139 mUnlockTokenHandle = new BluetoothGattCharacteristic( 140 UUID.fromString(getString(R.string.unlock_handle_uiid)), 141 BluetoothGattCharacteristic.PROPERTY_WRITE, 142 BluetoothGattCharacteristic.PERMISSION_WRITE); 143 144 mUnlockService.addCharacteristic(mUnlockEscrowToken); 145 mUnlockService.addCharacteristic(mUnlockTokenHandle); 146 } 147 148} 149