16fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang/* 26fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * Copyright (C) 2008 The Android Open Source Project 36fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * 46fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * Licensed under the Apache License, Version 2.0 (the "License"); 56fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * you may not use this file except in compliance with the License. 66fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * You may obtain a copy of the License at 76fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * 86fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * http://www.apache.org/licenses/LICENSE-2.0 96fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * 106fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * Unless required by applicable law or agreed to in writing, software 116fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * distributed under the License is distributed on an "AS IS" BASIS, 126fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * See the License for the specific language governing permissions and 146fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * limitations under the License. 156fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang */ 166fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 176fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changpackage android.bluetooth; 186fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 196fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.annotation.SdkConstant; 206fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.annotation.SdkConstant.SdkConstantType; 210f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ComponentName; 226fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.content.Context; 230f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.Intent; 240f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ServiceConnection; 250a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkeyimport android.os.Binder; 266fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.os.IBinder; 275a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport android.os.RemoteException; 286fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.util.Log; 296fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 305a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.ArrayList; 315a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 326fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 336fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang/** 3474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * This class provides the APIs to control the Bluetooth Pan 3574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * Profile. 3674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * 3774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh *<p>BluetoothPan is a proxy object for controlling the Bluetooth 3874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get 3974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * the BluetoothPan proxy object. 4074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * 4174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh *<p>Each method is protected with its appropriate permission. 4274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh *@hide 436fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang */ 4474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganeshpublic final class BluetoothPan implements BluetoothProfile { 456fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang private static final String TAG = "BluetoothPan"; 460f42037eb7b5118015c2caca635538324ccf0ccffredc private static final boolean DBG = true; 47563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie private static final boolean VDBG = false; 486fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 4974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh /** 5074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * Intent used to broadcast the change in connection state of the Pan 5174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * profile. 5274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * 5374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * <p>This intent will have 4 extras: 5474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * <ul> 5574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> 5674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> 5774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> 5874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * <li> {@link #EXTRA_LOCAL_ROLE} - Which local role the remote device is 5974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * bound to. </li> 6074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * </ul> 6174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * 6274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of 6374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, 6474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. 6574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * 6674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * <p> {@link #EXTRA_LOCAL_ROLE} can be one of {@link #LOCAL_NAP_ROLE} or 6774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * {@link #LOCAL_PANU_ROLE} 6874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to 6974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * receive. 7074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 7174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 7274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public static final String ACTION_CONNECTION_STATE_CHANGED = 7374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED"; 746fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 7574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh /** 7674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * Extra for {@link #ACTION_CONNECTION_STATE_CHANGED} intent 7774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * The local role of the PAN profile that the remote device is bound to. 7874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * It can be one of {@link #LOCAL_NAP_ROLE} or {@link #LOCAL_PANU_ROLE}. 7974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 805200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE"; 815200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh 820f42037eb7b5118015c2caca635538324ccf0ccffredc public static final int PAN_ROLE_NONE = 0; 8374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh /** 8474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * The local device is acting as a Network Access Point. 8574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 865200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh public static final int LOCAL_NAP_ROLE = 1; 870f42037eb7b5118015c2caca635538324ccf0ccffredc public static final int REMOTE_NAP_ROLE = 1; 885200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh 895200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh /** 9074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * The local device is acting as a PAN User. 916fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang */ 9274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public static final int LOCAL_PANU_ROLE = 2; 930f42037eb7b5118015c2caca635538324ccf0ccffredc public static final int REMOTE_PANU_ROLE = 2; 946fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 95fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh /** 96fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh * Return codes for the connect and disconnect Bluez / Dbus calls. 9774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * @hide 98fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh */ 99fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh public static final int PAN_DISCONNECT_FAILED_NOT_CONNECTED = 1000; 100fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh 10174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh /** 10274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * @hide 10374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 104fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh public static final int PAN_CONNECT_FAILED_ALREADY_CONNECTED = 1001; 105fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh 10674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh /** 10774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * @hide 10874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 109fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh public static final int PAN_CONNECT_FAILED_ATTEMPT_FAILED = 1002; 110fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh 11174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh /** 11274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * @hide 11374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 114fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh public static final int PAN_OPERATION_GENERIC_FAILURE = 1003; 115fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh 11674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh /** 11774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * @hide 11874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 119fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh public static final int PAN_OPERATION_SUCCESS = 1004; 120fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh 1210f42037eb7b5118015c2caca635538324ccf0ccffredc private Context mContext; 12274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private ServiceListener mServiceListener; 12374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private BluetoothAdapter mAdapter; 1240146463d70355592da85c3605aaaef4cf0b7335eJack He private volatile IBluetoothPan mPanService; 1256fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 1266fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang /** 1276fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * Create a BluetoothPan proxy object for interacting with the local 12874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * Bluetooth Service which handles the Pan profile 12974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * 1306fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang */ 1310f42037eb7b5118015c2caca635538324ccf0ccffredc /*package*/ BluetoothPan(Context context, ServiceListener l) { 1320f42037eb7b5118015c2caca635538324ccf0ccffredc mContext = context; 13374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mServiceListener = l; 13474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh mAdapter = BluetoothAdapter.getDefaultAdapter(); 135903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc try { 136903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback); 137903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } catch (RemoteException re) { 138903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re); 139903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 140221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn if (VDBG) Log.d(TAG, "BluetoothPan() call bindService"); 141221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn doBind(); 142221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn } 143221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn 144221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn boolean doBind() { 145221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn Intent intent = new Intent(IBluetoothPan.class.getName()); 146221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 147221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn intent.setComponent(comp); 148466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, 149466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn android.os.Process.myUserHandle())) { 150221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn Log.e(TAG, "Could not bind to Bluetooth Pan Service with " + intent); 151221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return false; 1526fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 153221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn return true; 1546fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 1556fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 1569bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh /*package*/ void close() { 157563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("close()"); 1589b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie 1599b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie IBluetoothManager mgr = mAdapter.getBluetoothManager(); 1609b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie if (mgr != null) { 1619b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie try { 1629b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie mgr.unregisterStateChangeCallback(mStateChangeCallback); 1639b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie } catch (RemoteException re) { 1649b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re); 1659b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie } 1660f42037eb7b5118015c2caca635538324ccf0ccffredc } 1679b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie 1689b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie synchronized (mConnection) { 1699b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie if (mPanService != null) { 1709b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie try { 1719b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie mPanService = null; 1729b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie mContext.unbindService(mConnection); 1739b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie } catch (Exception re) { 1749b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie Log.e(TAG,"",re); 1759b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie } 1769b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie } 177903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 1789b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie mServiceListener = null; 179903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 180903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc 181903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc protected void finalize() { 182903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc close(); 1839bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh } 1849bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh 1859b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie final private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { 186903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc 187903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc @Override 1881f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure public void onBluetoothStateChange(boolean on) { 1891f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure // Handle enable request to bind again. 1901f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure Log.d(TAG, "onBluetoothStateChange on: " + on); 191903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc if (on) { 1921f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure try { 1931f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure if (mPanService == null) { 1941f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure if (VDBG) Log.d(TAG, "onBluetoothStateChange calling doBind()"); 1951f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure doBind(); 1961f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure } 1971f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure 1981f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure } catch (IllegalStateException e) { 1991f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure Log.e(TAG,"onBluetoothStateChange: could not bind to PAN service: ", e); 2001f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure 2011f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure } catch (SecurityException e) { 2021f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure Log.e(TAG,"onBluetoothStateChange: could not bind to PAN service: ", e); 2031f8b844870eb9acb334b541b0b41de37e000d2f0Nitin Shivpure } 204903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } else { 205563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) Log.d(TAG,"Unbinding service..."); 206903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc synchronized (mConnection) { 207903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc try { 208903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc mPanService = null; 209903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc mContext.unbindService(mConnection); 210903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } catch (Exception re) { 211903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc Log.e(TAG,"",re); 212903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 213903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 214903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 215903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 216903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc }; 217903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc 2186fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang /** 219f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Initiate connection to a profile of the remote bluetooth device. 220f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 221f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> This API returns false in scenarios like the profile on the 222f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * device is already connected or Bluetooth is not turned on. 223f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * When this API returns true, it is guaranteed that 224f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * connection state intent for the profile will be broadcasted with 225f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * the state. Users can get the connection state of the profile 226f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * from this intent. 227f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 228f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 229f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * permission. 230f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 231f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @param device Remote Bluetooth Device 232f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @return false on immediate error, 233f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * true otherwise 2346fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * @hide 2356fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang */ 2366fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang public boolean connect(BluetoothDevice device) { 2376fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang if (DBG) log("connect(" + device + ")"); 2380146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothPan service = mPanService; 2390146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled() && isValidDevice(device)) { 24074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 2410146463d70355592da85c3605aaaef4cf0b7335eJack He return service.connect(device); 24274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 24374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 24474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 2450f42037eb7b5118015c2caca635538324ccf0ccffredc } 2466fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 2470146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 24874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 2496fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 2506fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 2516fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang /** 252f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Initiate disconnection from a profile 253f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 254f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> This API will return false in scenarios like the profile on the 255f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Bluetooth device is not in connected state etc. When this API returns, 256f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * true, it is guaranteed that the connection state change 257f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * intent will be broadcasted with the state. Users can get the 258f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * disconnection state of the profile from this intent. 259f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 260f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> If the disconnection is initiated by a remote device, the state 261f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * will transition from {@link #STATE_CONNECTED} to 262f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the 263f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * host (local) device the state will transition from 264f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to 265f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * state {@link #STATE_DISCONNECTED}. The transition to 266f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #STATE_DISCONNECTING} can be used to distinguish between the 267f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * two scenarios. 268f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 269f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 270f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * permission. 271f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 272f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @param device Remote Bluetooth Device 273f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @return false on immediate error, 274f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * true otherwise 2756fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * @hide 2766fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang */ 2776fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang public boolean disconnect(BluetoothDevice device) { 2786fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang if (DBG) log("disconnect(" + device + ")"); 2790146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothPan service = mPanService; 2800146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled() && isValidDevice(device)) { 28174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 2820146463d70355592da85c3605aaaef4cf0b7335eJack He return service.disconnect(device); 28374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 28474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 28574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 2860f42037eb7b5118015c2caca635538324ccf0ccffredc } 2876fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 2880146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 28974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 2906fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 2916fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 2925200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh /** 29374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * {@inheritDoc} 2945200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh */ 29574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public List<BluetoothDevice> getConnectedDevices() { 296563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getConnectedDevices()"); 2970146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothPan service = mPanService; 2980146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled()) { 29974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 3000146463d70355592da85c3605aaaef4cf0b7335eJack He return service.getConnectedDevices(); 30174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 30274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 30374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 3040f42037eb7b5118015c2caca635538324ccf0ccffredc } 3055200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh } 3060146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 30774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 3085200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh } 3095200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh 3105200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh /** 31174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * {@inheritDoc} 31274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 31374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 314563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getDevicesMatchingStates()"); 3150146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothPan service = mPanService; 3160146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled()) { 31774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 3180146463d70355592da85c3605aaaef4cf0b7335eJack He return service.getDevicesMatchingConnectionStates(states); 31974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 32074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 32174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 3220f42037eb7b5118015c2caca635538324ccf0ccffredc } 32374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 3240146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 32574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 32674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 32774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 32874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh /** 32974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * {@inheritDoc} 33074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 33174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public int getConnectionState(BluetoothDevice device) { 332563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getState(" + device + ")"); 3330146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothPan service = mPanService; 3340146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled() && isValidDevice(device)) { 33574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 3360146463d70355592da85c3605aaaef4cf0b7335eJack He return service.getConnectionState(device); 33774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 33874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 33974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return BluetoothProfile.STATE_DISCONNECTED; 3400f42037eb7b5118015c2caca635538324ccf0ccffredc } 34174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 3420146463d70355592da85c3605aaaef4cf0b7335eJack He if (service == null) Log.w(TAG, "Proxy not attached to service"); 34374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return BluetoothProfile.STATE_DISCONNECTED; 34474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 34574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 346b70765cc27a174d1d4a0bab7062733ebd3eae354Jaikumar Ganesh public void setBluetoothTethering(boolean value) { 34774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (DBG) log("setBluetoothTethering(" + value + ")"); 3480146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothPan service = mPanService; 3490146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled()) { 35058fbffc36f71fbccbf510bfd17797760dc738133Hemant Gupta try { 3510146463d70355592da85c3605aaaef4cf0b7335eJack He service.setBluetoothTethering(value); 35258fbffc36f71fbccbf510bfd17797760dc738133Hemant Gupta } catch (RemoteException e) { 35358fbffc36f71fbccbf510bfd17797760dc738133Hemant Gupta Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 35458fbffc36f71fbccbf510bfd17797760dc738133Hemant Gupta } 3550f42037eb7b5118015c2caca635538324ccf0ccffredc } 3566fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 3576fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 3586fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang public boolean isTetheringOn() { 359563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("isTetheringOn()"); 3600146463d70355592da85c3605aaaef4cf0b7335eJack He final IBluetoothPan service = mPanService; 3610146463d70355592da85c3605aaaef4cf0b7335eJack He if (service != null && isEnabled()) { 36258fbffc36f71fbccbf510bfd17797760dc738133Hemant Gupta try { 3630146463d70355592da85c3605aaaef4cf0b7335eJack He return service.isTetheringOn(); 36458fbffc36f71fbccbf510bfd17797760dc738133Hemant Gupta } catch (RemoteException e) { 36558fbffc36f71fbccbf510bfd17797760dc738133Hemant Gupta Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 36658fbffc36f71fbccbf510bfd17797760dc738133Hemant Gupta } 3670f42037eb7b5118015c2caca635538324ccf0ccffredc } 368e4caddbb7a3b39fd6a1ccf107c7dbf09bc8978e8Jaikumar Ganesh return false; 3696fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 37074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 3719b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie private final ServiceConnection mConnection = new ServiceConnection() { 3720f42037eb7b5118015c2caca635538324ccf0ccffredc public void onServiceConnected(ComponentName className, IBinder service) { 3730f42037eb7b5118015c2caca635538324ccf0ccffredc if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected"); 3740a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkey mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service)); 3750f42037eb7b5118015c2caca635538324ccf0ccffredc if (mServiceListener != null) { 3760f42037eb7b5118015c2caca635538324ccf0ccffredc mServiceListener.onServiceConnected(BluetoothProfile.PAN, 3770f42037eb7b5118015c2caca635538324ccf0ccffredc BluetoothPan.this); 3780f42037eb7b5118015c2caca635538324ccf0ccffredc } 3790f42037eb7b5118015c2caca635538324ccf0ccffredc } 3800f42037eb7b5118015c2caca635538324ccf0ccffredc public void onServiceDisconnected(ComponentName className) { 3810f42037eb7b5118015c2caca635538324ccf0ccffredc if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected"); 3820f42037eb7b5118015c2caca635538324ccf0ccffredc mPanService = null; 3830f42037eb7b5118015c2caca635538324ccf0ccffredc if (mServiceListener != null) { 3840f42037eb7b5118015c2caca635538324ccf0ccffredc mServiceListener.onServiceDisconnected(BluetoothProfile.PAN); 3850f42037eb7b5118015c2caca635538324ccf0ccffredc } 3860f42037eb7b5118015c2caca635538324ccf0ccffredc } 3870f42037eb7b5118015c2caca635538324ccf0ccffredc }; 3880f42037eb7b5118015c2caca635538324ccf0ccffredc 38974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private boolean isEnabled() { 3900146463d70355592da85c3605aaaef4cf0b7335eJack He return mAdapter.getState() == BluetoothAdapter.STATE_ON; 39174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 39274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 3930146463d70355592da85c3605aaaef4cf0b7335eJack He private static boolean isValidDevice(BluetoothDevice device) { 3940146463d70355592da85c3605aaaef4cf0b7335eJack He return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); 39574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 39674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 39774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private static void log(String msg) { 39874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.d(TAG, msg); 39974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 4009bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh} 401