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