1 /* 2 * Copyright (C) 2017 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.googlecode.android_scripting.facade.bluetooth; 18 19 import android.app.Service; 20 import android.bluetooth.BluetoothAdapter; 21 import android.bluetooth.BluetoothDevice; 22 import android.bluetooth.BluetoothHeadsetClient; 23 import android.bluetooth.BluetoothProfile; 24 import android.bluetooth.BluetoothUuid; 25 import android.os.ParcelUuid; 26 27 import com.googlecode.android_scripting.Log; 28 import com.googlecode.android_scripting.facade.FacadeManager; 29 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 30 import com.googlecode.android_scripting.rpc.Rpc; 31 import com.googlecode.android_scripting.rpc.RpcParameter; 32 33 import java.util.ArrayList; 34 import java.util.List; 35 36 public class BluetoothHfpClientFacade extends RpcReceiver { 37 static final ParcelUuid[] UUIDS = { 38 BluetoothUuid.Handsfree_AG, 39 }; 40 41 private final Service mService; 42 private final BluetoothAdapter mBluetoothAdapter; 43 44 private static boolean sIsHfpClientReady = false; 45 private static BluetoothHeadsetClient sHfpClientProfile = null; 46 47 public BluetoothHfpClientFacade(FacadeManager manager) { 48 super(manager); 49 mService = manager.getService(); 50 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 51 mBluetoothAdapter.getProfileProxy(mService, 52 new HfpClientServiceListener(), 53 BluetoothProfile.HEADSET_CLIENT); 54 } 55 56 class HfpClientServiceListener implements BluetoothProfile.ServiceListener { 57 @Override 58 public void onServiceConnected(int profile, BluetoothProfile proxy) { 59 sHfpClientProfile = (BluetoothHeadsetClient) proxy; 60 sIsHfpClientReady = true; 61 } 62 63 @Override 64 public void onServiceDisconnected(int profile) { 65 sIsHfpClientReady = false; 66 } 67 } 68 69 /** 70 * Connect to HfpClient. 71 * @param device - the BluetoothDevice object to connect Hfp client. 72 * @return if the connection was successfull or not. 73 */ 74 public Boolean hfpClientConnect(BluetoothDevice device) { 75 if (sHfpClientProfile == null) return false; 76 return sHfpClientProfile.connect(device); 77 } 78 79 /** 80 * Disconnect from HfpClient. 81 * @param device - the BluetoothDevice object to disconnect from Hfp client. 82 * @return if the disconnection was successfull or not. 83 */ 84 public Boolean hfpClientDisconnect(BluetoothDevice device) { 85 if (sHfpClientProfile == null) return false; 86 return sHfpClientProfile.disconnect(device); 87 } 88 89 /** 90 * Is Hfp Client profile ready. 91 * @return Hfp Client profile is ready or not. 92 */ 93 @Rpc(description = "Is HfpClient profile ready.") 94 public Boolean bluetoothHfpClientIsReady() { 95 return sIsHfpClientReady; 96 } 97 98 /** 99 * Set priority of the profile. 100 * @param deviceStr - Mac address of a BT device. 101 * @param priority - Priority that needs to be set. 102 */ 103 @Rpc(description = "Set priority of the profile") 104 public void bluetoothHfpClientSetPriority( 105 @RpcParameter(name = "device", 106 description = "Mac address of a BT device.") String deviceStr, 107 @RpcParameter(name = "priority", 108 description = "Priority that needs to be set.") 109 Integer priority) throws Exception { 110 if (sHfpClientProfile == null) return; 111 BluetoothDevice device = 112 BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), 113 deviceStr); 114 Log.d("Changing priority of device " + device.getAliasName() 115 + " p: " + priority); 116 sHfpClientProfile.setPriority(device, priority); 117 } 118 119 /** 120 * Get priority of the profile. 121 * @param deviceStr - Mac address of a BT device. 122 * @return Priority of the device. 123 */ 124 @Rpc(description = "Get priority of the profile") 125 public Integer bluetoothHfpClientGetPriority( 126 @RpcParameter(name = "device", description = 127 "Mac address of a BT device.") String deviceStr) 128 throws Exception { 129 if (sHfpClientProfile == null) return BluetoothProfile.PRIORITY_UNDEFINED; 130 BluetoothDevice device = BluetoothFacade.getDevice( 131 mBluetoothAdapter.getBondedDevices(), deviceStr); 132 return sHfpClientProfile.getPriority(device); 133 } 134 135 /** 136 * Connect to an HFP Client device. 137 * @param deviceStr - Name or MAC address of a bluetooth device. 138 * @return Hfp Client was connected or not. 139 */ 140 @Rpc(description = "Connect to an HFP Client device.") 141 public Boolean bluetoothHfpClientConnect( 142 @RpcParameter(name = "device", 143 description = "Name or MAC address of a bluetooth device.") 144 String deviceStr) 145 throws Exception { 146 if (sHfpClientProfile == null) return false; 147 try { 148 BluetoothDevice device = BluetoothFacade.getDevice( 149 BluetoothFacade.DiscoveredDevices, deviceStr); 150 Log.d("Connecting to device " + device.getAliasName()); 151 return hfpClientConnect(device); 152 } catch (Exception e) { 153 Log.e("bluetoothHfpClientConnect failed on getDevice " 154 + deviceStr + " with " + e); 155 return false; 156 } 157 } 158 159 /** 160 * Disconnect an HFP Client device. 161 * @param deviceStr - Name or MAC address of a bluetooth device. 162 * @return Hfp Client was disconnected or not. 163 */ 164 @Rpc(description = "Disconnect an HFP Client device.") 165 public Boolean bluetoothHfpClientDisconnect( 166 @RpcParameter(name = "device", 167 description = "Name or MAC address of a device.") 168 String deviceStr) { 169 if (sHfpClientProfile == null) return false; 170 Log.d("Connected devices: " + sHfpClientProfile.getConnectedDevices()); 171 try { 172 BluetoothDevice device = BluetoothFacade.getDevice( 173 sHfpClientProfile.getConnectedDevices(), deviceStr); 174 return hfpClientDisconnect(device); 175 } catch (Exception e) { 176 // Do nothing since it is disconnect and this 177 // function should force disconnect. 178 Log.e("bluetoothHfpClientConnect getDevice failed " + e); 179 } 180 return false; 181 } 182 183 /** 184 * Get all the devices connected through HFP Client. 185 * @return List of all the devices connected through HFP Client. 186 */ 187 @Rpc(description = "Get all the devices connected through HFP Client.") 188 public List<BluetoothDevice> bluetoothHfpClientGetConnectedDevices() { 189 if (sHfpClientProfile == null) return new ArrayList<BluetoothDevice>(); 190 return sHfpClientProfile.getConnectedDevices(); 191 } 192 193 /** 194 * Get the connection status of a device. 195 * @param deviceID - Name or MAC address of a bluetooth device. 196 * @return connection status of the device. 197 */ 198 @Rpc(description = "Get the connection status of a device.") 199 public Integer bluetoothHfpClientGetConnectionStatus( 200 @RpcParameter(name = "deviceID", 201 description = "Name or MAC address of a bluetooth device.") 202 String deviceID) { 203 if (sHfpClientProfile == null) { 204 return BluetoothProfile.STATE_DISCONNECTED; 205 } 206 List<BluetoothDevice> deviceList = 207 sHfpClientProfile.getConnectedDevices(); 208 BluetoothDevice device; 209 try { 210 device = BluetoothFacade.getDevice(deviceList, deviceID); 211 } catch (Exception e) { 212 Log.e(e); 213 return BluetoothProfile.STATE_DISCONNECTED; 214 } 215 return sHfpClientProfile.getConnectionState(device); 216 } 217 218 /** 219 * Get the audio routing state of specified device. 220 * @param deviceStr the Bluetooth MAC address of remote device 221 * @return Audio State of the device. 222 */ 223 @Rpc(description = "Get all the devices connected through HFP Client.") 224 public Integer bluetoothHfpClientGetAudioState( 225 @RpcParameter(name = "device", 226 description = "MAC address of a bluetooth device.") 227 String deviceStr) { 228 if (sHfpClientProfile == null) return -1; 229 BluetoothDevice device; 230 try { 231 device = BluetoothFacade.getDevice(sHfpClientProfile.getConnectedDevices(), deviceStr); 232 } catch (Exception e) { 233 // Do nothing since it is disconnect and this function should force disconnect. 234 Log.e("bluetoothHfpClientConnect getDevice failed " + e); 235 return -1; 236 } 237 return sHfpClientProfile.getAudioState(device); 238 } 239 240 /** 241 * Start Voice Recognition on remote device 242 * 243 * @param deviceStr the Bluetooth MAC address of remote device 244 * @return True if command was sent 245 */ 246 @Rpc(description = "Start Remote device Voice Recognition through HFP Client.") 247 public boolean bluetoothHfpClientStartVoiceRecognition( 248 @RpcParameter(name = "device", 249 description = "MAC address of a bluetooth device.") 250 String deviceStr) { 251 if (sHfpClientProfile == null) return false; 252 BluetoothDevice device; 253 try { 254 device = BluetoothFacade.getDevice( 255 sHfpClientProfile.getConnectedDevices(), deviceStr); 256 } catch (Exception e) { 257 // Do nothing since it is disconnect and this function should force disconnect. 258 Log.e("bluetoothHfpClientConnect getDevice failed " + e); 259 return false; 260 } 261 return sHfpClientProfile.startVoiceRecognition(device); 262 } 263 264 /** 265 * Stop Voice Recognition on remote device 266 * 267 * @param deviceStr the Bluetooth MAC address of remote device 268 * @return True if command was sent 269 */ 270 @Rpc(description = "Stop Remote device Voice Recognition through HFP Client.") 271 public boolean bluetoothHfpClientStopVoiceRecognition( 272 @RpcParameter(name = "device", 273 description = "MAC address of a bluetooth device.") 274 String deviceStr) { 275 if (sHfpClientProfile == null) return false; 276 BluetoothDevice device; 277 try { 278 device = BluetoothFacade.getDevice( 279 sHfpClientProfile.getConnectedDevices(), deviceStr); 280 } catch (Exception e) { 281 // Do nothing since it is disconnect 282 // and this function should force disconnect. 283 Log.e("bluetoothHfpClientConnect getDevice failed " + e); 284 return false; 285 } 286 return sHfpClientProfile.stopVoiceRecognition(device); 287 } 288 289 @Override 290 public void shutdown() { 291 } 292 } 293