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 static A2dpService sAd2dpService; 43 getName()44 protected String getName() { 45 return TAG; 46 } 47 initBinder()48 protected IProfileServiceBinder initBinder() { 49 return new BluetoothA2dpBinder(this); 50 } 51 start()52 protected boolean start() { 53 mStateMachine = A2dpStateMachine.make(this, this); 54 setA2dpService(this); 55 return true; 56 } 57 stop()58 protected boolean stop() { 59 mStateMachine.doQuit(); 60 return true; 61 } 62 cleanup()63 protected boolean cleanup() { 64 if (mStateMachine!= null) { 65 mStateMachine.cleanup(); 66 } 67 clearA2dpService(); 68 return true; 69 } 70 71 //API Methods 72 getA2dpService()73 public static synchronized A2dpService getA2dpService(){ 74 if (sAd2dpService != null && sAd2dpService.isAvailable()) { 75 if (DBG) Log.d(TAG, "getA2DPService(): returning " + sAd2dpService); 76 return sAd2dpService; 77 } 78 if (DBG) { 79 if (sAd2dpService == null) { 80 Log.d(TAG, "getA2dpService(): service is NULL"); 81 } else if (!(sAd2dpService.isAvailable())) { 82 Log.d(TAG,"getA2dpService(): service is not available"); 83 } 84 } 85 return null; 86 } 87 setA2dpService(A2dpService instance)88 private static synchronized void setA2dpService(A2dpService instance) { 89 if (instance != null && instance.isAvailable()) { 90 if (DBG) Log.d(TAG, "setA2dpService(): set to: " + sAd2dpService); 91 sAd2dpService = instance; 92 } else { 93 if (DBG) { 94 if (sAd2dpService == null) { 95 Log.d(TAG, "setA2dpService(): service not available"); 96 } else if (!sAd2dpService.isAvailable()) { 97 Log.d(TAG,"setA2dpService(): service is cleaning up"); 98 } 99 } 100 } 101 } 102 clearA2dpService()103 private static synchronized void clearA2dpService() { 104 sAd2dpService = null; 105 } 106 connect(BluetoothDevice device)107 public boolean connect(BluetoothDevice device) { 108 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 109 "Need BLUETOOTH ADMIN permission"); 110 111 if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { 112 return false; 113 } 114 115 int connectionState = mStateMachine.getConnectionState(device); 116 if (connectionState == BluetoothProfile.STATE_CONNECTED || 117 connectionState == BluetoothProfile.STATE_CONNECTING) { 118 return false; 119 } 120 121 mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device); 122 return true; 123 } 124 disconnect(BluetoothDevice device)125 boolean disconnect(BluetoothDevice device) { 126 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 127 "Need BLUETOOTH ADMIN permission"); 128 int connectionState = mStateMachine.getConnectionState(device); 129 if (connectionState != BluetoothProfile.STATE_CONNECTED && 130 connectionState != BluetoothProfile.STATE_CONNECTING) { 131 return false; 132 } 133 134 mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device); 135 return true; 136 } 137 getConnectedDevices()138 public List<BluetoothDevice> getConnectedDevices() { 139 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 140 return mStateMachine.getConnectedDevices(); 141 } 142 getDevicesMatchingConnectionStates(int[] states)143 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 144 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 145 return mStateMachine.getDevicesMatchingConnectionStates(states); 146 } 147 getConnectionState(BluetoothDevice device)148 int getConnectionState(BluetoothDevice device) { 149 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 150 return mStateMachine.getConnectionState(device); 151 } 152 setPriority(BluetoothDevice device, int priority)153 public boolean setPriority(BluetoothDevice device, int priority) { 154 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 155 "Need BLUETOOTH_ADMIN permission"); 156 Settings.Global.putInt(getContentResolver(), 157 Settings.Global.getBluetoothA2dpSinkPriorityKey(device.getAddress()), 158 priority); 159 if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority); 160 return true; 161 } 162 getPriority(BluetoothDevice device)163 public int getPriority(BluetoothDevice device) { 164 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 165 "Need BLUETOOTH_ADMIN permission"); 166 int priority = Settings.Global.getInt(getContentResolver(), 167 Settings.Global.getBluetoothA2dpSinkPriorityKey(device.getAddress()), 168 BluetoothProfile.PRIORITY_UNDEFINED); 169 return priority; 170 } 171 isA2dpPlaying(BluetoothDevice device)172 synchronized boolean isA2dpPlaying(BluetoothDevice device) { 173 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 174 "Need BLUETOOTH permission"); 175 if (DBG) Log.d(TAG, "isA2dpPlaying(" + device + ")"); 176 return mStateMachine.isPlaying(device); 177 } 178 179 //Binder object: Must be static class or memory leak may occur 180 private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub 181 implements IProfileServiceBinder { 182 private A2dpService mService; 183 getService()184 private A2dpService getService() { 185 if (!Utils.checkCaller()) { 186 Log.w(TAG,"A2dp call not allowed for non-active user"); 187 return null; 188 } 189 190 if (mService != null && mService.isAvailable()) { 191 return mService; 192 } 193 return null; 194 } 195 BluetoothA2dpBinder(A2dpService svc)196 BluetoothA2dpBinder(A2dpService svc) { 197 mService = svc; 198 } 199 cleanup()200 public boolean cleanup() { 201 mService = null; 202 return true; 203 } 204 connect(BluetoothDevice device)205 public boolean connect(BluetoothDevice device) { 206 A2dpService service = getService(); 207 if (service == null) return false; 208 return service.connect(device); 209 } 210 disconnect(BluetoothDevice device)211 public boolean disconnect(BluetoothDevice device) { 212 A2dpService service = getService(); 213 if (service == null) return false; 214 return service.disconnect(device); 215 } 216 getConnectedDevices()217 public List<BluetoothDevice> getConnectedDevices() { 218 A2dpService service = getService(); 219 if (service == null) return new ArrayList<BluetoothDevice>(0); 220 return service.getConnectedDevices(); 221 } 222 getDevicesMatchingConnectionStates(int[] states)223 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 224 A2dpService service = getService(); 225 if (service == null) return new ArrayList<BluetoothDevice>(0); 226 return service.getDevicesMatchingConnectionStates(states); 227 } 228 getConnectionState(BluetoothDevice device)229 public int getConnectionState(BluetoothDevice device) { 230 A2dpService service = getService(); 231 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 232 return service.getConnectionState(device); 233 } 234 setPriority(BluetoothDevice device, int priority)235 public boolean setPriority(BluetoothDevice device, int priority) { 236 A2dpService service = getService(); 237 if (service == null) return false; 238 return service.setPriority(device, priority); 239 } 240 getPriority(BluetoothDevice device)241 public int getPriority(BluetoothDevice device) { 242 A2dpService service = getService(); 243 if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED; 244 return service.getPriority(device); 245 } 246 isA2dpPlaying(BluetoothDevice device)247 public boolean isA2dpPlaying(BluetoothDevice device) { 248 A2dpService service = getService(); 249 if (service == null) return false; 250 return service.isA2dpPlaying(device); 251 } 252 }; 253 } 254