1 /* 2 * Copyright 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.bluetooth.bass_client; 18 19 import android.annotation.NonNull; 20 import android.bluetooth.BluetoothAdapter; 21 import android.bluetooth.BluetoothDevice; 22 import android.bluetooth.BluetoothLeBroadcastReceiveState; 23 import android.bluetooth.IBluetoothLeBroadcastAssistantCallback; 24 import android.bluetooth.le.BluetoothLeScanner; 25 import android.bluetooth.le.ScanCallback; 26 import android.bluetooth.le.ScanFilter; 27 import android.bluetooth.le.ScanResult; 28 import android.os.Handler; 29 import android.os.Message; 30 import android.os.ParcelUuid; 31 import android.util.Log; 32 33 import com.android.bluetooth.btservice.ServiceFactory; 34 35 import java.util.ArrayList; 36 import java.util.Arrays; 37 import java.util.HashMap; 38 import java.util.List; 39 import java.util.Map; 40 41 /** 42 * Bass Utility functions 43 */ 44 class BassUtils { 45 private static final String TAG = "BassUtils"; 46 47 // Using ArrayList as KEY to hashmap. May be not risk 48 // in this case as It is used to track the callback to cancel Scanning later 49 private final Map<ArrayList<IBluetoothLeBroadcastAssistantCallback>, ScanCallback> 50 mLeAudioSourceScanCallbacks = 51 new HashMap<ArrayList<IBluetoothLeBroadcastAssistantCallback>, ScanCallback>(); 52 private final Map<BluetoothDevice, ScanCallback> mBassAutoAssist = 53 new HashMap<BluetoothDevice, ScanCallback>(); 54 55 /*LE Scan related members*/ 56 private boolean mBroadcastersAround = false; 57 private BluetoothAdapter mBluetoothAdapter = null; 58 private BluetoothLeScanner mLeScanner = null; 59 private BassClientService mService = null; 60 private ServiceFactory mFactory = new ServiceFactory(); 61 BassUtils(BassClientService service)62 BassUtils(BassClientService service) { 63 mService = service; 64 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 65 mLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); 66 } 67 cleanUp()68 void cleanUp() { 69 if (mLeAudioSourceScanCallbacks != null) { 70 mLeAudioSourceScanCallbacks.clear(); 71 } 72 if (mBassAutoAssist != null) { 73 mBassAutoAssist.clear(); 74 } 75 } 76 77 private final Handler mAutoAssistScanHandler = 78 new Handler() { 79 public void handleMessage(Message msg) { 80 super.handleMessage(msg); 81 switch (msg.what) { 82 case BassConstants.AA_START_SCAN: 83 Message m = obtainMessage(BassConstants.AA_SCAN_TIMEOUT); 84 sendMessageDelayed(m, BassConstants.AA_SCAN_TIMEOUT_MS); 85 mService.startSearchingForSources(null); 86 break; 87 case BassConstants.AA_SCAN_SUCCESS: 88 // Able to find to desired desired Source Device 89 ScanResult scanRes = (ScanResult) msg.obj; 90 BluetoothDevice dev = scanRes.getDevice(); 91 mService.stopSearchingForSources(); 92 mService.selectSource(dev, scanRes, true); 93 break; 94 case BassConstants.AA_SCAN_FAILURE: 95 // Not able to find the given source 96 break; 97 case BassConstants.AA_SCAN_TIMEOUT: 98 mService.stopSearchingForSources(); 99 break; 100 } 101 } 102 }; 103 getAutoAssistScanHandler()104 @NonNull Handler getAutoAssistScanHandler() { 105 return mAutoAssistScanHandler; 106 } 107 triggerAutoAssist(BluetoothLeBroadcastReceiveState recvState)108 void triggerAutoAssist(BluetoothLeBroadcastReceiveState recvState) { 109 Message msg = mAutoAssistScanHandler.obtainMessage(BassConstants.AA_START_SCAN); 110 msg.obj = recvState.getSourceDevice(); 111 mAutoAssistScanHandler.sendMessage(msg); 112 } 113 containUuid(List<ScanFilter> filters, ParcelUuid uuid)114 static boolean containUuid(List<ScanFilter> filters, ParcelUuid uuid) { 115 for (ScanFilter filter: filters) { 116 if (filter.getServiceUuid().equals(uuid)) { 117 return true; 118 } 119 } 120 return false; 121 } 122 parseBroadcastId(byte[] broadcastIdBytes)123 static int parseBroadcastId(byte[] broadcastIdBytes) { 124 int broadcastId; 125 broadcastId = (0x00FF0000 & (broadcastIdBytes[2] << 16)); 126 broadcastId |= (0x0000FF00 & (broadcastIdBytes[1] << 8)); 127 broadcastId |= (0x000000FF & broadcastIdBytes[0]); 128 return broadcastId; 129 } 130 log(String msg)131 static void log(String msg) { 132 if (BassConstants.BASS_DBG) { 133 Log.d(TAG, msg); 134 } 135 } 136 printByteArray(byte[] array)137 static void printByteArray(byte[] array) { 138 log("Entire byte Array as string: " + Arrays.toString(array)); 139 log("printitng byte by bte"); 140 for (int i = 0; i < array.length; i++) { 141 log("array[" + i + "] :" + Byte.toUnsignedInt(array[i])); 142 } 143 } 144 reverse(byte[] address)145 static void reverse(byte[] address) { 146 int len = address.length; 147 for (int i = 0; i < len / 2; ++i) { 148 byte b = address[i]; 149 address[i] = address[len - 1 - i]; 150 address[len - 1 - i] = b; 151 } 152 } 153 } 154