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.HashSet; 29import java.util.UUID; 30 31/** 32 * A service that receives escrow token enrollment requests from remote devices. 33 */ 34public class CarEnrolmentService extends SimpleBleServer { 35 private static final String TAG = "CarEnrolmentService"; 36 37 public interface EnrolmentCallback { 38 void onEnrolmentDataReceived(byte[] token); 39 } 40 41 private BluetoothGattService mEnrolmentService; 42 private BluetoothGattCharacteristic mEnrolmentEscrowToken; 43 private BluetoothGattCharacteristic mEnrolmentTokenHandle; 44 45 private HashSet<EnrolmentCallback> mCallbacks; 46 47 private final IBinder mBinder = new EnrolmentServiceBinder(); 48 49 @Override 50 public void onCreate() { 51 super.onCreate(); 52 mCallbacks = new HashSet<>(); 53 setupEnrolmentService(); 54 } 55 56 public void start() { 57 ParcelUuid uuid = new ParcelUuid( 58 UUID.fromString(getString(R.string.enrollment_service_uuid))); 59 start(uuid, mEnrolmentService); 60 } 61 62 @Override 63 public IBinder onBind(Intent intent) { 64 return mBinder; 65 } 66 67 @Override 68 public void onCharacteristicWrite(BluetoothDevice device, 69 int requestId, BluetoothGattCharacteristic characteristic, 70 boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { 71 if (characteristic.getUuid().equals(mEnrolmentEscrowToken.getUuid())) { 72 if (Log.isLoggable(TAG, Log.DEBUG)) { 73 Log.d(TAG, "Enrolment token received, value: " + Utils.getLong(value)); 74 } 75 76 for (EnrolmentCallback callback : mCallbacks) { 77 callback.onEnrolmentDataReceived(value); 78 } 79 } 80 } 81 82 @Override 83 public void onCharacteristicRead(BluetoothDevice device, 84 int requestId, int offset, BluetoothGattCharacteristic characteristic) { 85 //Enrolment service should not have any read requests. 86 } 87 88 public void addEnrolmentCallback(EnrolmentCallback callback) { 89 mCallbacks.add(callback); 90 } 91 92 public void sendHandle(long handle, BluetoothDevice device) { 93 mEnrolmentTokenHandle.setValue(Utils.getBytes(handle)); 94 95 if (Log.isLoggable(TAG, Log.DEBUG)) { 96 Log.d(TAG, "Sending notification for EscrowToken Handle"); 97 } 98 mGattServer.notifyCharacteristicChanged(device, 99 mEnrolmentTokenHandle, false /* confirm */); 100 } 101 102 public class EnrolmentServiceBinder extends Binder { 103 public CarEnrolmentService getService() { 104 return CarEnrolmentService.this; 105 } 106 } 107 108 // Create services and characteristics for enrolling new unlocking escrow tokens 109 private void setupEnrolmentService() { 110 mEnrolmentService = new BluetoothGattService( 111 UUID.fromString(getString(R.string.enrollment_service_uuid)), 112 BluetoothGattService.SERVICE_TYPE_PRIMARY); 113 114 // Characteristic to describe the escrow token being used for unlock 115 mEnrolmentEscrowToken = new BluetoothGattCharacteristic( 116 UUID.fromString(getString(R.string.enrollment_token_uuid)), 117 BluetoothGattCharacteristic.PROPERTY_WRITE, 118 BluetoothGattCharacteristic.PERMISSION_WRITE); 119 120 // Characteristic to describe the handle being used for this escrow token 121 mEnrolmentTokenHandle = new BluetoothGattCharacteristic( 122 UUID.fromString(getString(R.string.enrollment_handle_uuid)), 123 BluetoothGattCharacteristic.PROPERTY_NOTIFY, 124 BluetoothGattCharacteristic.PERMISSION_READ); 125 126 mEnrolmentService.addCharacteristic(mEnrolmentEscrowToken); 127 mEnrolmentService.addCharacteristic(mEnrolmentTokenHandle); 128 } 129} 130