1cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo/* 2cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Copyright (C) 2016 The Android Open Source Project 3cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * 4cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Licensed under the Apache License, Version 2.0 (the "License"); 5cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * you may not use this file except in compliance with the License. 6cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * You may obtain a copy of the License at 7cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * 8cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * http://www.apache.org/licenses/LICENSE-2.0 9cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * 10cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Unless required by applicable law or agreed to in writing, software 11cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * distributed under the License is distributed on an "AS IS" BASIS, 12cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * See the License for the specific language governing permissions and 14cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * limitations under the License. 15cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */ 16cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 17cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzopackage android.bluetooth; 18cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 19cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.content.ComponentName; 20cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.content.Context; 21cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.content.Intent; 22cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.content.ServiceConnection; 230a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkeyimport android.os.Binder; 24cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.os.IBinder; 25a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack Heimport android.os.RemoteException; 26cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzoimport android.util.Log; 27cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 28a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack Heimport java.util.ArrayList; 29a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack Heimport java.util.List; 30a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He 31cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo/** 32cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * This class provides the APIs to control the Bluetooth PBAP Client Profile. 33a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * 34a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @hide 35cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */ 36cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzopublic final class BluetoothPbapClient implements BluetoothProfile { 37cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 38cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private static final String TAG = "BluetoothPbapClient"; 39cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private static final boolean DBG = false; 40cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private static final boolean VDBG = false; 41cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 42cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public static final String ACTION_CONNECTION_STATE_CHANGED = 4337ab815c96737ecbd6a4c807a42bbab5c661e521Jack He "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED"; 44cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 4516eeac356c68f3674677169b618774718ec982b2Jack He private volatile IBluetoothPbapClient mService; 46cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private final Context mContext; 47cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private ServiceListener mServiceListener; 48cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private BluetoothAdapter mAdapter; 49cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 50cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo /** There was an error trying to obtain the state */ 51a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He public static final int STATE_ERROR = -1; 52cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 53cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public static final int RESULT_FAILURE = 0; 54cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public static final int RESULT_SUCCESS = 1; 55cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo /** Connection canceled before completion. */ 56cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public static final int RESULT_CANCELED = 2; 57cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 582992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = 59cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo new IBluetoothStateChangeCallback.Stub() { 60cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public void onBluetoothStateChange(boolean up) { 61cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (DBG) { 62cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.d(TAG, "onBluetoothStateChange: PBAP CLIENT up=" + up); 63cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 64cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (!up) { 65cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (VDBG) { 66a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.d(TAG, "Unbinding service..."); 67cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 68cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo synchronized (mConnection) { 69cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 70cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mService = null; 71cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mContext.unbindService(mConnection); 72cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (Exception re) { 73a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.e(TAG, "", re); 74cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 75cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 76cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } else { 77cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo synchronized (mConnection) { 78cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 79cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (mService == null) { 80cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (VDBG) { 81a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.d(TAG, "Binding service..."); 82cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 83cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo doBind(); 84cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 85cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (Exception re) { 86a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.e(TAG, "", re); 87cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 88cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 89cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 90cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 91a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He }; 92cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 93cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo /** 94cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Create a BluetoothPbapClient proxy object. 95cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */ 96cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo BluetoothPbapClient(Context context, ServiceListener l) { 97cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (DBG) { 98cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.d(TAG, "Create BluetoothPbapClient proxy object"); 99cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 100cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mContext = context; 101cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mServiceListener = l; 102cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mAdapter = BluetoothAdapter.getDefaultAdapter(); 103cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo IBluetoothManager mgr = mAdapter.getBluetoothManager(); 104cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (mgr != null) { 105cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 106cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); 107cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (RemoteException e) { 108a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.e(TAG, "", e); 109cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 110cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 111cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo doBind(); 112cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 113cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 114cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private boolean doBind() { 115cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Intent intent = new Intent(IBluetoothPbapClient.class.getName()); 116cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 117cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo intent.setComponent(comp); 118cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, 119ad357d1839760849fcbcb8cbdce34003e8831acdJeff Sharkey mContext.getUser())) { 120cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent); 121cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return false; 122cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 123cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return true; 124cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 125cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 126cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo protected void finalize() throws Throwable { 127cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 128cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo close(); 129cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } finally { 130cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo super.finalize(); 131cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 132cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 133cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 134cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo /** 135cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Close the connection to the backing service. 136cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Other public functions of BluetoothPbapClient will return default error 137cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * results once close() has been called. Multiple invocations of close() 138cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * are ok. 139cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */ 140cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public synchronized void close() { 141cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo IBluetoothManager mgr = mAdapter.getBluetoothManager(); 142cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (mgr != null) { 143cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 144cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); 145cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (Exception e) { 146a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.e(TAG, "", e); 147cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 148cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 149cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 150cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo synchronized (mConnection) { 151cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (mService != null) { 152cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 153cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mService = null; 154cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mContext.unbindService(mConnection); 155cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (Exception re) { 156a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.e(TAG, "", re); 157cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 158cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 159cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 160cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mServiceListener = null; 161cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 162cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 163cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo /** 164cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Initiate connection. 165cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Upon successful connection to remote PBAP server the Client will 166cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * attempt to automatically download the users phonebook and call log. 167cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * 168a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param device a remote device we want connect to 169a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @return <code>true</code> if command has been issued successfully; <code>false</code> 170a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * otherwise; 171cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */ 172cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public boolean connect(BluetoothDevice device) { 173cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (DBG) { 174cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo log("connect(" + device + ") for PBAP Client."); 175cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 17616eeac356c68f3674677169b618774718ec982b2Jack He final IBluetoothPbapClient service = mService; 17716eeac356c68f3674677169b618774718ec982b2Jack He if (service != null && isEnabled() && isValidDevice(device)) { 178cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 17916eeac356c68f3674677169b618774718ec982b2Jack He return service.connect(device); 180cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (RemoteException e) { 181cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 182cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return false; 183cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 184cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 18516eeac356c68f3674677169b618774718ec982b2Jack He if (service == null) { 186cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.w(TAG, "Proxy not attached to service"); 187cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 188cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return false; 189cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 190cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 191cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo /** 192cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Initiate disconnect. 193cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * 194cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * @param device Remote Bluetooth Device 195a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @return false on error, true otherwise 196cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */ 197563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo public boolean disconnect(BluetoothDevice device) { 198cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (DBG) { 199a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He log("disconnect(" + device + ")" + new Exception()); 200cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 20116eeac356c68f3674677169b618774718ec982b2Jack He final IBluetoothPbapClient service = mService; 20216eeac356c68f3674677169b618774718ec982b2Jack He if (service != null && isEnabled() && isValidDevice(device)) { 203cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 20416eeac356c68f3674677169b618774718ec982b2Jack He service.disconnect(device); 205cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return true; 206cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (RemoteException e) { 207a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.e(TAG, Log.getStackTraceString(new Throwable())); 208a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He return false; 209cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 210cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 21116eeac356c68f3674677169b618774718ec982b2Jack He if (service == null) { 212cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.w(TAG, "Proxy not attached to service"); 213cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 214cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return false; 215cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 216cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 217cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo /** 218cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Get the list of connected devices. 219cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Currently at most one. 220cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * 221cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * @return list of connected devices 222cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */ 223cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo @Override 224cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public List<BluetoothDevice> getConnectedDevices() { 225cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (DBG) { 226cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo log("getConnectedDevices()"); 227cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 22816eeac356c68f3674677169b618774718ec982b2Jack He final IBluetoothPbapClient service = mService; 22916eeac356c68f3674677169b618774718ec982b2Jack He if (service != null && isEnabled()) { 230cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 23116eeac356c68f3674677169b618774718ec982b2Jack He return service.getConnectedDevices(); 232cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (RemoteException e) { 233cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 234cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return new ArrayList<BluetoothDevice>(); 235cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 236cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 23716eeac356c68f3674677169b618774718ec982b2Jack He if (service == null) { 238cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.w(TAG, "Proxy not attached to service"); 239cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 240cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return new ArrayList<BluetoothDevice>(); 241cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 242cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 243cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo /** 244cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Get the list of devices matching specified states. Currently at most one. 245cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * 246cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * @return list of matching devices 247cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */ 248cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo @Override 249cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 250cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (DBG) { 251cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo log("getDevicesMatchingStates()"); 252cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 25316eeac356c68f3674677169b618774718ec982b2Jack He final IBluetoothPbapClient service = mService; 25416eeac356c68f3674677169b618774718ec982b2Jack He if (service != null && isEnabled()) { 255cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 25616eeac356c68f3674677169b618774718ec982b2Jack He return service.getDevicesMatchingConnectionStates(states); 257cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (RemoteException e) { 258cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 259cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return new ArrayList<BluetoothDevice>(); 260cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 261cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 26216eeac356c68f3674677169b618774718ec982b2Jack He if (service == null) { 263cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.w(TAG, "Proxy not attached to service"); 264cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 265cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return new ArrayList<BluetoothDevice>(); 266cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 267cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 268cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo /** 269cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * Get connection state of device 270cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * 271cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo * @return device connection state 272cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo */ 273cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo @Override 274cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public int getConnectionState(BluetoothDevice device) { 275cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (DBG) { 276cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo log("getConnectionState(" + device + ")"); 277cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 27816eeac356c68f3674677169b618774718ec982b2Jack He final IBluetoothPbapClient service = mService; 27916eeac356c68f3674677169b618774718ec982b2Jack He if (service != null && isEnabled() && isValidDevice(device)) { 280cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo try { 28116eeac356c68f3674677169b618774718ec982b2Jack He return service.getConnectionState(device); 282cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } catch (RemoteException e) { 283cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 284cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return BluetoothProfile.STATE_DISCONNECTED; 285cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 286cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 28716eeac356c68f3674677169b618774718ec982b2Jack He if (service == null) { 288cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.w(TAG, "Proxy not attached to service"); 289cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 290cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return BluetoothProfile.STATE_DISCONNECTED; 291cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 292cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 293cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private final ServiceConnection mConnection = new ServiceConnection() { 294cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public void onServiceConnected(ComponentName className, IBinder service) { 295cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (DBG) { 296cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo log("Proxy object connected"); 297cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 2980a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkey mService = IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service)); 299cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (mServiceListener != null) { 300a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, 301a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He BluetoothPbapClient.this); 302cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 303cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 304a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He 305cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo public void onServiceDisconnected(ComponentName className) { 306cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (DBG) { 307cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo log("Proxy object disconnected"); 308cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 309cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mService = null; 310cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (mServiceListener != null) { 311cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT); 312cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 313cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 314cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo }; 315cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 316cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private static void log(String msg) { 317cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo Log.d(TAG, msg); 318cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 319cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 320cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo private boolean isEnabled() { 321cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 322cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) { 323cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return true; 324cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 325cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo log("Bluetooth is Not enabled"); 326cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo return false; 327cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 328cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo 32916eeac356c68f3674677169b618774718ec982b2Jack He private static boolean isValidDevice(BluetoothDevice device) { 33016eeac356c68f3674677169b618774718ec982b2Jack He return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); 331cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo } 332563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo 333563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo /** 334563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * Set priority of the profile 335563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * 336563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * <p> The device should already be paired. 337a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * Priority can be one of {@link #PRIORITY_ON} or 338563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * {@link #PRIORITY_OFF}, 339563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * 340563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * @param device Paired bluetooth device 34116eeac356c68f3674677169b618774718ec982b2Jack He * @param priority Priority of this profile 342563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * @return true if priority is set, false on error 343563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo */ 344563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo public boolean setPriority(BluetoothDevice device, int priority) { 345563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo if (DBG) { 346563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo log("setPriority(" + device + ", " + priority + ")"); 347563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 34816eeac356c68f3674677169b618774718ec982b2Jack He final IBluetoothPbapClient service = mService; 34916eeac356c68f3674677169b618774718ec982b2Jack He if (service != null && isEnabled() && isValidDevice(device)) { 3502992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He if (priority != BluetoothProfile.PRIORITY_OFF 3512992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He && priority != BluetoothProfile.PRIORITY_ON) { 352a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He return false; 353563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 354563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo try { 35516eeac356c68f3674677169b618774718ec982b2Jack He return service.setPriority(device, priority); 356563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } catch (RemoteException e) { 357563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 358563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo return false; 359563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 360563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 36116eeac356c68f3674677169b618774718ec982b2Jack He if (service == null) { 362563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo Log.w(TAG, "Proxy not attached to service"); 363563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 364563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo return false; 365563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 366563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo 367563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo /** 368563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * Get the priority of the profile. 369563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * 370563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * <p> The priority can be any of: 371563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, 372563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} 373563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * 374563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * @param device Bluetooth device 375563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo * @return priority of the device 376563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo */ 377563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo public int getPriority(BluetoothDevice device) { 378563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo if (VDBG) { 379563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo log("getPriority(" + device + ")"); 380563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 38116eeac356c68f3674677169b618774718ec982b2Jack He final IBluetoothPbapClient service = mService; 38216eeac356c68f3674677169b618774718ec982b2Jack He if (service != null && isEnabled() && isValidDevice(device)) { 383563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo try { 38416eeac356c68f3674677169b618774718ec982b2Jack He return service.getPriority(device); 385563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } catch (RemoteException e) { 386563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 387563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo return PRIORITY_OFF; 388563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 389563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 39016eeac356c68f3674677169b618774718ec982b2Jack He if (service == null) { 391563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo Log.w(TAG, "Proxy not attached to service"); 392563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 393563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo return PRIORITY_OFF; 394563c700f7025d2f792a52b7483725b3d58eaa7a6Joseph Pirozzo } 395cfa8a6469463ace9c3336e3686d950792a2c7ad4Joseph Pirozzo} 396