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