194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood/* 294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * Copyright (C) 2014 The Android Open Source Project 394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * 494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * you may not use this file except in compliance with the License. 694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * You may obtain a copy of the License at 794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * 894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * 1094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * Unless required by applicable law or agreed to in writing, software 1194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * See the License for the specific language governing permissions and 1494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * limitations under the License. 1594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood */ 1694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 1794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodpackage android.bluetooth; 1894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 1994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodimport android.content.ComponentName; 2094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodimport android.content.Context; 2194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodimport android.content.Intent; 2294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodimport android.content.ServiceConnection; 231bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwalimport android.media.MediaMetadata; 241bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwalimport android.media.session.PlaybackState; 2594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodimport android.os.IBinder; 2694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodimport android.os.RemoteException; 2794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodimport android.util.Log; 2894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 2994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodimport java.util.ArrayList; 3094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodimport java.util.List; 3194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 3294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood/** 331bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * This class provides the public APIs to control the Bluetooth AVRCP Controller. It currently 341bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * supports player information, playback support and track metadata. 3594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * 3694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood *<p>BluetoothAvrcpController is a proxy object for controlling the Bluetooth AVRCP 3794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get 3894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * the BluetoothAvrcpController proxy object. 3994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * 4094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * {@hide} 4194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood */ 4294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwoodpublic final class BluetoothAvrcpController implements BluetoothProfile { 4394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private static final String TAG = "BluetoothAvrcpController"; 441bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal private static final boolean DBG = false; 4594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private static final boolean VDBG = false; 4694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 4794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood /** 4894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * Intent used to broadcast the change in connection state of the AVRCP Controller 4994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * profile. 5094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * 5194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * <p>This intent will have 3 extras: 5294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * <ul> 5394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> 5494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> 5594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> 5694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * </ul> 5794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * 5894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of 5994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, 6094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. 6194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * 6294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to 6394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * receive. 6494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood */ 6594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood public static final String ACTION_CONNECTION_STATE_CHANGED = 661bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal "android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED"; 671bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 681bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /** 691bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * Intent used to broadcast the change in metadata state of playing track on the AVRCP 701bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * AG. 711bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * 721bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * <p>This intent will have the two extras: 731bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * <ul> 741bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * <li> {@link #EXTRA_METADATA} - {@link MediaMetadata} containing the current metadata.</li> 751bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * <li> {@link #EXTRA_PLAYBACK} - {@link PlaybackState} containing the current playback 761bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * state. </li> 771bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * </ul> 781bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal */ 791bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final String ACTION_TRACK_EVENT = 801bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal "android.bluetooth.avrcp-controller.profile.action.TRACK_EVENT"; 811bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 821bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 831bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /** 841bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * Intent used to broadcast the change in player application setting state on AVRCP AG. 851bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * 861bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * <p>This intent will have the following extras: 871bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * <ul> 881bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * <li> {@link #EXTRA_PLAYER_SETTING} - {@link BluetoothAvrcpPlayerSettings} containing the 891bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * most recent player setting. </li> 901bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * </ul> 911bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal */ 921bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final String ACTION_PLAYER_SETTING = 931bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal "android.bluetooth.avrcp-controller.profile.action.PLAYER_SETTING"; 941bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 951bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final String EXTRA_METADATA = 961bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal "android.bluetooth.avrcp-controller.profile.extra.METADATA"; 971bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 981bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final String EXTRA_PLAYBACK = 991bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal "android.bluetooth.avrcp-controller.profile.extra.PLAYBACK"; 1001bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 1011bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final String EXTRA_PLAYER_SETTING = 1021bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal "android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING"; 1031bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 1041bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /* 1051bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * KeyCoded for Pass Through Commands 1061bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal */ 1071bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_PLAY = 0x44; 1081bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_PAUSE = 0x46; 1091bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_VOL_UP = 0x41; 1101bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_VOL_DOWN = 0x42; 1111bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_STOP = 0x45; 1121bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_FF = 0x49; 1131bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_REWIND = 0x48; 1141bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_FORWARD = 0x4B; 1151bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_BACKWARD = 0x4C; 1161bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /* Key State Variables */ 1171bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int KEY_STATE_PRESSED = 0; 1181bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int KEY_STATE_RELEASED = 1; 1191bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /* Group Navigation Key Codes */ 1201bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_NEXT_GRP = 0x00; 1211bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public static final int PASS_THRU_CMD_ID_PREV_GRP = 0x01; 1221bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 12394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 12494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private Context mContext; 12594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private ServiceListener mServiceListener; 12694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private IBluetoothAvrcpController mService; 12794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private BluetoothAdapter mAdapter; 12894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 12994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = 1301bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal new IBluetoothStateChangeCallback.Stub() { 1311bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public void onBluetoothStateChange(boolean up) { 1321bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); 1331bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (!up) { 1341bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (VDBG) Log.d(TAG,"Unbinding service..."); 1351bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal synchronized (mConnection) { 1361bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal try { 1371bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal mService = null; 1381bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal mContext.unbindService(mConnection); 1391bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } catch (Exception re) { 1401bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal Log.e(TAG,"",re); 14194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 1421bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 1431bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } else { 1441bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal synchronized (mConnection) { 1451bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal try { 1461bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (mService == null) { 1471bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (VDBG) Log.d(TAG,"Binding service..."); 1481bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal doBind(); 14994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 1501bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } catch (Exception re) { 1511bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal Log.e(TAG,"",re); 15294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 15394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 15494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 1551bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 1561bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal }; 15794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 15894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood /** 15994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * Create a BluetoothAvrcpController proxy object for interacting with the local 16094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * Bluetooth AVRCP service. 16194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * 16294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood */ 16394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood /*package*/ BluetoothAvrcpController(Context context, ServiceListener l) { 16494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mContext = context; 16594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mServiceListener = l; 16694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mAdapter = BluetoothAdapter.getDefaultAdapter(); 16794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood IBluetoothManager mgr = mAdapter.getBluetoothManager(); 16894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mgr != null) { 16994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood try { 17094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); 17194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } catch (RemoteException e) { 17294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Log.e(TAG,"",e); 17394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 17494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 17594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 17694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood doBind(); 17794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 17894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 17994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood boolean doBind() { 18094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Intent intent = new Intent(IBluetoothAvrcpController.class.getName()); 18194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 18294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood intent.setComponent(comp); 18394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, 18494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood android.os.Process.myUserHandle())) { 18594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Log.e(TAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent); 18694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return false; 18794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 18894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return true; 18994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 19094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 19194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood /*package*/ void close() { 19294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mServiceListener = null; 19394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood IBluetoothManager mgr = mAdapter.getBluetoothManager(); 19494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mgr != null) { 19594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood try { 19694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); 19794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } catch (Exception e) { 19894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Log.e(TAG,"",e); 19994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 20094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 20194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 20294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood synchronized (mConnection) { 20394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mService != null) { 20494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood try { 20594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mService = null; 20694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mContext.unbindService(mConnection); 20794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } catch (Exception re) { 20894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Log.e(TAG,"",re); 20994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 21094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 21194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 21294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 21394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 21494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood public void finalize() { 21594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood close(); 21694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 21794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 21894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood /** 21994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * {@inheritDoc} 22094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood */ 22194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood public List<BluetoothDevice> getConnectedDevices() { 22294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (VDBG) log("getConnectedDevices()"); 22394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mService != null && isEnabled()) { 22494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood try { 22594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return mService.getConnectedDevices(); 22694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } catch (RemoteException e) { 22794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 22894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return new ArrayList<BluetoothDevice>(); 22994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 23094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 23194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mService == null) Log.w(TAG, "Proxy not attached to service"); 23294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return new ArrayList<BluetoothDevice>(); 23394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 23494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 23594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood /** 23694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * {@inheritDoc} 23794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood */ 23894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 23994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (VDBG) log("getDevicesMatchingStates()"); 24094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mService != null && isEnabled()) { 24194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood try { 24294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return mService.getDevicesMatchingConnectionStates(states); 24394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } catch (RemoteException e) { 24494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 24594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return new ArrayList<BluetoothDevice>(); 24694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 24794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 24894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mService == null) Log.w(TAG, "Proxy not attached to service"); 24994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return new ArrayList<BluetoothDevice>(); 25094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 25194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 25294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood /** 25394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood * {@inheritDoc} 25494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood */ 25594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood public int getConnectionState(BluetoothDevice device) { 25694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (VDBG) log("getState(" + device + ")"); 25794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mService != null && isEnabled() 25894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood && isValidDevice(device)) { 25994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood try { 26094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return mService.getConnectionState(device); 26194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } catch (RemoteException e) { 26294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 26394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return BluetoothProfile.STATE_DISCONNECTED; 26494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 26594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 26694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mService == null) Log.w(TAG, "Proxy not attached to service"); 26794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return BluetoothProfile.STATE_DISCONNECTED; 26894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 26994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 27094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood public void sendPassThroughCmd(BluetoothDevice device, int keyCode, int keyState) { 27194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (DBG) Log.d(TAG, "sendPassThroughCmd"); 27294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mService != null && isEnabled()) { 27394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood try { 27494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mService.sendPassThroughCmd(device, keyCode, keyState); 27594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return; 27694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } catch (RemoteException e) { 27794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Log.e(TAG, "Error talking to BT service in sendPassThroughCmd()", e); 27894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return; 27994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 28094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 28194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mService == null) Log.w(TAG, "Proxy not attached to service"); 28294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 28394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 2841bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /** 2851bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * Gets the player application settings. 2861bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * 2871bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * @return the {@link BluetoothAvrcpPlayerSettings} or {@link null} if there is an error. 2881bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal */ 2891bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) { 2901bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (DBG) Log.d(TAG, "getPlayerSettings"); 2911bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal BluetoothAvrcpPlayerSettings settings = null; 2921bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (mService != null && isEnabled()) { 2931bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal try { 2941bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal settings = mService.getPlayerSettings(device); 2951bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } catch (RemoteException e) { 2961bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal Log.e(TAG, "Error talking to BT service in getMetadata() " + e); 2971bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return null; 2981bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 2991bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3001bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return settings; 3011bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3021bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 3031bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /** 3041bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * Gets the metadata for the current track. 3051bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * 3061bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * This should be usually called when application UI needs to be updated, eg. when the track 3071bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * changes or immediately after connecting and getting the current state. 3081bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * @return the {@link MediaMetadata} or {@link null} if there is an error. 3091bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal */ 3101bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public MediaMetadata getMetadata(BluetoothDevice device) { 3111bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (DBG) Log.d(TAG, "getMetadata"); 3121bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal MediaMetadata metadata = null; 3131bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (mService != null && isEnabled()) { 3141bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal try { 3151bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal metadata = mService.getMetadata(device); 3161bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } catch (RemoteException e) { 3171bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal Log.e(TAG, "Error talking to BT service in getMetadata() " + e); 3181bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return null; 3191bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3201bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3211bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return metadata; 3221bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3231bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 3241bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /** 3251bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * Gets the playback state for current track. 3261bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * 3271bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * When the application is first connecting it can use current track state to get playback info. 3281bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * For all further updates it should listen to notifications. 3291bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * @return the {@link PlaybackState} or {@link null} if there is an error. 3301bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal */ 3311bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public PlaybackState getPlaybackState(BluetoothDevice device) { 3321bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (DBG) Log.d(TAG, "getPlaybackState"); 3331bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal PlaybackState playbackState = null; 3341bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (mService != null && isEnabled()) { 3351bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal try { 3361bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal playbackState = mService.getPlaybackState(device); 3371bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } catch (RemoteException e) { 3381bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal Log.e(TAG, 3391bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal "Error talking to BT service in getPlaybackState() " + e); 3401bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return null; 3411bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3421bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3431bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return playbackState; 3441bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3451bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 3461bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /** 3471bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * Sets the player app setting for current player. 3481bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * returns true in case setting is supported by remote, false otherwise 3491bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal */ 3501bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) { 3511bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (DBG) Log.d(TAG, "setPlayerApplicationSetting"); 3521bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (mService != null && isEnabled()) { 3531bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal try { 3541bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return mService.setPlayerApplicationSetting(plAppSetting); 3551bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } catch (RemoteException e) { 3561bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal Log.e(TAG, "Error talking to BT service in setPlayerApplicationSetting() " + e); 3571bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return false; 3581bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3591bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3601bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (mService == null) Log.w(TAG, "Proxy not attached to service"); 3611bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return false; 3621bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3631bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 3641bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal /* 3651bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * Send Group Navigation Command to Remote. 3661bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal * possible keycode values: next_grp, previous_grp defined above 3671bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal */ 3681bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) { 3691bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = " + keyState); 3701bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (mService != null && isEnabled()) { 3711bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal try { 3721bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal mService.sendGroupNavigationCmd(device, keyCode, keyState); 3731bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return; 3741bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } catch (RemoteException e) { 3751bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal Log.e(TAG, "Error talking to BT service in sendGroupNavigationCmd()", e); 3761bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal return; 3771bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3781bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3791bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal if (mService == null) Log.w(TAG, "Proxy not attached to service"); 3801bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal } 3811bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal 38294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private final ServiceConnection mConnection = new ServiceConnection() { 38394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood public void onServiceConnected(ComponentName className, IBinder service) { 38494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (DBG) Log.d(TAG, "Proxy object connected"); 38594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mService = IBluetoothAvrcpController.Stub.asInterface(service); 38694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 38794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mServiceListener != null) { 38894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER, 38994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood BluetoothAvrcpController.this); 39094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 39194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 39294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood public void onServiceDisconnected(ComponentName className) { 39394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (DBG) Log.d(TAG, "Proxy object disconnected"); 39494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mService = null; 39594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mServiceListener != null) { 39694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood mServiceListener.onServiceDisconnected(BluetoothProfile.AVRCP_CONTROLLER); 39794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 39894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 39994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood }; 40094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 40194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private boolean isEnabled() { 40294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; 40394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return false; 40494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 40594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 40694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private boolean isValidDevice(BluetoothDevice device) { 40794b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (device == null) return false; 40894b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 40994b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; 41094b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood return false; 41194b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 41294b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood 41394b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood private static void log(String msg) { 41494b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood Log.d(TAG, msg); 41594b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood } 41694b59de852df7b6ce16aef73a9b2c11be8f3102dMike Lockwood} 417