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; 256fdd0c6274c81b337ad35b70480f881daf7354c3Danica Changimport android.os.IBinder; 265a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport android.os.RemoteException; 275a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport android.os.ServiceManager; 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; 1240f42037eb7b5118015c2caca635538324ccf0ccffredc private 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 } 1400f42037eb7b5118015c2caca635538324ccf0ccffredc Log.d(TAG, "BluetoothPan() call bindService"); 1410f42037eb7b5118015c2caca635538324ccf0ccffredc if (!context.bindService(new Intent(IBluetoothPan.class.getName()), 1420f42037eb7b5118015c2caca635538324ccf0ccffredc mConnection, 0)) { 1430f42037eb7b5118015c2caca635538324ccf0ccffredc Log.e(TAG, "Could not bind to Bluetooth HID Service"); 1446fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 1450f42037eb7b5118015c2caca635538324ccf0ccffredc Log.d(TAG, "BluetoothPan(), bindService called"); 1466fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 1476fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 1489bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh /*package*/ void close() { 149563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("close()"); 1500f42037eb7b5118015c2caca635538324ccf0ccffredc if (mConnection != null) { 1510f42037eb7b5118015c2caca635538324ccf0ccffredc mContext.unbindService(mConnection); 1520f42037eb7b5118015c2caca635538324ccf0ccffredc mConnection = null; 1530f42037eb7b5118015c2caca635538324ccf0ccffredc } 1549bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh mServiceListener = null; 155903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc try { 156903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc mAdapter.getBluetoothManager().unregisterStateChangeCallback(mStateChangeCallback); 157903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } catch (RemoteException re) { 158903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re); 159903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 160903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 161903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc 162903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc protected void finalize() { 163903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc close(); 1649bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh } 1659bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh 166903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { 167903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc 168903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc @Override 169903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc public void onBluetoothStateChange(boolean on) throws RemoteException { 170903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc //Handle enable request to bind again. 171903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc if (on) { 172903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc Log.d(TAG, "onBluetoothStateChange(on) call bindService"); 173903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc if (!mContext.bindService(new Intent(IBluetoothPan.class.getName()), 174903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc mConnection, 0)) { 175903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc Log.e(TAG, "Could not bind to Bluetooth HID Service"); 176903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 177903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc Log.d(TAG, "BluetoothPan(), bindService called"); 178903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } else { 179563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) Log.d(TAG,"Unbinding service..."); 180903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc synchronized (mConnection) { 181903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc try { 182903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc mPanService = null; 183903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc mContext.unbindService(mConnection); 184903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } catch (Exception re) { 185903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc Log.e(TAG,"",re); 186903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 187903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 188903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 189903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc } 190903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc }; 191903ac6f399dcd4f574bf388daa7b5f5907d448d3fredc 1926fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang /** 193f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Initiate connection to a profile of the remote bluetooth device. 194f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 195f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> This API returns false in scenarios like the profile on the 196f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * device is already connected or Bluetooth is not turned on. 197f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * When this API returns true, it is guaranteed that 198f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * connection state intent for the profile will be broadcasted with 199f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * the state. Users can get the connection state of the profile 200f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * from this intent. 201f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 202f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 203f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * permission. 204f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 205f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @param device Remote Bluetooth Device 206f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @return false on immediate error, 207f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * true otherwise 2086fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * @hide 2096fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang */ 2106fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang public boolean connect(BluetoothDevice device) { 2116fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang if (DBG) log("connect(" + device + ")"); 2120f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService != null && isEnabled() && 21374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh isValidDevice(device)) { 21474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 2150f42037eb7b5118015c2caca635538324ccf0ccffredc return mPanService.connect(device); 21674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 21774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 21874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 2190f42037eb7b5118015c2caca635538324ccf0ccffredc } 2206fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 2210f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); 22274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 2236fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 2246fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 2256fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang /** 226f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Initiate disconnection from a profile 227f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 228f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> This API will return false in scenarios like the profile on the 229f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Bluetooth device is not in connected state etc. When this API returns, 230f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * true, it is guaranteed that the connection state change 231f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * intent will be broadcasted with the state. Users can get the 232f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * disconnection state of the profile from this intent. 233f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 234f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> If the disconnection is initiated by a remote device, the state 235f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * will transition from {@link #STATE_CONNECTED} to 236f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the 237f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * host (local) device the state will transition from 238f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to 239f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * state {@link #STATE_DISCONNECTED}. The transition to 240f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #STATE_DISCONNECTING} can be used to distinguish between the 241f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * two scenarios. 242f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 243f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 244f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * permission. 245f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 246f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @param device Remote Bluetooth Device 247f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @return false on immediate error, 248f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * true otherwise 2496fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang * @hide 2506fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang */ 2516fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang public boolean disconnect(BluetoothDevice device) { 2526fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang if (DBG) log("disconnect(" + device + ")"); 2530f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService != null && isEnabled() && 25474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh isValidDevice(device)) { 25574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 2560f42037eb7b5118015c2caca635538324ccf0ccffredc return mPanService.disconnect(device); 25774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 25874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 25974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 2600f42037eb7b5118015c2caca635538324ccf0ccffredc } 2616fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 2620f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); 26374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 2646fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 2656fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 2665200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh /** 26774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * {@inheritDoc} 2685200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh */ 26974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public List<BluetoothDevice> getConnectedDevices() { 270563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getConnectedDevices()"); 2710f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService != null && isEnabled()) { 27274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 2730f42037eb7b5118015c2caca635538324ccf0ccffredc return mPanService.getConnectedDevices(); 27474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 27574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 27674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 2770f42037eb7b5118015c2caca635538324ccf0ccffredc } 2785200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh } 2790f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); 28074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 2815200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh } 2825200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh 2835200c8ab721b56025340306bdecca651e6bf2f12Jaikumar Ganesh /** 28474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * {@inheritDoc} 28574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 28674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 287563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getDevicesMatchingStates()"); 2880f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService != null && isEnabled()) { 28974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 2900f42037eb7b5118015c2caca635538324ccf0ccffredc return mPanService.getDevicesMatchingConnectionStates(states); 29174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 29274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 29374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 2940f42037eb7b5118015c2caca635538324ccf0ccffredc } 29574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 2960f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); 29774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 29874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 29974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 30074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh /** 30174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh * {@inheritDoc} 30274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh */ 30374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh public int getConnectionState(BluetoothDevice device) { 304563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getState(" + device + ")"); 3050f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService != null && isEnabled() 30674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh && isValidDevice(device)) { 30774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh try { 3080f42037eb7b5118015c2caca635538324ccf0ccffredc return mPanService.getConnectionState(device); 30974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } catch (RemoteException e) { 31074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 31174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return BluetoothProfile.STATE_DISCONNECTED; 3120f42037eb7b5118015c2caca635538324ccf0ccffredc } 31374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 3140f42037eb7b5118015c2caca635538324ccf0ccffredc if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); 31574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return BluetoothProfile.STATE_DISCONNECTED; 31674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 31774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 318b70765cc27a174d1d4a0bab7062733ebd3eae354Jaikumar Ganesh public void setBluetoothTethering(boolean value) { 31974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (DBG) log("setBluetoothTethering(" + value + ")"); 3206fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang try { 3210f42037eb7b5118015c2caca635538324ccf0ccffredc mPanService.setBluetoothTethering(value); 3226fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } catch (RemoteException e) { 32374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 3240f42037eb7b5118015c2caca635538324ccf0ccffredc } 3256fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 3266fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang 3276fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang public boolean isTetheringOn() { 328563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("isTetheringOn()"); 3296fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang try { 3300f42037eb7b5118015c2caca635538324ccf0ccffredc return mPanService.isTetheringOn(); 3316fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } catch (RemoteException e) { 33274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); 3330f42037eb7b5118015c2caca635538324ccf0ccffredc } 334e4caddbb7a3b39fd6a1ccf107c7dbf09bc8978e8Jaikumar Ganesh return false; 3356fdd0c6274c81b337ad35b70480f881daf7354c3Danica Chang } 33674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 3370f42037eb7b5118015c2caca635538324ccf0ccffredc private ServiceConnection mConnection = new ServiceConnection() { 3380f42037eb7b5118015c2caca635538324ccf0ccffredc public void onServiceConnected(ComponentName className, IBinder service) { 3390f42037eb7b5118015c2caca635538324ccf0ccffredc if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected"); 3400f42037eb7b5118015c2caca635538324ccf0ccffredc mPanService = IBluetoothPan.Stub.asInterface(service); 3410f42037eb7b5118015c2caca635538324ccf0ccffredc 3420f42037eb7b5118015c2caca635538324ccf0ccffredc if (mServiceListener != null) { 3430f42037eb7b5118015c2caca635538324ccf0ccffredc mServiceListener.onServiceConnected(BluetoothProfile.PAN, 3440f42037eb7b5118015c2caca635538324ccf0ccffredc BluetoothPan.this); 3450f42037eb7b5118015c2caca635538324ccf0ccffredc } 3460f42037eb7b5118015c2caca635538324ccf0ccffredc } 3470f42037eb7b5118015c2caca635538324ccf0ccffredc public void onServiceDisconnected(ComponentName className) { 3480f42037eb7b5118015c2caca635538324ccf0ccffredc if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected"); 3490f42037eb7b5118015c2caca635538324ccf0ccffredc mPanService = null; 3500f42037eb7b5118015c2caca635538324ccf0ccffredc if (mServiceListener != null) { 3510f42037eb7b5118015c2caca635538324ccf0ccffredc mServiceListener.onServiceDisconnected(BluetoothProfile.PAN); 3520f42037eb7b5118015c2caca635538324ccf0ccffredc } 3530f42037eb7b5118015c2caca635538324ccf0ccffredc } 3540f42037eb7b5118015c2caca635538324ccf0ccffredc }; 3550f42037eb7b5118015c2caca635538324ccf0ccffredc 35674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private boolean isEnabled() { 35774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; 35874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 35974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 36074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 36174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private boolean isValidDevice(BluetoothDevice device) { 36274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (device == null) return false; 36374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 36474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; 36574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh return false; 36674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 36774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh 36874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh private static void log(String msg) { 36974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh Log.d(TAG, msg); 37074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh } 3719bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh} 372