blob: ff5973236f75c2d7988d29853c2f61f6dd022b8d [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.content.Context;
import android.content.res.Resources;
import android.os.ParcelUuid;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
/**
* An advertiser for the Bluetooth LE based Fast Pair service.
* FastPairProvider enables easy Bluetooth pairing between a peripheral and a phone participating in
* the Fast Pair Seeker role. When the seeker finds a compatible peripheral a notification prompts
* the user to begin pairing if desired. A peripheral should call startAdvertising when it is
* appropriate to pair, and stopAdvertising when pairing is complete or it is no longer appropriate
* to pair.
*/
class FastPairProvider {
private static final String TAG = "FastPairProvider";
private static final boolean DBG = Utils.DBG;
// Service ID assigned for FastPair.
private static final ParcelUuid FastPairServiceUuid = ParcelUuid
.fromString("0000FE2C-0000-1000-8000-00805f9b34fb");
private AdvertiseSettings mSettings;
private AdvertiseData mData;
private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
private AdvertiseCallback mAdvertiseCallback;
FastPairProvider(Context context) {
Resources res = context.getResources();
int modelId = res.getInteger(R.integer.fastPairModelId);
if (modelId == 0) {
Log.w(TAG, "Model ID undefined, disabling");
return;
}
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(
Context.BLUETOOTH_SERVICE);
if (bluetoothManager != null) {
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
if (bluetoothAdapter != null) {
mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
}
}
AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY);
settingsBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
settingsBuilder.setConnectable(true);
settingsBuilder.setTimeout(0);
mSettings = settingsBuilder.build();
AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
ByteBuffer modelIdBytes = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(
modelId);
byte[] fastPairServiceData = Arrays.copyOfRange(modelIdBytes.array(), 0, 3);
dataBuilder.addServiceData(FastPairServiceUuid, fastPairServiceData);
dataBuilder.setIncludeTxPowerLevel(true).build();
mData = dataBuilder.build();
mAdvertiseCallback = new FastPairAdvertiseCallback();
}
/* register the BLE advertisement using the model id provided during construction */
boolean startAdvertising() {
if (mBluetoothLeAdvertiser != null) {
mBluetoothLeAdvertiser.startAdvertising(mSettings, mData, mAdvertiseCallback);
return true;
}
return false;
}
/* unregister the BLE advertisement. */
boolean stopAdvertising() {
if (mBluetoothLeAdvertiser != null) {
mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
return true;
}
return false;
}
/* Callback to handle status when advertising starts. */
private class FastPairAdvertiseCallback extends AdvertiseCallback {
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
if (DBG) Log.d(TAG, "Advertising failed");
}
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
if (DBG) Log.d(TAG, "Advertising successfully started");
}
}
}