1 /* 2 * Copyright (C) 2022 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.pandora 18 19 import android.bluetooth.BluetoothDevice 20 import android.bluetooth.BluetoothGatt 21 import android.bluetooth.BluetoothGattCharacteristic 22 import android.bluetooth.BluetoothGattServer 23 import android.bluetooth.BluetoothGattServerCallback 24 import android.bluetooth.BluetoothGattService 25 import android.bluetooth.BluetoothManager 26 import android.content.Context 27 import android.util.Log 28 import java.util.UUID 29 import kotlinx.coroutines.CoroutineScope 30 import kotlinx.coroutines.flow.MutableSharedFlow 31 import kotlinx.coroutines.launch 32 33 class GattServerManager( 34 bluetoothManager: BluetoothManager, 35 context: Context, 36 scope: CoroutineScope 37 ) { 38 val TAG = "PandoraGattServerManager" 39 40 val services = mutableMapOf<UUID, BluetoothGattService>() 41 val serviceFlow = MutableSharedFlow<BluetoothGattService>() 42 var negociatedMtu = -1 43 44 val callback = 45 object : BluetoothGattServerCallback() { onServiceAddednull46 override fun onServiceAdded(status: Int, service: BluetoothGattService) { 47 Log.i(TAG, "onServiceAdded status=$status") 48 check(status == BluetoothGatt.GATT_SUCCESS) 49 scope.launch { serviceFlow.emit(service) } 50 } onMtuChangednull51 override fun onMtuChanged(device: BluetoothDevice, mtu: Int) { 52 Log.i(TAG, "onMtuChanged mtu=$mtu") 53 negociatedMtu = mtu 54 } 55 onCharacteristicReadRequestnull56 override fun onCharacteristicReadRequest( 57 device: BluetoothDevice, 58 requestId: Int, 59 offset: Int, 60 characteristic: BluetoothGattCharacteristic 61 ) { 62 Log.i(TAG, "onCharacteristicReadRequest requestId=$requestId") 63 if (negociatedMtu != -1) { 64 server.sendResponse( 65 device, 66 requestId, 67 BluetoothGatt.GATT_SUCCESS, 68 offset, 69 ByteArray(negociatedMtu) 70 ) 71 } else { 72 server.sendResponse( 73 device, 74 requestId, 75 BluetoothGatt.GATT_SUCCESS, 76 offset, 77 ByteArray(512 - offset) 78 ) 79 } 80 } 81 onCharacteristicWriteRequestnull82 override fun onCharacteristicWriteRequest( 83 device: BluetoothDevice, 84 requestId: Int, 85 characteristic: BluetoothGattCharacteristic, 86 preparedWrite: Boolean, 87 responseNeeded: Boolean, 88 offset: Int, 89 value: ByteArray 90 ) { 91 Log.i(TAG, "onCharacteristicWriteRequest requestId=$requestId") 92 } 93 onExecuteWritenull94 override fun onExecuteWrite(device: BluetoothDevice, requestId: Int, execute: Boolean) { 95 Log.i(TAG, "onExecuteWrite requestId=$requestId") 96 } 97 } 98 99 val server: BluetoothGattServer = bluetoothManager.openGattServer(context, callback) 100 } 101