• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.pan;
18 
19 import android.app.Service;
20 import android.bluetooth.BluetoothDevice;
21 import android.bluetooth.BluetoothPan;
22 import android.bluetooth.BluetoothProfile;
23 import android.bluetooth.BluetoothTetheringDataTracker;
24 import android.bluetooth.IBluetooth;
25 import android.bluetooth.IBluetoothPan;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.PackageManager;
29 import android.content.res.Resources.NotFoundException;
30 import android.net.ConnectivityManager;
31 import android.net.InterfaceConfiguration;
32 import android.net.LinkAddress;
33 import android.net.NetworkUtils;
34 import android.os.Handler;
35 import android.os.IBinder;
36 import android.os.INetworkManagementService;
37 import android.os.Message;
38 import android.os.RemoteException;
39 import android.os.ServiceManager;
40 import android.provider.Settings;
41 import android.util.Log;
42 import com.android.bluetooth.btservice.ProfileService;
43 import com.android.bluetooth.Utils;
44 import java.net.InetAddress;
45 import java.util.ArrayList;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.List;
49 import java.util.Map;
50 
51 
52 /**
53  * Provides Bluetooth Pan Device profile, as a service in
54  * the Bluetooth application.
55  * @hide
56  */
57 public class PanService extends ProfileService {
58     private static final String TAG = "PanService";
59     private static final boolean DBG = false;
60 
61     private static final String BLUETOOTH_IFACE_ADDR_START= "192.168.44.1";
62     private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5;
63     private static final int BLUETOOTH_PREFIX_LENGTH        = 24;
64 
65     private HashMap<BluetoothDevice, BluetoothPanDevice> mPanDevices;
66     private ArrayList<String> mBluetoothIfaceAddresses;
67     private int mMaxPanDevices;
68     private String mPanIfName;
69     private boolean mNativeAvailable;
70 
71     private static final int MESSAGE_CONNECT = 1;
72     private static final int MESSAGE_DISCONNECT = 2;
73     private static final int MESSAGE_CONNECT_STATE_CHANGED = 11;
74     private boolean mTetherOn = false;
75 
76 
77     static {
classInitNative()78         classInitNative();
79     }
80 
getName()81     protected String getName() {
82         return TAG;
83     }
84 
initBinder()85     public IProfileServiceBinder initBinder() {
86         return new BluetoothPanBinder(this);
87     }
88 
start()89     protected boolean start() {
90         mPanDevices = new HashMap<BluetoothDevice, BluetoothPanDevice>();
91         mBluetoothIfaceAddresses = new ArrayList<String>();
92         try {
93             mMaxPanDevices = getResources().getInteger(
94                                  com.android.internal.R.integer.config_max_pan_devices);
95         } catch (NotFoundException e) {
96             mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS;
97         }
98         initializeNative();
99         mNativeAvailable=true;
100         return true;
101     }
102 
stop()103     protected boolean stop() {
104         mHandler.removeCallbacksAndMessages(null);
105         return true;
106     }
107 
cleanup()108     protected boolean cleanup() {
109         if (mNativeAvailable) {
110             cleanupNative();
111             mNativeAvailable=false;
112         }
113         if(mPanDevices != null) {
114             List<BluetoothDevice> DevList = getConnectedDevices();
115             for(BluetoothDevice dev : DevList) {
116                handlePanDeviceStateChange(dev, mPanIfName, BluetoothProfile.STATE_DISCONNECTED,
117                                                    BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
118             }
119             mPanDevices.clear();
120         }
121         if(mBluetoothIfaceAddresses != null) {
122             mBluetoothIfaceAddresses.clear();
123         }
124         return true;
125     }
126 
127     private final Handler mHandler = new Handler() {
128         @Override
129         public void handleMessage(Message msg) {
130             switch (msg.what) {
131                 case MESSAGE_CONNECT:
132                 {
133                     BluetoothDevice device = (BluetoothDevice) msg.obj;
134                     if (!connectPanNative(Utils.getByteAddress(device), BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE)) {
135                         handlePanDeviceStateChange(device, null, BluetoothProfile.STATE_CONNECTING,
136                                                    BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
137                         handlePanDeviceStateChange(device, null, BluetoothProfile.STATE_DISCONNECTED,
138                                                    BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
139                         break;
140                     }
141                 }
142                     break;
143                 case MESSAGE_DISCONNECT:
144                 {
145                     BluetoothDevice device = (BluetoothDevice) msg.obj;
146                     if (!disconnectPanNative(Utils.getByteAddress(device)) ) {
147                         handlePanDeviceStateChange(device, mPanIfName, BluetoothProfile.STATE_DISCONNECTING,
148                                                    BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
149                         handlePanDeviceStateChange(device, mPanIfName, BluetoothProfile.STATE_DISCONNECTED,
150                                                    BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
151                         break;
152                     }
153                 }
154                     break;
155                 case MESSAGE_CONNECT_STATE_CHANGED:
156                 {
157                     ConnectState cs = (ConnectState)msg.obj;
158                     BluetoothDevice device = getDevice(cs.addr);
159                     // TBD get iface from the msg
160                     if (DBG) log("MESSAGE_CONNECT_STATE_CHANGED: " + device + " state: " + cs.state);
161                     handlePanDeviceStateChange(device, mPanIfName /* iface */, convertHalState(cs.state),
162                                                cs.local_role,  cs.remote_role);
163                 }
164                 break;
165             }
166         }
167     };
168 
169     /**
170      * Handlers for incoming service calls
171      */
172     private static class BluetoothPanBinder extends IBluetoothPan.Stub implements IProfileServiceBinder {
173         private PanService mService;
BluetoothPanBinder(PanService svc)174         public BluetoothPanBinder(PanService svc) {
175             mService = svc;
176         }
cleanup()177         public boolean cleanup() {
178             mService = null;
179             return true;
180         }
getService()181         private PanService getService() {
182             if (!Utils.checkCaller()) {
183                 Log.w(TAG,"Pan call not allowed for non-active user");
184                 return null;
185             }
186 
187             if (mService  != null && mService.isAvailable()) {
188                 return mService;
189             }
190             return null;
191         }
connect(BluetoothDevice device)192         public boolean connect(BluetoothDevice device) {
193             PanService service = getService();
194             if (service == null) return false;
195             return service.connect(device);
196         }
disconnect(BluetoothDevice device)197         public boolean disconnect(BluetoothDevice device) {
198             PanService service = getService();
199             if (service == null) return false;
200             return service.disconnect(device);
201         }
getConnectionState(BluetoothDevice device)202         public int getConnectionState(BluetoothDevice device) {
203             PanService service = getService();
204             if (service == null) return BluetoothPan.STATE_DISCONNECTED;
205             return service.getConnectionState(device);
206         }
isPanNapOn()207         private boolean isPanNapOn() {
208             PanService service = getService();
209             if (service == null) return false;
210             return service.isPanNapOn();
211         }
isPanUOn()212         private boolean isPanUOn() {
213             if(DBG) Log.d(TAG, "isTetheringOn call getPanLocalRoleNative");
214             PanService service = getService();
215             return service.isPanUOn();
216         }
isTetheringOn()217         public boolean isTetheringOn() {
218             // TODO(BT) have a variable marking the on/off state
219             PanService service = getService();
220             if (service == null) return false;
221             return service.isTetheringOn();
222         }
setBluetoothTethering(boolean value)223         public void setBluetoothTethering(boolean value) {
224             PanService service = getService();
225             if (service == null) return;
226             Log.d(TAG, "setBluetoothTethering: " + value +", mTetherOn: " + service.mTetherOn);
227             service.setBluetoothTethering(value);
228         }
229 
getConnectedDevices()230         public List<BluetoothDevice> getConnectedDevices() {
231             PanService service = getService();
232             if (service == null) return new ArrayList<BluetoothDevice>(0);
233             return service.getConnectedDevices();
234         }
235 
getDevicesMatchingConnectionStates(int[] states)236         public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
237             PanService service = getService();
238             if (service == null) return new ArrayList<BluetoothDevice>(0);
239             return service.getDevicesMatchingConnectionStates(states);
240         }
241     };
242 
connect(BluetoothDevice device)243     boolean connect(BluetoothDevice device) {
244         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
245         if (getConnectionState(device) != BluetoothProfile.STATE_DISCONNECTED) {
246             Log.e(TAG, "Pan Device not disconnected: " + device);
247             return false;
248         }
249         Message msg = mHandler.obtainMessage(MESSAGE_CONNECT,device);
250         mHandler.sendMessage(msg);
251         return true;
252     }
253 
disconnect(BluetoothDevice device)254     boolean disconnect(BluetoothDevice device) {
255         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
256         Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT,device);
257         mHandler.sendMessage(msg);
258         return true;
259     }
260 
getConnectionState(BluetoothDevice device)261     int getConnectionState(BluetoothDevice device) {
262         BluetoothPanDevice panDevice = mPanDevices.get(device);
263         if (panDevice == null) {
264             return BluetoothPan.STATE_DISCONNECTED;
265         }
266         return panDevice.mState;
267     }
268 
isPanNapOn()269     boolean isPanNapOn() {
270         if(DBG) Log.d(TAG, "isTetheringOn call getPanLocalRoleNative");
271         return (getPanLocalRoleNative() & BluetoothPan.LOCAL_NAP_ROLE) != 0;
272     }
isPanUOn()273      boolean isPanUOn() {
274         if(DBG) Log.d(TAG, "isTetheringOn call getPanLocalRoleNative");
275         return (getPanLocalRoleNative() & BluetoothPan.LOCAL_PANU_ROLE) != 0;
276     }
isTetheringOn()277      boolean isTetheringOn() {
278         // TODO(BT) have a variable marking the on/off state
279         return mTetherOn;
280     }
281 
setBluetoothTethering(boolean value)282     void setBluetoothTethering(boolean value) {
283         if(DBG) Log.d(TAG, "setBluetoothTethering: " + value +", mTetherOn: " + mTetherOn);
284         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
285         if(mTetherOn != value) {
286             //drop any existing panu or pan-nap connection when changing the tethering state
287             mTetherOn = value;
288             List<BluetoothDevice> DevList = getConnectedDevices();
289             for(BluetoothDevice dev : DevList)
290                 disconnect(dev);
291         }
292     }
293 
getConnectedDevices()294     List<BluetoothDevice> getConnectedDevices() {
295         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
296         List<BluetoothDevice> devices = getDevicesMatchingConnectionStates(
297                 new int[] {BluetoothProfile.STATE_CONNECTED});
298         return devices;
299     }
300 
getDevicesMatchingConnectionStates(int[] states)301     List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
302          enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
303         List<BluetoothDevice> panDevices = new ArrayList<BluetoothDevice>();
304 
305         for (BluetoothDevice device: mPanDevices.keySet()) {
306             int panDeviceState = getConnectionState(device);
307             for (int state : states) {
308                 if (state == panDeviceState) {
309                     panDevices.add(device);
310                     break;
311                 }
312             }
313         }
314         return panDevices;
315     }
316 
317     static protected class ConnectState {
ConnectState(byte[] address, int state, int error, int local_role, int remote_role)318         public ConnectState(byte[] address, int state, int error, int local_role, int remote_role) {
319             this.addr = address;
320             this.state = state;
321             this.error = error;
322             this.local_role = local_role;
323             this.remote_role = remote_role;
324         }
325         byte[] addr;
326         int state;
327         int error;
328         int local_role;
329         int remote_role;
330     };
onConnectStateChanged(byte[] address, int state, int error, int local_role, int remote_role)331     private void onConnectStateChanged(byte[] address, int state, int error, int local_role, int remote_role) {
332         if (DBG) log("onConnectStateChanged: " + state + ", local role:" + local_role + ", remote_role: " + remote_role);
333         Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_STATE_CHANGED);
334         msg.obj = new ConnectState(address, state, error, local_role, remote_role);
335         mHandler.sendMessage(msg);
336     }
onControlStateChanged(int local_role, int state, int error, String ifname)337     private void onControlStateChanged(int local_role, int state, int error, String ifname) {
338         if (DBG)
339             log("onControlStateChanged: " + state + ", error: " + error + ", ifname: " + ifname);
340         if(error == 0)
341             mPanIfName = ifname;
342     }
343 
convertHalState(int halState)344     private static int convertHalState(int halState) {
345         switch (halState) {
346             case CONN_STATE_CONNECTED:
347                 return BluetoothProfile.STATE_CONNECTED;
348             case CONN_STATE_CONNECTING:
349                 return BluetoothProfile.STATE_CONNECTING;
350             case CONN_STATE_DISCONNECTED:
351                 return BluetoothProfile.STATE_DISCONNECTED;
352             case CONN_STATE_DISCONNECTING:
353                 return BluetoothProfile.STATE_DISCONNECTING;
354             default:
355                 Log.e(TAG, "bad pan connection state: " + halState);
356                 return BluetoothProfile.STATE_DISCONNECTED;
357         }
358     }
359 
handlePanDeviceStateChange(BluetoothDevice device, String iface, int state, int local_role, int remote_role)360     void handlePanDeviceStateChange(BluetoothDevice device,
361                                     String iface, int state, int local_role, int remote_role) {
362         if(DBG) Log.d(TAG, "handlePanDeviceStateChange: device: " + device + ", iface: " + iface +
363                     ", state: " + state + ", local_role:" + local_role + ", remote_role:" + remote_role);
364         int prevState;
365         String ifaceAddr = null;
366         BluetoothPanDevice panDevice = mPanDevices.get(device);
367         if (panDevice == null) {
368             prevState = BluetoothProfile.STATE_DISCONNECTED;
369         } else {
370             prevState = panDevice.mState;
371             ifaceAddr = panDevice.mIfaceAddr;
372         }
373         Log.d(TAG, "handlePanDeviceStateChange preState: " + prevState + " state: " + state);
374         if (prevState == state) return;
375         if (remote_role == BluetoothPan.LOCAL_PANU_ROLE) {
376             if (state == BluetoothProfile.STATE_CONNECTED) {
377                 if((!mTetherOn)||(local_role == BluetoothPan.LOCAL_PANU_ROLE)){
378                     Log.d(TAG,"handlePanDeviceStateChange BT tethering is off/Local role is PANU "+
379                               "drop the connection");
380                     disconnectPanNative(Utils.getByteAddress(device));
381                     return;
382                 }
383                 Log.d(TAG, "handlePanDeviceStateChange LOCAL_NAP_ROLE:REMOTE_PANU_ROLE");
384                 ifaceAddr = enableTethering(iface);
385                 if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");
386 
387             } else if (state == BluetoothProfile.STATE_DISCONNECTED) {
388                 if (ifaceAddr != null) {
389                     mBluetoothIfaceAddresses.remove(ifaceAddr);
390                     ifaceAddr = null;
391                 }
392             }
393         } else {
394             // PANU Role = reverse Tether
395             Log.d(TAG, "handlePanDeviceStateChange LOCAL_PANU_ROLE:REMOTE_NAP_ROLE");
396             if (state == BluetoothProfile.STATE_CONNECTED) {
397                 if(DBG) Log.d(TAG, "handlePanDeviceStateChange: panu STATE_CONNECTED, startReverseTether");
398                 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
399                 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
400                 Log.d(TAG, "call INetworkManagementService.startReverseTethering()");
401                 try {
402                     service.startReverseTethering(iface);
403                 } catch (Exception e) {
404                     Log.e(TAG, "Cannot start reverse tethering: " + e);
405                     return;
406                 }
407             } else if (state == BluetoothProfile.STATE_DISCONNECTED &&
408                   (prevState == BluetoothProfile.STATE_CONNECTED ||
409                   prevState == BluetoothProfile.STATE_DISCONNECTING)) {
410                 if(DBG) Log.d(TAG, "handlePanDeviceStateChange: stopReverseTether, panDevice.mIface: "
411                                     + panDevice.mIface);
412                 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
413                 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
414                 try {
415                     service.stopReverseTethering();
416                 } catch(Exception e) {
417                     Log.e(TAG, "Cannot stop reverse tethering: " + e);
418                     return;
419                 }
420             }
421         }
422 
423         if (panDevice == null) {
424             panDevice = new BluetoothPanDevice(state, ifaceAddr, iface, local_role);
425             mPanDevices.put(device, panDevice);
426         } else {
427             panDevice.mState = state;
428             panDevice.mIfaceAddr = ifaceAddr;
429             panDevice.mLocalRole = local_role;
430             panDevice.mIface = iface;
431         }
432 
433         /* Notifying the connection state change of the profile before sending the intent for
434            connection state change, as it was causing a race condition, with the UI not being
435            updated with the correct connection state. */
436         Log.d(TAG, "Pan Device state : device: " + device + " State:" +
437                        prevState + "->" + state);
438         notifyProfileConnectionStateChanged(device, BluetoothProfile.PAN, state, prevState);
439         Intent intent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
440         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
441         intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_STATE, prevState);
442         intent.putExtra(BluetoothPan.EXTRA_STATE, state);
443         intent.putExtra(BluetoothPan.EXTRA_LOCAL_ROLE, local_role);
444         sendBroadcast(intent, BLUETOOTH_PERM);
445     }
446 
447     // configured when we start tethering
enableTethering(String iface)448     private String enableTethering(String iface) {
449         if (DBG) Log.d(TAG, "updateTetherState:" + iface);
450 
451         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
452         INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
453         ConnectivityManager cm =
454             (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
455         String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
456 
457         // bring toggle the interfaces
458         String[] currentIfaces = new String[0];
459         try {
460             currentIfaces = service.listInterfaces();
461         } catch (Exception e) {
462             Log.e(TAG, "Error listing Interfaces :" + e);
463             return null;
464         }
465 
466         boolean found = false;
467         for (String currIface: currentIfaces) {
468             if (currIface.equals(iface)) {
469                 found = true;
470                 break;
471             }
472         }
473 
474         if (!found) return null;
475 
476         String address = createNewTetheringAddressLocked();
477         if (address == null) return null;
478 
479         InterfaceConfiguration ifcg = null;
480         try {
481             ifcg = service.getInterfaceConfig(iface);
482             if (ifcg != null) {
483                 InetAddress addr = null;
484                 LinkAddress linkAddr = ifcg.getLinkAddress();
485                 if (linkAddr == null || (addr = linkAddr.getAddress()) == null ||
486                         addr.equals(NetworkUtils.numericToInetAddress("0.0.0.0")) ||
487                         addr.equals(NetworkUtils.numericToInetAddress("::0"))) {
488                     addr = NetworkUtils.numericToInetAddress(address);
489                 }
490                 ifcg.setInterfaceUp();
491                 ifcg.setLinkAddress(new LinkAddress(addr, BLUETOOTH_PREFIX_LENGTH));
492                 ifcg.clearFlag("running");
493                 // TODO(BT) ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
494                 service.setInterfaceConfig(iface, ifcg);
495                 if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
496                     Log.e(TAG, "Error tethering "+iface);
497                 }
498             }
499         } catch (Exception e) {
500             Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
501             return null;
502         }
503         return address;
504     }
505 
createNewTetheringAddressLocked()506     private String createNewTetheringAddressLocked() {
507         if (getConnectedPanDevices().size() == mMaxPanDevices) {
508             if (DBG) Log.d(TAG, "Max PAN device connections reached");
509             return null;
510         }
511         String address = BLUETOOTH_IFACE_ADDR_START;
512         while (true) {
513             if (mBluetoothIfaceAddresses.contains(address)) {
514                 String[] addr = address.split("\\.");
515                 Integer newIp = Integer.parseInt(addr[2]) + 1;
516                 address = address.replace(addr[2], newIp.toString());
517             } else {
518                 break;
519             }
520         }
521         mBluetoothIfaceAddresses.add(address);
522         return address;
523     }
524 
getConnectedPanDevices()525     private List<BluetoothDevice> getConnectedPanDevices() {
526         List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
527 
528         for (BluetoothDevice device: mPanDevices.keySet()) {
529             if (getPanDeviceConnectionState(device) == BluetoothProfile.STATE_CONNECTED) {
530                 devices.add(device);
531             }
532         }
533         return devices;
534     }
535 
getPanDeviceConnectionState(BluetoothDevice device)536     private int getPanDeviceConnectionState(BluetoothDevice device) {
537         BluetoothPanDevice panDevice = mPanDevices.get(device);
538         if (panDevice == null) {
539             return BluetoothProfile.STATE_DISCONNECTED;
540         }
541         return panDevice.mState;
542     }
543 
544     private class BluetoothPanDevice {
545         private int mState;
546         private String mIfaceAddr;
547         private String mIface;
548         private int mLocalRole; // Which local role is this PAN device bound to
549 
BluetoothPanDevice(int state, String ifaceAddr, String iface, int localRole)550         BluetoothPanDevice(int state, String ifaceAddr, String iface, int localRole) {
551             mState = state;
552             mIfaceAddr = ifaceAddr;
553             mIface = iface;
554             mLocalRole = localRole;
555         }
556     }
557 
558     // Constants matching Hal header file bt_hh.h
559     // bthh_connection_state_t
560     private final static int CONN_STATE_CONNECTED = 0;
561     private final static int CONN_STATE_CONNECTING = 1;
562     private final static int CONN_STATE_DISCONNECTED = 2;
563     private final static int CONN_STATE_DISCONNECTING = 3;
564 
classInitNative()565     private native static void classInitNative();
initializeNative()566     private native void initializeNative();
cleanupNative()567     private native void cleanupNative();
connectPanNative(byte[] btAddress, int local_role, int remote_role)568     private native boolean connectPanNative(byte[] btAddress, int local_role, int remote_role);
disconnectPanNative(byte[] btAddress)569     private native boolean disconnectPanNative(byte[] btAddress);
enablePanNative(int local_role)570     private native boolean enablePanNative(int local_role);
getPanLocalRoleNative()571     private native int getPanLocalRoleNative();
572 
573 }
574