BluetoothA2dp.java revision c8fa4ff838a0c3d2c67db65540fa751e5abe27ed
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.bluetooth; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.SdkConstant; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.SdkConstant.SdkConstantType; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 2341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganeshimport android.os.ParcelUuid; 2462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport android.os.RemoteException; 2562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport android.os.ServiceManager; 2662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport android.server.BluetoothA2dpService; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2903cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganeshimport java.util.ArrayList; 3003cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganeshimport java.util.List; 3162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 3462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * This class provides the public APIs to control the Bluetooth A2DP 3562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * profile. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh *<p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP 3862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get 3962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * the BluetoothA2dp proxy object. 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> Android only supports one connected Bluetooth A2dp device at a time. 4262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Each method is protected with its appropriate permission. 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshpublic final class BluetoothA2dp implements BluetoothProfile { 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "BluetoothA2dp"; 46f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project private static final boolean DBG = false; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 4962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Intent used to broadcast the change in connection state of the A2DP 5062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * profile. 5162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 5262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p>This intent will have 3 extras: 53c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <ul> 54c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> 55c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> 56c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> 57c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * </ul> 5862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 5962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of 6062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, 6162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. 6262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 63c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to 64c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * receive. 6562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh */ 6662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 6762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public static final String ACTION_CONNECTION_STATE_CHANGED = 6862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED"; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 7162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Intent used to broadcast the change in the Playing state of the A2DP 7262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * profile. 7362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 7462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p>This intent will have 3 extras: 75c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <ul> 76c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> 77c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> 78c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. <li/> 79c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * </ul> 8062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 8162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of 8262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING}, 8362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 84c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to 85c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * receive. 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 8862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public static final String ACTION_PLAYING_STATE_CHANGED = 8962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED"; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 9262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * A2DP sink device is streaming music. This state can be one of 9362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of 9462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #ACTION_PLAYING_STATE_CHANGED} intent. 9562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh */ 9662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public static final int STATE_PLAYING = 10; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 9962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * A2DP sink device is NOT streaming music. This state can be one of 10062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of 10162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #ACTION_PLAYING_STATE_CHANGED} intent. 10262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh */ 10362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public static final int STATE_NOT_PLAYING = 11; 104bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly 10562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private ServiceListener mServiceListener; 10662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private IBluetoothA2dp mService; 10762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private BluetoothAdapter mAdapter; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a BluetoothA2dp proxy object for interacting with the local 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bluetooth A2DP service. 11262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /*package*/ BluetoothA2dp(Context mContext, ServiceListener l) { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE); 11662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh mServiceListener = l; 11762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh mAdapter = BluetoothAdapter.getDefaultAdapter(); 118081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan if (b != null) { 119081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan mService = IBluetoothA2dp.Stub.asInterface(b); 12062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mServiceListener != null) { 12162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh mServiceListener.onServiceConnected(BluetoothProfile.A2DP, this); 12262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 123081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan } else { 124081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan Log.w(TAG, "Bluetooth A2DP service not available!"); 125081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan 126081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan // Instead of throwing an exception which prevents people from going 127081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan // into Wireless settings in the emulator. Let it crash later when it is actually used. 128081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan mService = null; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 13362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 13462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @hide 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean connect(BluetoothDevice device) { 13762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("connect(" + device + ")"); 13862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 13962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 14062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 14162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.connect(device); 14262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 14362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 14462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 14562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 14862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 15262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 15362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @hide 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean disconnect(BluetoothDevice device) { 15662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("disconnect(" + device + ")"); 15762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 15862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 15962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 16062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.disconnect(device); 16162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 16262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 16362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 16462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 16762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 17162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 172f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan */ 17303cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh public List<BluetoothDevice> getConnectedDevices() { 17462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("getConnectedDevices()"); 17562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled()) { 17662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 17703cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return mService.getConnectedDevices(); 17862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 17962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 18003cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 18162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 182f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan } 18362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 18403cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 185f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan } 186f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan 18762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 18862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 189f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan */ 19003cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 19162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("getDevicesMatchingStates()"); 19262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled()) { 19362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 19403cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return mService.getDevicesMatchingConnectionStates(states); 19562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 19662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 19703cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 19862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 199f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan } 20062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 20103cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 202f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan } 203f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan 20462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 20562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 20762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public int getConnectionState(BluetoothDevice device) { 20862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("getState(" + device + ")"); 20962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() 21062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh && isValidDevice(device)) { 21162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 21262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.getConnectionState(device); 21362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 21462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 21562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return BluetoothProfile.STATE_DISCONNECTED; 21662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 21762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 21862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 21962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return BluetoothProfile.STATE_DISCONNECTED; 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 22362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 22662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean setPriority(BluetoothDevice device, int priority) { 22762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("setPriority(" + device + ", " + priority + ")"); 22862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() 22962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh && isValidDevice(device)) { 23062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (priority != BluetoothProfile.PRIORITY_OFF && 23162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh priority != BluetoothProfile.PRIORITY_ON) { 23262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 23362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 23462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 23562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.setPriority(device, priority); 23662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 23762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 23862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 23962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 24262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 24662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 247b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh * @hide 248b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh */ 24962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public int getPriority(BluetoothDevice device) { 25062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("getPriority(" + device + ")"); 25162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() 25262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh && isValidDevice(device)) { 25362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 25462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.getPriority(device); 25562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 25662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 25762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return BluetoothProfile.PRIORITY_OFF; 25862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 259b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh } 26062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 26162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return BluetoothProfile.PRIORITY_OFF; 262b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh } 263b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh 26462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 26562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Check if A2DP profile is streaming music. 26662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 267c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 26862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 26962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @param device BluetoothDevice device 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 27162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean isA2dpPlaying(BluetoothDevice device) { 27262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() 27362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh && isValidDevice(device)) { 27462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 27562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.isA2dpPlaying(device); 27662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 27762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 27862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 27962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 28262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 28662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Initiate suspend from an A2DP sink. 28762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 28862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> This API will return false in scenarios like the A2DP 28962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * device is not in connected state etc. When this API returns, 290c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * true, it is guaranteed that {@link #ACTION_CONNECTION_STATE_CHANGED} 29162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * intent will be broadcasted with the state. Users can get the 29262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * state of the A2DP device from this intent. 29362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 29462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 295c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * permission. 29662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 29762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @param device Remote A2DP sink 29862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @return false on immediate error, 29962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * true otherwise 30062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @hide 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 30262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean suspendSink(BluetoothDevice device) { 30362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() 30462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh && isValidDevice(device)) { 30562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 30662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.suspendSink(device); 30762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 30862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 30962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 31062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 31362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 31762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Initiate resume from a suspended A2DP sink. 31862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 31962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> This API will return false in scenarios like the A2DP 32062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * device is not in suspended state etc. When this API returns, 32162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * true, it is guaranteed that {@link #ACTION_SINK_STATE_CHANGED} 32262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * intent will be broadcasted with the state. Users can get the 32362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * state of the A2DP device from this intent. 32462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 32562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 32662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 32762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @param device Remote A2DP sink 32862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @return false on immediate error, 32962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * true otherwise 33062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @hide 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 33262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean resumeSink(BluetoothDevice device) { 33362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() 33462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh && isValidDevice(device)) { 33562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 33662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.resumeSink(device); 33762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 33862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 33962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 34062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 34362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34641d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh /** 34741d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh * This function checks if the remote device is an AVCRP 34841d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh * target and thus whether we should send volume keys 34941d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh * changes or not. 35041d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh * @hide 35141d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh */ 35241d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh public boolean shouldSendVolumeKeys(BluetoothDevice device) { 35341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh if (isEnabled() && isValidDevice(device)) { 35441d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh ParcelUuid[] uuids = device.getUuids(); 35541d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh if (uuids == null) return false; 35641d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh 35741d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh for (ParcelUuid uuid: uuids) { 35841d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh if (BluetoothUuid.isAvrcpTarget(uuid)) { 35941d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh return true; 36041d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh } 36141d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh } 36241d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh } 36341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh return false; 36441d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh } 36541d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh 36662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 36762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Helper for converting a state to a string. 36862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For debug use only - strings are not internationalized. 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String stateToString(int state) { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (state) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_DISCONNECTED: 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "disconnected"; 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_CONNECTING: 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "connecting"; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_CONNECTED: 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "connected"; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_DISCONNECTING: 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "disconnecting"; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_PLAYING: 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "playing"; 38462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh case STATE_NOT_PLAYING: 38562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return "not playing"; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "<unknown state " + state + ">"; 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 390f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project 39162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private boolean isEnabled() { 39262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; 39362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 39462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 39562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 39662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private boolean isValidDevice(BluetoothDevice device) { 39762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (device == null) return false; 39862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 39962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; 40062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 40162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 40262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 403f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project private static void log(String msg) { 40462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.d(TAG, msg); 405f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project } 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 407