1/* 2 * Copyright (C) 2018 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 17package com.android.car; 18 19import android.bluetooth.BluetoothAdapter; 20import android.bluetooth.BluetoothManager; 21 22import android.bluetooth.le.AdvertiseCallback; 23import android.bluetooth.le.AdvertiseData; 24import android.bluetooth.le.AdvertiseSettings; 25import android.bluetooth.le.BluetoothLeAdvertiser; 26import android.content.Context; 27import android.content.res.Resources; 28import android.os.ParcelUuid; 29import android.util.Log; 30 31import java.nio.ByteBuffer; 32import java.nio.ByteOrder; 33import java.util.Arrays; 34 35/** 36 * An advertiser for the Bluetooth LE based Fast Pair service. 37 * FastPairProvider enables easy Bluetooth pairing between a peripheral and a phone participating in 38 * the Fast Pair Seeker role. When the seeker finds a compatible peripheral a notification prompts 39 * the user to begin pairing if desired. A peripheral should call startAdvertising when it is 40 * appropriate to pair, and stopAdvertising when pairing is complete or it is no longer appropriate 41 * to pair. 42 */ 43class FastPairProvider { 44 45 private static final String TAG = "FastPairProvider"; 46 private static final boolean DBG = Utils.DBG; 47 48 // Service ID assigned for FastPair. 49 private static final ParcelUuid FastPairServiceUuid = ParcelUuid 50 .fromString("0000FE2C-0000-1000-8000-00805f9b34fb"); 51 52 private AdvertiseSettings mSettings; 53 private AdvertiseData mData; 54 private BluetoothLeAdvertiser mBluetoothLeAdvertiser; 55 private AdvertiseCallback mAdvertiseCallback; 56 57 58 FastPairProvider(Context context) { 59 Resources res = context.getResources(); 60 int modelId = res.getInteger(R.integer.fastPairModelId); 61 if (modelId == 0) { 62 Log.w(TAG, "Model ID undefined, disabling"); 63 return; 64 } 65 66 BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService( 67 Context.BLUETOOTH_SERVICE); 68 if (bluetoothManager != null) { 69 BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter(); 70 if (bluetoothAdapter != null) { 71 mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser(); 72 } 73 } 74 75 AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder(); 76 settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY); 77 settingsBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH); 78 settingsBuilder.setConnectable(true); 79 settingsBuilder.setTimeout(0); 80 mSettings = settingsBuilder.build(); 81 82 AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder(); 83 ByteBuffer modelIdBytes = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt( 84 modelId); 85 byte[] fastPairServiceData = Arrays.copyOfRange(modelIdBytes.array(), 0, 3); 86 dataBuilder.addServiceData(FastPairServiceUuid, fastPairServiceData); 87 dataBuilder.setIncludeTxPowerLevel(true).build(); 88 mData = dataBuilder.build(); 89 90 mAdvertiseCallback = new FastPairAdvertiseCallback(); 91 } 92 93 /* register the BLE advertisement using the model id provided during construction */ 94 boolean startAdvertising() { 95 if (mBluetoothLeAdvertiser != null) { 96 mBluetoothLeAdvertiser.startAdvertising(mSettings, mData, mAdvertiseCallback); 97 return true; 98 } 99 return false; 100 } 101 102 /* unregister the BLE advertisement. */ 103 boolean stopAdvertising() { 104 if (mBluetoothLeAdvertiser != null) { 105 mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback); 106 return true; 107 } 108 return false; 109 } 110 111 /* Callback to handle status when advertising starts. */ 112 private class FastPairAdvertiseCallback extends AdvertiseCallback { 113 @Override 114 public void onStartFailure(int errorCode) { 115 super.onStartFailure(errorCode); 116 if (DBG) Log.d(TAG, "Advertising failed"); 117 } 118 119 @Override 120 public void onStartSuccess(AdvertiseSettings settingsInEffect) { 121 super.onStartSuccess(settingsInEffect); 122 if (DBG) Log.d(TAG, "Advertising successfully started"); 123 } 124 } 125} 126