13f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu/* 23f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Copyright (C) 2008 The Android Open Source Project 33f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * 43f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Licensed under the Apache License, Version 2.0 (the "License"); 53f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * you may not use this file except in compliance with the License. 63f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * You may obtain a copy of the License at 73f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * 83f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * http://www.apache.org/licenses/LICENSE-2.0 93f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * 103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Unless required by applicable law or agreed to in writing, software 113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * distributed under the License is distributed on an "AS IS" BASIS, 123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * See the License for the specific language governing permissions and 143f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * limitations under the License. 153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liupackage android.bluetooth; 183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 193f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.ComponentName; 203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.Context; 213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.Intent; 223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.content.ServiceConnection; 233f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.os.RemoteException; 243f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.os.IBinder; 253f41673265dcaaef058703311c5481e8a51fd8beJiafa Liuimport android.util.Log; 263f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 273f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu/** 283f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * The Android Bluetooth API is not finalized, and *will* change. Use at your 293f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * own risk. 303f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * 313f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Public API for controlling the Bluetooth Pbap Service. This includes 323f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Bluetooth Phone book Access profile. 333f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap is a proxy object for controlling the Bluetooth Pbap 343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Service via IPC. 353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * 363f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Creating a BluetoothPbap object will create a binding with the 373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap service. Users of this object should call close() when they 383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * are finished with the BluetoothPbap, so that this proxy object can unbind 393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * from the service. 403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * 413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * This BluetoothPbap object is not immediately bound to the 423f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothPbap service. Use the ServiceListener interface to obtain a 433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * notification when it is bound, this is especially important if you wish to 443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * immediately call methods on BluetoothPbap after construction. 453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * 463f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Android only supports one connected Bluetooth Pce at a time. 473f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * 483f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * @hide 493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 503f41673265dcaaef058703311c5481e8a51fd8beJiafa Liupublic class BluetoothPbap { 513f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu private static final String TAG = "BluetoothPbap"; 53563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie private static final boolean DBG = true; 54563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie private static final boolean VDBG = false; 553f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** int extra for PBAP_STATE_CHANGED_ACTION */ 573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final String PBAP_STATE = 583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu "android.bluetooth.pbap.intent.PBAP_STATE"; 593f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** int extra for PBAP_STATE_CHANGED_ACTION */ 603f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final String PBAP_PREVIOUS_STATE = 613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu "android.bluetooth.pbap.intent.PBAP_PREVIOUS_STATE"; 623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 63f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa /** Indicates the state of a pbap connection state has changed. 643f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * This intent will always contain PBAP_STATE, PBAP_PREVIOUS_STATE and 653f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * BluetoothIntent.ADDRESS extras. 663f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final String PBAP_STATE_CHANGED_ACTION = 683f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED"; 693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu private IBluetoothPbap mService; 713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu private final Context mContext; 729bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh private ServiceListener mServiceListener; 736f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta private BluetoothAdapter mAdapter; 743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** There was an error trying to obtain the state */ 763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final int STATE_ERROR = -1; 77bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly /** No client currently connected */ 783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final int STATE_DISCONNECTED = 0; 793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** Connection attempt in progress */ 803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final int STATE_CONNECTING = 1; 81bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly /** Client is currently connected */ 823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final int STATE_CONNECTED = 2; 833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 843f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final int RESULT_FAILURE = 0; 853f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final int RESULT_SUCCESS = 1; 863f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** Connection canceled before completion. */ 873f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public static final int RESULT_CANCELED = 2; 883f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 893f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 903f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * An interface for notifying Bluetooth PCE IPC clients when they have 91c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan * been connected to the BluetoothPbap service. 923f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 933f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public interface ServiceListener { 943f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 953f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Called to notify the client when this proxy object has been 963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * connected to the BluetoothPbap service. Clients must wait for 973f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * this callback before making IPC calls on the BluetoothPbap 983f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * service. 993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 1006f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta public void onServiceConnected(BluetoothPbap proxy); 1013f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 1023f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 1033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Called to notify the client that this proxy object has been 1043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * disconnected from the BluetoothPbap service. Clients must not 1053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * make IPC calls on the BluetoothPbap service after this callback. 1063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * This callback will currently only occur if the application hosting 1073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * the BluetoothPbap service, but may be called more often in future. 1083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 1093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public void onServiceDisconnected(); 1103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 1113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 1126f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = 1136f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta new IBluetoothStateChangeCallback.Stub() { 1146f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta public void onBluetoothStateChange(boolean up) { 1156f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); 1166f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta if (!up) { 117563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) Log.d(TAG,"Unbinding service..."); 1186f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta synchronized (mConnection) { 1196f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta try { 1206f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta mService = null; 1216f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta mContext.unbindService(mConnection); 1226f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } catch (Exception re) { 1236f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta Log.e(TAG,"",re); 1246f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1256f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1266f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } else { 1276f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta synchronized (mConnection) { 1286f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta try { 1296f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta if (mService == null) { 130563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) Log.d(TAG,"Binding service..."); 131221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn doBind(); 1326f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1336f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } catch (Exception re) { 1346f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta Log.e(TAG,"",re); 1356f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1366f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1376f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1386f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1396f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta }; 1406f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta 1413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 142c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan * Create a BluetoothPbap proxy object. 1433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 1443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public BluetoothPbap(Context context, ServiceListener l) { 1453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu mContext = context; 1463f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu mServiceListener = l; 1476f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta mAdapter = BluetoothAdapter.getDefaultAdapter(); 1486f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta IBluetoothManager mgr = mAdapter.getBluetoothManager(); 1496f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta if (mgr != null) { 1506f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta try { 1516f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); 1526f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } catch (RemoteException e) { 1536f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta Log.e(TAG,"",e); 1546f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1556f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 156221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn doBind(); 157221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn } 158221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn 159221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn boolean doBind() { 160221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn Intent intent = new Intent(IBluetoothPbap.class.getName()); 161221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 162221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn intent.setComponent(comp); 163466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, 164466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn android.os.Process.myUserHandle())) { 165221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent); 166221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return false; 1673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 168221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return true; 1693f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 1703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 1713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu protected void finalize() throws Throwable { 1723f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu try { 1733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu close(); 1743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } finally { 1753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu super.finalize(); 1763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 1773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 1783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 1793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 1803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Close the connection to the backing service. 181c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan * Other public functions of BluetoothPbap will return default error 1823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * results once close() has been called. Multiple invocations of close() 1833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * are ok. 1843f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 1853f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public synchronized void close() { 1866f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta IBluetoothManager mgr = mAdapter.getBluetoothManager(); 1876f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta if (mgr != null) { 1886f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta try { 1896f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); 1906f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } catch (Exception e) { 1916f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta Log.e(TAG,"",e); 1926f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1936f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 1946f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta 1956f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta synchronized (mConnection) { 1966f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta if (mService != null) { 1976f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta try { 1986f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta mService = null; 1996f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta mContext.unbindService(mConnection); 2006f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } catch (Exception re) { 2016f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta Log.e(TAG,"",re); 2026f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 2036f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta } 2043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 2059bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh mServiceListener = null; 2063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 2073f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 2083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 209c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan * Get the current state of the BluetoothPbap service. 2103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * @return One of the STATE_ return codes, or STATE_ERROR if this proxy 211c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan * object is currently not connected to the Pbap service. 2123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 2133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public int getState() { 214563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getState()"); 2153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (mService != null) { 2163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu try { 2173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu return mService.getState(); 2183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } catch (RemoteException e) {Log.e(TAG, e.toString());} 2193f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } else { 2203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu Log.w(TAG, "Proxy not attached to service"); 2213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (DBG) log(Log.getStackTraceString(new Throwable())); 2223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 223c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan return BluetoothPbap.STATE_ERROR; 2243f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 2253f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 2263f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 227bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * Get the currently connected remote Bluetooth device (PCE). 228bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * @return The remote Bluetooth device, or null if not in connected or 229bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * connecting state, or if this proxy object is not connected to 230bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * the Pbap service. 2313f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 232bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public BluetoothDevice getClient() { 233563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getClient()"); 2343f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (mService != null) { 2353f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu try { 236bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return mService.getClient(); 2373f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } catch (RemoteException e) {Log.e(TAG, e.toString());} 2383f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } else { 2393f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu Log.w(TAG, "Proxy not attached to service"); 2403f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (DBG) log(Log.getStackTraceString(new Throwable())); 2413f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 2423f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu return null; 2433f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 2443f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 2453f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 246bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * Returns true if the specified Bluetooth device is connected (does not 247bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * include connecting). Returns false if not connected, or if this proxy 248bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * object is not currently connected to the Pbap service. 2493f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 250bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public boolean isConnected(BluetoothDevice device) { 251563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("isConnected(" + device + ")"); 2523f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (mService != null) { 2533f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu try { 254bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly return mService.isConnected(device); 2553f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } catch (RemoteException e) {Log.e(TAG, e.toString());} 2563f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } else { 2573f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu Log.w(TAG, "Proxy not attached to service"); 2583f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (DBG) log(Log.getStackTraceString(new Throwable())); 2593f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 2603f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu return false; 2613f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 2623f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 2633f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 264bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * Disconnects the current Pbap client (PCE). Currently this call blocks, 265f51eadaf1f83abfe16a609a4ded6d789494689b2Jake Hamby * it may soon be made asynchronous. Returns false if this proxy object is 266c8b04a93a619ba91997d7454865f0a71fb6ae981Jackson Fan * not currently connected to the Pbap service. 2673f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 268bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly public boolean disconnect() { 269bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly if (DBG) log("disconnect()"); 2703f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (mService != null) { 2713f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu try { 272bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly mService.disconnect(); 2733f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu return true; 2743f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } catch (RemoteException e) {Log.e(TAG, e.toString());} 2753f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } else { 2763f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu Log.w(TAG, "Proxy not attached to service"); 2773f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (DBG) log(Log.getStackTraceString(new Throwable())); 2783f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 2793f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu return false; 2803f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 2813f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 2823f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu /** 2833f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * Check class bits for possible PBAP support. 2843f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * This is a simple heuristic that tries to guess if a device with the 2853f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * given class bits might support PBAP. It is not accurate for all 2863f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * devices. It tries to err on the side of false positives. 2873f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu * @return True if this device might support PBAP. 2883f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu */ 289005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly public static boolean doesClassMatchSink(BluetoothClass btClass) { 2903f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu // TODO optimize the rule 291005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly switch (btClass.getDeviceClass()) { 2923f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu case BluetoothClass.Device.COMPUTER_DESKTOP: 2933f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu case BluetoothClass.Device.COMPUTER_LAPTOP: 2943f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu case BluetoothClass.Device.COMPUTER_SERVER: 2953f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: 2963f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu return true; 2973f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu default: 2983f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu return false; 2993f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 3003f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 3013f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 3029b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie private final ServiceConnection mConnection = new ServiceConnection() { 3033f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public void onServiceConnected(ComponentName className, IBinder service) { 3043f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (DBG) log("Proxy object connected"); 3053f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu mService = IBluetoothPbap.Stub.asInterface(service); 3063f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (mServiceListener != null) { 3076f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta mServiceListener.onServiceConnected(BluetoothPbap.this); 3083f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 3093f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 3103f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu public void onServiceDisconnected(ComponentName className) { 3113f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (DBG) log("Proxy object disconnected"); 3123f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu mService = null; 3133f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu if (mServiceListener != null) { 3143f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu mServiceListener.onServiceDisconnected(); 3153f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 3163f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 3173f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu }; 3183f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu 3193f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu private static void log(String msg) { 3203f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu Log.d(TAG, msg); 3213f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu } 3223f41673265dcaaef058703311c5481e8a51fd8beJiafa Liu} 323