蓝牙之三-StateMachine

来源:互联网 发布:阿里云服务器托管 编辑:程序博客网 时间:2024/05/16 23:53

蓝牙和wifi的管理上都使用到了状态机。

该状态机属于分层状态机管理消息。一个状态对应于一个<State>对象,并且状态必须实现<processMessage>方法,可选的实现方法是<enter/exit/getName>,<enter/exit>方法对应于构造和析构函数,它们被用于初始化和清理状态。<getName>方法返回状态的名称,缺省的方式是返回返回类名称,但是也许返回实例的名称是使用者更想要的方式,尤其是一个状态类具有多个实例的时候。

当状态机使用创建后,<addState>方法用于创建状态层次,<setInitialState>用于标识哪些是初始的状态。构造完成后程序调用<start>方法用于初始化和启动状态机。状态机的第一个动作是为所有的状态层次(从最原始的父类开始)调用<enter>方法。这在处理任何消息之前完成。如下的mP1.enter将唤醒mS1.enter。最中发送该状态的的信息被当前状态处理,也就是被<mS1.processMessage>方法。

     mP1      /   \ mS2   mS1 ----> initial state

在状态机被创建和启动后,消息的创建方法是<obtainMessage>,消息的发送方法是<sendMessage>。当状态机接收到一个消息时,当前状态的<processMessage>方法将被调用,在上面的例子中,mS1.processMessage将被首先唤醒,该状态可使用<transitionTo>方法将当前状态切换到一个新状态。

状态机中的每个状态可以有零或一个父状态,如果子状态无法处理一个消息,父状态将返回fase或者NOT_HANDLED代为处理。如果一个消息从没被处理,则<unhandledMessage>方法被调用作为消息处理的最后机会。

当状态机完成所有的处理后也许会调用<transitionToHaltingState>。当<processingMessage>返回时,状态机将会会处于<HaltfingState>并且调用<halting>方法。任何后续发给状态机的消息将会唤醒<haltedProcessMessage>方法。

如果要完全停止状态机<quit>或者<quitNow>方法将被调用。这将进一步调用当前状态和父状态的<exit>方法,调用<onQuiting>然后退出线程。

由于状态按层级方式组织,一个状态的进入将引起一个状态的退出。

状态可能使用到的另外两个方法是<deferMessage>和<sendMessageAtFrontOfQueue>。<sendMessageAtFrontOfQueue>将消息放在stack队列的前端而非尾端。<deferMessage>将信息保存在一个list上直到新状态切换,这时所有deferred 消息将被放大状态机队列的首端,最早消息放在最前端。然后这些消息将被当前状态在其它任何消息前被处理。

以8个状态的状态机说明上述过程。

         mP0        /   \       mP1   mS0       /   \     mS2   mS1    /  \    \    mS3  mS4  mS5  ---> initial state
在启动mS5后,处于激活状态的state是mP0,mP1,mS1,mS5。所以当一个消息来临是,processMessage处理消息的过程是mS5,mS1,mP1,mP0,如果哪个状态返回false或者NOT_HANDLED则就会用父状态处理方法。

假设mS5接收的消息,其能够处理,并且处理过程确认需要切换状态,其将会调用transitionTo(mS4)并且返回ture或者HANDLED。状态机从processMessage返回后立即知道它们的共同父状态是mP1.其将会调用mS5.exit,mS1.exit,mS2.enter以及mS4.enter。新的激活状态的state是mP0,mP1,mS2,mS4。所以当下一个消息来临时mS4.processMessage将被唤醒。

如下是一个hello world实例。

class HelloWorld extends StateMachine {   HelloWorld(String name) {        super(name);        addState(mState1);        setInitialState(mState1);    }    public static HelloWorld makeHelloWorld() {        HelloWorld hw = new HelloWorld("hw");        hw.start();        return hw;    }    class State1 extends State {        @Override public boolean processMessage(Message message) {            log("Hello World");            return HANDLED;            }    }    State1 mState1 = new State1();}void testHelloWorld() {    HelloWorld hw = makeHelloWorld();    hw.sendMessage(hw.obtainMessage());}

在蓝牙的BondStateMachine.java中就用到了状态机。

final class BondStateMachine extends StateMachine {...//这里定义了private的构造函数,不能通过new方法创建BondStateMachine的对象。private BondStateMachine(AdapterService service,            AdapterProperties prop, RemoteDevices remoteDevices) {        super("BondStateMachine:");        addState(mStableState);        addState(mPendingCommandState);        mRemoteDevices = remoteDevices;        mAdapterService = service;        mAdapterProperties = prop;        mAdapter = BluetoothAdapter.getDefaultAdapter();        setInitialState(mStableState);    }//public方法,通过make方法创建该对象    public static BondStateMachine make(AdapterService service,            AdapterProperties prop, RemoteDevices remoteDevices) {        Log.d(TAG, "make");        BondStateMachine bsm = new BondStateMachine(service, prop, remoteDevices);        bsm.start();        return bsm;    }... private class StableState extends State {        @Override        public void enter() {            infoLog("StableState(): Entering Off State");        }        @Override        public boolean processMessage(Message msg) {            BluetoothDevice dev = (BluetoothDevice)msg.obj;            switch(msg.what) {              case CREATE_BOND:                  createBond(dev, msg.arg1, true);                  break;              case REMOVE_BOND:                  removeBond(dev, true);                  break;              case BONDING_STATE_CHANGE:                int newState = msg.arg1;                /* if incoming pairing, transition to pending state */                if (newState == BluetoothDevice.BOND_BONDING)                {                    sendIntent(dev, newState, 0);                    transitionTo(mPendingCommandState);                }                else if (newState == BluetoothDevice.BOND_NONE)                {                    /* if the link key was deleted by the stack */                    sendIntent(dev, newState, 0);                }                else                {                    Log.e(TAG, "In stable state, received invalid newState: " + newState);                }                break;              case CANCEL_BOND:              default:                   Log.e(TAG, "Received unhandled state: " + msg.what);                   return false;            }            return true;        }    }    private class PendingCommandState extends State {        private final ArrayList<BluetoothDevice> mDevices =            new ArrayList<BluetoothDevice>();        @Override        public void enter() {            infoLog("Entering PendingCommandState State");            BluetoothDevice dev = (BluetoothDevice)getCurrentMessage().obj;        }        @Override        public boolean processMessage(Message msg) {            BluetoothDevice dev = (BluetoothDevice)msg.obj;            DeviceProperties devProp = mRemoteDevices.getDeviceProperties(dev);            boolean result = false;             if (mDevices.contains(dev) && msg.what != CANCEL_BOND &&                   msg.what != BONDING_STATE_CHANGE && msg.what != SSP_REQUEST &&                   msg.what != PIN_REQUEST) {                 deferMessage(msg);                 return true;             }            Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);            switch (msg.what) {                case CREATE_BOND:                    result = createBond(dev, msg.arg1, false);                    break;                case REMOVE_BOND:                    result = removeBond(dev, false);                    break;                case CANCEL_BOND:                    result = cancelBond(dev);                    break;                case BONDING_STATE_CHANGE:                    int newState = msg.arg1;                    int reason = getUnbondReasonFromHALCode(msg.arg2);                    sendIntent(dev, newState, reason);                    if(newState != BluetoothDevice.BOND_BONDING )                    {                        /* this is either none/bonded, remove and transition */                        result = !mDevices.remove(dev);                        if (mDevices.isEmpty()) {                            // Whenever mDevices is empty, then we need to                            // set result=false. Else, we will end up adding                            // the device to the list again. This prevents us                            // from pairing with a device that we just unpaired                            result = false;                            transitionTo(mStableState);                        }                        if (newState == BluetoothDevice.BOND_NONE)                        {                            mAdapterService.setPhonebookAccessPermission(dev,                                    BluetoothDevice.ACCESS_UNKNOWN);                            mAdapterService.setMessageAccessPermission(dev,                                    BluetoothDevice.ACCESS_UNKNOWN);                            mAdapterService.setSimAccessPermission(dev,                                    BluetoothDevice.ACCESS_UNKNOWN);                            // Set the profile Priorities to undefined                            clearProfilePriorty(dev);                        }                        else if (newState == BluetoothDevice.BOND_BONDED)                        {                           // Do not set profile priority                           // Profile priority should be set after SDP completion                           // Restore the profile priorty settings                           //setProfilePriorty(dev);                        }                    }                    else if(!mDevices.contains(dev))                        result=true;                    break;                case SSP_REQUEST:                    int passkey = msg.arg1;                    int variant = msg.arg2;                    sendDisplayPinIntent(devProp.getAddress(), passkey, variant);                    break;                case PIN_REQUEST:                    BluetoothClass btClass = dev.getBluetoothClass();                    int btDeviceClass = btClass.getDeviceClass();                    if (btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD ||                         btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING) {                        // Its a keyboard. Follow the HID spec recommendation of creating the                        // passkey and displaying it to the user. If the keyboard doesn't follow                        // the spec recommendation, check if the keyboard has a fixed PIN zero                        // and pair.                        //TODO: Maintain list of devices that have fixed pin                        // Generate a variable 6-digit PIN in range of 100000-999999                        // This is not truly random but good enough.                        int pin = 100000 + (int)Math.floor((Math.random() * (999999 - 100000)));                        sendDisplayPinIntent(devProp.getAddress(), pin,                                 BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN);                        break;                    }                    if (msg.arg2 == 1) { // Minimum 16 digit pin required here                        sendDisplayPinIntent(devProp.getAddress(), 0,                                BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS);                    } else {                        // In PIN_REQUEST, there is no passkey to display.So do not send the                        // EXTRA_PAIRING_KEY type in the intent( 0 in SendDisplayPinIntent() )                        sendDisplayPinIntent(devProp.getAddress(), 0,                                              BluetoothDevice.PAIRING_VARIANT_PIN);                    }                    break;                default:                    Log.e(TAG, "Received unhandled event:" + msg.what);                    return false;            }            if (result) mDevices.add(dev);            return true;        }    }

实现了两个state,一个是StableState一个是PendingCommandState。它们又各自实现了enter和processMessage方法。BondStateMachine的构造函数添加了两个state。

        addState(mStableState);        addState(mPendingCommandState);

并使用setInitialState为mStateState。

setInitialState(mStableState);
构造完成后调用start方法启动状态机。

        bsm.start();
调用start启动状态机后,所有状态的enter方法会被调用。

接下来就是消息的创建,发送

    void bondStateChangeCallback(int status, byte[] address, int newState) {        BluetoothDevice device = mRemoteDevices.getDevice(address);        if (device == null) {            infoLog("No record of the device:" + device);            // This device will be added as part of the BONDING_STATE_CHANGE intent processing            // in sendIntent above            device = mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));        }        infoLog("bondStateChangeCallback: Status: " + status + " Address: " + device                + " newState: " + newState);        Message msg =<strong> obtainMessage</strong>(BONDING_STATE_CHANGE);        msg.obj = device;        if (newState == BOND_STATE_BONDED)            msg.arg1 = BluetoothDevice.BOND_BONDED;        else if (newState == BOND_STATE_BONDING)            msg.arg1 = BluetoothDevice.BOND_BONDING;        else            msg.arg1 = BluetoothDevice.BOND_NONE;        msg.arg2 = status;        <strong>sendMessage</strong>(msg);    }    void sspRequestCallback(byte[] address, byte[] name, int cod, int pairingVariant,            int passkey) {        //TODO(BT): Get wakelock and update name and cod        BluetoothDevice bdDevice = mRemoteDevices.getDevice(address);        if (bdDevice == null) {            mRemoteDevices.addDeviceProperties(address);        }        infoLog("sspRequestCallback: " + address + " name: " + name + " cod: " +                cod + " pairingVariant " + pairingVariant + " passkey: " + passkey);        int variant;        boolean displayPasskey = false;        switch(pairingVariant) {            case AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION :                variant = BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION;                displayPasskey = true;            break;            case AbstractionLayer.BT_SSP_VARIANT_CONSENT :                variant = BluetoothDevice.PAIRING_VARIANT_CONSENT;            break;            case AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY :                variant = BluetoothDevice.PAIRING_VARIANT_PASSKEY;            break;            case AbstractionLayer.BT_SSP_VARIANT_PASSKEY_NOTIFICATION :                variant = BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY;                displayPasskey = true;            break;            default:                errorLog("SSP Pairing variant not present");                return;        }        BluetoothDevice device = mRemoteDevices.getDevice(address);        if (device == null) {           warnLog("Device is not known for:" + Utils.getAddressStringFromByte(address));           mRemoteDevices.addDeviceProperties(address);           device = mRemoteDevices.getDevice(address);        }        Message msg = <strong>obtainMessage</strong>(SSP_REQUEST);        msg.obj = device;        if(displayPasskey)            msg.arg1 = passkey;        msg.arg2 = variant;        <strong>sendMessage</strong>(msg);    }    void pinRequestCallback(byte[] address, byte[] name, int cod, boolean min16Digits) {        //TODO(BT): Get wakelock and update name and cod        BluetoothDevice bdDevice = mRemoteDevices.getDevice(address);        if (bdDevice == null) {            mRemoteDevices.addDeviceProperties(address);        }        infoLog("pinRequestCallback: " + address + " name:" + name + " cod:" +                cod);        Message msg = <strong>obtainMessage</strong>(PIN_REQUEST);        msg.obj = bdDevice;        msg.arg2 = min16Digits ? 1 : 0; // Use arg2 to pass the min16Digit boolean        <strong>sendMessage</strong>(msg);    }
上面的三个方法会被native层调用,native层根据需要调用这些函数以通知最上层的java。

<./packages/apps/Bluetooth/src/com/android/bluetooth/btservice/JniCallbacks.java>final class JniCallbacks {..    void pinRequestCallback(byte[] address, byte[] name, int cod, boolean min16Digits) {        mBondStateMachine.pinRequestCallback(address, name, cod, min16Digits);    }    void bondStateChangeCallback(int status, byte[] address, int newState) {        mBondStateMachine.bondStateChangeCallback(status, address, newState);    }...}
  如

 《packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp》 287 static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr, 288                                         bt_bond_state_t state) { 289     jbyteArray addr; 290     int i; 291     if (!checkCallbackThread()) { 292        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 293        return; 294     } 295     if (!bd_addr) { 296         ALOGE("Address is null in %s", __FUNCTION__); 297         return; 298     } 299     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 300     if (addr == NULL) { 301        ALOGE("Address allocation failed in %s", __FUNCTION__); 302        return; 303     } 304     callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr); 305 //   3 调用这个方法 306     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status, 307                                 addr, (jint)state); 308     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 309     callbackEnv->DeleteLocalRef(addr); 310 } 602 static void classInitNative(JNIEnv* env, jclass clazz) { 603     int err; 604     hw_module_t* module; 605 //   1   java反射法,找到java里的class文件 606     jclass jniCallbackClass = 607         env->FindClass("com/android/bluetooth/btservice/JniCallbacks"); 608     sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks", 609         "Lcom/android/bluetooth/btservice/JniCallbacks;"); 610//   2 找java class里的方法 611     method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V"); 612  613     method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass, 614                                                              "adapterPropertyChangedCallback", 615                                                              "([I[[B)V"); 616     method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass, 617                                                            "discoveryStateChangeCallback", "(I)V"); 618  619     method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass, 620                                                             "devicePropertyChangedCallback", 621                                                             "([B[I[[B)V"); 622     method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V"); 623     method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback", 624                                                  "([B[BIZ)V"); 625     method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback", 626                                                  "([B[BIII)V"); 627  628     method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass, 629                                                      "bondStateChangeCallback", "(I[BI)V"); 630  631     method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass, 632                                                     "aclStateChangeCallback", "(I[BI)V");1133 static JNINativeMethod sMethods[] = {1134     /* name, signature, funcPtr */1135     {"classInitNative", "()V", (void *) classInitNative},1136     {"initNative", "()Z", (void *) initNative},1137     {"cleanupNative", "()V", (void*) cleanupNative},1138     {"enableNative", "()Z",  (void*) enableNative},1139     {"disableNative", "()Z",  (void*) disableNative},1140     {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},1141     {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},1142     {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},1143     {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},1144     {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},1145     {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},1146     {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},1147     {"createBondNative", "([BI)Z", (void*) createBondNative},1148     {"removeBondNative", "([B)Z", (void*) removeBondNative},1149     {"cancelBondNative", "([B)Z", (void*) cancelBondNative},1150     {"getConnectionStateNative", "([B)I", (void*) getConnectionStateNative},1151     {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},1152     {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},1153     {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},1154     {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative},1155     {"createSocketChannelNative", "(ILjava/lang/String;[BII)I",1156      (void*) createSocketChannelNative},1157     {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative},1158     {"alarmFiredNative", "()V", (void *) alarmFiredNative},1159     {"readEnergyInfo", "()I", (void*) readEnergyInfo},1160     {"dumpNative", "(Ljava/io/FileDescriptor;)V", (void*) dumpNative},1161     {"factoryResetNative", "()Z", (void*)factoryResetNative}1162 };1164 int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)1165 {1166     return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",1167                                     sMethods, NELEM(sMethods));1168 }1176 jint JNI_OnLoad(JavaVM *jvm, void *reserved)1177 {1178     JNIEnv *e;1179     int status;1180 1181     ALOGV("Bluetooth Adapter Service : loading JNI\n");1182 1183     // Check JNI version1184     if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {1185         ALOGE("JNI version mismatch error");1186         return JNI_ERR;1187     }1188 1189     if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {1190         ALOGE("jni adapter service registration failure, status: %d", status);1191         return JNI_ERR;1192      }...
JNI加载,上述代码的意义是将cpp里的函数导出给java层调用。

./Bluetooth/src/com/android/bluetooth/btservice/AdapterApp.java:34:        System.loadLibrary("bluetooth_jni");


由上述可以看出在AdapterApp里JNI组件被加载。上面的是cpp函数给java调用。

classInitNative函数,实现了java函数给cpp使用。

 《packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp》602 static void classInitNative(JNIEnv* env, jclass clazz) { 603     int err; 604     hw_module_t* module; 605  606     jclass jniCallbackClass = 607         env->FindClass("com/android/bluetooth/btservice/<strong>JniCallbacks</strong>"); 608     sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks", 609         "Lcom/android/bluetooth/btservice/JniCallbacks;"); 610  611     method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V"); 612  613     method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass, 614                                                              "adapterPropertyChangedCallback", 615                                                              "([I[[B)V"); 616     method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass, 617                                                            "discoveryStateChangeCallback", "(I)V"); 618  619     method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass, 620                                                             "devicePropertyChangedCallback", 621                                                             "([B[I[[B)V"); 622     method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V"); 623     method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback", 624                                                  "([B[BIZ)V"); 625     method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback", 626                                                  "([B[BIII)V"); 627 <strong> 628     method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass, 629                                                      "bondStateChangeCallback", "(I[BI)V");</strong> 630  631     method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass, 632                                                     "aclStateChangeCallback", "(I[BI)V"); 633  634     method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z"); 635     method_acquireWakeLock = env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z"); 636     method_releaseWakeLock = env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z"); 637     method_energyInfo = env->GetMethodID(clazz, "energyInfoCallback", "(IIJJJJ)V"); 638  639     char value[PROPERTY_VALUE_MAX]; 640     property_get("bluetooth.mock_stack", value, ""); 641  642     const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID); 643  644     err = hw_get_module(id, (hw_module_t const**)&module); 645  646     if (err == 0) { 647         hw_device_t* abstraction; 648         err = module->methods->open(module, id, &abstraction);
上述函数

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java  83 public class AdapterService extends Service {  128     static {  129         classInitNative();  130     }...2099     private native static void classInitNative();2100     private native boolean initNative();2101     private native void cleanupNative();2112     /*package*/ native boolean createBondNative(byte[] address, int transport);2113     /*package*/ native boolean removeBondNative(byte[] address);2114     /*package*/ native boolean cancelBondNative(byte[] address);2115     /*package*/ native boolean sdpSearchNative(byte[] address, byte[] uuid);2116 2117     /*package*/ native int getConnectionStateNative(byte[] address);
上面提到classInitNative函数,这个函数的定义如下:
packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cppstatic void classInitNative(JNIEnv* env, jclass clazz) {    int err;    hw_module_t* module;    jclass jniCallbackClass =        env->FindClass("com/android/bluetooth/btservice/<strong>JniCallbacks</strong>");    sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",        "Lcom/android/bluetooth/btservice/JniCallbacks;");    method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");    method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,                                                             "adapterPropertyChangedCallback",                                                             "([I[[B)V");    method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,                                                           "discoveryStateChangeCallback", "(I)V");    method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,                                                            "devicePropertyChangedCallback",                                                            "([B[I[[B)V");    method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");    method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",                                                 "([B[BIZ)V");    method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",                                                 "([B[BIII)V");    method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,                                                     "bondStateChangeCallback", "(I[BI)V");    method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,                                                    "aclStateChangeCallback", "(I[BI)V");    method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");    method_acquireWakeLock = env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");    method_releaseWakeLock = env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");    method_energyInfo = env->GetMethodID(clazz, "energyInfoCallback", "(IIJJJJ)V");
这个函数加载了JniCallbacksl类

final class JniCallbacks {    private RemoteDevices mRemoteDevices;    private AdapterProperties mAdapterProperties;    private AdapterState mAdapterStateMachine;    private BondStateMachine mBondStateMachine;    JniCallbacks(AdapterState adapterStateMachine,AdapterProperties adapterProperties) {        mAdapterStateMachine = adapterStateMachine;        mAdapterProperties = adapterProperties;    }    void init(BondStateMachine bondStateMachine, RemoteDevices remoteDevices) {        mRemoteDevices = remoteDevices;        mBondStateMachine = bondStateMachine;    }    void deviceFoundCallback(byte[] address) {        mRemoteDevices.deviceFoundCallback(address);    }    void pinRequestCallback(byte[] address, byte[] name, int cod, boolean min16Digits) {        mBondStateMachine.pinRequestCallback(address, name, cod, min16Digits);    }    void <strong>bondStateChangeCallback</strong>(int status, byte[] address, int newState) {        mBondStateMachine.bondStateChangeCallback(status, address, newState);    }

java层的bond方法于此,这时相关与将java层的函数接口又映射到了native层,使得c语言中可以通过
method_bondStateChangeCallback
调用这个方法。
java层也可以发送消息

 //packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java         boolean createBond(BluetoothDevice device, int transport) {        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,            "Need BLUETOOTH ADMIN permission");        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);        if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {            return false;        }        // Pairing is unreliable while scanning, so cancel discovery        // Note, remove this when native stack improves        cancelDiscoveryNative();        Message msg =<strong> mBondStateMachine.obtainMessage</strong>(BondStateMachine.CREATE_BOND);        msg.obj = device;        msg.arg1 = transport;        <strong>mBondStateMachine.sendMessage</strong>(msg);        return true;    }    boolean removeBond(BluetoothDevice device) {        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);        if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {            return false;        }        Message msg = <strong>mBondStateMachine.obtainMessage</strong>(BondStateMachine.REMOVE_BOND);        msg.obj = device;        <strong>mBondStateMachine.sendMessage</strong>(msg);        return true;    }

 
0 0
原创粉丝点击