• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.BluetoothAudioConfig;
20 import android.bluetooth.BluetoothDevice;
21 import android.bluetooth.BluetoothProfile;
22 import android.bluetooth.IBluetoothA2dpSink;
23 import android.util.Log;
24 import com.android.bluetooth.btservice.ProfileService;
25 import com.android.bluetooth.Utils;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Map;
29 
30 /**
31  * Provides Bluetooth A2DP Sink profile, as a service in the Bluetooth application.
32  * @hide
33  */
34 public class A2dpSinkService extends ProfileService {
35     private static final boolean DBG = false;
36     private static final String TAG = "A2dpSinkService";
37 
38     private A2dpSinkStateMachine mStateMachine;
39     private static A2dpSinkService sA2dpSinkService;
40 
getName()41     protected String getName() {
42         return TAG;
43     }
44 
initBinder()45     protected IProfileServiceBinder initBinder() {
46         return new BluetoothA2dpSinkBinder(this);
47     }
48 
start()49     protected boolean start() {
50         mStateMachine = A2dpSinkStateMachine.make(this, this);
51         setA2dpSinkService(this);
52         return true;
53     }
54 
stop()55     protected boolean stop() {
56         mStateMachine.doQuit();
57         return true;
58     }
59 
cleanup()60     protected boolean cleanup() {
61         if (mStateMachine!= null) {
62             mStateMachine.cleanup();
63         }
64         clearA2dpSinkService();
65         return true;
66     }
67 
68     //API Methods
69 
getA2dpSinkService()70     public static synchronized A2dpSinkService getA2dpSinkService(){
71         if (sA2dpSinkService != null && sA2dpSinkService.isAvailable()) {
72             if (DBG) Log.d(TAG, "getA2dpSinkService(): returning " + sA2dpSinkService);
73             return sA2dpSinkService;
74         }
75         if (DBG)  {
76             if (sA2dpSinkService == null) {
77                 Log.d(TAG, "getA2dpSinkService(): service is NULL");
78             } else if (!(sA2dpSinkService.isAvailable())) {
79                 Log.d(TAG,"getA2dpSinkService(): service is not available");
80             }
81         }
82         return null;
83     }
84 
setA2dpSinkService(A2dpSinkService instance)85     private static synchronized void setA2dpSinkService(A2dpSinkService instance) {
86         if (instance != null && instance.isAvailable()) {
87             if (DBG) Log.d(TAG, "setA2dpSinkService(): set to: " + sA2dpSinkService);
88             sA2dpSinkService = instance;
89         } else {
90             if (DBG)  {
91                 if (sA2dpSinkService == null) {
92                     Log.d(TAG, "setA2dpSinkService(): service not available");
93                 } else if (!sA2dpSinkService.isAvailable()) {
94                     Log.d(TAG,"setA2dpSinkService(): service is cleaning up");
95                 }
96             }
97         }
98     }
99 
clearA2dpSinkService()100     private static synchronized void clearA2dpSinkService() {
101         sA2dpSinkService = null;
102     }
103 
connect(BluetoothDevice device)104     public boolean connect(BluetoothDevice device) {
105         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
106                                        "Need BLUETOOTH ADMIN permission");
107 
108         int connectionState = mStateMachine.getConnectionState(device);
109         if (connectionState == BluetoothProfile.STATE_CONNECTED ||
110             connectionState == BluetoothProfile.STATE_CONNECTING) {
111             return false;
112         }
113 
114         mStateMachine.sendMessage(A2dpSinkStateMachine.CONNECT, device);
115         return true;
116     }
117 
disconnect(BluetoothDevice device)118     boolean disconnect(BluetoothDevice device) {
119         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
120                                        "Need BLUETOOTH ADMIN permission");
121         int connectionState = mStateMachine.getConnectionState(device);
122         if (connectionState != BluetoothProfile.STATE_CONNECTED &&
123             connectionState != BluetoothProfile.STATE_CONNECTING) {
124             return false;
125         }
126 
127         mStateMachine.sendMessage(A2dpSinkStateMachine.DISCONNECT, device);
128         return true;
129     }
130 
getConnectedDevices()131     public List<BluetoothDevice> getConnectedDevices() {
132         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
133         return mStateMachine.getConnectedDevices();
134     }
135 
getDevicesMatchingConnectionStates(int[] states)136     List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
137         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
138         return mStateMachine.getDevicesMatchingConnectionStates(states);
139     }
140 
getConnectionState(BluetoothDevice device)141     int getConnectionState(BluetoothDevice device) {
142         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
143         return mStateMachine.getConnectionState(device);
144     }
145 
getAudioConfig(BluetoothDevice device)146     BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
147         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
148         return mStateMachine.getAudioConfig(device);
149     }
150 
151     //Binder object: Must be static class or memory leak may occur
152     private static class BluetoothA2dpSinkBinder extends IBluetoothA2dpSink.Stub
153         implements IProfileServiceBinder {
154         private A2dpSinkService mService;
155 
getService()156         private A2dpSinkService getService() {
157             if (!Utils.checkCaller()) {
158                 Log.w(TAG,"A2dp call not allowed for non-active user");
159                 return null;
160             }
161 
162             if (mService != null && mService.isAvailable()) {
163                 return mService;
164             }
165             return null;
166         }
167 
BluetoothA2dpSinkBinder(A2dpSinkService svc)168         BluetoothA2dpSinkBinder(A2dpSinkService svc) {
169             mService = svc;
170         }
171 
cleanup()172         public boolean cleanup()  {
173             mService = null;
174             return true;
175         }
176 
connect(BluetoothDevice device)177         public boolean connect(BluetoothDevice device) {
178             A2dpSinkService service = getService();
179             if (service == null) return false;
180             return service.connect(device);
181         }
182 
disconnect(BluetoothDevice device)183         public boolean disconnect(BluetoothDevice device) {
184             A2dpSinkService service = getService();
185             if (service == null) return false;
186             return service.disconnect(device);
187         }
188 
getConnectedDevices()189         public List<BluetoothDevice> getConnectedDevices() {
190             A2dpSinkService service = getService();
191             if (service == null) return new ArrayList<BluetoothDevice>(0);
192             return service.getConnectedDevices();
193         }
194 
getDevicesMatchingConnectionStates(int[] states)195         public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
196             A2dpSinkService service = getService();
197             if (service == null) return new ArrayList<BluetoothDevice>(0);
198             return service.getDevicesMatchingConnectionStates(states);
199         }
200 
getConnectionState(BluetoothDevice device)201         public int getConnectionState(BluetoothDevice device) {
202             A2dpSinkService service = getService();
203             if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
204             return service.getConnectionState(device);
205         }
206 
getAudioConfig(BluetoothDevice device)207         public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
208             A2dpSinkService service = getService();
209             if (service == null) return null;
210             return service.getAudioConfig(device);
211         }
212     };
213 
214     @Override
dump(StringBuilder sb)215     public void dump(StringBuilder sb) {
216         super.dump(sb);
217         if (mStateMachine != null) {
218             mStateMachine.dump(sb);
219         }
220     }
221 }
222