blob: 927aa2127e9aadf1b548c70fae375600d9fdf817 [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() {
202 close();
203 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700204 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700205 * Initiate connection to a profile of the remote bluetooth device.
206 *
207 * <p> Currently, the system supports only 1 connection to the
208 * A2DP profile. The API will automatically disconnect connected
209 * devices before connecting.
210 *
211 * <p> This API returns false in scenarios like the profile on the
212 * device is already connected or Bluetooth is not turned on.
213 * When this API returns true, it is guaranteed that
214 * connection state intent for the profile will be broadcasted with
215 * the state. Users can get the connection state of the profile
216 * from this intent.
217 *
218 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
219 * permission.
220 *
221 * @param device Remote Bluetooth Device
222 * @return false on immediate error,
223 * true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700224 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700226 public boolean connect(BluetoothDevice device) {
227 if (DBG) log("connect(" + device + ")");
228 if (mService != null && isEnabled() &&
229 isValidDevice(device)) {
230 try {
231 return mService.connect(device);
232 } catch (RemoteException e) {
233 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
234 return false;
235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700237 if (mService == null) Log.w(TAG, "Proxy not attached to service");
238 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 }
240
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700241 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700242 * Initiate disconnection from a profile
243 *
244 * <p> This API will return false in scenarios like the profile on the
245 * Bluetooth device is not in connected state etc. When this API returns,
246 * true, it is guaranteed that the connection state change
247 * intent will be broadcasted with the state. Users can get the
248 * disconnection state of the profile from this intent.
249 *
250 * <p> If the disconnection is initiated by a remote device, the state
251 * will transition from {@link #STATE_CONNECTED} to
252 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
253 * host (local) device the state will transition from
254 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
255 * state {@link #STATE_DISCONNECTED}. The transition to
256 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
257 * two scenarios.
258 *
259 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
260 * permission.
261 *
262 * @param device Remote Bluetooth Device
263 * @return false on immediate error,
264 * true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700265 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700267 public boolean disconnect(BluetoothDevice device) {
268 if (DBG) log("disconnect(" + device + ")");
269 if (mService != null && isEnabled() &&
270 isValidDevice(device)) {
271 try {
272 return mService.disconnect(device);
273 } catch (RemoteException e) {
274 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
275 return false;
276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700278 if (mService == null) Log.w(TAG, "Proxy not attached to service");
279 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 }
281
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700282 /**
283 * {@inheritDoc}
284 */
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700285 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xie563e4142012-10-09 22:10:37 -0700286 if (VDBG) log("getConnectedDevices()");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700287 if (mService != null && isEnabled()) {
288 try {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700289 return mService.getConnectedDevices();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700290 } catch (RemoteException e) {
291 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700292 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700293 }
294 }
295 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700296 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700297 }
298
299 /**
300 * {@inheritDoc}
301 */
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700302 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xie563e4142012-10-09 22:10:37 -0700303 if (VDBG) log("getDevicesMatchingStates()");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700304 if (mService != null && isEnabled()) {
305 try {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700306 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700307 } catch (RemoteException e) {
308 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700309 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700310 }
311 }
312 if (mService == null) Log.w(TAG, "Proxy not attached to service");
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700313 return new ArrayList<BluetoothDevice>();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700314 }
315
316 /**
317 * {@inheritDoc}
318 */
319 public int getConnectionState(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700320 if (VDBG) log("getState(" + device + ")");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700321 if (mService != null && isEnabled()
322 && isValidDevice(device)) {
323 try {
324 return mService.getConnectionState(device);
325 } catch (RemoteException e) {
326 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
327 return BluetoothProfile.STATE_DISCONNECTED;
328 }
329 }
330 if (mService == null) Log.w(TAG, "Proxy not attached to service");
331 return BluetoothProfile.STATE_DISCONNECTED;
332 }
333
334 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700335 * Set priority of the profile
336 *
337 * <p> The device should already be paired.
fredc0f420372012-04-12 00:02:00 -0700338 * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700339 * {@link #PRIORITY_OFF},
340 *
341 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
342 * permission.
343 *
344 * @param device Paired bluetooth device
345 * @param priority
346 * @return true if priority is set, false on error
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700347 * @hide
348 */
349 public boolean setPriority(BluetoothDevice device, int priority) {
350 if (DBG) log("setPriority(" + device + ", " + priority + ")");
351 if (mService != null && isEnabled()
352 && isValidDevice(device)) {
353 if (priority != BluetoothProfile.PRIORITY_OFF &&
Ganesh Ganapathi Batta6f6c54512012-07-31 16:08:17 -0700354 priority != BluetoothProfile.PRIORITY_ON){
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700355 return false;
356 }
357 try {
358 return mService.setPriority(device, priority);
359 } catch (RemoteException e) {
360 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
361 return false;
362 }
363 }
364 if (mService == null) Log.w(TAG, "Proxy not attached to service");
365 return false;
366 }
367
368 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700369 * Get the priority of the profile.
370 *
371 * <p> The priority can be any of:
372 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
373 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
374 *
375 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
376 *
377 * @param device Bluetooth device
378 * @return priority of the device
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700379 * @hide
380 */
381 public int getPriority(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700382 if (VDBG) log("getPriority(" + device + ")");
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700383 if (mService != null && isEnabled()
384 && isValidDevice(device)) {
385 try {
386 return mService.getPriority(device);
387 } catch (RemoteException e) {
388 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
389 return BluetoothProfile.PRIORITY_OFF;
390 }
391 }
392 if (mService == null) Log.w(TAG, "Proxy not attached to service");
393 return BluetoothProfile.PRIORITY_OFF;
394 }
395
396 /**
John Du5a0cf7a2013-07-19 11:30:34 -0700397 * Checks if Avrcp device supports the absolute volume feature.
398 *
399 * @return true if device supports absolute volume
400 * @hide
401 */
402 public boolean isAvrcpAbsoluteVolumeSupported() {
403 if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
404 if (mService != null && isEnabled()) {
405 try {
406 return mService.isAvrcpAbsoluteVolumeSupported();
407 } catch (RemoteException e) {
408 Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
409 return false;
410 }
411 }
412 if (mService == null) Log.w(TAG, "Proxy not attached to service");
413 return false;
414 }
415
416 /**
417 * Tells remote device to adjust volume. Only if absolute volume is supported.
418 *
419 * @param direction 1 to increase volume, or -1 to decrease volume
420 * @hide
421 */
422 public void adjustAvrcpAbsoluteVolume(int direction) {
423 if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
424 if (mService != null && isEnabled()) {
425 try {
426 mService.adjustAvrcpAbsoluteVolume(direction);
427 return;
428 } catch (RemoteException e) {
429 Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
430 return;
431 }
432 }
433 if (mService == null) Log.w(TAG, "Proxy not attached to service");
434 }
435
436 /**
437 * Tells remote device to set an absolute volume. Only if absolute volume is supported
438 *
439 * @param volume Absolute volume to be set on AVRCP side
440 * @hide
441 */
442 public void setAvrcpAbsoluteVolume(int volume) {
443 if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
444 if (mService != null && isEnabled()) {
445 try {
446 mService.setAvrcpAbsoluteVolume(volume);
447 return;
448 } catch (RemoteException e) {
449 Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
450 return;
451 }
452 }
453 if (mService == null) Log.w(TAG, "Proxy not attached to service");
454 }
455
456 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700457 * Check if A2DP profile is streaming music.
458 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -0800459 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700460 *
461 * @param device BluetoothDevice device
462 */
463 public boolean isA2dpPlaying(BluetoothDevice device) {
464 if (mService != null && isEnabled()
465 && isValidDevice(device)) {
466 try {
467 return mService.isA2dpPlaying(device);
468 } catch (RemoteException e) {
469 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
470 return false;
471 }
472 }
473 if (mService == null) Log.w(TAG, "Proxy not attached to service");
474 return false;
475 }
476
477 /**
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -0700478 * This function checks if the remote device is an AVCRP
479 * target and thus whether we should send volume keys
480 * changes or not.
481 * @hide
482 */
483 public boolean shouldSendVolumeKeys(BluetoothDevice device) {
484 if (isEnabled() && isValidDevice(device)) {
485 ParcelUuid[] uuids = device.getUuids();
486 if (uuids == null) return false;
487
488 for (ParcelUuid uuid: uuids) {
489 if (BluetoothUuid.isAvrcpTarget(uuid)) {
490 return true;
491 }
492 }
493 }
494 return false;
495 }
496
Matthew Xiea0c68032011-06-25 21:47:07 -0700497 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700498 * Helper for converting a state to a string.
499 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 * For debug use only - strings are not internationalized.
501 * @hide
502 */
503 public static String stateToString(int state) {
504 switch (state) {
505 case STATE_DISCONNECTED:
506 return "disconnected";
507 case STATE_CONNECTING:
508 return "connecting";
509 case STATE_CONNECTED:
510 return "connected";
511 case STATE_DISCONNECTING:
512 return "disconnecting";
513 case STATE_PLAYING:
514 return "playing";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700515 case STATE_NOT_PLAYING:
516 return "not playing";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 default:
518 return "<unknown state " + state + ">";
519 }
520 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800521
Matthew Xie9b693992013-10-10 11:21:40 -0700522 private final ServiceConnection mConnection = new ServiceConnection() {
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800523 public void onServiceConnected(ComponentName className, IBinder service) {
524 if (DBG) Log.d(TAG, "Proxy object connected");
525 mService = IBluetoothA2dp.Stub.asInterface(service);
526
527 if (mServiceListener != null) {
528 mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
529 }
530 }
531 public void onServiceDisconnected(ComponentName className) {
532 if (DBG) Log.d(TAG, "Proxy object disconnected");
533 mService = null;
534 if (mServiceListener != null) {
535 mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
536 }
537 }
538 };
539
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700540 private boolean isEnabled() {
541 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
542 return false;
543 }
544
545 private boolean isValidDevice(BluetoothDevice device) {
546 if (device == null) return false;
547
548 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
549 return false;
550 }
551
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800552 private static void log(String msg) {
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700553 Log.d(TAG, msg);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800554 }
Hemant Gupta3b76a4b2014-02-14 19:53:31 +0530555
556 /** @hide */
557 public void sendPassThroughCmd(int keyCode, int keyState) {
558 if (DBG) Log.d(TAG, "sendPassThroughCmd");
559 if (mService != null && isEnabled()) {
560 try {
561 mService.sendPassThroughCmd(keyCode, keyState);
562 return;
563 } catch (RemoteException e) {
564 Log.e(TAG, "Error talking to BT service in sendPassThroughCmd()", e);
565 return;
566 }
567 }
568 if (mService == null) Log.w(TAG, "Proxy not attached to service");
569 }
570
571 /** @hide */
572 public boolean isAvrcpConnected(BluetoothDevice device) {
573 if (DBG) Log.d(TAG, "isAvrcpConnected");
574 if (mService != null && isEnabled()) {
575 try {
576 return mService.isAvrcpConnected(device);
577 } catch (RemoteException e) {
578 Log.e(TAG, "Error talking to BT service in isAvrcpConnected()", e);
579 return false;
580 }
581 }
582 if (mService == null) Log.w(TAG, "Proxy not attached to service");
583 return false;
584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585}