蓝牙之三-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; }
- 蓝牙之三-StateMachine
- StateMachine
- StateMachine
- Android蓝牙源码分析——StateMachine状态机
- Android开发之蓝牙详解(三)
- Android开发之蓝牙通信(三)
- iOS之蓝牙简介和使用(三):CoreBlueTooth
- 蓝牙实战(三)
- 蓝牙,WiFi(三)
- 蓝牙上路之 初识蓝牙
- vsinoplayer statemachine
- StateMachine状态机
- statemachine详解
- statemachine状态机
- android -- 蓝牙 bluetooth (三)搜索蓝牙
- android -- 蓝牙 bluetooth (三)搜索蓝牙
- android -- 蓝牙 bluetooth (三)搜索蓝牙
- android -- 蓝牙 bluetooth (三)搜索蓝牙
- javascript编程之OOP
- android 绘图之Paint详解
- 【Web容器】Tomcat源码分析(6)-请求原理分析(中)
- 对引用参数&的理解
- C++ hdoj 2011 多项式求和
- 蓝牙之三-StateMachine
- C语言学习中连用两个scanf遇到的一个问题
- python字节编译
- spring MVC 之controller (一)
- Java内部类
- 数据结构实验之栈一:进制转换
- C#类中的属性转换为要发送http的参数
- 【Web容器】Tomcat源码分析(7)-请求原理分析(下)
- 方格填数-搜索练习题