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 java.util.List; 20 import java.util.ArrayList; 21 22 import android.app.Service; 23 import android.bluetooth.BluetoothA2dpSink; 24 import android.bluetooth.BluetoothAdapter; 25 import android.bluetooth.BluetoothDevice; 26 import android.bluetooth.BluetoothProfile; 27 import android.bluetooth.BluetoothUuid; 28 import android.os.ParcelUuid; 29 30 import com.googlecode.android_scripting.Log; 31 import com.googlecode.android_scripting.facade.FacadeManager; 32 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 33 import com.googlecode.android_scripting.rpc.Rpc; 34 import com.googlecode.android_scripting.rpc.RpcParameter; 35 36 public class BluetoothA2dpSinkFacade extends RpcReceiver { 37 static final ParcelUuid[] SOURCE_UUIDS = { 38 BluetoothUuid.AudioSource, 39 }; 40 41 private final Service mService; 42 private final BluetoothAdapter mBluetoothAdapter; 43 44 private static BluetoothA2dpSink sA2dpSinkProfile = null; 45 46 public BluetoothA2dpSinkFacade(FacadeManager manager) { 47 super(manager); 48 mService = manager.getService(); 49 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 50 mBluetoothAdapter.getProfileProxy(mService, new A2dpSinkServiceListener(), 51 BluetoothProfile.A2DP_SINK); 52 } 53 54 class A2dpSinkServiceListener implements BluetoothProfile.ServiceListener { 55 @Override 56 public void onServiceConnected(int profile, BluetoothProfile proxy) { 57 sA2dpSinkProfile = (BluetoothA2dpSink) proxy; 58 } 59 60 @Override 61 public void onServiceDisconnected(int profile) { 62 sA2dpSinkProfile = null; 63 } 64 } 65 66 public Boolean a2dpSinkConnect(BluetoothDevice device) { 67 if (sA2dpSinkProfile == null) return false; 68 return sA2dpSinkProfile.connect(device); 69 } 70 71 public Boolean a2dpSinkDisconnect(BluetoothDevice device) { 72 if (sA2dpSinkProfile == null) return false; 73 return sA2dpSinkProfile.disconnect(device); 74 } 75 76 @Rpc(description = "Set priority of the profile") 77 public void bluetoothA2dpSinkSetPriority( 78 @RpcParameter(name = "device", description = "Mac address of a BT device.") 79 String deviceStr, 80 @RpcParameter(name = "priority", description = "Priority that needs to be set.") 81 Integer priority) 82 throws Exception { 83 if (sA2dpSinkProfile == null) return; 84 BluetoothDevice device = 85 BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), deviceStr); 86 Log.d("Changing priority of device " + device.getAliasName() + " p: " + priority); 87 sA2dpSinkProfile.setPriority(device, priority); 88 } 89 90 @Rpc(description = "get priority of the profile") 91 public Integer bluetoothA2dpSinkGetPriority( 92 @RpcParameter(name = "device", description = "Mac address of a BT device.") 93 String deviceStr) 94 throws Exception { 95 if (sA2dpSinkProfile == null) return BluetoothProfile.PRIORITY_UNDEFINED; 96 BluetoothDevice device = 97 BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), deviceStr); 98 return sA2dpSinkProfile.getPriority(device); 99 } 100 101 @Rpc(description = "Is A2dpSink profile ready.") 102 public Boolean bluetoothA2dpSinkIsReady() { 103 return (sA2dpSinkProfile != null); 104 } 105 106 @Rpc(description = "Connect to an A2DP Sink device.") 107 public Boolean bluetoothA2dpSinkConnect( 108 @RpcParameter(name = "device", description = "Name or MAC address of a bluetooth device.") 109 String deviceStr) 110 throws Exception { 111 if (sA2dpSinkProfile == null) return false; 112 BluetoothDevice device = 113 BluetoothFacade.getDevice(BluetoothFacade.DiscoveredDevices, deviceStr); 114 Log.d("Connecting to device " + device.getAliasName()); 115 return a2dpSinkConnect(device); 116 } 117 118 @Rpc(description = "Disconnect an A2DP Sink device.") 119 public Boolean bluetoothA2dpSinkDisconnect( 120 @RpcParameter(name = "device", description = "Name or MAC address of a device.") 121 String deviceStr) { 122 if (sA2dpSinkProfile == null) return false; 123 Log.d("Connected devices: " + sA2dpSinkProfile.getConnectedDevices()); 124 BluetoothDevice device = null; 125 try { 126 device = BluetoothFacade.getDevice(sA2dpSinkProfile.getConnectedDevices(), deviceStr); 127 return a2dpSinkDisconnect(device); 128 } catch (Exception e) { 129 // Do nothing here. Since it is disconnect this function should force shutdown anyways. 130 Log.d("bluetoothA2dpSinkDisconnect error while getDevice " + e); 131 } 132 return false; 133 } 134 135 @Rpc(description = "Get all the devices connected through A2DP Sink.") 136 public List<BluetoothDevice> bluetoothA2dpSinkGetConnectedDevices() { 137 if (sA2dpSinkProfile == null) return new ArrayList<BluetoothDevice>(); 138 return sA2dpSinkProfile.getConnectedDevices(); 139 } 140 141 @Rpc(description = "Get the connection status of a device.") 142 public Integer bluetoothA2dpSinkGetConnectionStatus( 143 @RpcParameter(name = "deviceID", 144 description = "Name or MAC address of a bluetooth device.") 145 String deviceID) { 146 if (sA2dpSinkProfile == null) { 147 return BluetoothProfile.STATE_DISCONNECTED; 148 } 149 List<BluetoothDevice> deviceList = sA2dpSinkProfile.getConnectedDevices(); 150 BluetoothDevice device; 151 try { 152 device = BluetoothFacade.getDevice(deviceList, deviceID); 153 } catch (Exception e) { 154 Log.e(e); 155 return BluetoothProfile.STATE_DISCONNECTED; 156 } 157 return sA2dpSinkProfile.getConnectionState(device); 158 } 159 160 @Override 161 public void shutdown() { 162 } 163 } 164