A2dpService.java revision 15d36984a79d6e35c659edb0efdf929f0b526bd5
16c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie/* 26c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * Copyright (C) 2012 Google Inc. 36c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */ 46c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiepackage com.android.bluetooth.a2dp; 56c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 66c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.bluetooth.BluetoothDevice; 76c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.bluetooth.BluetoothProfile; 86c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.bluetooth.IBluetoothA2dp; 96c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.content.Context; 106c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.content.Intent; 116c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.provider.Settings; 126c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.util.Log; 1374ae04c73312403e89db0f8e9bd9601d403b4783fredcimport java.util.ArrayList; 146c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport java.util.List; 156654f5c903de510a70f9e72cd5ad7837b615d93ffredcimport java.util.Iterator; 166654f5c903de510a70f9e72cd5ad7837b615d93ffredcimport java.util.Map; 17b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport com.android.bluetooth.btservice.ProfileService; 186c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 196c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie/** 206c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * Provides Bluetooth A2DP profile, as a service in the Bluetooth application. 216c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * @hide 226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */ 23b5cc776c9353a203cdde97e62b25f05d9633d14cfredcpublic class A2dpService extends ProfileService { 246c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private static final boolean DBG = true; 25b5cc776c9353a203cdde97e62b25f05d9633d14cfredc private static final String TAG="A2dpService"; 266c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private A2dpStateMachine mStateMachine; 286c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 2974ae04c73312403e89db0f8e9bd9601d403b4783fredc protected String getName() { 3074ae04c73312403e89db0f8e9bd9601d403b4783fredc return TAG; 3174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 3274ae04c73312403e89db0f8e9bd9601d403b4783fredc 3374ae04c73312403e89db0f8e9bd9601d403b4783fredc protected IProfileServiceBinder initBinder() { 3474ae04c73312403e89db0f8e9bd9601d403b4783fredc return new BluetoothA2dpBinder(this); 3574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 366c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 37b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected boolean start() { 3874ae04c73312403e89db0f8e9bd9601d403b4783fredc mStateMachine = new A2dpStateMachine(this,this); 396654f5c903de510a70f9e72cd5ad7837b615d93ffredc mStateMachine.start(); 40b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return true; 416654f5c903de510a70f9e72cd5ad7837b615d93ffredc } 426654f5c903de510a70f9e72cd5ad7837b615d93ffredc 43b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected boolean stop() { 4415d36984a79d6e35c659edb0efdf929f0b526bd5Fred mStateMachine.doQuit(); 4574ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 4674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 4774ae04c73312403e89db0f8e9bd9601d403b4783fredc 4874ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean cleanup() { 496654f5c903de510a70f9e72cd5ad7837b615d93ffredc if (mStateMachine!= null) { 506654f5c903de510a70f9e72cd5ad7837b615d93ffredc mStateMachine.cleanup(); 516654f5c903de510a70f9e72cd5ad7837b615d93ffredc } 52b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return true; 53b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 546654f5c903de510a70f9e72cd5ad7837b615d93ffredc 5574ae04c73312403e89db0f8e9bd9601d403b4783fredc //API Methods 5674ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean connect(BluetoothDevice device) { 5774ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 5874ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH ADMIN permission"); 5974ae04c73312403e89db0f8e9bd9601d403b4783fredc 6074ae04c73312403e89db0f8e9bd9601d403b4783fredc if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { 6174ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 6274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 6374ae04c73312403e89db0f8e9bd9601d403b4783fredc 6474ae04c73312403e89db0f8e9bd9601d403b4783fredc int connectionState = mStateMachine.getConnectionState(device); 6574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (connectionState == BluetoothProfile.STATE_CONNECTED || 6674ae04c73312403e89db0f8e9bd9601d403b4783fredc connectionState == BluetoothProfile.STATE_CONNECTING) { 6774ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 6874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 6974ae04c73312403e89db0f8e9bd9601d403b4783fredc 7074ae04c73312403e89db0f8e9bd9601d403b4783fredc mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device); 7174ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 72b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 73b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 7474ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean disconnect(BluetoothDevice device) { 7574ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 7674ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH ADMIN permission"); 7774ae04c73312403e89db0f8e9bd9601d403b4783fredc int connectionState = mStateMachine.getConnectionState(device); 7874ae04c73312403e89db0f8e9bd9601d403b4783fredc if (connectionState != BluetoothProfile.STATE_CONNECTED && 7974ae04c73312403e89db0f8e9bd9601d403b4783fredc connectionState != BluetoothProfile.STATE_CONNECTING) { 8074ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 8174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 8274ae04c73312403e89db0f8e9bd9601d403b4783fredc 8374ae04c73312403e89db0f8e9bd9601d403b4783fredc mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device); 8474ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 856c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 866c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 8774ae04c73312403e89db0f8e9bd9601d403b4783fredc List<BluetoothDevice> getConnectedDevices() { 8874ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 8974ae04c73312403e89db0f8e9bd9601d403b4783fredc return mStateMachine.getConnectedDevices(); 9074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 916c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 9274ae04c73312403e89db0f8e9bd9601d403b4783fredc List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 9374ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9474ae04c73312403e89db0f8e9bd9601d403b4783fredc return mStateMachine.getDevicesMatchingConnectionStates(states); 9574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 966c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 9774ae04c73312403e89db0f8e9bd9601d403b4783fredc int getConnectionState(BluetoothDevice device) { 9874ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 9974ae04c73312403e89db0f8e9bd9601d403b4783fredc return mStateMachine.getConnectionState(device); 10074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 10174ae04c73312403e89db0f8e9bd9601d403b4783fredc 10274ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean setPriority(BluetoothDevice device, int priority) { 10374ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 10474ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 10574ae04c73312403e89db0f8e9bd9601d403b4783fredc Settings.Secure.putInt(getContentResolver(), 10674ae04c73312403e89db0f8e9bd9601d403b4783fredc Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()), 10774ae04c73312403e89db0f8e9bd9601d403b4783fredc priority); 10874ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority); 10974ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 11074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 1116c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 11274ae04c73312403e89db0f8e9bd9601d403b4783fredc int getPriority(BluetoothDevice device) { 11374ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 11474ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 11574ae04c73312403e89db0f8e9bd9601d403b4783fredc int priority = Settings.Secure.getInt(getContentResolver(), 11674ae04c73312403e89db0f8e9bd9601d403b4783fredc Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()), 11774ae04c73312403e89db0f8e9bd9601d403b4783fredc BluetoothProfile.PRIORITY_UNDEFINED); 11874ae04c73312403e89db0f8e9bd9601d403b4783fredc return priority; 11974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 12074ae04c73312403e89db0f8e9bd9601d403b4783fredc 12174ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized boolean isA2dpPlaying(BluetoothDevice device) { 12274ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, 12374ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH permission"); 12474ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) Log.d(TAG, "isA2dpPlaying(" + device + ")"); 12574ae04c73312403e89db0f8e9bd9601d403b4783fredc return mStateMachine.isPlaying(device); 12674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 12774ae04c73312403e89db0f8e9bd9601d403b4783fredc 12874ae04c73312403e89db0f8e9bd9601d403b4783fredc //Binder object: Must be static class or memory leak may occur 12974ae04c73312403e89db0f8e9bd9601d403b4783fredc private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub 13074ae04c73312403e89db0f8e9bd9601d403b4783fredc implements IProfileServiceBinder { 13174ae04c73312403e89db0f8e9bd9601d403b4783fredc private A2dpService mService; 13274ae04c73312403e89db0f8e9bd9601d403b4783fredc 13374ae04c73312403e89db0f8e9bd9601d403b4783fredc private A2dpService getService() { 13474ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mService != null && mService.isAvailable()) { 13574ae04c73312403e89db0f8e9bd9601d403b4783fredc return mService; 1366c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 13774ae04c73312403e89db0f8e9bd9601d403b4783fredc return null; 13874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 1396c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 14074ae04c73312403e89db0f8e9bd9601d403b4783fredc BluetoothA2dpBinder(A2dpService svc) { 14174ae04c73312403e89db0f8e9bd9601d403b4783fredc mService = svc; 14274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 14374ae04c73312403e89db0f8e9bd9601d403b4783fredc 14474ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean cleanup() { 14574ae04c73312403e89db0f8e9bd9601d403b4783fredc mService = null; 1466c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return true; 1476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 14974ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean connect(BluetoothDevice device) { 15074ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 15174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 15274ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.connect(device); 15374ae04c73312403e89db0f8e9bd9601d403b4783fredc } 1546c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 15574ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean disconnect(BluetoothDevice device) { 15674ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 15774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 15874ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.disconnect(device); 1596c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1606c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1616c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public List<BluetoothDevice> getConnectedDevices() { 16274ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 16374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return new ArrayList<BluetoothDevice>(0); 16474ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getConnectedDevices(); 1656c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1666c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1676c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 16874ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 16974ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return new ArrayList<BluetoothDevice>(0); 17074ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getDevicesMatchingConnectionStates(states); 1716c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1736c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public int getConnectionState(BluetoothDevice device) { 17474ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 17574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 17674ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getConnectionState(device); 1776c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1786c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1796c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public boolean setPriority(BluetoothDevice device, int priority) { 18074ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 18174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 18274ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.setPriority(device, priority); 1836c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1846c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1856c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public int getPriority(BluetoothDevice device) { 18674ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 18774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED; 18874ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getPriority(device); 1896c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1906c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 19174ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean isA2dpPlaying(BluetoothDevice device) { 19274ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 19374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 19474ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.isA2dpPlaying(device); 1956c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1966c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie }; 1976c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie} 198