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