• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.a2dp;
18 
19 import android.bluetooth.BluetoothDevice;
20 import android.bluetooth.BluetoothProfile;
21 import android.bluetooth.IBluetoothA2dp;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.provider.Settings;
25 import android.util.Log;
26 import com.android.bluetooth.btservice.ProfileService;
27 import com.android.bluetooth.Utils;
28 import java.util.ArrayList;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 
33 /**
34  * Provides Bluetooth A2DP profile, as a service in the Bluetooth application.
35  * @hide
36  */
37 public class A2dpService extends ProfileService {
38     private static final boolean DBG = false;
39     private static final String TAG="A2dpService";
40 
41     private A2dpStateMachine mStateMachine;
42     private Avrcp mAvrcp;
43     private static A2dpService sAd2dpService;
44 
getName()45     protected String getName() {
46         return TAG;
47     }
48 
initBinder()49     protected IProfileServiceBinder initBinder() {
50         return new BluetoothA2dpBinder(this);
51     }
52 
start()53     protected boolean start() {
54         mAvrcp = Avrcp.make(this);
55         mStateMachine = A2dpStateMachine.make(this, this);
56         setA2dpService(this);
57         return true;
58     }
59 
stop()60     protected boolean stop() {
61         mStateMachine.doQuit();
62         mAvrcp.doQuit();
63         return true;
64     }
65 
cleanup()66     protected boolean cleanup() {
67         if (mStateMachine!= null) {
68             mStateMachine.cleanup();
69         }
70         if (mAvrcp != null) {
71             mAvrcp.cleanup();
72             mAvrcp = null;
73         }
74         clearA2dpService();
75         return true;
76     }
77 
78     //API Methods
79 
getA2dpService()80     public static synchronized A2dpService getA2dpService(){
81         if (sAd2dpService != null && sAd2dpService.isAvailable()) {
82             if (DBG) Log.d(TAG, "getA2DPService(): returning " + sAd2dpService);
83             return sAd2dpService;
84         }
85         if (DBG)  {
86             if (sAd2dpService == null) {
87                 Log.d(TAG, "getA2dpService(): service is NULL");
88             } else if (!(sAd2dpService.isAvailable())) {
89                 Log.d(TAG,"getA2dpService(): service is not available");
90             }
91         }
92         return null;
93     }
94 
setA2dpService(A2dpService instance)95     private static synchronized void setA2dpService(A2dpService instance) {
96         if (instance != null && instance.isAvailable()) {
97             if (DBG) Log.d(TAG, "setA2dpService(): set to: " + sAd2dpService);
98             sAd2dpService = instance;
99         } else {
100             if (DBG)  {
101                 if (sAd2dpService == null) {
102                     Log.d(TAG, "setA2dpService(): service not available");
103                 } else if (!sAd2dpService.isAvailable()) {
104                     Log.d(TAG,"setA2dpService(): service is cleaning up");
105                 }
106             }
107         }
108     }
109 
clearA2dpService()110     private static synchronized void clearA2dpService() {
111         sAd2dpService = null;
112     }
113 
connect(BluetoothDevice device)114     public boolean connect(BluetoothDevice device) {
115         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
116                                        "Need BLUETOOTH ADMIN permission");
117 
118         if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
119             return false;
120         }
121 
122         int connectionState = mStateMachine.getConnectionState(device);
123         if (connectionState == BluetoothProfile.STATE_CONNECTED ||
124             connectionState == BluetoothProfile.STATE_CONNECTING) {
125             return false;
126         }
127 
128         mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
129         return true;
130     }
131 
disconnect(BluetoothDevice device)132     boolean disconnect(BluetoothDevice device) {
133         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
134                                        "Need BLUETOOTH ADMIN permission");
135         int connectionState = mStateMachine.getConnectionState(device);
136         if (connectionState != BluetoothProfile.STATE_CONNECTED &&
137             connectionState != BluetoothProfile.STATE_CONNECTING) {
138             return false;
139         }
140 
141         mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device);
142         return true;
143     }
144 
getConnectedDevices()145     public List<BluetoothDevice> getConnectedDevices() {
146         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
147         return mStateMachine.getConnectedDevices();
148     }
149 
getDevicesMatchingConnectionStates(int[] states)150     List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
151         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
152         return mStateMachine.getDevicesMatchingConnectionStates(states);
153     }
154 
getConnectionState(BluetoothDevice device)155     int getConnectionState(BluetoothDevice device) {
156         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
157         return mStateMachine.getConnectionState(device);
158     }
159 
setPriority(BluetoothDevice device, int priority)160     public boolean setPriority(BluetoothDevice device, int priority) {
161         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
162                                        "Need BLUETOOTH_ADMIN permission");
163         Settings.Global.putInt(getContentResolver(),
164             Settings.Global.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
165             priority);
166         if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority);
167         return true;
168     }
169 
getPriority(BluetoothDevice device)170     public int getPriority(BluetoothDevice device) {
171         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
172                                        "Need BLUETOOTH_ADMIN permission");
173         int priority = Settings.Global.getInt(getContentResolver(),
174             Settings.Global.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
175             BluetoothProfile.PRIORITY_UNDEFINED);
176         return priority;
177     }
178 
179     /* Absolute volume implementation */
isAvrcpAbsoluteVolumeSupported()180     public boolean isAvrcpAbsoluteVolumeSupported() {
181         return mAvrcp.isAbsoluteVolumeSupported();
182     }
183 
adjustAvrcpAbsoluteVolume(int direction)184     public void adjustAvrcpAbsoluteVolume(int direction) {
185         mAvrcp.adjustVolume(direction);
186     }
187 
setAvrcpAbsoluteVolume(int volume)188     public void setAvrcpAbsoluteVolume(int volume) {
189         mAvrcp.setAbsoluteVolume(volume);
190     }
191 
setAvrcpAudioState(int state)192     public void setAvrcpAudioState(int state) {
193         mAvrcp.setA2dpAudioState(state);
194     }
195 
isA2dpPlaying(BluetoothDevice device)196     synchronized boolean isA2dpPlaying(BluetoothDevice device) {
197         enforceCallingOrSelfPermission(BLUETOOTH_PERM,
198                                        "Need BLUETOOTH permission");
199         if (DBG) Log.d(TAG, "isA2dpPlaying(" + device + ")");
200         return mStateMachine.isPlaying(device);
201     }
202 
203     //Binder object: Must be static class or memory leak may occur
204     private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub
205         implements IProfileServiceBinder {
206         private A2dpService mService;
207 
getService()208         private A2dpService getService() {
209             if (!Utils.checkCaller()) {
210                 Log.w(TAG,"A2dp call not allowed for non-active user");
211                 return null;
212             }
213 
214             if (mService != null && mService.isAvailable()) {
215                 return mService;
216             }
217             return null;
218         }
219 
BluetoothA2dpBinder(A2dpService svc)220         BluetoothA2dpBinder(A2dpService svc) {
221             mService = svc;
222         }
223 
cleanup()224         public boolean cleanup()  {
225             mService = null;
226             return true;
227         }
228 
connect(BluetoothDevice device)229         public boolean connect(BluetoothDevice device) {
230             A2dpService service = getService();
231             if (service == null) return false;
232             return service.connect(device);
233         }
234 
disconnect(BluetoothDevice device)235         public boolean disconnect(BluetoothDevice device) {
236             A2dpService service = getService();
237             if (service == null) return false;
238             return service.disconnect(device);
239         }
240 
getConnectedDevices()241         public List<BluetoothDevice> getConnectedDevices() {
242             A2dpService service = getService();
243             if (service == null) return new ArrayList<BluetoothDevice>(0);
244             return service.getConnectedDevices();
245         }
246 
getDevicesMatchingConnectionStates(int[] states)247         public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
248             A2dpService service = getService();
249             if (service == null) return new ArrayList<BluetoothDevice>(0);
250             return service.getDevicesMatchingConnectionStates(states);
251         }
252 
getConnectionState(BluetoothDevice device)253         public int getConnectionState(BluetoothDevice device) {
254             A2dpService service = getService();
255             if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
256             return service.getConnectionState(device);
257         }
258 
setPriority(BluetoothDevice device, int priority)259         public boolean setPriority(BluetoothDevice device, int priority) {
260             A2dpService service = getService();
261             if (service == null) return false;
262             return service.setPriority(device, priority);
263         }
264 
getPriority(BluetoothDevice device)265         public int getPriority(BluetoothDevice device) {
266             A2dpService service = getService();
267             if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED;
268             return service.getPriority(device);
269         }
270 
isAvrcpAbsoluteVolumeSupported()271         public boolean isAvrcpAbsoluteVolumeSupported() {
272             A2dpService service = getService();
273             if (service == null) return false;
274             return service.isAvrcpAbsoluteVolumeSupported();
275         }
276 
adjustAvrcpAbsoluteVolume(int direction)277         public void adjustAvrcpAbsoluteVolume(int direction) {
278             A2dpService service = getService();
279             if (service == null) return;
280             service.adjustAvrcpAbsoluteVolume(direction);
281         }
282 
setAvrcpAbsoluteVolume(int volume)283         public void setAvrcpAbsoluteVolume(int volume) {
284             A2dpService service = getService();
285             if (service == null) return;
286             service.setAvrcpAbsoluteVolume(volume);
287         }
288 
isA2dpPlaying(BluetoothDevice device)289         public boolean isA2dpPlaying(BluetoothDevice device) {
290             A2dpService service = getService();
291             if (service == null) return false;
292             return service.isA2dpPlaying(device);
293         }
294     };
295 }
296