blob: 767f59eb129722873f66b30ed107b522529b8cab [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;
RoboErik4197cb62015-01-21 15:45:32 -080025import android.media.AudioManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.os.IBinder;
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -070027import android.os.ParcelUuid;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070028import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.util.Log;
30
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -070031import java.util.ArrayList;
32import java.util.List;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
35/**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070036 * This class provides the public APIs to control the Bluetooth A2DP
37 * profile.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038 *
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070039 *<p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
40 * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
41 * the BluetoothA2dp proxy object.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042 *
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070043 * <p> Android only supports one connected Bluetooth A2dp device at a time.
44 * Each method is protected with its appropriate permission.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070046public final class BluetoothA2dp implements BluetoothProfile {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047 private static final String TAG = "BluetoothA2dp";
Matthew Xie3e8c82e2012-02-16 16:57:18 -080048 private static final boolean DBG = true;
Matthew Xie563e4142012-10-09 22:10:37 -070049 private static final boolean VDBG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070051 /**
52 * Intent used to broadcast the change in connection state of the A2DP
53 * profile.
54 *
55 * <p>This intent will have 3 extras:
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080056 * <ul>
57 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
58 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
59 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
60 * </ul>
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070061 *
Jaikumar Ganesh0706fed2011-01-26 11:46:56 -080062 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070063 * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
64 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
65 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080066 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
67 * receive.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 */
69 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070070 public static final String ACTION_CONNECTION_STATE_CHANGED =
71 "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070073 /**
74 * Intent used to broadcast the change in the Playing state of the A2DP
75 * profile.
76 *
77 * <p>This intent will have 3 extras:
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080078 * <ul>
79 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
80 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
Jaikumar Ganesh0706fed2011-01-26 11:46:56 -080081 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080082 * </ul>
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070083 *
Jaikumar Ganesh0706fed2011-01-26 11:46:56 -080084 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070085 * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
86 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080087 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
88 * receive.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070089 */
90 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
91 public static final String ACTION_PLAYING_STATE_CHANGED =
92 "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093
Hemant Gupta3b76a4b2014-02-14 19:53:31 +053094 /** @hide */
95 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
96 public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED =
97 "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
98
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070099 /**
100 * A2DP sink device is streaming music. This state can be one of
101 * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
102 * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
103 */
104 public static final int STATE_PLAYING = 10;
Nick Pellybd022f42009-08-14 18:33:38 -0700105
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700106 /**
107 * A2DP sink device is NOT streaming music. This state can be one of
108 * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
109 * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
110 */
111 public static final int STATE_NOT_PLAYING = 11;
112
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800113 private Context mContext;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700114 private ServiceListener mServiceListener;
115 private IBluetoothA2dp mService;
116 private BluetoothAdapter mAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117
fredc0f420372012-04-12 00:02:00 -0700118 final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
119 new IBluetoothStateChangeCallback.Stub() {
120 public void onBluetoothStateChange(boolean up) {
121 if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
122 if (!up) {
Matthew Xie563e4142012-10-09 22:10:37 -0700123 if (VDBG) Log.d(TAG,"Unbinding service...");
fredc0f420372012-04-12 00:02:00 -0700124 synchronized (mConnection) {
125 try {
126 mService = null;
127 mContext.unbindService(mConnection);
128 } catch (Exception re) {
129 Log.e(TAG,"",re);
130 }
131 }
132 } else {
133 synchronized (mConnection) {
134 try {
135 if (mService == null) {
Matthew Xie563e4142012-10-09 22:10:37 -0700136 if (VDBG) Log.d(TAG,"Binding service...");
Dianne Hackborn221ea892013-08-04 16:50:16 -0700137 doBind();
fredc0f420372012-04-12 00:02:00 -0700138 }
139 } catch (Exception re) {
140 Log.e(TAG,"",re);
141 }
142 }
143 }
144 }
145 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 /**
147 * Create a BluetoothA2dp proxy object for interacting with the local
148 * Bluetooth A2DP service.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700149 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 */
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800151 /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
152 mContext = context;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700153 mServiceListener = l;
154 mAdapter = BluetoothAdapter.getDefaultAdapter();
fredc0f420372012-04-12 00:02:00 -0700155 IBluetoothManager mgr = mAdapter.getBluetoothManager();
156 if (mgr != null) {
157 try {
158 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
159 } catch (RemoteException e) {
160 Log.e(TAG,"",e);
161 }
162 }
163
Dianne Hackborn221ea892013-08-04 16:50:16 -0700164 doBind();
165 }
166
167 boolean doBind() {
168 Intent intent = new Intent(IBluetoothA2dp.class.getName());
169 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
170 intent.setComponent(comp);
Dianne Hackborn466ce962014-03-19 18:06:58 -0700171 if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
172 android.os.Process.myUserHandle())) {
Dianne Hackborn221ea892013-08-04 16:50:16 -0700173 Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
174 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 }
Dianne Hackborn221ea892013-08-04 16:50:16 -0700176 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 }
178
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800179 /*package*/ void close() {
180 mServiceListener = null;
fredc0f420372012-04-12 00:02:00 -0700181 IBluetoothManager mgr = mAdapter.getBluetoothManager();
182 if (mgr != null) {
183 try {
184 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
185 } catch (Exception e) {
186 Log.e(TAG,"",e);
187 }
188 }
189
190 synchronized (mConnection) {
191 if (mService != null) {
192 try {
193 mService = null;
194 mContext.unbindService(mConnection);
195 } catch (Exception re) {
196 Log.e(TAG,"",re);
197 }
198 }
199 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800200 }
201
fredc0f420372012-04-12 00:02:00 -0700202 public void finalize() {
Mathias Jeppsson2d2d8c22013-08-06 11:41:55 +0200203 // The empty finalize needs to be kept or the
204 // cts signature tests would fail.
fredc0f420372012-04-12 00:02:00 -0700205 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700206 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700207 * Initiate connection to a profile of the remote bluetooth device.
208 *
209 * <p> Currently, the system supports only 1 connection to the
210 * A2DP profile. The API will automatically disconnect connected
211 * devices before connecting.
212 *
213 * <p> This API returns false in scenarios like the profile on the
214 * device is already connected or Bluetooth is not turned on.
215 * When this API returns true, it is guaranteed that
216 * connection state intent for the profile will be broadcasted with
217 * the state. Users can get the connection state of the profile
218 * from this intent.
219 *
220 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
221 * permission.
222 *
223 * @param device Remote Bluetooth Device
224 * @return false on immediate error,
225 * true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700226 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700228 public boolean connect(BluetoothDevice device) {
229 if (DBG) log("connect(" + device + ")");
230 if (mService != null && isEnabled() &&
231 isValidDevice(device)) {
232 try {
233 return mService.connect(device);
234 } catch (RemoteException e) {
235 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
236 return false;
237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700239 if (mService == null) Log.w(TAG, "Proxy not attached to service");
240 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 }
242
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700243 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700244 * Initiate disconnection from a profile
245 *
246 * <p> This API will return false in scenarios like the profile on the
247 * Bluetooth device is not in connected state etc. When this API returns,
248 * true, it is guaranteed that the connection state change
249 * intent will be broadcasted with the state. Users can get the
250 * disconnection state of the profile from this intent.
251 *
252 * <p> If the disconnection is initiated by a remote device, the state
253 * will transition from {@link #STATE_CONNECTED} to
254 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
255 * host (local) device the state will transition from
256 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
257 * state {@link #STATE_DISCONNECTED}. The transition to
258 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
259 * two scenarios.
260 *
261 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
262 * permission.
263 *
264 * @param device Remote Bluetooth Device
265 * @return false on immediate error,
266 * true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700267 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700269 public boolean disconnect(BluetoothDevice device) {
270 if (DBG) log("disconnect(" + device + ")");
271 if (mService != null && isEnabled() &&
272 isValidDevice(device)) {
273 try {
274 return mService.disconnect(device);
275 } catch (RemoteException e) {
276 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
277 return false;
278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700280 if (mService == null) Log.w(TAG, "Proxy not attached to service");
281 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 }
283
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700284 /**
285 * {@inheritDoc}
286 */
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700287 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xie563e4142012-10-09 22:10:37 -0700288 if (VDBG) log("getConnectedDevices()");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700289 if (mService != null && isEnabled()) {
290 try {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700291 return mService.getConnectedDevices();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700292 } catch (RemoteException e) {
293 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700294 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700295 }
296 }
297 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700298 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700299 }
300
301 /**
302 * {@inheritDoc}
303 */
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700304 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xie563e4142012-10-09 22:10:37 -0700305 if (VDBG) log("getDevicesMatchingStates()");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700306 if (mService != null && isEnabled()) {
307 try {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700308 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700309 } catch (RemoteException e) {
310 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700311 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700312 }
313 }
314 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700315 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700316 }
317
318 /**
319 * {@inheritDoc}
320 */
321 public int getConnectionState(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700322 if (VDBG) log("getState(" + device + ")");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700323 if (mService != null && isEnabled()
324 && isValidDevice(device)) {
325 try {
326 return mService.getConnectionState(device);
327 } catch (RemoteException e) {
328 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
329 return BluetoothProfile.STATE_DISCONNECTED;
330 }
331 }
332 if (mService == null) Log.w(TAG, "Proxy not attached to service");
333 return BluetoothProfile.STATE_DISCONNECTED;
334 }
335
336 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700337 * Set priority of the profile
338 *
339 * <p> The device should already be paired.
fredc0f420372012-04-12 00:02:00 -0700340 * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700341 * {@link #PRIORITY_OFF},
342 *
343 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
344 * permission.
345 *
346 * @param device Paired bluetooth device
347 * @param priority
348 * @return true if priority is set, false on error
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700349 * @hide
350 */
351 public boolean setPriority(BluetoothDevice device, int priority) {
352 if (DBG) log("setPriority(" + device + ", " + priority + ")");
353 if (mService != null && isEnabled()
354 && isValidDevice(device)) {
355 if (priority != BluetoothProfile.PRIORITY_OFF &&
Ganesh Ganapathi Batta6f6c54512012-07-31 16:08:17 -0700356 priority != BluetoothProfile.PRIORITY_ON){
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700357 return false;
358 }
359 try {
360 return mService.setPriority(device, priority);
361 } catch (RemoteException e) {
362 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
363 return false;
364 }
365 }
366 if (mService == null) Log.w(TAG, "Proxy not attached to service");
367 return false;
368 }
369
370 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700371 * Get the priority of the profile.
372 *
373 * <p> The priority can be any of:
374 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
375 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
376 *
377 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
378 *
379 * @param device Bluetooth device
380 * @return priority of the device
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700381 * @hide
382 */
383 public int getPriority(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700384 if (VDBG) log("getPriority(" + device + ")");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700385 if (mService != null && isEnabled()
386 && isValidDevice(device)) {
387 try {
388 return mService.getPriority(device);
389 } catch (RemoteException e) {
390 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
391 return BluetoothProfile.PRIORITY_OFF;
392 }
393 }
394 if (mService == null) Log.w(TAG, "Proxy not attached to service");
395 return BluetoothProfile.PRIORITY_OFF;
396 }
397
398 /**
John Du5a0cf7a2013-07-19 11:30:34 -0700399 * Checks if Avrcp device supports the absolute volume feature.
400 *
401 * @return true if device supports absolute volume
402 * @hide
403 */
404 public boolean isAvrcpAbsoluteVolumeSupported() {
405 if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
406 if (mService != null && isEnabled()) {
407 try {
408 return mService.isAvrcpAbsoluteVolumeSupported();
409 } catch (RemoteException e) {
410 Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
411 return false;
412 }
413 }
414 if (mService == null) Log.w(TAG, "Proxy not attached to service");
415 return false;
416 }
417
418 /**
RoboErik4197cb62015-01-21 15:45:32 -0800419 * Tells remote device to adjust volume. Only if absolute volume is
420 * supported. Uses the following values:
421 * <ul>
422 * <li>{@link AudioManager#ADJUST_LOWER}</li>
423 * <li>{@link AudioManager#ADJUST_RAISE}</li>
424 * <li>{@link AudioManager#ADJUST_MUTE}</li>
425 * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
426 * </ul>
John Du5a0cf7a2013-07-19 11:30:34 -0700427 *
RoboErik4197cb62015-01-21 15:45:32 -0800428 * @param direction One of the supported adjust values.
John Du5a0cf7a2013-07-19 11:30:34 -0700429 * @hide
430 */
431 public void adjustAvrcpAbsoluteVolume(int direction) {
432 if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
433 if (mService != null && isEnabled()) {
434 try {
435 mService.adjustAvrcpAbsoluteVolume(direction);
436 return;
437 } catch (RemoteException e) {
438 Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
439 return;
440 }
441 }
442 if (mService == null) Log.w(TAG, "Proxy not attached to service");
443 }
444
445 /**
446 * Tells remote device to set an absolute volume. Only if absolute volume is supported
447 *
448 * @param volume Absolute volume to be set on AVRCP side
449 * @hide
450 */
451 public void setAvrcpAbsoluteVolume(int volume) {
452 if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
453 if (mService != null && isEnabled()) {
454 try {
455 mService.setAvrcpAbsoluteVolume(volume);
456 return;
457 } catch (RemoteException e) {
458 Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
459 return;
460 }
461 }
462 if (mService == null) Log.w(TAG, "Proxy not attached to service");
463 }
464
465 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700466 * Check if A2DP profile is streaming music.
467 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -0800468 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700469 *
470 * @param device BluetoothDevice device
471 */
472 public boolean isA2dpPlaying(BluetoothDevice device) {
473 if (mService != null && isEnabled()
474 && isValidDevice(device)) {
475 try {
476 return mService.isA2dpPlaying(device);
477 } catch (RemoteException e) {
478 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
479 return false;
480 }
481 }
482 if (mService == null) Log.w(TAG, "Proxy not attached to service");
483 return false;
484 }
485
486 /**
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -0700487 * This function checks if the remote device is an AVCRP
488 * target and thus whether we should send volume keys
489 * changes or not.
490 * @hide
491 */
492 public boolean shouldSendVolumeKeys(BluetoothDevice device) {
493 if (isEnabled() && isValidDevice(device)) {
494 ParcelUuid[] uuids = device.getUuids();
495 if (uuids == null) return false;
496
497 for (ParcelUuid uuid: uuids) {
498 if (BluetoothUuid.isAvrcpTarget(uuid)) {
499 return true;
500 }
501 }
502 }
503 return false;
504 }
505
Matthew Xiea0c68032011-06-25 21:47:07 -0700506 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700507 * Helper for converting a state to a string.
508 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509 * For debug use only - strings are not internationalized.
510 * @hide
511 */
512 public static String stateToString(int state) {
513 switch (state) {
514 case STATE_DISCONNECTED:
515 return "disconnected";
516 case STATE_CONNECTING:
517 return "connecting";
518 case STATE_CONNECTED:
519 return "connected";
520 case STATE_DISCONNECTING:
521 return "disconnecting";
522 case STATE_PLAYING:
523 return "playing";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700524 case STATE_NOT_PLAYING:
525 return "not playing";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 default:
527 return "<unknown state " + state + ">";
528 }
529 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800530
Matthew Xie9b693992013-10-10 11:21:40 -0700531 private final ServiceConnection mConnection = new ServiceConnection() {
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800532 public void onServiceConnected(ComponentName className, IBinder service) {
533 if (DBG) Log.d(TAG, "Proxy object connected");
534 mService = IBluetoothA2dp.Stub.asInterface(service);
535
536 if (mServiceListener != null) {
537 mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
538 }
539 }
540 public void onServiceDisconnected(ComponentName className) {
541 if (DBG) Log.d(TAG, "Proxy object disconnected");
542 mService = null;
543 if (mServiceListener != null) {
544 mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
545 }
546 }
547 };
548
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700549 private boolean isEnabled() {
550 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
551 return false;
552 }
553
554 private boolean isValidDevice(BluetoothDevice device) {
555 if (device == null) return false;
556
557 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
558 return false;
559 }
560
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800561 private static void log(String msg) {
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700562 Log.d(TAG, msg);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564}