A2dpService.java revision 33b6b7d2b08dcd7ced1809e2ac653c5e8c2514af
16c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie/* 2ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Copyright (C) 2012 The Android Open Source Project 3ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 4ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Licensed under the Apache License, Version 2.0 (the "License"); 5ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * you may not use this file except in compliance with the License. 6ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * You may obtain a copy of the License at 7ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 8ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * http://www.apache.org/licenses/LICENSE-2.0 9ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 10ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Unless required by applicable law or agreed to in writing, software 11ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * distributed under the License is distributed on an "AS IS" BASIS, 12ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * See the License for the specific language governing permissions and 14ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * limitations under the License. 156c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */ 16ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu 176c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiepackage com.android.bluetooth.a2dp; 186c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1933b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavovimport android.bluetooth.BluetoothCodecConfig; 206c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.bluetooth.BluetoothDevice; 216c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.bluetooth.BluetoothProfile; 22e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Guptaimport android.bluetooth.BluetoothUuid; 236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.bluetooth.IBluetoothA2dp; 24e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Guptaimport android.os.ParcelUuid; 256c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.provider.Settings; 266c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieimport android.util.Log; 27066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport com.android.bluetooth.avrcp.Avrcp; 2837510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport com.android.bluetooth.btservice.ProfileService; 2937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport com.android.bluetooth.Utils; 3074ae04c73312403e89db0f8e9bd9601d403b4783fredcimport java.util.ArrayList; 3137510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xuimport java.util.List; 3233b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavovimport java.util.Objects; 336c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 346c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie/** 356c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * Provides Bluetooth A2DP profile, as a service in the Bluetooth application. 366c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie * @hide 376c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */ 38b5cc776c9353a203cdde97e62b25f05d9633d14cfredcpublic class A2dpService extends ProfileService { 39fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie private static final boolean DBG = false; 40b5cc776c9353a203cdde97e62b25f05d9633d14cfredc private static final String TAG="A2dpService"; 416c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 426c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie private A2dpStateMachine mStateMachine; 43c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu private Avrcp mAvrcp; 444f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta private static A2dpService sAd2dpService; 45e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta static final ParcelUuid[] A2DP_SOURCE_UUID = { 46e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta BluetoothUuid.AudioSource 47e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta }; 48e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta static final ParcelUuid[] A2DP_SOURCE_SINK_UUIDS = { 49e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta BluetoothUuid.AudioSource, 50e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta BluetoothUuid.AudioSink 51e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta }; 526c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 5374ae04c73312403e89db0f8e9bd9601d403b4783fredc protected String getName() { 5474ae04c73312403e89db0f8e9bd9601d403b4783fredc return TAG; 5574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 5674ae04c73312403e89db0f8e9bd9601d403b4783fredc 5774ae04c73312403e89db0f8e9bd9601d403b4783fredc protected IProfileServiceBinder initBinder() { 5874ae04c73312403e89db0f8e9bd9601d403b4783fredc return new BluetoothA2dpBinder(this); 5974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 606c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 61b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected boolean start() { 62c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mAvrcp = Avrcp.make(this); 63188f205b5f093850d4cc627917a21204be36c56aZhihai Xu mStateMachine = A2dpStateMachine.make(this, this); 644f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta setA2dpService(this); 65b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return true; 666654f5c903de510a70f9e72cd5ad7837b615d93ffredc } 676654f5c903de510a70f9e72cd5ad7837b615d93ffredc 68b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected boolean stop() { 69ff833ce646e50c3593a313cd6a0be53577e41112Thomas Lehaux if (mStateMachine != null) { 70ff833ce646e50c3593a313cd6a0be53577e41112Thomas Lehaux mStateMachine.doQuit(); 71ff833ce646e50c3593a313cd6a0be53577e41112Thomas Lehaux } 722609a11670563837625f7dde2192deaba7417e46Andre Eisenbach if (mAvrcp != null) { 732609a11670563837625f7dde2192deaba7417e46Andre Eisenbach mAvrcp.doQuit(); 742609a11670563837625f7dde2192deaba7417e46Andre Eisenbach } 7574ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 7674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 7774ae04c73312403e89db0f8e9bd9601d403b4783fredc 7874ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean cleanup() { 796654f5c903de510a70f9e72cd5ad7837b615d93ffredc if (mStateMachine!= null) { 806654f5c903de510a70f9e72cd5ad7837b615d93ffredc mStateMachine.cleanup(); 816654f5c903de510a70f9e72cd5ad7837b615d93ffredc } 82c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu if (mAvrcp != null) { 83c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mAvrcp.cleanup(); 84c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu mAvrcp = null; 85c1c259c0ace7195240f1443c805995bfe8692a72Zhihai Xu } 864f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta clearA2dpService(); 87b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return true; 88b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 896654f5c903de510a70f9e72cd5ad7837b615d93ffredc 9074ae04c73312403e89db0f8e9bd9601d403b4783fredc //API Methods 914f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta 924f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta public static synchronized A2dpService getA2dpService(){ 934f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (sAd2dpService != null && sAd2dpService.isAvailable()) { 944f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (DBG) Log.d(TAG, "getA2DPService(): returning " + sAd2dpService); 954f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta return sAd2dpService; 964f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 974f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (DBG) { 984f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (sAd2dpService == null) { 994f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta Log.d(TAG, "getA2dpService(): service is NULL"); 1004f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } else if (!(sAd2dpService.isAvailable())) { 1014f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta Log.d(TAG,"getA2dpService(): service is not available"); 1024f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1034f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1044f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta return null; 1054f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1064f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta 1074f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta private static synchronized void setA2dpService(A2dpService instance) { 1084f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (instance != null && instance.isAvailable()) { 1094f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (DBG) Log.d(TAG, "setA2dpService(): set to: " + sAd2dpService); 1104f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta sAd2dpService = instance; 1114f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } else { 1124f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (DBG) { 1134f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta if (sAd2dpService == null) { 1144f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta Log.d(TAG, "setA2dpService(): service not available"); 1154f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } else if (!sAd2dpService.isAvailable()) { 1164f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta Log.d(TAG,"setA2dpService(): service is cleaning up"); 1174f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1184f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1194f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1204f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1214f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta 1224f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta private static synchronized void clearA2dpService() { 1234f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta sAd2dpService = null; 1244f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta } 1254f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta 1264f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta public boolean connect(BluetoothDevice device) { 12774ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 12874ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH ADMIN permission"); 12974ae04c73312403e89db0f8e9bd9601d403b4783fredc 13074ae04c73312403e89db0f8e9bd9601d403b4783fredc if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { 13174ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 13274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 133e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta ParcelUuid[] featureUuids = device.getUuids(); 134e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta if ((BluetoothUuid.containsAnyUuid(featureUuids, A2DP_SOURCE_UUID)) && 135e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta !(BluetoothUuid.containsAllUuids(featureUuids ,A2DP_SOURCE_SINK_UUIDS))) { 136e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta Log.e(TAG,"Remote does not have A2dp Sink UUID"); 137e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta return false; 138e316dfc9b3f648ad3d7b2691927758ea885043c0Anubhav Gupta } 13974ae04c73312403e89db0f8e9bd9601d403b4783fredc 14074ae04c73312403e89db0f8e9bd9601d403b4783fredc int connectionState = mStateMachine.getConnectionState(device); 14174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (connectionState == BluetoothProfile.STATE_CONNECTED || 14274ae04c73312403e89db0f8e9bd9601d403b4783fredc connectionState == BluetoothProfile.STATE_CONNECTING) { 14374ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 14474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 14574ae04c73312403e89db0f8e9bd9601d403b4783fredc 14674ae04c73312403e89db0f8e9bd9601d403b4783fredc mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device); 14774ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 148b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 149b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 15074ae04c73312403e89db0f8e9bd9601d403b4783fredc boolean disconnect(BluetoothDevice device) { 15174ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 15274ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH ADMIN permission"); 15374ae04c73312403e89db0f8e9bd9601d403b4783fredc int connectionState = mStateMachine.getConnectionState(device); 15474ae04c73312403e89db0f8e9bd9601d403b4783fredc if (connectionState != BluetoothProfile.STATE_CONNECTED && 15574ae04c73312403e89db0f8e9bd9601d403b4783fredc connectionState != BluetoothProfile.STATE_CONNECTING) { 15674ae04c73312403e89db0f8e9bd9601d403b4783fredc return false; 15774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 15874ae04c73312403e89db0f8e9bd9601d403b4783fredc 15974ae04c73312403e89db0f8e9bd9601d403b4783fredc mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device); 16074ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 1616c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 1626c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1634f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta public List<BluetoothDevice> getConnectedDevices() { 16474ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 16574ae04c73312403e89db0f8e9bd9601d403b4783fredc return mStateMachine.getConnectedDevices(); 16674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 1676c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 16874ae04c73312403e89db0f8e9bd9601d403b4783fredc List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 16974ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 17074ae04c73312403e89db0f8e9bd9601d403b4783fredc return mStateMachine.getDevicesMatchingConnectionStates(states); 17174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 1726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 17374ae04c73312403e89db0f8e9bd9601d403b4783fredc int getConnectionState(BluetoothDevice device) { 17474ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 17574ae04c73312403e89db0f8e9bd9601d403b4783fredc return mStateMachine.getConnectionState(device); 17674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 17774ae04c73312403e89db0f8e9bd9601d403b4783fredc 1784f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta public boolean setPriority(BluetoothDevice device, int priority) { 17974ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 18074ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 181c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey Settings.Global.putInt(getContentResolver(), 182c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey Settings.Global.getBluetoothA2dpSinkPriorityKey(device.getAddress()), 18374ae04c73312403e89db0f8e9bd9601d403b4783fredc priority); 18474ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority); 18574ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 18674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 1876c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 1884f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta public int getPriority(BluetoothDevice device) { 18974ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 19074ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH_ADMIN permission"); 191c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey int priority = Settings.Global.getInt(getContentResolver(), 192c7ead6d5827f3832b9210e92fab7597142059852Jeff Sharkey Settings.Global.getBluetoothA2dpSinkPriorityKey(device.getAddress()), 19374ae04c73312403e89db0f8e9bd9601d403b4783fredc BluetoothProfile.PRIORITY_UNDEFINED); 19474ae04c73312403e89db0f8e9bd9601d403b4783fredc return priority; 19574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 19674ae04c73312403e89db0f8e9bd9601d403b4783fredc 19717675906064bb72fdcca75baa56cdf8bb8968d01John Du /* Absolute volume implementation */ 19817675906064bb72fdcca75baa56cdf8bb8968d01John Du public boolean isAvrcpAbsoluteVolumeSupported() { 19917675906064bb72fdcca75baa56cdf8bb8968d01John Du return mAvrcp.isAbsoluteVolumeSupported(); 20017675906064bb72fdcca75baa56cdf8bb8968d01John Du } 20117675906064bb72fdcca75baa56cdf8bb8968d01John Du 20217675906064bb72fdcca75baa56cdf8bb8968d01John Du public void adjustAvrcpAbsoluteVolume(int direction) { 20317675906064bb72fdcca75baa56cdf8bb8968d01John Du mAvrcp.adjustVolume(direction); 20417675906064bb72fdcca75baa56cdf8bb8968d01John Du } 20517675906064bb72fdcca75baa56cdf8bb8968d01John Du 20617675906064bb72fdcca75baa56cdf8bb8968d01John Du public void setAvrcpAbsoluteVolume(int volume) { 20717675906064bb72fdcca75baa56cdf8bb8968d01John Du mAvrcp.setAbsoluteVolume(volume); 20817675906064bb72fdcca75baa56cdf8bb8968d01John Du } 20917675906064bb72fdcca75baa56cdf8bb8968d01John Du 210188f205b5f093850d4cc627917a21204be36c56aZhihai Xu public void setAvrcpAudioState(int state) { 211188f205b5f093850d4cc627917a21204be36c56aZhihai Xu mAvrcp.setA2dpAudioState(state); 212188f205b5f093850d4cc627917a21204be36c56aZhihai Xu } 213188f205b5f093850d4cc627917a21204be36c56aZhihai Xu 21411798b011c962b602217b479130d413f3b30f19aLiejun Tao public void resetAvrcpBlacklist(BluetoothDevice device) { 215ff495eca3027c9b3aa7d8ef4e9cfd2cde3bbb664Pavlin Radoslavov if (mAvrcp != null) { 216ff495eca3027c9b3aa7d8ef4e9cfd2cde3bbb664Pavlin Radoslavov mAvrcp.resetBlackList(device.getAddress()); 217ff495eca3027c9b3aa7d8ef4e9cfd2cde3bbb664Pavlin Radoslavov } 21811798b011c962b602217b479130d413f3b30f19aLiejun Tao } 21911798b011c962b602217b479130d413f3b30f19aLiejun Tao 22074ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized boolean isA2dpPlaying(BluetoothDevice device) { 22174ae04c73312403e89db0f8e9bd9601d403b4783fredc enforceCallingOrSelfPermission(BLUETOOTH_PERM, 22274ae04c73312403e89db0f8e9bd9601d403b4783fredc "Need BLUETOOTH permission"); 22374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) Log.d(TAG, "isA2dpPlaying(" + device + ")"); 22474ae04c73312403e89db0f8e9bd9601d403b4783fredc return mStateMachine.isPlaying(device); 22574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 22674ae04c73312403e89db0f8e9bd9601d403b4783fredc 22733b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov public BluetoothCodecConfig getCodecConfig() { 22833b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 22933b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov if (DBG) Log.d(TAG, "getCodecConfig()"); 23033b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov return mStateMachine.getCodecConfig(); 23133b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov } 23233b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov 23333b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov public void setCodecConfigPreference(BluetoothCodecConfig codecConfig) { 23433b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 23533b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov if (DBG) Log.d(TAG, "setCodecConfigPreference(): " + Objects.toString(codecConfig)); 23633b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov mStateMachine.setCodecConfigPreference(codecConfig); 23733b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov } 23833b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov 23974ae04c73312403e89db0f8e9bd9601d403b4783fredc //Binder object: Must be static class or memory leak may occur 24074ae04c73312403e89db0f8e9bd9601d403b4783fredc private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub 24174ae04c73312403e89db0f8e9bd9601d403b4783fredc implements IProfileServiceBinder { 24274ae04c73312403e89db0f8e9bd9601d403b4783fredc private A2dpService mService; 24374ae04c73312403e89db0f8e9bd9601d403b4783fredc 24474ae04c73312403e89db0f8e9bd9601d403b4783fredc private A2dpService getService() { 24537510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu if (!Utils.checkCaller()) { 24637510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu Log.w(TAG,"A2dp call not allowed for non-active user"); 24737510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu return null; 24837510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu } 24937510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu 25037510150ee738ccfa5913f7120e28f25ae7768dfZhihai Xu if (mService != null && mService.isAvailable()) { 25174ae04c73312403e89db0f8e9bd9601d403b4783fredc return mService; 2526c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 25374ae04c73312403e89db0f8e9bd9601d403b4783fredc return null; 25474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 2556c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 25674ae04c73312403e89db0f8e9bd9601d403b4783fredc BluetoothA2dpBinder(A2dpService svc) { 25774ae04c73312403e89db0f8e9bd9601d403b4783fredc mService = svc; 25874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 25974ae04c73312403e89db0f8e9bd9601d403b4783fredc 26074ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean cleanup() { 26174ae04c73312403e89db0f8e9bd9601d403b4783fredc mService = null; 2626c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie return true; 2636c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 2646c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 26574ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean connect(BluetoothDevice device) { 26674ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 26774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 26874ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.connect(device); 26974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 2706c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 27174ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean disconnect(BluetoothDevice device) { 27274ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 27374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 27474ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.disconnect(device); 2756c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 2766c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 2776c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public List<BluetoothDevice> getConnectedDevices() { 27874ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 27974ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return new ArrayList<BluetoothDevice>(0); 28074ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getConnectedDevices(); 2816c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 2826c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 2836c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 28474ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 28574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return new ArrayList<BluetoothDevice>(0); 28674ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getDevicesMatchingConnectionStates(states); 2876c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 2886c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 2896c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public int getConnectionState(BluetoothDevice device) { 29074ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 29174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 29274ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getConnectionState(device); 2936c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 2946c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 2956c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public boolean setPriority(BluetoothDevice device, int priority) { 29674ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 29774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 29874ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.setPriority(device, priority); 2996c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 3006c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 3016c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie public int getPriority(BluetoothDevice device) { 30274ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 30374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED; 30474ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.getPriority(device); 3056c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 3066c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie 30717675906064bb72fdcca75baa56cdf8bb8968d01John Du public boolean isAvrcpAbsoluteVolumeSupported() { 30817675906064bb72fdcca75baa56cdf8bb8968d01John Du A2dpService service = getService(); 30917675906064bb72fdcca75baa56cdf8bb8968d01John Du if (service == null) return false; 31017675906064bb72fdcca75baa56cdf8bb8968d01John Du return service.isAvrcpAbsoluteVolumeSupported(); 31117675906064bb72fdcca75baa56cdf8bb8968d01John Du } 31217675906064bb72fdcca75baa56cdf8bb8968d01John Du 31317675906064bb72fdcca75baa56cdf8bb8968d01John Du public void adjustAvrcpAbsoluteVolume(int direction) { 31417675906064bb72fdcca75baa56cdf8bb8968d01John Du A2dpService service = getService(); 31517675906064bb72fdcca75baa56cdf8bb8968d01John Du if (service == null) return; 31617675906064bb72fdcca75baa56cdf8bb8968d01John Du service.adjustAvrcpAbsoluteVolume(direction); 31717675906064bb72fdcca75baa56cdf8bb8968d01John Du } 31817675906064bb72fdcca75baa56cdf8bb8968d01John Du 31917675906064bb72fdcca75baa56cdf8bb8968d01John Du public void setAvrcpAbsoluteVolume(int volume) { 32017675906064bb72fdcca75baa56cdf8bb8968d01John Du A2dpService service = getService(); 32117675906064bb72fdcca75baa56cdf8bb8968d01John Du if (service == null) return; 32217675906064bb72fdcca75baa56cdf8bb8968d01John Du service.setAvrcpAbsoluteVolume(volume); 32317675906064bb72fdcca75baa56cdf8bb8968d01John Du } 32417675906064bb72fdcca75baa56cdf8bb8968d01John Du 32574ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean isA2dpPlaying(BluetoothDevice device) { 32674ae04c73312403e89db0f8e9bd9601d403b4783fredc A2dpService service = getService(); 32774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (service == null) return false; 32874ae04c73312403e89db0f8e9bd9601d403b4783fredc return service.isA2dpPlaying(device); 3296c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie } 33033b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov 33133b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov public BluetoothCodecConfig getCodecConfig() { 33233b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov A2dpService service = getService(); 33333b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov if (service == null) return null; 33433b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov return service.getCodecConfig(); 33533b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov } 33633b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov 33733b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov public void setCodecConfigPreference(BluetoothCodecConfig codecConfig) { 33833b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov A2dpService service = getService(); 33933b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov if (service == null) return; 34033b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov service.setCodecConfigPreference(codecConfig); 34133b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov } 3426c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie }; 343838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 344838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood @Override 345838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood public void dump(StringBuilder sb) { 346838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood super.dump(sb); 347838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood if (mStateMachine != null) { 348838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood mStateMachine.dump(sb); 349838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 350838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood if (mAvrcp != null) { 351838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood mAvrcp.dump(sb); 352838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 353838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 3546c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie} 355