A2dpService.java revision 4f5430babbc5a8f870e5a578a4ea3452f41dd97a
1/*
2 * Copyright (C) 2012 Google Inc.
3 */
4package com.android.bluetooth.a2dp;
5
6import android.bluetooth.BluetoothDevice;
7import android.bluetooth.BluetoothProfile;
8import android.bluetooth.IBluetoothA2dp;
9import android.content.Context;
10import android.content.Intent;
11import android.provider.Settings;
12import android.util.Log;
13import java.util.ArrayList;
14import java.util.List;
15import java.util.Iterator;
16import java.util.Map;
17import com.android.bluetooth.btservice.ProfileService;
18
19/**
20 * Provides Bluetooth A2DP profile, as a service in the Bluetooth application.
21 * @hide
22 */
23public class A2dpService extends ProfileService {
24    private static final boolean DBG = true;
25    private static final String TAG="A2dpService";
26
27    private A2dpStateMachine mStateMachine;
28    private static A2dpService sAd2dpService;
29
30    protected String getName() {
31        return TAG;
32    }
33
34    protected IProfileServiceBinder initBinder() {
35        return new BluetoothA2dpBinder(this);
36    }
37
38    protected boolean start() {
39        mStateMachine = new A2dpStateMachine(this,this);
40        mStateMachine.start();
41        setA2dpService(this);
42        return true;
43    }
44
45    protected boolean stop() {
46        // TODO(BT) mStateMachine.quit();
47        return true;
48    }
49
50    protected boolean cleanup() {
51        if (mStateMachine!= null) {
52            mStateMachine.cleanup();
53            mStateMachine=null;
54        }
55        clearA2dpService();
56        return true;
57    }
58
59    //API Methods
60
61    public static synchronized A2dpService getA2dpService(){
62        if (sAd2dpService != null && sAd2dpService.isAvailable()) {
63            if (DBG) Log.d(TAG, "getA2DPService(): returning " + sAd2dpService);
64            return sAd2dpService;
65        }
66        if (DBG)  {
67            if (sAd2dpService == null) {
68                Log.d(TAG, "getA2dpService(): service is NULL");
69            } else if (!(sAd2dpService.isAvailable())) {
70                Log.d(TAG,"getA2dpService(): service is not available");
71            }
72        }
73        return null;
74    }
75
76    private static synchronized void setA2dpService(A2dpService instance) {
77        if (instance != null && instance.isAvailable()) {
78            if (DBG) Log.d(TAG, "setA2dpService(): set to: " + sAd2dpService);
79            sAd2dpService = instance;
80        } else {
81            if (DBG)  {
82                if (sAd2dpService == null) {
83                    Log.d(TAG, "setA2dpService(): service not available");
84                } else if (!sAd2dpService.isAvailable()) {
85                    Log.d(TAG,"setA2dpService(): service is cleaning up");
86                }
87            }
88        }
89    }
90
91    private static synchronized void clearA2dpService() {
92        sAd2dpService = null;
93    }
94
95    public boolean connect(BluetoothDevice device) {
96        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
97                                       "Need BLUETOOTH ADMIN permission");
98
99        if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
100            return false;
101        }
102
103        int connectionState = mStateMachine.getConnectionState(device);
104        if (connectionState == BluetoothProfile.STATE_CONNECTED ||
105            connectionState == BluetoothProfile.STATE_CONNECTING) {
106            return false;
107        }
108
109        mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
110        return true;
111    }
112
113    boolean disconnect(BluetoothDevice device) {
114        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
115                                       "Need BLUETOOTH ADMIN permission");
116        int connectionState = mStateMachine.getConnectionState(device);
117        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
118            connectionState != BluetoothProfile.STATE_CONNECTING) {
119            return false;
120        }
121
122        mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device);
123        return true;
124    }
125
126    public List<BluetoothDevice> getConnectedDevices() {
127        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
128        return mStateMachine.getConnectedDevices();
129    }
130
131    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
132        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
133        return mStateMachine.getDevicesMatchingConnectionStates(states);
134    }
135
136    int getConnectionState(BluetoothDevice device) {
137        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
138        return mStateMachine.getConnectionState(device);
139    }
140
141    public boolean setPriority(BluetoothDevice device, int priority) {
142        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
143                                       "Need BLUETOOTH_ADMIN permission");
144        Settings.Secure.putInt(getContentResolver(),
145            Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
146            priority);
147        if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority);
148        return true;
149    }
150
151    public int getPriority(BluetoothDevice device) {
152        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
153                                       "Need BLUETOOTH_ADMIN permission");
154        int priority = Settings.Secure.getInt(getContentResolver(),
155            Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
156            BluetoothProfile.PRIORITY_UNDEFINED);
157        return priority;
158    }
159
160    synchronized boolean isA2dpPlaying(BluetoothDevice device) {
161        enforceCallingOrSelfPermission(BLUETOOTH_PERM,
162                                       "Need BLUETOOTH permission");
163        if (DBG) Log.d(TAG, "isA2dpPlaying(" + device + ")");
164        return mStateMachine.isPlaying(device);
165    }
166
167    //Binder object: Must be static class or memory leak may occur
168    private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub
169        implements IProfileServiceBinder {
170        private A2dpService mService;
171
172        private A2dpService getService() {
173            if (mService  != null && mService.isAvailable()) {
174                return mService;
175            }
176            return null;
177        }
178
179        BluetoothA2dpBinder(A2dpService svc) {
180            mService = svc;
181        }
182
183        public boolean cleanup()  {
184            mService = null;
185            return true;
186        }
187
188        public boolean connect(BluetoothDevice device) {
189            A2dpService service = getService();
190            if (service == null) return false;
191            return service.connect(device);
192        }
193
194        public boolean disconnect(BluetoothDevice device) {
195            A2dpService service = getService();
196            if (service == null) return false;
197            return service.disconnect(device);
198        }
199
200        public List<BluetoothDevice> getConnectedDevices() {
201            A2dpService service = getService();
202            if (service == null) return new ArrayList<BluetoothDevice>(0);
203            return service.getConnectedDevices();
204        }
205
206        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
207            A2dpService service = getService();
208            if (service == null) return new ArrayList<BluetoothDevice>(0);
209            return service.getDevicesMatchingConnectionStates(states);
210        }
211
212        public int getConnectionState(BluetoothDevice device) {
213            A2dpService service = getService();
214            if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
215            return service.getConnectionState(device);
216        }
217
218        public boolean setPriority(BluetoothDevice device, int priority) {
219            A2dpService service = getService();
220            if (service == null) return false;
221            return service.setPriority(device, priority);
222        }
223
224        public int getPriority(BluetoothDevice device) {
225            A2dpService service = getService();
226            if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED;
227            return service.getPriority(device);
228        }
229
230        public boolean isA2dpPlaying(BluetoothDevice device) {
231            A2dpService service = getService();
232            if (service == null) return false;
233            return service.isA2dpPlaying(device);
234        }
235    };
236}
237