aboutsummaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorJoseph Pirozzo <pirozzoj@google.com>2018-01-10 15:05:57 -0800
committerJoseph Pirozzo <pirozzoj@google.com>2018-01-22 14:50:13 -0800
commite5ac56c9a8671f967dd908fe7fc6704780521aa1 (patch)
tree976c44c5ae09fb9314ea6439de54b6ad63dd933c /service
parentafdb50df2c90f94cd86e2468b4e22a8e7b9a642c (diff)
downloadCar-e5ac56c9a8671f967dd908fe7fc6704780521aa1.tar.gz
Bluetooth Fast Pair
Enable advertisement of head unit as a connectable device via Fast Pair. The fastPairModelId stored in the config file must be overriden by vendors to their specific device Id. Bug: 38321459 Test: runtest -x packages/services/Car/tests/carservice_test/ -c com.android.car.FastPairProviderTest Disable Restrictions and move Android phone close to Bluetooth Antenna, observe Fast Pair dialog on phone. Change-Id: Iae707849537c3ef3b16a2b0738a72007d3961741
Diffstat (limited to 'service')
-rw-r--r--service/res/values/config.xml5
-rw-r--r--service/src/com/android/car/BluetoothDeviceConnectionPolicy.java15
-rw-r--r--service/src/com/android/car/FastPairProvider.java125
3 files changed, 145 insertions, 0 deletions
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index 1b5430958c..5b8996cd92 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -125,4 +125,9 @@
strongly recommended that it be protected with the
android.car.permission.STORAGE_MONITORING permission. -->
<string name="intentReceiverForUnacceptableIoMetrics"></string>
+
+ <!-- The Model ID to advertise Bluetooth Fast Pair connections with. Must be overlayed with
+ device specific model id. -->
+ <integer name="fastPairModelId">0x000000</integer>
+
</resources>
diff --git a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
index 8b34ab7b75..e8fd37048b 100644
--- a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
+++ b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
@@ -129,6 +129,9 @@ public class BluetoothDeviceConnectionPolicy {
// Car Bluetooth Priority Settings Manager
private final CarBluetoothService mCarBluetoothService;
+ // Fast Pair Provider to allow discovery of new phones
+ private final FastPairProvider mFastPairProvider;
+
// The Bluetooth profiles that the CarService will try to auto-connect on.
private final List<Integer> mProfilesToConnect;
private final List<Integer> mPrioritiesSupported;
@@ -198,6 +201,7 @@ public class BluetoothDeviceConnectionPolicy {
if (mBluetoothAdapter == null) {
Log.w(TAG, "No Bluetooth Adapter Available");
}
+ mFastPairProvider = new FastPairProvider(mContext);
}
/**
@@ -584,6 +588,8 @@ public class BluetoothDeviceConnectionPolicy {
mCarCabinService.registerListener(mCabinEventListener);
mCarSensorService.registerOrUpdateSensorListener(
CarSensorManager.SENSOR_TYPE_IGNITION_STATE, 0, mCarSensorEventListener);
+ mCarSensorService.registerOrUpdateSensorListener(
+ CarSensorManager.SENSOR_TYPE_DRIVING_STATUS, 0, mCarSensorEventListener);
mUserServiceHelper.registerServiceCallback(mServiceCallback);
}
@@ -640,6 +646,15 @@ public class BluetoothDeviceConnectionPolicy {
if (event.intValues[0] == CarSensorEvent.IGNITION_STATE_START) {
initiateConnection();
}
+ } else if (event.sensorType == CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) {
+ if (DBG) {
+ Log.d(TAG, "Sensor value : " + event.intValues[0]);
+ }
+ if ((event.intValues[0] & CarSensorEvent.DRIVE_STATUS_NO_CONFIG) == CarSensorEvent.DRIVE_STATUS_NO_CONFIG) {
+ mFastPairProvider.stopAdvertising();
+ } else {
+ mFastPairProvider.startAdvertising();
+ }
}
}
}
diff --git a/service/src/com/android/car/FastPairProvider.java b/service/src/com/android/car/FastPairProvider.java
new file mode 100644
index 0000000000..ff5973236f
--- /dev/null
+++ b/service/src/com/android/car/FastPairProvider.java
@@ -0,0 +1,125 @@
+/*
+ * 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");
+ }
+ }
+}