蓝牙之十三-HFPclient JNI层
来源:互联网 发布:hough变换算法 编辑:程序博客网 时间:2024/06/06 07:26
JNI到app(JAVA)
<packages/apps/Bluetooth/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java>final class HeadsetClientStateMachine extends StateMachine {//静态块方法 static { classInitNative(); } private HeadsetClientStateMachine(HeadsetClientService context) { initializeNative(); } private native static void classInitNative(); private native void initializeNative(); private native void cleanupNative(); private native boolean connectNative(byte[] address); private native boolean disconnectNative(byte[] address); private native boolean connectAudioNative(byte[] address); private native boolean disconnectAudioNative(byte[] address);、 private native boolean startVoiceRecognitionNative(); private native boolean stopVoiceRecognitionNative(); private native boolean setVolumeNative(int volumeType, int volume); private native boolean dialNative(String number); private native boolean dialMemoryNative(int location); private native boolean handleCallActionNative(int action, int index); private native boolean queryCurrentCallsNative(); private native boolean queryCurrentOperatorNameNative(); private native boolean retrieveSubscriberInfoNative(); private native boolean sendDtmfNative(byte code); private native boolean requestLastVoiceTagNumberNative(); private native boolean sendATCmdNative(int ATCmd, int val1, int val2, String arg);}在如下文件会调用:
packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp:1199: if ((status = android::register_com_android_bluetooth_hfpclient(e)) < 0) {该方法的实现如下:
<packages/apps/Bluetooth/jni/com_android_bluetooth_hfpclient.cpp>static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void *) classInitNative}, {"initializeNative", "()V", (void *) initializeNative}, {"cleanupNative", "()V", (void *) cleanupNative}, {"connectNative", "([B)Z", (void *) connectNative}, {"disconnectNative", "([B)Z", (void *) disconnectNative}, {"connectAudioNative", "([B)Z", (void *) connectAudioNative}, {"disconnectAudioNative", "([B)Z", (void *) disconnectAudioNative}, {"startVoiceRecognitionNative", "()Z", (void *) startVoiceRecognitionNative}, {"stopVoiceRecognitionNative", "()Z", (void *) stopVoiceRecognitionNative}, {"setVolumeNative", "(II)Z", (void *) setVolumeNative}, {"dialNative", "(Ljava/lang/String;)Z", (void *) dialNative}, {"dialMemoryNative", "(I)Z", (void *) dialMemoryNative}, {"handleCallActionNative", "(II)Z", (void *) handleCallActionNative}, {"queryCurrentCallsNative", "()Z", (void *) queryCurrentCallsNative}, {"queryCurrentOperatorNameNative", "()Z", (void *) queryCurrentOperatorNameNative}, {"retrieveSubscriberInfoNative", "()Z", (void *) retrieveSubscriberInfoNative}, {"sendDtmfNative", "(B)Z", (void *) sendDtmfNative}, {"requestLastVoiceTagNumberNative", "()Z", (void *) requestLastVoiceTagNumberNative}, {"sendATCmdNative", "(IIILjava/lang/String;)Z", (void *) sendATCmdNative},};int register_com_android_bluetooth_hfpclient(JNIEnv* env){ return jniRegisterNativeMethods(env, "com/android/bluetooth/hfpclient/HeadsetClientStateMachine", sMethods, NELEM(sMethods));}该函数的作用是将com_android_bluetooth_hfpclient.cpp里的cpp函数注册以供java层调用。在开篇的文章的HeadsetClientStateMachine.java里调用了
静态块和构造函数里的方法在创建这个对象时会被执行。
static void classInitNative(JNIEnv* env, jclass clazz) { method_onConnectionStateChanged = env->GetMethodID(clazz, "onConnectionStateChanged", "(III[B)V"); method_onAudioStateChanged = env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V"); method_onVrStateChanged = env->GetMethodID(clazz, "onVrStateChanged", "(I)V"); method_onNetworkState = env->GetMethodID(clazz, "onNetworkState", "(I)V"); method_onNetworkRoaming = env->GetMethodID(clazz, "onNetworkRoaming", "(I)V"); method_onNetworkSignal = env->GetMethodID(clazz, "onNetworkSignal", "(I)V"); method_onBatteryLevel = env->GetMethodID(clazz, "onBatteryLevel", "(I)V"); method_onCurrentOperator = env->GetMethodID(clazz, "onCurrentOperator", "(Ljava/lang/String;)V"); method_onCall = env->GetMethodID(clazz, "onCall", "(I)V"); method_onCallSetup = env->GetMethodID(clazz, "onCallSetup", "(I)V"); method_onCallHeld = env->GetMethodID(clazz, "onCallHeld", "(I)V"); method_onRespAndHold = env->GetMethodID(clazz, "onRespAndHold", "(I)V"); method_onClip = env->GetMethodID(clazz, "onClip", "(Ljava/lang/String;)V"); method_onCallWaiting = env->GetMethodID(clazz, "onCallWaiting", "(Ljava/lang/String;)V"); method_onCurrentCalls = env->GetMethodID(clazz, "onCurrentCalls", "(IIIILjava/lang/String;)V"); method_onVolumeChange = env->GetMethodID(clazz, "onVolumeChange", "(II)V"); method_onCmdResult = env->GetMethodID(clazz, "onCmdResult", "(II)V"); method_onSubscriberInfo = env->GetMethodID(clazz, "onSubscriberInfo", "(Ljava/lang/String;I)V"); method_onInBandRing = env->GetMethodID(clazz, "onInBandRing", "(I)V"); method_onLastVoiceTagNumber = env->GetMethodID(clazz, "onLastVoiceTagNumber", "(Ljava/lang/String;)V"); method_onRingIndication = env->GetMethodID(clazz, "onRingIndication","()V"); ALOGI("%s succeeds", __FUNCTION__);}static void initializeNative(JNIEnv *env, jobject object) { const bt_interface_t* btInf; bt_status_t status;//检查Bluetooth 模块是否加载,HFP client依赖该模块被加载。 btInf = getBluetoothInterface(); if (btInf == NULL) { ALOGE("Bluetooth module is not loaded"); return; } if (sBluetoothHfpClientInterface != NULL) { ALOGW("Cleaning up Bluetooth HFP Client Interface before initializing"); sBluetoothHfpClientInterface->cleanup(); sBluetoothHfpClientInterface = NULL; } if (mCallbacksObj != NULL) { ALOGW("Cleaning up Bluetooth HFP Client callback object"); env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = NULL; } sBluetoothHfpClientInterface = (bthf_client_interface_t *) btInf->get_profile_interface(BT_PROFILE_HANDSFREE_CLIENT_ID); if (sBluetoothHfpClientInterface == NULL) { ALOGE("Failed to get Bluetooth HFP Client Interface"); return; } status = sBluetoothHfpClientInterface->init(&sBluetoothHfpClientCallbacks); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed to initialize Bluetooth HFP Client, status: %d", status); sBluetoothHfpClientInterface = NULL; return; } mCallbacksObj = env->NewGlobalRef(object);}这两个函数中,前一个函数在java类中查找了若干方法,这些方法被cpp函数调用,这里就是被com_android_bluetooth_hfpclient.cpp文件里的函数使用,这样就完成了java到cpp的映射。好了到这里就是JNI实现了JAVA到cpp和cpp到JAVA的函数映射关系。
JNI到协议栈(纯C)
在上面的第二个函数initializeNative实现了该功能。
<system/bt/btif/src/bluetooth.c>static const bt_interface_t bluetoothInterface = { sizeof(bluetoothInterface), init, enable, disable, cleanup, get_adapter_properties, get_adapter_property, set_adapter_property, get_remote_device_properties, get_remote_device_property, set_remote_device_property, get_remote_service_record, get_remote_services, start_discovery, cancel_discovery, create_bond, remove_bond, cancel_bond, get_connection_state, pin_reply, ssp_reply, get_profile_interface, dut_mode_configure, dut_mode_send,#if BLE_INCLUDED == TRUE le_test_mode,#else NULL,#endif config_hci_snoop_log, set_os_callouts, read_energy_info, dump, config_clear};const bt_interface_t* bluetooth__get_bluetooth_interface (){ /* fixme -- add property to disable bt interface ? */ return &bluetoothInterface;} static int open_bluetooth_stack(const struct hw_module_t *module, UNUSED_ATTR char const *name, struct hw_device_t **abstraction) { static bluetooth_device_t device = { .common = { .tag = HARDWARE_DEVICE_TAG, .version = 0, .close = close_bluetooth_stack, }, .get_bluetooth_interface = bluetooth__get_bluetooth_interface }; device.common.module = (struct hw_module_t *)module; *abstraction = (struct hw_device_t *)&device; return 0;}static struct hw_module_methods_t bt_stack_module_methods = { .open = open_bluetooth_stack,};struct hw_module_t HAL_MODULE_INFO_SYM = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = BT_HARDWARE_MODULE_ID, .name = "Bluetooth Stack", .author = "The Android Open Source Project", .methods = &bt_stack_module_methods};BT_HARDWARE_MODULE_ID定义于
<./hardware/libhardware/include/hardware/bluetooth.h>#define BT_HARDWARE_MODULE_ID "bluetooth"#define BT_STACK_MODULE_ID "bluetooth"#define BT_PROFILE_HANDSFREE_CLIENT_ID "handsfree_client"
状态机
/**19 * Bluetooth Headset Client StateMachine20 * (Disconnected)21 * | ^ ^22 * CONNECT | | | DISCONNECTED23 * V | |24 * (Connecting) |25 * | |26 * CONNECTED | | DISCONNECT27 * V |28 * (Connected)29 * | ^30 * CONNECT_AUDIO | | DISCONNECT_AUDIO31 * V |32 * (AudioOn)33 */
状态机如上。有四个子类用于管理上述状态
private final Disconnected mDisconnected; private final Connecting mConnecting; private final Connected mConnected; private final AudioOn mAudioOn;
BroadcastReceiver也就是“广播接收者”的意思,它是用来接收来自系统和应用中的广播。
在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastReceiver是对发送出来的 Broadcast进行过滤接受并响应的一类组件。
下面将详细的阐述如何发送Broadcast和使用BroadcastReceiver过滤接收的过程:
(1)首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action、Category)装入一个Intent对象,然后通过调 用 sendOrderBroadcast()或sendStickyBroadcast()方法,把 Intent对象以广播方式发送出去。
(2)当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的 Intent相匹配,若匹配则就会调用BroadcastReceiver的onReceive()方法。所以当我们定义一个 BroadcastReceiver的时候,都需要实现onReceive()方法。
JNI实现回调
通过JNI在Native层调用JAVA层的方法,来实现Native层向JAVA层传递消息。
JNICallback.java
public class JNICallback extends Activity { static { System.loadLibrary("callback"); } public void callback(int notify_id, int param) { Log.e("JNICallback","notify_id="+notify_id+";param="+param); } public native void setCallBack(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); setCallBack(); }
com_JNICallback_JNICallback.cpp
void JNICALL Java_com_JNICallback_JNICallback_setCallBack (JNIEnv *env, jobject obj) { LOGE("jni callback (0)"); jclass cls = env->GetObjectClass(obj); jmethodID callback = env->GetMethodID(cls,"callback","(II)V"); env->CallVoidMethod(obj,callback,5,10); LOGE("jni callback (1)"); }
二、JNI调用JAVA函数
获取实例的类定义 jclass cls = env->GetObjectClass(obj);
获取方法定义 jmethodID callback = env->GetMethodID(cls,"callback","(II)V");
调用方法 env->CallVoidMethod(obj,callback,5,10);
三、参数和返回值的格式
- 蓝牙之十三-HFPclient JNI层
- 蓝牙之十九-HFPclient
- 蓝牙之二十三-beacon
- Android 蓝牙模块之应用层之经典蓝牙
- 蓝牙之十二-HFP app层
- android_wifi读书笔记之3-JNI层 分析
- [Android源码分析]蓝牙配对之jni之上的点点滴滴
- [Android源码分析]蓝牙打开流程分析——jni层之上的方方面面
- Spring Framework 开发参考手册 之十三 集成表现层
- 某大型银行深化系统之十三:业务应用层
- 【iOS-cocos2d-X 游戏开发之十三】详细讲解在Xcode中利用预编译并通过Jni调用Android的Java层代码(cocos2dx里访问调用Android函数)!
- 【iOS-cocos2d-X 游戏开发之十三】详细讲解在Xcode中利用预编译并通过Jni调用Android的Java层代码(cocos2dx里访问调用Android函数)!
- android ndk 开发之 在 框架层使用 jni
- Android底层开发(二)之JNI层 第三步
- Android之HAL层编写JNI供Java接口访问
- Android JNI之JAVA调用C/C++层
- 蓝牙协议层概要
- [Android源码分析]蓝牙打开流程分析——jni层之下的偷偷摸摸(Service Record的创建)
- 在java中运行Bat批处理
- Why disable specific warning not working in Visual Studio
- 安卓控件 listView 的学习及优化 (ConvetView、viewHolder)
- 关于信念
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- 蓝牙之十三-HFPclient JNI层
- IBM 混合数据仓库架构介绍
- MySQL提示:The server quit without updating PID file
- 训练第四周之矩阵快速幂
- socket通信
- 筛选法求素数 关键词——置零
- Prim最小生成树算法(C++)
- Echart动态加载数据
- express4.X框架中使用socket.io