blob: 0450150f871f12b98410d27b007b4e038155c5eb [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
Hemant Gupta3b76a4b2014-02-14 19:53:31 +053093 /** @hide */
94 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
95 public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED =
96 "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
97
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070098 /**
99 * A2DP sink device is streaming music. This state can be one of
100 * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
101 * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
102 */
103 public static final int STATE_PLAYING = 10;
Nick Pellybd022f42009-08-14 18:33:38 -0700104
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700105 /**
106 * A2DP sink device is NOT streaming music. This state can be one of
107 * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
108 * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
109 */
110 public static final int STATE_NOT_PLAYING = 11;
111
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800112 private Context mContext;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700113 private ServiceListener mServiceListener;
114 private IBluetoothA2dp mService;
115 private BluetoothAdapter mAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116
fredc0f420372012-04-12 00:02:00 -0700117 final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
118 new IBluetoothStateChangeCallback.Stub() {
119 public void onBluetoothStateChange(boolean up) {
120 if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
121 if (!up) {
Matthew Xie563e4142012-10-09 22:10:37 -0700122 if (VDBG) Log.d(TAG,"Unbinding service...");
fredc0f420372012-04-12 00:02:00 -0700123 synchronized (mConnection) {
124 try {
125 mService = null;
126 mContext.unbindService(mConnection);
127 } catch (Exception re) {
128 Log.e(TAG,"",re);
129 }
130 }
131 } else {
132 synchronized (mConnection) {
133 try {
134 if (mService == null) {
Matthew Xie563e4142012-10-09 22:10:37 -0700135 if (VDBG) Log.d(TAG,"Binding service...");
Dianne Hackborn221ea892013-08-04 16:50:16 -0700136 doBind();
fredc0f420372012-04-12 00:02:00 -0700137 }
138 } catch (Exception re) {
139 Log.e(TAG,"",re);
140 }
141 }
142 }
143 }
144 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 /**
146 * Create a BluetoothA2dp proxy object for interacting with the local
147 * Bluetooth A2DP service.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700148 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 */
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800150 /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
151 mContext = context;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700152 mServiceListener = l;
153 mAdapter = BluetoothAdapter.getDefaultAdapter();
fredc0f420372012-04-12 00:02:00 -0700154 IBluetoothManager mgr = mAdapter.getBluetoothManager();
155 if (mgr != null) {
156 try {
157 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
158 } catch (RemoteException e) {
159 Log.e(TAG,"",e);
160 }
161 }
162
Dianne Hackborn221ea892013-08-04 16:50:16 -0700163 doBind();
164 }
165
166 boolean doBind() {
167 Intent intent = new Intent(IBluetoothA2dp.class.getName());
168 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
169 intent.setComponent(comp);
Dianne Hackborn466ce962014-03-19 18:06:58 -0700170 if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
171 android.os.Process.myUserHandle())) {
Dianne Hackborn221ea892013-08-04 16:50:16 -0700172 Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
173 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 }
Dianne Hackborn221ea892013-08-04 16:50:16 -0700175 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 }
177
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800178 /*package*/ void close() {
179 mServiceListener = null;
fredc0f420372012-04-12 00:02:00 -0700180 IBluetoothManager mgr = mAdapter.getBluetoothManager();
181 if (mgr != null) {
182 try {
183 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
184 } catch (Exception e) {
185 Log.e(TAG,"",e);
186 }
187 }
188
189 synchronized (mConnection) {
190 if (mService != null) {
191 try {
192 mService = null;
193 mContext.unbindService(mConnection);
194 } catch (Exception re) {
195 Log.e(TAG,"",re);
196 }
197 }
198 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800199 }
200
fredc0f420372012-04-12 00:02:00 -0700201 public void finalize() {
Mathias Jeppsson2d2d8c22013-08-06 11:41:55 +0200202 // The empty finalize needs to be kept or the
203 // cts signature tests would fail.
fredc0f420372012-04-12 00:02:00 -0700204 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700205 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700206 * Initiate connection to a profile of the remote bluetooth device.
207 *
208 * <p> Currently, the system supports only 1 connection to the
209 * A2DP profile. The API will automatically disconnect connected
210 * devices before connecting.
211 *
212 * <p> This API returns false in scenarios like the profile on the
213 * device is already connected or Bluetooth is not turned on.
214 * When this API returns true, it is guaranteed that
215 * connection state intent for the profile will be broadcasted with
216 * the state. Users can get the connection state of the profile
217 * from this intent.
218 *
219 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
220 * permission.
221 *
222 * @param device Remote Bluetooth Device
223 * @return false on immediate error,
224 * true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700225 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700227 public boolean connect(BluetoothDevice device) {
228 if (DBG) log("connect(" + device + ")");
229 if (mService != null && isEnabled() &&
230 isValidDevice(device)) {
231 try {
232 return mService.connect(device);
233 } catch (RemoteException e) {
234 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
235 return false;
236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700238 if (mService == null) Log.w(TAG, "Proxy not attached to service");
239 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 }
241
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700242 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700243 * Initiate disconnection from a profile
244 *
245 * <p> This API will return false in scenarios like the profile on the
246 * Bluetooth device is not in connected state etc. When this API returns,
247 * true, it is guaranteed that the connection state change
248 * intent will be broadcasted with the state. Users can get the
249 * disconnection state of the profile from this intent.
250 *
251 * <p> If the disconnection is initiated by a remote device, the state
252 * will transition from {@link #STATE_CONNECTED} to
253 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
254 * host (local) device the state will transition from
255 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
256 * state {@link #STATE_DISCONNECTED}. The transition to
257 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
258 * two scenarios.
259 *
260 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
261 * permission.
262 *
263 * @param device Remote Bluetooth Device
264 * @return false on immediate error,
265 * true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700266 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700268 public boolean disconnect(BluetoothDevice device) {
269 if (DBG) log("disconnect(" + device + ")");
270 if (mService != null && isEnabled() &&
271 isValidDevice(device)) {
272 try {
273 return mService.disconnect(device);
274 } catch (RemoteException e) {
275 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
276 return false;
277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700279 if (mService == null) Log.w(TAG, "Proxy not attached to service");
280 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 }
282
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700283 /**
284 * {@inheritDoc}
285 */
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700286 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xie563e4142012-10-09 22:10:37 -0700287 if (VDBG) log("getConnectedDevices()");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700288 if (mService != null && isEnabled()) {
289 try {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700290 return mService.getConnectedDevices();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700291 } catch (RemoteException e) {
292 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700293 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700294 }
295 }
296 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700297 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700298 }
299
300 /**
301 * {@inheritDoc}
302 */
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700303 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xie563e4142012-10-09 22:10:37 -0700304 if (VDBG) log("getDevicesMatchingStates()");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700305 if (mService != null && isEnabled()) {
306 try {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700307 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700308 } catch (RemoteException e) {
309 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700310 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700311 }
312 }
313 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700314 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700315 }
316
317 /**
318 * {@inheritDoc}
319 */
320 public int getConnectionState(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700321 if (VDBG) log("getState(" + device + ")");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700322 if (mService != null && isEnabled()
323 && isValidDevice(device)) {
324 try {
325 return mService.getConnectionState(device);
326 } catch (RemoteException e) {
327 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
328 return BluetoothProfile.STATE_DISCONNECTED;
329 }
330 }
331 if (mService == null) Log.w(TAG, "Proxy not attached to service");
332 return BluetoothProfile.STATE_DISCONNECTED;
333 }
334
335 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700336 * Set priority of the profile
337 *
338 * <p> The device should already be paired.
fredc0f420372012-04-12 00:02:00 -0700339 * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700340 * {@link #PRIORITY_OFF},
341 *
342 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
343 * permission.
344 *
345 * @param device Paired bluetooth device
346 * @param priority
347 * @return true if priority is set, false on error
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700348 * @hide
349 */
350 public boolean setPriority(BluetoothDevice device, int priority) {
351 if (DBG) log("setPriority(" + device + ", " + priority + ")");
352 if (mService != null && isEnabled()
353 && isValidDevice(device)) {
354 if (priority != BluetoothProfile.PRIORITY_OFF &&
Ganesh Ganapathi Batta6f6c54512012-07-31 16:08:17 -0700355 priority != BluetoothProfile.PRIORITY_ON){
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700356 return false;
357 }
358 try {
359 return mService.setPriority(device, priority);
360 } catch (RemoteException e) {
361 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
362 return false;
363 }
364 }
365 if (mService == null) Log.w(TAG, "Proxy not attached to service");
366 return false;
367 }
368
369 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700370 * Get the priority of the profile.
371 *
372 * <p> The priority can be any of:
373 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
374 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
375 *
376 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
377 *
378 * @param device Bluetooth device
379 * @return priority of the device
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700380 * @hide
381 */
382 public int getPriority(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700383 if (VDBG) log("getPriority(" + device + ")");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700384 if (mService != null && isEnabled()
385 && isValidDevice(device)) {
386 try {
387 return mService.getPriority(device);
388 } catch (RemoteException e) {
389 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
390 return BluetoothProfile.PRIORITY_OFF;
391 }
392 }
393 if (mService == null) Log.w(TAG, "Proxy not attached to service");
394 return BluetoothProfile.PRIORITY_OFF;
395 }
396
397 /**
John Du5a0cf7a2013-07-19 11:30:34 -0700398 * Checks if Avrcp device supports the absolute volume feature.
399 *
400 * @return true if device supports absolute volume
401 * @hide
402 */
403 public boolean isAvrcpAbsoluteVolumeSupported() {
404 if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
405 if (mService != null && isEnabled()) {
406 try {
407 return mService.isAvrcpAbsoluteVolumeSupported();
408 } catch (RemoteException e) {
409 Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
410 return false;
411 }
412 }
413 if (mService == null) Log.w(TAG, "Proxy not attached to service");
414 return false;
415 }
416
417 /**
418 * Tells remote device to adjust volume. Only if absolute volume is supported.
419 *
420 * @param direction 1 to increase volume, or -1 to decrease volume
421 * @hide
422 */
423 public void adjustAvrcpAbsoluteVolume(int direction) {
424 if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
425 if (mService != null && isEnabled()) {
426 try {
427 mService.adjustAvrcpAbsoluteVolume(direction);
428 return;
429 } catch (RemoteException e) {
430 Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
431 return;
432 }
433 }
434 if (mService == null) Log.w(TAG, "Proxy not attached to service");
435 }
436
437 /**
438 * Tells remote device to set an absolute volume. Only if absolute volume is supported
439 *
440 * @param volume Absolute volume to be set on AVRCP side
441 * @hide
442 */
443 public void setAvrcpAbsoluteVolume(int volume) {
444 if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
445 if (mService != null && isEnabled()) {
446 try {
447 mService.setAvrcpAbsoluteVolume(volume);
448 return;
449 } catch (RemoteException e) {
450 Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
451 return;
452 }
453 }
454 if (mService == null) Log.w(TAG, "Proxy not attached to service");
455 }
456
457 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700458 * Check if A2DP profile is streaming music.
459 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -0800460 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700461 *
462 * @param device BluetoothDevice device
463 */
464 public boolean isA2dpPlaying(BluetoothDevice device) {
465 if (mService != null && isEnabled()
466 && isValidDevice(device)) {
467 try {
468 return mService.isA2dpPlaying(device);
469 } catch (RemoteException e) {
470 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
471 return false;
472 }
473 }
474 if (mService == null) Log.w(TAG, "Proxy not attached to service");
475 return false;
476 }
477
478 /**
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -0700479 * This function checks if the remote device is an AVCRP
480 * target and thus whether we should send volume keys
481 * changes or not.
482 * @hide
483 */
484 public boolean shouldSendVolumeKeys(BluetoothDevice device) {
485 if (isEnabled() && isValidDevice(device)) {
486 ParcelUuid[] uuids = device.getUuids();
487 if (uuids == null) return false;
488
489 for (ParcelUuid uuid: uuids) {
490 if (BluetoothUuid.isAvrcpTarget(uuid)) {
491 return true;
492 }
493 }
494 }
495 return false;
496 }
497
Matthew Xiea0c68032011-06-25 21:47:07 -0700498 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700499 * Helper for converting a state to a string.
500 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 * For debug use only - strings are not internationalized.
502 * @hide
503 */
504 public static String stateToString(int state) {
505 switch (state) {
506 case STATE_DISCONNECTED:
507 return "disconnected";
508 case STATE_CONNECTING:
509 return "connecting";
510 case STATE_CONNECTED:
511 return "connected";
512 case STATE_DISCONNECTING:
513 return "disconnecting";
514 case STATE_PLAYING:
515 return "playing";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700516 case STATE_NOT_PLAYING:
517 return "not playing";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 default:
519 return "<unknown state " + state + ">";
520 }
521 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800522
Matthew Xie9b693992013-10-10 11:21:40 -0700523 private final ServiceConnection mConnection = new ServiceConnection() {
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800524 public void onServiceConnected(ComponentName className, IBinder service) {
525 if (DBG) Log.d(TAG, "Proxy object connected");
526 mService = IBluetoothA2dp.Stub.asInterface(service);
527
528 if (mServiceListener != null) {
529 mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
530 }
531 }
532 public void onServiceDisconnected(ComponentName className) {
533 if (DBG) Log.d(TAG, "Proxy object disconnected");
534 mService = null;
535 if (mServiceListener != null) {
536 mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
537 }
538 }
539 };
540
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700541 private boolean isEnabled() {
542 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
543 return false;
544 }
545
546 private boolean isValidDevice(BluetoothDevice device) {
547 if (device == null) return false;
548
549 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
550 return false;
551 }
552
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800553 private static void log(String msg) {
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700554 Log.d(TAG, msg);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556}