blob: 7841b83cf92cf3f060c02c625bd713e72d904e13 [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
Tor Norbye2d497522015-04-23 17:10:21 -070019import android.Manifest;
20import android.annotation.RequiresPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.annotation.SdkConstant;
22import android.annotation.SdkConstant.SdkConstantType;
Matthew Xie3e8c82e2012-02-16 16:57:18 -080023import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.Context;
Matthew Xie3e8c82e2012-02-16 16:57:18 -080025import android.content.Intent;
26import android.content.ServiceConnection;
RoboErik4197cb62015-01-21 15:45:32 -080027import android.media.AudioManager;
Jeff Sharkey0a17db12016-11-04 11:23:46 -060028import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.os.IBinder;
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -070030import android.os.ParcelUuid;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070031import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.util.Log;
33
Calvin Ond7d16b92016-06-20 15:59:48 -070034import com.android.internal.annotations.GuardedBy;
35
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -070036import java.util.ArrayList;
37import java.util.List;
Calvin Ond7d16b92016-06-20 15:59:48 -070038import java.util.concurrent.locks.ReentrantReadWriteLock;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040
41/**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070042 * This class provides the public APIs to control the Bluetooth A2DP
43 * profile.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044 *
Jack Hea355e5e2017-08-22 16:06:54 -070045 * <p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070046 * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
47 * the BluetoothA2dp proxy object.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 *
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070049 * <p> Android only supports one connected Bluetooth A2dp device at a time.
50 * Each method is protected with its appropriate permission.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070052public final class BluetoothA2dp implements BluetoothProfile {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 private static final String TAG = "BluetoothA2dp";
Matthew Xie3e8c82e2012-02-16 16:57:18 -080054 private static final boolean DBG = true;
Matthew Xie563e4142012-10-09 22:10:37 -070055 private static final boolean VDBG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070057 /**
58 * Intent used to broadcast the change in connection state of the A2DP
59 * profile.
60 *
61 * <p>This intent will have 3 extras:
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080062 * <ul>
Jack Hea355e5e2017-08-22 16:06:54 -070063 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
64 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
65 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080066 * </ul>
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070067 *
Jaikumar Ganesh0706fed2011-01-26 11:46:56 -080068 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070069 * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
70 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
71 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080072 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
73 * receive.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 */
75 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070076 public static final String ACTION_CONNECTION_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -070077 "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070079 /**
80 * Intent used to broadcast the change in the Playing state of the A2DP
81 * profile.
82 *
83 * <p>This intent will have 3 extras:
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080084 * <ul>
Jack Hea355e5e2017-08-22 16:06:54 -070085 * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
86 * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
87 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080088 * </ul>
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070089 *
Jaikumar Ganesh0706fed2011-01-26 11:46:56 -080090 * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070091 * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
92 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -080093 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
94 * receive.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070095 */
96 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
97 public static final String ACTION_PLAYING_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -070098 "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099
Hemant Gupta3b76a4b2014-02-14 19:53:31 +0530100 /** @hide */
101 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
102 public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700103 "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
Hemant Gupta3b76a4b2014-02-14 19:53:31 +0530104
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700105 /**
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800106 * Intent used to broadcast the change in the Audio Codec state of the
107 * A2DP Source profile.
108 *
Pavlin Radoslavovb37f1812017-01-25 16:54:07 -0800109 * <p>This intent will have 2 extras:
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800110 * <ul>
Jack Hea355e5e2017-08-22 16:06:54 -0700111 * <li> {@link BluetoothCodecStatus#EXTRA_CODEC_STATUS} - The codec status. </li>
112 * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently
113 * connected, otherwise it is not included.</li>
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800114 * </ul>
115 *
116 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
117 * receive.
118 *
119 * @hide
120 */
121 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
122 public static final String ACTION_CODEC_CONFIG_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700123 "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED";
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800124
125 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700126 * A2DP sink device is streaming music. This state can be one of
127 * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
128 * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
129 */
Jack Hea355e5e2017-08-22 16:06:54 -0700130 public static final int STATE_PLAYING = 10;
Nick Pellybd022f42009-08-14 18:33:38 -0700131
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700132 /**
133 * A2DP sink device is NOT streaming music. This state can be one of
134 * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
135 * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
136 */
Jack Hea355e5e2017-08-22 16:06:54 -0700137 public static final int STATE_NOT_PLAYING = 11;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700138
Antony Sargentf5772c62017-04-26 16:37:53 -0700139 /**
140 * We don't have a stored preference for whether or not the given A2DP sink device supports
141 * optional codecs.
Jack Hea355e5e2017-08-22 16:06:54 -0700142 *
143 * @hide
144 */
Antony Sargentf5772c62017-04-26 16:37:53 -0700145 public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
146
147 /**
148 * The given A2DP sink device does not support optional codecs.
Jack Hea355e5e2017-08-22 16:06:54 -0700149 *
150 * @hide
151 */
Antony Sargentf5772c62017-04-26 16:37:53 -0700152 public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
153
154 /**
155 * The given A2DP sink device does support optional codecs.
Jack Hea355e5e2017-08-22 16:06:54 -0700156 *
157 * @hide
158 */
Antony Sargentf5772c62017-04-26 16:37:53 -0700159 public static final int OPTIONAL_CODECS_SUPPORTED = 1;
160
161 /**
162 * We don't have a stored preference for whether optional codecs should be enabled or disabled
163 * for the given A2DP device.
Jack Hea355e5e2017-08-22 16:06:54 -0700164 *
165 * @hide
166 */
Antony Sargentf5772c62017-04-26 16:37:53 -0700167 public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
168
169 /**
170 * Optional codecs should be disabled for the given A2DP device.
Jack Hea355e5e2017-08-22 16:06:54 -0700171 *
172 * @hide
173 */
Antony Sargentf5772c62017-04-26 16:37:53 -0700174 public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
175
176 /**
Jack Hea355e5e2017-08-22 16:06:54 -0700177 * Optional codecs should be enabled for the given A2DP device.
178 *
179 * @hide
180 */
Antony Sargentf5772c62017-04-26 16:37:53 -0700181 public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
182
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800183 private Context mContext;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700184 private ServiceListener mServiceListener;
Calvin Ond7d16b92016-06-20 15:59:48 -0700185 private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
Jack Hea355e5e2017-08-22 16:06:54 -0700186 @GuardedBy("mServiceLock")
187 private IBluetoothA2dp mService;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700188 private BluetoothAdapter mAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
Jack He2992cd02017-08-22 21:21:23 -0700190 private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
fredc0f420372012-04-12 00:02:00 -0700191 new IBluetoothStateChangeCallback.Stub() {
192 public void onBluetoothStateChange(boolean up) {
193 if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
194 if (!up) {
Calvin Ond7d16b92016-06-20 15:59:48 -0700195 if (VDBG) Log.d(TAG, "Unbinding service...");
196 try {
197 mServiceLock.writeLock().lock();
198 mService = null;
199 mContext.unbindService(mConnection);
200 } catch (Exception re) {
201 Log.e(TAG, "", re);
202 } finally {
203 mServiceLock.writeLock().unlock();
fredc0f420372012-04-12 00:02:00 -0700204 }
205 } else {
Calvin Ond7d16b92016-06-20 15:59:48 -0700206 try {
207 mServiceLock.readLock().lock();
208 if (mService == null) {
Jack Hea355e5e2017-08-22 16:06:54 -0700209 if (VDBG) Log.d(TAG, "Binding service...");
Calvin Ond7d16b92016-06-20 15:59:48 -0700210 doBind();
fredc0f420372012-04-12 00:02:00 -0700211 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700212 } catch (Exception re) {
Jack Hea355e5e2017-08-22 16:06:54 -0700213 Log.e(TAG, "", re);
Calvin Ond7d16b92016-06-20 15:59:48 -0700214 } finally {
215 mServiceLock.readLock().unlock();
fredc0f420372012-04-12 00:02:00 -0700216 }
217 }
218 }
Jack Hea355e5e2017-08-22 16:06:54 -0700219 };
220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 /**
222 * Create a BluetoothA2dp proxy object for interacting with the local
223 * Bluetooth A2DP service.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 */
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800225 /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
226 mContext = context;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700227 mServiceListener = l;
228 mAdapter = BluetoothAdapter.getDefaultAdapter();
fredc0f420372012-04-12 00:02:00 -0700229 IBluetoothManager mgr = mAdapter.getBluetoothManager();
230 if (mgr != null) {
231 try {
232 mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
233 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -0700234 Log.e(TAG, "", e);
fredc0f420372012-04-12 00:02:00 -0700235 }
236 }
237
Dianne Hackborn221ea892013-08-04 16:50:16 -0700238 doBind();
239 }
240
241 boolean doBind() {
242 Intent intent = new Intent(IBluetoothA2dp.class.getName());
243 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
244 intent.setComponent(comp);
Dianne Hackborn466ce962014-03-19 18:06:58 -0700245 if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
246 android.os.Process.myUserHandle())) {
Dianne Hackborn221ea892013-08-04 16:50:16 -0700247 Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
248 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 }
Dianne Hackborn221ea892013-08-04 16:50:16 -0700250 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 }
252
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800253 /*package*/ void close() {
254 mServiceListener = null;
fredc0f420372012-04-12 00:02:00 -0700255 IBluetoothManager mgr = mAdapter.getBluetoothManager();
256 if (mgr != null) {
257 try {
258 mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
259 } catch (Exception e) {
Jack Hea355e5e2017-08-22 16:06:54 -0700260 Log.e(TAG, "", e);
fredc0f420372012-04-12 00:02:00 -0700261 }
262 }
263
Calvin Ond7d16b92016-06-20 15:59:48 -0700264 try {
265 mServiceLock.writeLock().lock();
fredc0f420372012-04-12 00:02:00 -0700266 if (mService != null) {
Calvin Ond7d16b92016-06-20 15:59:48 -0700267 mService = null;
268 mContext.unbindService(mConnection);
fredc0f420372012-04-12 00:02:00 -0700269 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700270 } catch (Exception re) {
271 Log.e(TAG, "", re);
272 } finally {
273 mServiceLock.writeLock().unlock();
fredc0f420372012-04-12 00:02:00 -0700274 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -0800275 }
276
Jack He2992cd02017-08-22 21:21:23 -0700277 @Override
fredc0f420372012-04-12 00:02:00 -0700278 public void finalize() {
Mathias Jeppsson2d2d8c22013-08-06 11:41:55 +0200279 // The empty finalize needs to be kept or the
280 // cts signature tests would fail.
fredc0f420372012-04-12 00:02:00 -0700281 }
Jack Hea355e5e2017-08-22 16:06:54 -0700282
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700283 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700284 * Initiate connection to a profile of the remote bluetooth device.
285 *
286 * <p> Currently, the system supports only 1 connection to the
287 * A2DP profile. The API will automatically disconnect connected
288 * devices before connecting.
289 *
290 * <p> This API returns false in scenarios like the profile on the
291 * device is already connected or Bluetooth is not turned on.
292 * When this API returns true, it is guaranteed that
293 * connection state intent for the profile will be broadcasted with
294 * the state. Users can get the connection state of the profile
295 * from this intent.
296 *
297 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
298 * permission.
299 *
300 * @param device Remote Bluetooth Device
Jack Hea355e5e2017-08-22 16:06:54 -0700301 * @return false on immediate error, true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700302 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700304 public boolean connect(BluetoothDevice device) {
305 if (DBG) log("connect(" + device + ")");
Calvin Ond7d16b92016-06-20 15:59:48 -0700306 try {
307 mServiceLock.readLock().lock();
Jack He2992cd02017-08-22 21:21:23 -0700308 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700309 return mService.connect(device);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700310 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700311 if (mService == null) Log.w(TAG, "Proxy not attached to service");
312 return false;
313 } catch (RemoteException e) {
314 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
315 return false;
316 } finally {
317 mServiceLock.readLock().unlock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 }
319 }
320
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700321 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700322 * Initiate disconnection from a profile
323 *
324 * <p> This API will return false in scenarios like the profile on the
325 * Bluetooth device is not in connected state etc. When this API returns,
326 * true, it is guaranteed that the connection state change
327 * intent will be broadcasted with the state. Users can get the
328 * disconnection state of the profile from this intent.
329 *
330 * <p> If the disconnection is initiated by a remote device, the state
331 * will transition from {@link #STATE_CONNECTED} to
332 * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
333 * host (local) device the state will transition from
334 * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
335 * state {@link #STATE_DISCONNECTED}. The transition to
336 * {@link #STATE_DISCONNECTING} can be used to distinguish between the
337 * two scenarios.
338 *
339 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
340 * permission.
341 *
342 * @param device Remote Bluetooth Device
Jack Hea355e5e2017-08-22 16:06:54 -0700343 * @return false on immediate error, true otherwise
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700344 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 */
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700346 public boolean disconnect(BluetoothDevice device) {
347 if (DBG) log("disconnect(" + device + ")");
Calvin Ond7d16b92016-06-20 15:59:48 -0700348 try {
349 mServiceLock.readLock().lock();
Jack He2992cd02017-08-22 21:21:23 -0700350 if (mService != null && isEnabled() && isValidDevice(device)) {
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700351 return mService.disconnect(device);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700352 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700353 if (mService == null) Log.w(TAG, "Proxy not attached to service");
354 return false;
355 } catch (RemoteException e) {
356 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
357 return false;
358 } finally {
359 mServiceLock.readLock().unlock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360 }
361 }
362
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700363 /**
364 * {@inheritDoc}
365 */
Jack He2992cd02017-08-22 21:21:23 -0700366 @Override
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700367 public List<BluetoothDevice> getConnectedDevices() {
Matthew Xie563e4142012-10-09 22:10:37 -0700368 if (VDBG) log("getConnectedDevices()");
Calvin Ond7d16b92016-06-20 15:59:48 -0700369 try {
370 mServiceLock.readLock().lock();
371 if (mService != null && isEnabled()) {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700372 return mService.getConnectedDevices();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700373 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700374 if (mService == null) Log.w(TAG, "Proxy not attached to service");
375 return new ArrayList<BluetoothDevice>();
376 } catch (RemoteException e) {
377 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
378 return new ArrayList<BluetoothDevice>();
379 } finally {
380 mServiceLock.readLock().unlock();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700381 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700382 }
383
384 /**
385 * {@inheritDoc}
386 */
Jack He2992cd02017-08-22 21:21:23 -0700387 @Override
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700388 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Matthew Xie563e4142012-10-09 22:10:37 -0700389 if (VDBG) log("getDevicesMatchingStates()");
Calvin Ond7d16b92016-06-20 15:59:48 -0700390 try {
391 mServiceLock.readLock().lock();
392 if (mService != null && isEnabled()) {
Jaikumar Ganesh03cd78c2010-10-18 16:41:53 -0700393 return mService.getDevicesMatchingConnectionStates(states);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700394 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700395 if (mService == null) Log.w(TAG, "Proxy not attached to service");
396 return new ArrayList<BluetoothDevice>();
397 } catch (RemoteException e) {
398 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
399 return new ArrayList<BluetoothDevice>();
400 } finally {
401 mServiceLock.readLock().unlock();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700402 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700403 }
404
405 /**
406 * {@inheritDoc}
407 */
Jack He2992cd02017-08-22 21:21:23 -0700408 @Override
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700409 public int getConnectionState(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700410 if (VDBG) log("getState(" + device + ")");
Calvin Ond7d16b92016-06-20 15:59:48 -0700411 try {
412 mServiceLock.readLock().lock();
413 if (mService != null && isEnabled()
Jack Hea355e5e2017-08-22 16:06:54 -0700414 && isValidDevice(device)) {
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700415 return mService.getConnectionState(device);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700416 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700417 if (mService == null) Log.w(TAG, "Proxy not attached to service");
418 return BluetoothProfile.STATE_DISCONNECTED;
419 } catch (RemoteException e) {
420 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
421 return BluetoothProfile.STATE_DISCONNECTED;
422 } finally {
423 mServiceLock.readLock().unlock();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700424 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700425 }
426
427 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700428 * Set priority of the profile
429 *
430 * <p> The device should already be paired.
Jack Hea355e5e2017-08-22 16:06:54 -0700431 * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700432 * {@link #PRIORITY_OFF},
433 *
434 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
435 * permission.
436 *
437 * @param device Paired bluetooth device
438 * @param priority
439 * @return true if priority is set, false on error
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700440 * @hide
441 */
442 public boolean setPriority(BluetoothDevice device, int priority) {
443 if (DBG) log("setPriority(" + device + ", " + priority + ")");
Calvin Ond7d16b92016-06-20 15:59:48 -0700444 try {
445 mServiceLock.readLock().lock();
446 if (mService != null && isEnabled()
Jack Hea355e5e2017-08-22 16:06:54 -0700447 && isValidDevice(device)) {
Jack He2992cd02017-08-22 21:21:23 -0700448 if (priority != BluetoothProfile.PRIORITY_OFF
449 && priority != BluetoothProfile.PRIORITY_ON) {
Calvin Ond7d16b92016-06-20 15:59:48 -0700450 return false;
451 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700452 return mService.setPriority(device, priority);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700453 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700454 if (mService == null) Log.w(TAG, "Proxy not attached to service");
455 return false;
456 } catch (RemoteException e) {
457 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
458 return false;
459 } finally {
460 mServiceLock.readLock().unlock();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700461 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700462 }
463
464 /**
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700465 * Get the priority of the profile.
466 *
467 * <p> The priority can be any of:
468 * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
469 * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
470 *
Jaikumar Ganeshf8789162011-05-26 13:56:40 -0700471 * @param device Bluetooth device
472 * @return priority of the device
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700473 * @hide
474 */
Tor Norbye2d497522015-04-23 17:10:21 -0700475 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700476 public int getPriority(BluetoothDevice device) {
Matthew Xie563e4142012-10-09 22:10:37 -0700477 if (VDBG) log("getPriority(" + device + ")");
Calvin Ond7d16b92016-06-20 15:59:48 -0700478 try {
479 mServiceLock.readLock().lock();
480 if (mService != null && isEnabled()
Jack Hea355e5e2017-08-22 16:06:54 -0700481 && isValidDevice(device)) {
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700482 return mService.getPriority(device);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700483 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700484 if (mService == null) Log.w(TAG, "Proxy not attached to service");
485 return BluetoothProfile.PRIORITY_OFF;
486 } catch (RemoteException e) {
487 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
488 return BluetoothProfile.PRIORITY_OFF;
489 } finally {
490 mServiceLock.readLock().unlock();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700491 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700492 }
493
494 /**
John Du5a0cf7a2013-07-19 11:30:34 -0700495 * Checks if Avrcp device supports the absolute volume feature.
496 *
497 * @return true if device supports absolute volume
498 * @hide
499 */
500 public boolean isAvrcpAbsoluteVolumeSupported() {
501 if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
Calvin Ond7d16b92016-06-20 15:59:48 -0700502 try {
503 mServiceLock.readLock().lock();
504 if (mService != null && isEnabled()) {
John Du5a0cf7a2013-07-19 11:30:34 -0700505 return mService.isAvrcpAbsoluteVolumeSupported();
John Du5a0cf7a2013-07-19 11:30:34 -0700506 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700507 if (mService == null) Log.w(TAG, "Proxy not attached to service");
508 return false;
509 } catch (RemoteException e) {
510 Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
511 return false;
512 } finally {
513 mServiceLock.readLock().unlock();
John Du5a0cf7a2013-07-19 11:30:34 -0700514 }
John Du5a0cf7a2013-07-19 11:30:34 -0700515 }
516
517 /**
RoboErik4197cb62015-01-21 15:45:32 -0800518 * Tells remote device to adjust volume. Only if absolute volume is
519 * supported. Uses the following values:
520 * <ul>
521 * <li>{@link AudioManager#ADJUST_LOWER}</li>
522 * <li>{@link AudioManager#ADJUST_RAISE}</li>
523 * <li>{@link AudioManager#ADJUST_MUTE}</li>
524 * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
525 * </ul>
John Du5a0cf7a2013-07-19 11:30:34 -0700526 *
RoboErik4197cb62015-01-21 15:45:32 -0800527 * @param direction One of the supported adjust values.
John Du5a0cf7a2013-07-19 11:30:34 -0700528 * @hide
529 */
530 public void adjustAvrcpAbsoluteVolume(int direction) {
531 if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
Calvin Ond7d16b92016-06-20 15:59:48 -0700532 try {
533 mServiceLock.readLock().lock();
534 if (mService != null && isEnabled()) {
John Du5a0cf7a2013-07-19 11:30:34 -0700535 mService.adjustAvrcpAbsoluteVolume(direction);
John Du5a0cf7a2013-07-19 11:30:34 -0700536 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700537 if (mService == null) Log.w(TAG, "Proxy not attached to service");
538 } catch (RemoteException e) {
539 Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
540 } finally {
541 mServiceLock.readLock().unlock();
John Du5a0cf7a2013-07-19 11:30:34 -0700542 }
John Du5a0cf7a2013-07-19 11:30:34 -0700543 }
544
545 /**
546 * Tells remote device to set an absolute volume. Only if absolute volume is supported
547 *
548 * @param volume Absolute volume to be set on AVRCP side
549 * @hide
550 */
551 public void setAvrcpAbsoluteVolume(int volume) {
552 if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
Calvin Ond7d16b92016-06-20 15:59:48 -0700553 try {
554 mServiceLock.readLock().lock();
555 if (mService != null && isEnabled()) {
John Du5a0cf7a2013-07-19 11:30:34 -0700556 mService.setAvrcpAbsoluteVolume(volume);
John Du5a0cf7a2013-07-19 11:30:34 -0700557 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700558 if (mService == null) Log.w(TAG, "Proxy not attached to service");
559 } catch (RemoteException e) {
560 Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
561 } finally {
562 mServiceLock.readLock().unlock();
John Du5a0cf7a2013-07-19 11:30:34 -0700563 }
John Du5a0cf7a2013-07-19 11:30:34 -0700564 }
565
566 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700567 * Check if A2DP profile is streaming music.
568 *
Jaikumar Ganeshc8fa4ff2011-01-25 16:03:13 -0800569 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700570 *
571 * @param device BluetoothDevice device
572 */
573 public boolean isA2dpPlaying(BluetoothDevice device) {
Calvin Ond7d16b92016-06-20 15:59:48 -0700574 try {
575 mServiceLock.readLock().lock();
576 if (mService != null && isEnabled()
Jack Hea355e5e2017-08-22 16:06:54 -0700577 && isValidDevice(device)) {
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700578 return mService.isA2dpPlaying(device);
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700579 }
Calvin Ond7d16b92016-06-20 15:59:48 -0700580 if (mService == null) Log.w(TAG, "Proxy not attached to service");
581 return false;
582 } catch (RemoteException e) {
583 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
584 return false;
585 } finally {
586 mServiceLock.readLock().unlock();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700587 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700588 }
589
590 /**
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -0700591 * This function checks if the remote device is an AVCRP
592 * target and thus whether we should send volume keys
593 * changes or not.
Jack Hea355e5e2017-08-22 16:06:54 -0700594 *
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -0700595 * @hide
596 */
597 public boolean shouldSendVolumeKeys(BluetoothDevice device) {
598 if (isEnabled() && isValidDevice(device)) {
599 ParcelUuid[] uuids = device.getUuids();
600 if (uuids == null) return false;
601
Jack Hea355e5e2017-08-22 16:06:54 -0700602 for (ParcelUuid uuid : uuids) {
Jaikumar Ganesh41d5c802010-10-13 19:11:28 -0700603 if (BluetoothUuid.isAvrcpTarget(uuid)) {
604 return true;
605 }
606 }
607 }
608 return false;
609 }
610
Matthew Xiea0c68032011-06-25 21:47:07 -0700611 /**
Pavlin Radoslavovb37f1812017-01-25 16:54:07 -0800612 * Gets the current codec status (configuration and capability).
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800613 *
Pavlin Radoslavovb37f1812017-01-25 16:54:07 -0800614 * @return the current codec status
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800615 * @hide
616 */
Pavlin Radoslavovb37f1812017-01-25 16:54:07 -0800617 public BluetoothCodecStatus getCodecStatus() {
618 if (DBG) Log.d(TAG, "getCodecStatus");
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800619 try {
620 mServiceLock.readLock().lock();
621 if (mService != null && isEnabled()) {
Pavlin Radoslavovb37f1812017-01-25 16:54:07 -0800622 return mService.getCodecStatus();
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800623 }
624 if (mService == null) {
625 Log.w(TAG, "Proxy not attached to service");
626 }
627 return null;
628 } catch (RemoteException e) {
Pavlin Radoslavovb37f1812017-01-25 16:54:07 -0800629 Log.e(TAG, "Error talking to BT service in getCodecStatus()", e);
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800630 return null;
631 } finally {
632 mServiceLock.readLock().unlock();
633 }
634 }
635
636 /**
637 * Sets the codec configuration preference.
638 *
639 * @param codecConfig the codec configuration preference
640 * @hide
641 */
642 public void setCodecConfigPreference(BluetoothCodecConfig codecConfig) {
643 if (DBG) Log.d(TAG, "setCodecConfigPreference");
644 try {
645 mServiceLock.readLock().lock();
646 if (mService != null && isEnabled()) {
647 mService.setCodecConfigPreference(codecConfig);
648 }
649 if (mService == null) Log.w(TAG, "Proxy not attached to service");
650 return;
651 } catch (RemoteException e) {
652 Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);
653 return;
654 } finally {
655 mServiceLock.readLock().unlock();
656 }
657 }
658
659 /**
Pavlin Radoslavov011597b2017-02-24 10:19:14 -0800660 * Enables the optional codecs.
661 *
662 * @hide
663 */
664 public void enableOptionalCodecs() {
665 if (DBG) Log.d(TAG, "enableOptionalCodecs");
666 enableDisableOptionalCodecs(true);
667 }
668
669 /**
670 * Disables the optional codecs.
671 *
672 * @hide
673 */
674 public void disableOptionalCodecs() {
675 if (DBG) Log.d(TAG, "disableOptionalCodecs");
676 enableDisableOptionalCodecs(false);
677 }
678
679 /**
680 * Enables or disables the optional codecs.
681 *
682 * @param enable if true, enable the optional codecs, other disable them
683 */
684 private void enableDisableOptionalCodecs(boolean enable) {
685 try {
686 mServiceLock.readLock().lock();
687 if (mService != null && isEnabled()) {
688 if (enable) {
689 mService.enableOptionalCodecs();
690 } else {
691 mService.disableOptionalCodecs();
692 }
693 }
694 if (mService == null) Log.w(TAG, "Proxy not attached to service");
695 return;
696 } catch (RemoteException e) {
697 Log.e(TAG, "Error talking to BT service in enableDisableOptionalCodecs()", e);
698 return;
699 } finally {
700 mServiceLock.readLock().unlock();
701 }
702 }
703
704 /**
Antony Sargentf5772c62017-04-26 16:37:53 -0700705 * Returns whether this device supports optional codecs.
706 *
707 * @param device The device to check
708 * @return one of OPTIONAL_CODECS_SUPPORT_UNKNOWN, OPTIONAL_CODECS_NOT_SUPPORTED, or
Jack Hea355e5e2017-08-22 16:06:54 -0700709 * OPTIONAL_CODECS_SUPPORTED.
Antony Sargentf5772c62017-04-26 16:37:53 -0700710 * @hide
711 */
712 public int supportsOptionalCodecs(BluetoothDevice device) {
713 try {
714 mServiceLock.readLock().lock();
715 if (mService != null && isEnabled() && isValidDevice(device)) {
716 return mService.supportsOptionalCodecs(device);
717 }
718 if (mService == null) Log.w(TAG, "Proxy not attached to service");
719 return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
720 } catch (RemoteException e) {
721 Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
722 return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
723 } finally {
724 mServiceLock.readLock().unlock();
725 }
726 }
727
728 /**
729 * Returns whether this device should have optional codecs enabled.
730 *
731 * @param device The device in question.
732 * @return one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
Jack Hea355e5e2017-08-22 16:06:54 -0700733 * OPTIONAL_CODECS_PREF_DISABLED.
Antony Sargentf5772c62017-04-26 16:37:53 -0700734 * @hide
735 */
736 public int getOptionalCodecsEnabled(BluetoothDevice device) {
737 try {
738 mServiceLock.readLock().lock();
739 if (mService != null && isEnabled() && isValidDevice(device)) {
740 return mService.getOptionalCodecsEnabled(device);
741 }
742 if (mService == null) Log.w(TAG, "Proxy not attached to service");
743 return OPTIONAL_CODECS_PREF_UNKNOWN;
744 } catch (RemoteException e) {
745 Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
746 return OPTIONAL_CODECS_PREF_UNKNOWN;
747 } finally {
748 mServiceLock.readLock().unlock();
749 }
750 }
751
752 /**
753 * Sets a persistent preference for whether a given device should have optional codecs enabled.
754 *
755 * @param device The device to set this preference for.
756 * @param value Whether the optional codecs should be enabled for this device. This should be
Jack Hea355e5e2017-08-22 16:06:54 -0700757 * one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
758 * OPTIONAL_CODECS_PREF_DISABLED.
Antony Sargentf5772c62017-04-26 16:37:53 -0700759 * @hide
760 */
761 public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
762 try {
Jack He2992cd02017-08-22 21:21:23 -0700763 if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
764 && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED
765 && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) {
Antony Sargentf5772c62017-04-26 16:37:53 -0700766 Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
767 return;
768 }
769 mServiceLock.readLock().lock();
770 if (mService != null && isEnabled()
771 && isValidDevice(device)) {
772 mService.setOptionalCodecsEnabled(device, value);
773 }
774 if (mService == null) Log.w(TAG, "Proxy not attached to service");
775 return;
776 } catch (RemoteException e) {
777 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
778 return;
779 } finally {
780 mServiceLock.readLock().unlock();
781 }
782 }
783
784 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700785 * Helper for converting a state to a string.
786 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 * For debug use only - strings are not internationalized.
Jack Hea355e5e2017-08-22 16:06:54 -0700788 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 * @hide
790 */
791 public static String stateToString(int state) {
792 switch (state) {
Jack Hea355e5e2017-08-22 16:06:54 -0700793 case STATE_DISCONNECTED:
794 return "disconnected";
795 case STATE_CONNECTING:
796 return "connecting";
797 case STATE_CONNECTED:
798 return "connected";
799 case STATE_DISCONNECTING:
800 return "disconnecting";
801 case STATE_PLAYING:
802 return "playing";
803 case STATE_NOT_PLAYING:
804 return "not playing";
805 default:
806 return "<unknown state " + state + ">";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 }
808 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800809
Matthew Xie9b693992013-10-10 11:21:40 -0700810 private final ServiceConnection mConnection = new ServiceConnection() {
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800811 public void onServiceConnected(ComponentName className, IBinder service) {
812 if (DBG) Log.d(TAG, "Proxy object connected");
Calvin Ond7d16b92016-06-20 15:59:48 -0700813 try {
814 mServiceLock.writeLock().lock();
Jeff Sharkey0a17db12016-11-04 11:23:46 -0600815 mService = IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
Calvin Ond7d16b92016-06-20 15:59:48 -0700816 } finally {
817 mServiceLock.writeLock().unlock();
818 }
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800819
820 if (mServiceListener != null) {
821 mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
822 }
823 }
Jack Hea355e5e2017-08-22 16:06:54 -0700824
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800825 public void onServiceDisconnected(ComponentName className) {
826 if (DBG) Log.d(TAG, "Proxy object disconnected");
Calvin Ond7d16b92016-06-20 15:59:48 -0700827 try {
828 mServiceLock.writeLock().lock();
829 mService = null;
830 } finally {
831 mServiceLock.writeLock().unlock();
832 }
Matthew Xie3e8c82e2012-02-16 16:57:18 -0800833 if (mServiceListener != null) {
834 mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
835 }
836 }
837 };
838
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700839 private boolean isEnabled() {
Jack Hea355e5e2017-08-22 16:06:54 -0700840 if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
841 return false;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700842 }
843
844 private boolean isValidDevice(BluetoothDevice device) {
Jack Hea355e5e2017-08-22 16:06:54 -0700845 if (device == null) return false;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700846
Jack Hea355e5e2017-08-22 16:06:54 -0700847 if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
848 return false;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700849 }
850
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800851 private static void log(String msg) {
Jack Hea355e5e2017-08-22 16:06:54 -0700852 Log.d(TAG, msg);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800853 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854}