1 /* 2 * Copyright (C) 2016 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.googlecode.android_scripting.facade.bluetooth; 18 19 import java.util.List; 20 21 import android.app.Service; 22 import android.bluetooth.BluetoothA2dp; 23 import android.bluetooth.BluetoothAdapter; 24 import android.bluetooth.BluetoothDevice; 25 import android.bluetooth.BluetoothProfile; 26 import android.bluetooth.BluetoothUuid; 27 import android.os.ParcelUuid; 28 29 import com.googlecode.android_scripting.Log; 30 import com.googlecode.android_scripting.facade.FacadeManager; 31 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 32 import com.googlecode.android_scripting.rpc.Rpc; 33 import com.googlecode.android_scripting.rpc.RpcParameter; 34 35 public class BluetoothA2dpFacade extends RpcReceiver { 36 static final ParcelUuid[] SINK_UUIDS = { 37 BluetoothUuid.AudioSink, BluetoothUuid.AdvAudioDist, 38 }; 39 private final Service mService; 40 private final BluetoothAdapter mBluetoothAdapter; 41 42 private static boolean sIsA2dpReady = false; 43 private static BluetoothA2dp sA2dpProfile = null; 44 BluetoothA2dpFacade(FacadeManager manager)45 public BluetoothA2dpFacade(FacadeManager manager) { 46 super(manager); 47 mService = manager.getService(); 48 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 49 mBluetoothAdapter.getProfileProxy(mService, new A2dpServiceListener(), 50 BluetoothProfile.A2DP); 51 } 52 53 class A2dpServiceListener implements BluetoothProfile.ServiceListener { 54 @Override onServiceConnected(int profile, BluetoothProfile proxy)55 public void onServiceConnected(int profile, BluetoothProfile proxy) { 56 sA2dpProfile = (BluetoothA2dp) proxy; 57 sIsA2dpReady = true; 58 } 59 60 @Override onServiceDisconnected(int profile)61 public void onServiceDisconnected(int profile) { 62 sIsA2dpReady = false; 63 } 64 } 65 a2dpConnect(BluetoothDevice device)66 public Boolean a2dpConnect(BluetoothDevice device) { 67 List<BluetoothDevice> sinks = sA2dpProfile.getConnectedDevices(); 68 if (sinks != null) { 69 for (BluetoothDevice sink : sinks) { 70 sA2dpProfile.disconnect(sink); 71 } 72 } 73 return sA2dpProfile.connect(device); 74 } 75 a2dpDisconnect(BluetoothDevice device)76 public Boolean a2dpDisconnect(BluetoothDevice device) { 77 if (sA2dpProfile == null) return false; 78 if (sA2dpProfile.getPriority(device) > BluetoothProfile.PRIORITY_ON) { 79 sA2dpProfile.setPriority(device, BluetoothProfile.PRIORITY_ON); 80 } 81 return sA2dpProfile.disconnect(device); 82 } 83 84 /** 85 * Checks to see if the A2DP profile is ready for use. 86 * 87 * @return Returns true if the A2DP Profile is ready. 88 */ 89 @Rpc(description = "Is A2dp profile ready.") bluetoothA2dpIsReady()90 public Boolean bluetoothA2dpIsReady() { 91 return sIsA2dpReady; 92 } 93 94 /** 95 * Connect to remote device using the A2DP profile. 96 * 97 * @param deviceId the name or mac address of the remote Bluetooth device. 98 * @return True if connected successfully. 99 * @throws Exception 100 */ 101 @Rpc(description = "Connect to an A2DP device.") bluetoothA2dpConnect( @pcParametername = "deviceID", description = "Name or MAC address of a bluetooth device.") String deviceID)102 public Boolean bluetoothA2dpConnect( 103 @RpcParameter(name = "deviceID", description = "Name or MAC address of a bluetooth device.") 104 String deviceID) 105 throws Exception { 106 if (sA2dpProfile == null) 107 return false; 108 BluetoothDevice mDevice = BluetoothFacade.getDevice( 109 BluetoothFacade.DiscoveredDevices, deviceID); 110 Log.d("Connecting to device " + mDevice.getAliasName()); 111 return a2dpConnect(mDevice); 112 } 113 114 /** 115 * Disconnect a remote device using the A2DP profile. 116 * 117 * @param deviceId the name or mac address of the remote Bluetooth device. 118 * @return True if connected successfully. 119 * @throws Exception 120 */ 121 @Rpc(description = "Disconnect an A2DP device.") bluetoothA2dpDisconnect( @pcParametername = "deviceID", description = "Name or MAC address of a device.") String deviceID)122 public Boolean bluetoothA2dpDisconnect( 123 @RpcParameter(name = "deviceID", description = "Name or MAC address of a device.") 124 String deviceID) 125 throws Exception { 126 if (sA2dpProfile == null) 127 return false; 128 List<BluetoothDevice> connectedA2dpDevices = sA2dpProfile.getConnectedDevices(); 129 Log.d("Connected a2dp devices " + connectedA2dpDevices); 130 BluetoothDevice mDevice = BluetoothFacade.getDevice(connectedA2dpDevices, deviceID); 131 return a2dpDisconnect(mDevice); 132 } 133 134 /** 135 * Get the list of devices connected through the A2DP profile. 136 * 137 * @return List of bluetooth devices that are in one of the following states: 138 * connected, connecting, and disconnecting. 139 */ 140 @Rpc(description = "Get all the devices connected through A2DP.") bluetoothA2dpGetConnectedDevices()141 public List<BluetoothDevice> bluetoothA2dpGetConnectedDevices() { 142 while (!sIsA2dpReady); 143 return sA2dpProfile.getDevicesMatchingConnectionStates( 144 new int[] {BluetoothProfile.STATE_CONNECTED, 145 BluetoothProfile.STATE_CONNECTING, 146 BluetoothProfile.STATE_DISCONNECTING}); 147 } 148 149 @Override shutdown()150 public void shutdown() { 151 } 152 } 153