1fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie/* 2fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Copyright (C) 2008 The Android Open Source Project 3fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * 4fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Licensed under the Apache License, Version 2.0 (the "License"); 5fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * you may not use this file except in compliance with the License. 6fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * You may obtain a copy of the License at 7fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * 8fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * http://www.apache.org/licenses/LICENSE-2.0 9fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * 10fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Unless required by applicable law or agreed to in writing, software 11fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * distributed under the License is distributed on an "AS IS" BASIS, 12fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * See the License for the specific language governing permissions and 14fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * limitations under the License. 15fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie */ 16fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 17fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xiepackage android.bluetooth; 18fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 19fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xieimport android.content.ComponentName; 20fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xieimport android.content.Context; 21fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xieimport android.content.Intent; 22fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xieimport android.content.ServiceConnection; 230146463d70355592da85c3605aaaef4cf0b7335eJack Heimport android.os.Binder; 240146463d70355592da85c3605aaaef4cf0b7335eJack Heimport android.os.IBinder; 250146463d70355592da85c3605aaaef4cf0b7335eJack Heimport android.os.RemoteException; 26fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xieimport android.util.Log; 27fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 280146463d70355592da85c3605aaaef4cf0b7335eJack Heimport java.util.ArrayList; 290146463d70355592da85c3605aaaef4cf0b7335eJack Heimport java.util.List; 300146463d70355592da85c3605aaaef4cf0b7335eJack He 31fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie/** 32fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * This class provides the APIs to control the Bluetooth MAP 33fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Profile. 34fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie *@hide 35fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie */ 360d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulzpublic final class BluetoothMap implements BluetoothProfile { 37fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 38fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie private static final String TAG = "BluetoothMap"; 39fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie private static final boolean DBG = true; 40fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie private static final boolean VDBG = false; 41fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 420d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz public static final String ACTION_CONNECTION_STATE_CHANGED = 430d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; 44fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 450146463d70355592da85c3605aaaef4cf0b7335eJack He private volatile IBluetoothMap mService; 46fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie private final Context mContext; 47fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie private ServiceListener mServiceListener; 48fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie private BluetoothAdapter mAdapter; 49fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 50fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie /** There was an error trying to obtain the state */ 51fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public static final int STATE_ERROR = -1; 52fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 53fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public static final int RESULT_FAILURE = 0; 54fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public static final int RESULT_SUCCESS = 1; 55fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie /** Connection canceled before completion. */ 56fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public static final int RESULT_CANCELED = 2; 57fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 58fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = 59fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie new IBluetoothStateChangeCallback.Stub() { 60fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public void onBluetoothStateChange(boolean up) { 61fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); 62fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (!up) { 63fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (VDBG) Log.d(TAG,"Unbinding service..."); 64fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie synchronized (mConnection) { 65fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 66fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mService = null; 67fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mContext.unbindService(mConnection); 68fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } catch (Exception re) { 69fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie Log.e(TAG,"",re); 70fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 71fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 72fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } else { 73fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie synchronized (mConnection) { 74fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 75fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (mService == null) { 76fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (VDBG) Log.d(TAG,"Binding service..."); 770d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz doBind(); 78fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 79fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } catch (Exception re) { 80fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie Log.e(TAG,"",re); 81fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 82fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 83fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 84fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 85fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie }; 86fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 87fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie /** 88fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Create a BluetoothMap proxy object. 89fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie */ 900d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz /*package*/ BluetoothMap(Context context, ServiceListener l) { 910d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz if (DBG) Log.d(TAG, "Create BluetoothMap proxy object"); 92fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mContext = context; 93fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mServiceListener = l; 94fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mAdapter = BluetoothAdapter.getDefaultAdapter(); 95fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie IBluetoothManager mgr = mAdapter.getBluetoothManager(); 96fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (mgr != null) { 97fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 98fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); 99fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } catch (RemoteException e) { 100fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie Log.e(TAG,"",e); 101fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 102fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 1030d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz doBind(); 1040d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 1050d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz 1060d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz boolean doBind() { 1070d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz Intent intent = new Intent(IBluetoothMap.class.getName()); 1080d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 1090d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz intent.setComponent(comp); 110466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, 111466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn android.os.Process.myUserHandle())) { 1120d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent); 1130d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return false; 114fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 1150d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return true; 116fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 117fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 118fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie protected void finalize() throws Throwable { 119fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 120fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie close(); 121fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } finally { 122fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie super.finalize(); 123fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 124fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 125fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 126fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie /** 127fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Close the connection to the backing service. 128fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Other public functions of BluetoothMap will return default error 129fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * results once close() has been called. Multiple invocations of close() 130fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * are ok. 131fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie */ 132fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public synchronized void close() { 133fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie IBluetoothManager mgr = mAdapter.getBluetoothManager(); 134fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (mgr != null) { 135fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 136fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); 137fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } catch (Exception e) { 138fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie Log.e(TAG,"",e); 139fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 140fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 141fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 142fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie synchronized (mConnection) { 143fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (mService != null) { 144fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 145fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mService = null; 146fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mContext.unbindService(mConnection); 147fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } catch (Exception re) { 148fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie Log.e(TAG,"",re); 149fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 150fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 151fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 152fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mServiceListener = null; 153fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 154fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 155fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie /** 156fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Get the current state of the BluetoothMap service. 157fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * @return One of the STATE_ return codes, or STATE_ERROR if this proxy 158fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * object is currently not connected to the Map service. 159fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie */ 160fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public int getState() { 161fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (VDBG) log("getState()"); 1620146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothMap service = mService; 1630146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null) { 164fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 1650146463d70355592da85c3605aaaef4cf0b7335eJack He return service.getState(); 1660146463d70355592da85c3605aaaef4cf0b7335eJack He } catch (RemoteException e) { 1670146463d70355592da85c3605aaaef4cf0b7335eJack He Log.e(TAG, e.toString()); 1680146463d70355592da85c3605aaaef4cf0b7335eJack He } 169fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } else { 170fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie Log.w(TAG, "Proxy not attached to service"); 171fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (DBG) log(Log.getStackTraceString(new Throwable())); 172fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 173fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie return BluetoothMap.STATE_ERROR; 174fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 175fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 176fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie /** 177fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Get the currently connected remote Bluetooth device (PCE). 178fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * @return The remote Bluetooth device, or null if not in connected or 179fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * connecting state, or if this proxy object is not connected to 180fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * the Map service. 181fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie */ 182fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public BluetoothDevice getClient() { 183fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (VDBG) log("getClient()"); 1840146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothMap service = mService; 1850146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null) { 186fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 1870146463d70355592da85c3605aaaef4cf0b7335eJack He return service.getClient(); 1880146463d70355592da85c3605aaaef4cf0b7335eJack He } catch (RemoteException e) { 1890146463d70355592da85c3605aaaef4cf0b7335eJack He Log.e(TAG, e.toString()); 1900146463d70355592da85c3605aaaef4cf0b7335eJack He } 191fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } else { 192fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie Log.w(TAG, "Proxy not attached to service"); 193fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (DBG) log(Log.getStackTraceString(new Throwable())); 194fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 195fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie return null; 196fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 197fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 198fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie /** 1990d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Returns true if the specified Bluetooth device is connected. 2000d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Returns false if not connected, or if this proxy object is not 2010d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * currently connected to the Map service. 202fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie */ 203fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public boolean isConnected(BluetoothDevice device) { 204fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (VDBG) log("isConnected(" + device + ")"); 2050146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothMap service = mService; 2060146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null) { 207fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 2080146463d70355592da85c3605aaaef4cf0b7335eJack He return service.isConnected(device); 2090146463d70355592da85c3605aaaef4cf0b7335eJack He } catch (RemoteException e) { 2100146463d70355592da85c3605aaaef4cf0b7335eJack He Log.e(TAG, e.toString()); 2110146463d70355592da85c3605aaaef4cf0b7335eJack He } 212fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } else { 213fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie Log.w(TAG, "Proxy not attached to service"); 214fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (DBG) log(Log.getStackTraceString(new Throwable())); 215fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 216fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie return false; 217fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 218fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 219fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie /** 2200d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Initiate connection. Initiation of outgoing connections is not 2210d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * supported for MAP server. 222fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie */ 2230d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz public boolean connect(BluetoothDevice device) { 2240d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz if (DBG) log("connect(" + device + ")" + "not supported for MAPS"); 2250d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return false; 2260d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 2270d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz 2280d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz /** 2290d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Initiate disconnect. 2300d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * 2310d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @param device Remote Bluetooth Device 2320d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @return false on error, 2330d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * true otherwise 2340d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz */ 2350d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz public boolean disconnect(BluetoothDevice device) { 2360d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz if (DBG) log("disconnect(" + device + ")"); 2370146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothMap service = mService; 2380146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled() && isValidDevice(device)) { 239fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie try { 2400146463d70355592da85c3605aaaef4cf0b7335eJack He return service.disconnect(device); 2410d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } catch (RemoteException e) { 2420d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz Log.e(TAG, Log.getStackTraceString(new Throwable())); 2430d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return false; 2440d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 245fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 2460146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 247fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie return false; 248fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 249fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 250fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie /** 251fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * Check class bits for possible Map support. 252fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * This is a simple heuristic that tries to guess if a device with the 253fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * given class bits might support Map. It is not accurate for all 254fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * devices. It tries to err on the side of false positives. 255fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie * @return True if this device might support Map. 256fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie */ 257fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public static boolean doesClassMatchSink(BluetoothClass btClass) { 258fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie // TODO optimize the rule 259fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie switch (btClass.getDeviceClass()) { 260fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie case BluetoothClass.Device.COMPUTER_DESKTOP: 261fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie case BluetoothClass.Device.COMPUTER_LAPTOP: 262fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie case BluetoothClass.Device.COMPUTER_SERVER: 263fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: 264fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie return true; 265fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie default: 266fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie return false; 267fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 268fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 269fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 2700d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz /** 2710d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Get the list of connected devices. Currently at most one. 2720d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * 2730d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @return list of connected devices 2740d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz */ 2750d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz public List<BluetoothDevice> getConnectedDevices() { 2760d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz if (DBG) log("getConnectedDevices()"); 2770146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothMap service = mService; 2780146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled()) { 2790d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz try { 2800146463d70355592da85c3605aaaef4cf0b7335eJack He return service.getConnectedDevices(); 2810d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } catch (RemoteException e) { 2820d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz Log.e(TAG, Log.getStackTraceString(new Throwable())); 2830d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return new ArrayList<BluetoothDevice>(); 2840d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 2850d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 2860146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 2870d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return new ArrayList<BluetoothDevice>(); 2880d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 2890d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz 2900d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz /** 2910d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Get the list of devices matching specified states. Currently at most one. 2920d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * 2930d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @return list of matching devices 2940d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz */ 2950d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 2960d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz if (DBG) log("getDevicesMatchingStates()"); 2970146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothMap service = mService; 2980146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled()) { 2990d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz try { 3000146463d70355592da85c3605aaaef4cf0b7335eJack He return service.getDevicesMatchingConnectionStates(states); 3010d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } catch (RemoteException e) { 3020d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz Log.e(TAG, Log.getStackTraceString(new Throwable())); 3030d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return new ArrayList<BluetoothDevice>(); 3040d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3050d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3060146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 3070d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return new ArrayList<BluetoothDevice>(); 3080d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3090d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz 3100d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz /** 3110d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Get connection state of device 3120d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * 3130d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @return device connection state 3140d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz */ 3150d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz public int getConnectionState(BluetoothDevice device) { 3160d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz if (DBG) log("getConnectionState(" + device + ")"); 3170146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothMap service = mService; 3180146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled() && isValidDevice(device)) { 3190d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz try { 3200146463d70355592da85c3605aaaef4cf0b7335eJack He return service.getConnectionState(device); 3210d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } catch (RemoteException e) { 3220d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz Log.e(TAG, Log.getStackTraceString(new Throwable())); 3230d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return BluetoothProfile.STATE_DISCONNECTED; 3240d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3250d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3260146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 3270d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return BluetoothProfile.STATE_DISCONNECTED; 3280d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3290d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz 3300d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz /** 3310d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Set priority of the profile 3320d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * 3330d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * <p> The device should already be paired. 3340d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Priority can be one of {@link #PRIORITY_ON} or 3350d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * {@link #PRIORITY_OFF}, 3360d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * 3370d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @param device Paired bluetooth device 3380d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @param priority 3390d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @return true if priority is set, false on error 3400d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz */ 3410d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz public boolean setPriority(BluetoothDevice device, int priority) { 3420d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz if (DBG) log("setPriority(" + device + ", " + priority + ")"); 3430146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothMap service = mService; 3440146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled() && isValidDevice(device)) { 3450146463d70355592da85c3605aaaef4cf0b7335eJack He if (priority != BluetoothProfile.PRIORITY_OFF 3460146463d70355592da85c3605aaaef4cf0b7335eJack He && priority != BluetoothProfile.PRIORITY_ON) { 3470146463d70355592da85c3605aaaef4cf0b7335eJack He return false; 3480d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3490d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz try { 3500146463d70355592da85c3605aaaef4cf0b7335eJack He return service.setPriority(device, priority); 3510d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } catch (RemoteException e) { 3520d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz Log.e(TAG, Log.getStackTraceString(new Throwable())); 3530d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return false; 3540d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3550d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3560146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 3570d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return false; 3580d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3590d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz 3600d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz /** 3610d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * Get the priority of the profile. 3620d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * 3630d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * <p> The priority can be any of: 3640d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, 3650d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} 3660d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * 3670d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @param device Bluetooth device 3680d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz * @return priority of the device 3690d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz */ 3700d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz public int getPriority(BluetoothDevice device) { 3710d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz if (VDBG) log("getPriority(" + device + ")"); 3720146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothMap service = mService; 3730146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled() && isValidDevice(device)) { 3740d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz try { 3750146463d70355592da85c3605aaaef4cf0b7335eJack He return service.getPriority(device); 3760d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } catch (RemoteException e) { 3770d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz Log.e(TAG, Log.getStackTraceString(new Throwable())); 3780d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return PRIORITY_OFF; 3790d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3800d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3810146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 3820d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return PRIORITY_OFF; 3830d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 3840d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz 3859b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie private final ServiceConnection mConnection = new ServiceConnection() { 386fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public void onServiceConnected(ComponentName className, IBinder service) { 387fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (DBG) log("Proxy object connected"); 3880a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkey mService = IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service)); 389fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (mServiceListener != null) { 3900d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this); 391fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 392fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 393fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie public void onServiceDisconnected(ComponentName className) { 394fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (DBG) log("Proxy object disconnected"); 395fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie mService = null; 396fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie if (mServiceListener != null) { 3970d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz mServiceListener.onServiceDisconnected(BluetoothProfile.MAP); 398fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 399fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 400fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie }; 401fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie 402fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie private static void log(String msg) { 403fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie Log.d(TAG, msg); 404fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie } 4050d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz 4060d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz private boolean isEnabled() { 4070d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 4080d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true; 4090d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz log("Bluetooth is Not enabled"); 4100d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz return false; 4110d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 4120146463d70355592da85c3605aaaef4cf0b7335eJack He private static boolean isValidDevice(BluetoothDevice device) { 4130146463d70355592da85c3605aaaef4cf0b7335eJack He return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); 4140d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz } 4150d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz 416fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie} 417