blob: e7e4a0f47fd2cc326d72369e22f6fd3dc294af91 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 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
17package android.bluetooth;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
Matthew Xie3e8c82e2012-02-16 16:57:18 -080021import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.Context;
Matthew Xie3e8c82e2012-02-16 16:57:18 -080023import android.content.Intent;
24import android.content.ServiceConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.os.IBinder;
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -070026import android.os.ParcelUuid;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070027import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.util.Log;
29
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -070030import java.util.ArrayList;
31import java.util.List;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033
34/**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070035 * This class provides the public APIs to control the Bluetooth A2DP
36 * profile.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037 *
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070038 *<p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
39 * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
40 * the BluetoothA2dp proxy object.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 *
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070042 * <p> Android only supports one connected Bluetooth A2dp device at a time.
43 * Each method is protected with its appropriate permission.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070045public final class BluetoothA2dp implements BluetoothProfile {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046 private static final String TAG = "BluetoothA2dp";
Matthew Xie3e8c82e2012-02-16 16:57:18 -080047 private static final boolean DBG = true;
Matthew Xie563e4142012-10-09 22:10:37 -070048 private static final boolean VDBG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070050 /**
51 * Intent used to broadcast the change in connection state of the A2DP
52 * profile.
53 *
54 * <p>This intent will have 3 extras:
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080055 * <ul>
56 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
57 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
58 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
59 * </ul>
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070060 *
Jaikumar Ganesh0706fed2011-01-26 11:46:56 -080061 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070062 * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
63 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
64 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080065 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
66 * receive.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067 */
68 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070069 public static final String ACTION_CONNECTION_STATE_CHANGED =
70 "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070072 /**
73 * Intent used to broadcast the change in the Playing state of the A2DP
74 * profile.
75 *
76 * <p>This intent will have 3 extras:
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080077 * <ul>
78 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
79 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
Jaikumar Ganesh0706fed2011-01-26 11:46:56 -080080 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080081 * </ul>
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070082 *
Jaikumar Ganesh0706fed2011-01-26 11:46:56 -080083 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070084 * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
85 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080086 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
87 * receive.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070088 */
89 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
90 public static final String ACTION_PLAYING_STATE_CHANGED =
91 "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070093 /**
94 * A2DP sink device is streaming music. This state can be one of
95 * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
96 * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
97 */
98 public static final int STATE_PLAYING = 10;
Nick Pellybd022f42009-08-14 18:33:38 -070099
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700100 /**
101 * A2DP sink device is NOT streaming music. This state can be one of
102 * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
103 * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
104 */
105 public static final int STATE_NOT_PLAYING = 11;
106
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800107 private Context mContext;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700108 private ServiceListener mServiceListener;
109 private IBluetoothA2dp mService;
110 private BluetoothAdapter mAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111
fredc0f420372012-04-12 00:02:00 -0700112 final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
113 new IBluetoothStateChangeCallback.Stub() {
114 public void onBluetoothStateChange(boolean up) {
115 if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
116 if (!up) {
Matthew Xie563e4142012-10-09 22:10:37 -0700117 if (VDBG) Log.d(TAG,"Unbinding service...");
fredc0f420372012-04-12 00:02:00 -0700118 synchronized (mConnection) {
119 try {
120 mService = null;
121 mContext.unbindService(mConnection);
122 } catch (Exception re) {
123 Log.e(TAG,"",re);
124 }
125 }
126 } else {
127 synchronized (mConnection) {
128 try {
129 if (mService == null) {
Matthew Xie563e4142012-10-09 22:10:37 -0700130 if (VDBG) Log.d(TAG,"Binding service...");
Dianne Hackborn221ea892013-08-04 16:50:16 -0700131 doBind();
fredc0f420372012-04-12 00:02:00 -0700132 }
133 } catch (Exception re) {
134 Log.e(TAG,"",re);
135 }
136 }
137 }
138 }
139 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 /**
141 * Create a BluetoothA2dp proxy object for interacting with the local
142 * Bluetooth A2DP service.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700143 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 */
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800145 /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
146 mContext = context;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700147 mServiceListener = l;
148 mAdapter = BluetoothAdapter.getDefaultAdapter();
fredc0f420372012-04-12 00:02:00 -0700149 IBluetoothManager mgr = mAdapter.getBluetoothManager();
150 if (mgr != null) {
151 try {
152 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
153 } catch (RemoteException e) {
154 Log.e(TAG,"",e);
155 }
156 }
157
Dianne Hackborn221ea892013-08-04 16:50:16 -0700158 doBind();
159 }
160
161 boolean doBind() {
162 Intent intent = new Intent(IBluetoothA2dp.class.getName());
163 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
164 intent.setComponent(comp);
165 if (comp == null || !mContext.bindService(intent, mConnection, 0)) {
166 Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
167 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 }
Dianne Hackborn221ea892013-08-04 16:50:16 -0700169 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 }
171
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800172 /*package*/ void close() {
173 mServiceListener = null;
fredc0f420372012-04-12 00:02:00 -0700174 IBluetoothManager mgr = mAdapter.getBluetoothManager();
175 if (mgr != null) {
176 try {
177 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
178 } catch (Exception e) {
179 Log.e(TAG,"",e);
180 }
181 }
182
183 synchronized (mConnection) {
184 if (mService != null) {
185 try {
186 mService = null;
187 mContext.unbindService(mConnection);
188 } catch (Exception re) {
189 Log.e(TAG,"",re);
190 }
191 }
192 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800193 }
194
fredc0f420372012-04-12 00:02:00 -0700195 public void finalize() {
196 close();
197 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700198 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700199 * Initiate connection to a profile of the remote bluetooth device.
200 *
201 * <p> Currently, the system supports only 1 connection to the
202 * A2DP profile. The API will automatically disconnect connected
203 * devices before connecting.
204 *
205 * <p> This API returns false in scenarios like the profile on the
206 * device is already connected or Bluetooth is not turned on.
207 * When this API returns true, it is guaranteed that
208 * connection state intent for the profile will be broadcasted with
209 * the state. Users can get the connection state of the profile
210 * from this intent.
211 *
212 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
213 * permission.
214 *
215 * @param device Remote Bluetooth Device
216 * @return false on immediate error,
217 * true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700218 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700220 public boolean connect(BluetoothDevice device) {
221 if (DBG) log("connect(" + device + ")");
222 if (mService != null && isEnabled() &&
223 isValidDevice(device)) {
224 try {
225 return mService.connect(device);
226 } catch (RemoteException e) {
227 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
228 return false;
229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700231 if (mService == null) Log.w(TAG, "Proxy not attached to service");
232 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 }
234
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700235 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700236 * Initiate disconnection from a profile
237 *
238 * <p> This API will return false in scenarios like the profile on the
239 * Bluetooth device is not in connected state etc. When this API returns,
240 * true, it is guaranteed that the connection state change
241 * intent will be broadcasted with the state. Users can get the
242 * disconnection state of the profile from this intent.
243 *
244 * <p> If the disconnection is initiated by a remote device, the state
245 * will transition from {@link #STATE_CONNECTED} to
246 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
247 * host (local) device the state will transition from
248 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
249 * state {@link #STATE_DISCONNECTED}. The transition to
250 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
251 * two scenarios.
252 *
253 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
254 * permission.
255 *
256 * @param device Remote Bluetooth Device
257 * @return false on immediate error,
258 * true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700259 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700261 public boolean disconnect(BluetoothDevice device) {
262 if (DBG) log("disconnect(" + device + ")");
263 if (mService != null && isEnabled() &&
264 isValidDevice(device)) {
265 try {
266 return mService.disconnect(device);
267 } catch (RemoteException e) {
268 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
269 return false;
270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700272 if (mService == null) Log.w(TAG, "Proxy not attached to service");
273 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 }
275
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700276 /**
277 * {@inheritDoc}
278 */
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700279 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xie563e4142012-10-09 22:10:37 -0700280 if (VDBG) log("getConnectedDevices()");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700281 if (mService != null && isEnabled()) {
282 try {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700283 return mService.getConnectedDevices();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700284 } catch (RemoteException e) {
285 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700286 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700287 }
288 }
289 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700290 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700291 }
292
293 /**
294 * {@inheritDoc}
295 */
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700296 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xie563e4142012-10-09 22:10:37 -0700297 if (VDBG) log("getDevicesMatchingStates()");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700298 if (mService != null && isEnabled()) {
299 try {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700300 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700301 } catch (RemoteException e) {
302 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700303 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700304 }
305 }
306 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700307 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700308 }
309
310 /**
311 * {@inheritDoc}
312 */
313 public int getConnectionState(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700314 if (VDBG) log("getState(" + device + ")");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700315 if (mService != null && isEnabled()
316 && isValidDevice(device)) {
317 try {
318 return mService.getConnectionState(device);
319 } catch (RemoteException e) {
320 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
321 return BluetoothProfile.STATE_DISCONNECTED;
322 }
323 }
324 if (mService == null) Log.w(TAG, "Proxy not attached to service");
325 return BluetoothProfile.STATE_DISCONNECTED;
326 }
327
328 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700329 * Set priority of the profile
330 *
331 * <p> The device should already be paired.
fredc0f420372012-04-12 00:02:00 -0700332 * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700333 * {@link #PRIORITY_OFF},
334 *
335 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
336 * permission.
337 *
338 * @param device Paired bluetooth device
339 * @param priority
340 * @return true if priority is set, false on error
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700341 * @hide
342 */
343 public boolean setPriority(BluetoothDevice device, int priority) {
344 if (DBG) log("setPriority(" + device + ", " + priority + ")");
345 if (mService != null && isEnabled()
346 && isValidDevice(device)) {
347 if (priority != BluetoothProfile.PRIORITY_OFF &&
Ganesh Ganapathi Batta6f6c54512012-07-31 16:08:17 -0700348 priority != BluetoothProfile.PRIORITY_ON){
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700349 return false;
350 }
351 try {
352 return mService.setPriority(device, priority);
353 } catch (RemoteException e) {
354 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
355 return false;
356 }
357 }
358 if (mService == null) Log.w(TAG, "Proxy not attached to service");
359 return false;
360 }
361
362 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700363 * Get the priority of the profile.
364 *
365 * <p> The priority can be any of:
366 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
367 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
368 *
369 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
370 *
371 * @param device Bluetooth device
372 * @return priority of the device
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700373 * @hide
374 */
375 public int getPriority(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700376 if (VDBG) log("getPriority(" + device + ")");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700377 if (mService != null && isEnabled()
378 && isValidDevice(device)) {
379 try {
380 return mService.getPriority(device);
381 } catch (RemoteException e) {
382 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
383 return BluetoothProfile.PRIORITY_OFF;
384 }
385 }
386 if (mService == null) Log.w(TAG, "Proxy not attached to service");
387 return BluetoothProfile.PRIORITY_OFF;
388 }
389
390 /**
John Du5a0cf7a2013-07-19 11:30:34 -0700391 * Checks if Avrcp device supports the absolute volume feature.
392 *
393 * @return true if device supports absolute volume
394 * @hide
395 */
396 public boolean isAvrcpAbsoluteVolumeSupported() {
397 if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
398 if (mService != null && isEnabled()) {
399 try {
400 return mService.isAvrcpAbsoluteVolumeSupported();
401 } catch (RemoteException e) {
402 Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
403 return false;
404 }
405 }
406 if (mService == null) Log.w(TAG, "Proxy not attached to service");
407 return false;
408 }
409
410 /**
411 * Tells remote device to adjust volume. Only if absolute volume is supported.
412 *
413 * @param direction 1 to increase volume, or -1 to decrease volume
414 * @hide
415 */
416 public void adjustAvrcpAbsoluteVolume(int direction) {
417 if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
418 if (mService != null && isEnabled()) {
419 try {
420 mService.adjustAvrcpAbsoluteVolume(direction);
421 return;
422 } catch (RemoteException e) {
423 Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
424 return;
425 }
426 }
427 if (mService == null) Log.w(TAG, "Proxy not attached to service");
428 }
429
430 /**
431 * Tells remote device to set an absolute volume. Only if absolute volume is supported
432 *
433 * @param volume Absolute volume to be set on AVRCP side
434 * @hide
435 */
436 public void setAvrcpAbsoluteVolume(int volume) {
437 if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
438 if (mService != null && isEnabled()) {
439 try {
440 mService.setAvrcpAbsoluteVolume(volume);
441 return;
442 } catch (RemoteException e) {
443 Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
444 return;
445 }
446 }
447 if (mService == null) Log.w(TAG, "Proxy not attached to service");
448 }
449
450 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700451 * Check if A2DP profile is streaming music.
452 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -0800453 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700454 *
455 * @param device BluetoothDevice device
456 */
457 public boolean isA2dpPlaying(BluetoothDevice device) {
458 if (mService != null && isEnabled()
459 && isValidDevice(device)) {
460 try {
461 return mService.isA2dpPlaying(device);
462 } catch (RemoteException e) {
463 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
464 return false;
465 }
466 }
467 if (mService == null) Log.w(TAG, "Proxy not attached to service");
468 return false;
469 }
470
471 /**
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -0700472 * This function checks if the remote device is an AVCRP
473 * target and thus whether we should send volume keys
474 * changes or not.
475 * @hide
476 */
477 public boolean shouldSendVolumeKeys(BluetoothDevice device) {
478 if (isEnabled() && isValidDevice(device)) {
479 ParcelUuid[] uuids = device.getUuids();
480 if (uuids == null) return false;
481
482 for (ParcelUuid uuid: uuids) {
483 if (BluetoothUuid.isAvrcpTarget(uuid)) {
484 return true;
485 }
486 }
487 }
488 return false;
489 }
490
Matthew Xiea0c68032011-06-25 21:47:07 -0700491 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700492 * Helper for converting a state to a string.
493 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 * For debug use only - strings are not internationalized.
495 * @hide
496 */
497 public static String stateToString(int state) {
498 switch (state) {
499 case STATE_DISCONNECTED:
500 return "disconnected";
501 case STATE_CONNECTING:
502 return "connecting";
503 case STATE_CONNECTED:
504 return "connected";
505 case STATE_DISCONNECTING:
506 return "disconnecting";
507 case STATE_PLAYING:
508 return "playing";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700509 case STATE_NOT_PLAYING:
510 return "not playing";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 default:
512 return "<unknown state " + state + ">";
513 }
514 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800515
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800516 private ServiceConnection mConnection = new ServiceConnection() {
517 public void onServiceConnected(ComponentName className, IBinder service) {
518 if (DBG) Log.d(TAG, "Proxy object connected");
519 mService = IBluetoothA2dp.Stub.asInterface(service);
520
521 if (mServiceListener != null) {
522 mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
523 }
524 }
525 public void onServiceDisconnected(ComponentName className) {
526 if (DBG) Log.d(TAG, "Proxy object disconnected");
527 mService = null;
528 if (mServiceListener != null) {
529 mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
530 }
531 }
532 };
533
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700534 private boolean isEnabled() {
535 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
536 return false;
537 }
538
539 private boolean isValidDevice(BluetoothDevice device) {
540 if (device == null) return false;
541
542 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
543 return false;
544 }
545
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800546 private static void log(String msg) {
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700547 Log.d(TAG, msg);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549}