Home | History | Annotate | Download | only in car
      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 
     17 package com.android.car;
     18 
     19 import android.bluetooth.BluetoothAdapter;
     20 import android.bluetooth.BluetoothManager;
     21 
     22 import android.bluetooth.le.AdvertiseCallback;
     23 import android.bluetooth.le.AdvertiseData;
     24 import android.bluetooth.le.AdvertiseSettings;
     25 import android.bluetooth.le.BluetoothLeAdvertiser;
     26 import android.content.Context;
     27 import android.content.res.Resources;
     28 import android.os.ParcelUuid;
     29 import android.util.Log;
     30 
     31 import java.nio.ByteBuffer;
     32 import java.nio.ByteOrder;
     33 import 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  */
     43 class 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