A2dpService.java revision 3fafe61ef25c1899fdc817c52163aec16c31055c
1/* 2 * Copyright (C) 2012 Google Inc. 3 */ 4package com.android.bluetooth.a2dp; 5 6import android.app.Service; 7import android.bluetooth.BluetoothAdapter; 8import android.bluetooth.BluetoothDevice; 9import android.bluetooth.BluetoothProfile; 10import android.bluetooth.IBluetoothA2dp; 11import android.content.BroadcastReceiver; 12import android.content.Context; 13import android.content.Intent; 14import android.os.Handler; 15import android.os.IBinder; 16import android.os.Message; 17import android.provider.Settings; 18import android.util.Log; 19import java.util.List; 20import java.util.Iterator; 21import java.util.Map; 22import android.content.pm.PackageManager; 23import com.android.bluetooth.btservice.AdapterService; 24 25/** 26 * Provides Bluetooth A2DP profile, as a service in the Bluetooth application. 27 * @hide 28 */ 29public class A2dpService extends Service { 30 private static final String TAG = "BluetoothA2dpService"; 31 private static final boolean DBG = true; 32 33 static final String BLUETOOTH_ADMIN_PERM = 34 android.Manifest.permission.BLUETOOTH_ADMIN; 35 static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 36 37 private BluetoothAdapter mAdapter; 38 private A2dpStateMachine mStateMachine; 39 40 @Override 41 public void onCreate() { 42 log("onCreate"); 43 super.onCreate(); 44 mAdapter = BluetoothAdapter.getDefaultAdapter(); 45 } 46 47 @Override 48 public IBinder onBind(Intent intent) { 49 log("onBind"); 50 return mBinder; 51 } 52 53 public void onStart(Intent intent, int startId) { 54 log("onStart"); 55 56 if (mAdapter == null) { 57 Log.w(TAG, "Stopping profile service: device does not have BT"); 58 stop(); 59 } 60 61 if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM)!=PackageManager.PERMISSION_GRANTED) { 62 Log.e(TAG, "Permission denied!"); 63 return; 64 } 65 66 String action = intent.getStringExtra(AdapterService.EXTRA_ACTION); 67 if (!AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) { 68 Log.e(TAG, "Invalid action " + action); 69 return; 70 } 71 72 int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 73 if(state==BluetoothAdapter.STATE_OFF) { 74 stop(); 75 } else if (state== BluetoothAdapter.STATE_ON){ 76 start(); 77 } 78 } 79 80 @Override 81 public void onDestroy() { 82 super.onDestroy(); 83 if (DBG) log("Destroying service."); 84 if(mAdapter != null) 85 mAdapter = null; 86 } 87 88 private void start() { 89 if (DBG) log("startService()"); 90 mStateMachine = new A2dpStateMachine(this); 91 mStateMachine.start(); 92 93 //Notify adapter service 94 AdapterService sAdapter = AdapterService.getAdapterService(); 95 if (sAdapter!= null) { 96 sAdapter.onProfileServiceStateChanged(getClass().getName(), BluetoothAdapter.STATE_ON); 97 } 98 } 99 100 private void stop() { 101 if (DBG) log("stopService()"); 102 if (mStateMachine!= null) { 103 mStateMachine.quit(); 104 mStateMachine.cleanup(); 105 mStateMachine=null; 106 } 107 108 //Notify adapter service 109 AdapterService sAdapter = AdapterService.getAdapterService(); 110 if (sAdapter!= null) { 111 sAdapter.onProfileServiceStateChanged(getClass().getName(), BluetoothAdapter.STATE_OFF); 112 } 113 stopSelf(); 114 } 115 116 /** 117 * Handlers for incoming service calls 118 */ 119 private final IBluetoothA2dp.Stub mBinder = new IBluetoothA2dp.Stub() { 120 121 public boolean connect(BluetoothDevice device) { 122 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 123 "Need BLUETOOTH ADMIN permission"); 124 125 if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { 126 return false; 127 } 128 129 int connectionState = mStateMachine.getConnectionState(device); 130 if (connectionState == BluetoothProfile.STATE_CONNECTED || 131 connectionState == BluetoothProfile.STATE_CONNECTING) { 132 return false; 133 } 134 135 mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device); 136 return true; 137 } 138 139 public boolean disconnect(BluetoothDevice device) { 140 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 141 "Need BLUETOOTH ADMIN permission"); 142 int connectionState = mStateMachine.getConnectionState(device); 143 if (connectionState != BluetoothProfile.STATE_CONNECTED && 144 connectionState != BluetoothProfile.STATE_CONNECTING) { 145 return false; 146 } 147 148 mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device); 149 return true; 150 } 151 152 public List<BluetoothDevice> getConnectedDevices() { 153 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 154 return mStateMachine.getConnectedDevices(); 155 } 156 157 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 158 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 159 return mStateMachine.getDevicesMatchingConnectionStates(states); 160 } 161 162 public int getConnectionState(BluetoothDevice device) { 163 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 164 return mStateMachine.getConnectionState(device); 165 } 166 167 public boolean setPriority(BluetoothDevice device, int priority) { 168 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 169 "Need BLUETOOTH_ADMIN permission"); 170 Settings.Secure.putInt(getContentResolver(), 171 Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()), 172 priority); 173 if (DBG) log("Saved priority " + device + " = " + priority); 174 return true; 175 } 176 177 public int getPriority(BluetoothDevice device) { 178 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 179 "Need BLUETOOTH_ADMIN permission"); 180 int priority = Settings.Secure.getInt(getContentResolver(), 181 Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()), 182 BluetoothProfile.PRIORITY_UNDEFINED); 183 return priority; 184 } 185 186 public synchronized boolean isA2dpPlaying(BluetoothDevice device) { 187 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 188 "Need BLUETOOTH permission"); 189 if (DBG) log("isA2dpPlaying(" + device + ")"); 190 return mStateMachine.isPlaying(device); 191 } 192 }; 193 194 private static void log(String msg) { 195 Log.d(TAG, msg); 196 } 197} 198