blob: 38c5f3a7a97253413e8a9a366e20ce4d4cbba6f0 [file] [log] [blame]
/*
* Copyright (C) 2012 Google Inc.
*/
package com.android.bluetooth.a2dp;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothA2dp;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.util.Log;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.Utils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Provides Bluetooth A2DP profile, as a service in the Bluetooth application.
* @hide
*/
public class A2dpService extends ProfileService {
private static final boolean DBG = false;
private static final String TAG="A2dpService";
private A2dpStateMachine mStateMachine;
private static A2dpService sAd2dpService;
protected String getName() {
return TAG;
}
protected IProfileServiceBinder initBinder() {
return new BluetoothA2dpBinder(this);
}
protected boolean start() {
mStateMachine = A2dpStateMachine.make(this, this);
setA2dpService(this);
return true;
}
protected boolean stop() {
mStateMachine.doQuit();
return true;
}
protected boolean cleanup() {
if (mStateMachine!= null) {
mStateMachine.cleanup();
}
clearA2dpService();
return true;
}
//API Methods
public static synchronized A2dpService getA2dpService(){
if (sAd2dpService != null && sAd2dpService.isAvailable()) {
if (DBG) Log.d(TAG, "getA2DPService(): returning " + sAd2dpService);
return sAd2dpService;
}
if (DBG) {
if (sAd2dpService == null) {
Log.d(TAG, "getA2dpService(): service is NULL");
} else if (!(sAd2dpService.isAvailable())) {
Log.d(TAG,"getA2dpService(): service is not available");
}
}
return null;
}
private static synchronized void setA2dpService(A2dpService instance) {
if (instance != null && instance.isAvailable()) {
if (DBG) Log.d(TAG, "setA2dpService(): set to: " + sAd2dpService);
sAd2dpService = instance;
} else {
if (DBG) {
if (sAd2dpService == null) {
Log.d(TAG, "setA2dpService(): service not available");
} else if (!sAd2dpService.isAvailable()) {
Log.d(TAG,"setA2dpService(): service is cleaning up");
}
}
}
}
private static synchronized void clearA2dpService() {
sAd2dpService = null;
}
public boolean connect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
return false;
}
int connectionState = mStateMachine.getConnectionState(device);
if (connectionState == BluetoothProfile.STATE_CONNECTED ||
connectionState == BluetoothProfile.STATE_CONNECTING) {
return false;
}
mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
return true;
}
boolean disconnect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
int connectionState = mStateMachine.getConnectionState(device);
if (connectionState != BluetoothProfile.STATE_CONNECTED &&
connectionState != BluetoothProfile.STATE_CONNECTING) {
return false;
}
mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device);
return true;
}
public List<BluetoothDevice> getConnectedDevices() {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
return mStateMachine.getConnectedDevices();
}
List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
return mStateMachine.getDevicesMatchingConnectionStates(states);
}
int getConnectionState(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
return mStateMachine.getConnectionState(device);
}
public boolean setPriority(BluetoothDevice device, int priority) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
Settings.Global.putInt(getContentResolver(),
Settings.Global.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
priority);
if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority);
return true;
}
public int getPriority(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
int priority = Settings.Global.getInt(getContentResolver(),
Settings.Global.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
BluetoothProfile.PRIORITY_UNDEFINED);
return priority;
}
synchronized boolean isA2dpPlaying(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM,
"Need BLUETOOTH permission");
if (DBG) Log.d(TAG, "isA2dpPlaying(" + device + ")");
return mStateMachine.isPlaying(device);
}
//Binder object: Must be static class or memory leak may occur
private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub
implements IProfileServiceBinder {
private A2dpService mService;
private A2dpService getService() {
if (!Utils.checkCaller()) {
Log.w(TAG,"A2dp call not allowed for non-active user");
return null;
}
if (mService != null && mService.isAvailable()) {
return mService;
}
return null;
}
BluetoothA2dpBinder(A2dpService svc) {
mService = svc;
}
public boolean cleanup() {
mService = null;
return true;
}
public boolean connect(BluetoothDevice device) {
A2dpService service = getService();
if (service == null) return false;
return service.connect(device);
}
public boolean disconnect(BluetoothDevice device) {
A2dpService service = getService();
if (service == null) return false;
return service.disconnect(device);
}
public List<BluetoothDevice> getConnectedDevices() {
A2dpService service = getService();
if (service == null) return new ArrayList<BluetoothDevice>(0);
return service.getConnectedDevices();
}
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
A2dpService service = getService();
if (service == null) return new ArrayList<BluetoothDevice>(0);
return service.getDevicesMatchingConnectionStates(states);
}
public int getConnectionState(BluetoothDevice device) {
A2dpService service = getService();
if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
return service.getConnectionState(device);
}
public boolean setPriority(BluetoothDevice device, int priority) {
A2dpService service = getService();
if (service == null) return false;
return service.setPriority(device, priority);
}
public int getPriority(BluetoothDevice device) {
A2dpService service = getService();
if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED;
return service.getPriority(device);
}
public boolean isA2dpPlaying(BluetoothDevice device) {
A2dpService service = getService();
if (service == null) return false;
return service.isA2dpPlaying(device);
}
};
}