Android从驱动层到应用程序层的通信
研究一下android从驱动层到应用层的通信机制是很有必要的,如新增加一个硬件并在应用层去控制硬件都需要用到,目的是知道需要增加哪些东西删改哪些东西而让系统依然工作正常。
总共需要增改的有四个东西,驱动、服务(jni、java)、应用apk
采用的方式是在驱动层写个字符型设备驱动其中内含一个定时器,每隔2秒发送一个uevent事件并改变sys下相关文件的内容,然后建立一个服务去读取文件并通过intent向上层广播,最后在应用程序层接收此事件并在TextView中显示出来
一、驱动层
kernel/drivers/char/uevent_test/test.c
Kconfig
Makefile
驱动层与服务层之间用到的通信机制是sys文件系统的uevent机制,涉及的函数有以下几个
在sys文件系统下建立一个类
class_create(THIS_MODULE, "uevent_timer");
在类里建立一个设备
device_create(uevent_timer_class, NULL, UEVENT_TIMER_MAJOR, NULL, "uevent_timer_status");
在设备目录下建立一个文件
device_create(uevent_timer_class, NULL, UEVENT_TIMER_MAJOR, NULL, "uevent_timer_status");
在本项目中建立的目录文件是/sys/class/uevent_timer/uevent_timer_status/status
注意思在使用kobject_uevent函数发送uevent事件时需要建立一个工作队列来发送,否则会在发送过程中内核死掉。
INIT_WORK(&uevent_timer_dev->changed_work, timer_change_work);
通过schedule_work(&uevent_timer_dev->changed_work);来调用timer_change_work函数,在此函数中利用
kobject_uevent(&uevent_timer_dev->clsdev->kobj, KOBJ_CHANGE);
来发送uevent事件.
当上层读取file时会调用uevent_timer_show_attrs函数来更新及显示文件内容
当上层写入file时会调用 uevent_timer_store_attrs函数来更新及写入文件内容
二、服务层
新建以下两个文件
php?mod=tag&id=6090" target="_blank" class="relatedlink">Frameworks/base/services/jni/com_android_server_UeventTimerService.cpp frameworks/base/services/jni/onload.cpp
frameworks/base/services/java/com/android/server/UeventTimerService.java
frameworks/base/services/java/com/android/server/SystEMServer.java
(1)JNI层
JNI是java调用本地的接口,JNI主要工作是打开驱动所创建的file并将其值读出来,
在static int readFROMFile(const char* path, char* buf, size_t size)函数中读取值
使用
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"native_update", "()V", (void*)android_server_UeventTimerService_update},
};注册一个函数native_update以供服务的java层调用
修改onload.cpp,在其中加入
int register_android_server_UeventTimerService(JNIEnv* env);在JNI_OnLoad中加入
register_android_server_UeventTimerService(JNIEnv* env);在加载时启动此服务
(2)java层
建立一个类
Class UeventTimerService extends Binder{
Private int mUeventTimerStatus;
Public UeventTimerService(){/
mUEventObserver.startObserving("SUBSYSTEM=uevent_timer");
};//此函数中调用开始服务
private UEventObserver mUEventObserver = new UEventObserver() {
@Override
public void onUEvent(UEventObserver.UEvent event) {
update();
sendIntent();
}
};建立一个服务并重写onUEvent函数
private native void native_update();
private synchronized final void update() {
native_update();//调用jni中注册的native_update()函数
}
private final void sendIntent() {
Intent intent = new Intent("uevent_timer_status");//启动广播
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);//建立一个发送
intent.putExtra("status", mUeventTimerStatus);//发送变量
ActivityManagerNative.broADCastStickyIntent(intent, null);//向上层广播
}
在SystemServer.java中加入
UeventTimerService ueventtimer = null;
在try catch块中加入
ueventtimer = new UeventTimerService();
ServiceManager.addService("ueventtimer", ueventtimer);
三、应用层apk
onResume(){
super.onResume();
IntentFiLTEr filter = new IntentFilter();
filter.adDACtion("uevent_timer_status");
registerReceiver(mBroadcastReceiver, filter);
}
onPause(){
super.onPause();
unregisterReceiver(mBroadcastReceiver);
}
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("uevent_timer_status")) {
int status = intent.getIntExtra("status", 0);
String statusString = "";
switch (status) {
case 0:
statusString = "counting";
break;
case 1:
statusString = "stop";
break;
default:
statusString = "unknown";
}
Log.i("=====My_application========",statusString);
tv.setText(statusString);//改变textView的显示值
}
}
};
在AndroiDMAnifest.xml中加入
<action android:name="uevent_timer_status" />
打开监听
多好的东西啊!自己很想总结,都还没来得及开始弄!
没怎么看懂啊 。
好东西,感谢分享。
牛人就是不一样
驱动和本地函数(.cpp)通过sysfs沟通,本地函数和java通过jni沟通.
非常好的东西
虽说只有短短一页,但是要想完全理解透彻估计要半年之后了
这个例子感觉有点复杂呀.其实很简单,驱动+jni+apk就行了.比如一个LED,驱动负责底层控制IOCTRL,并且产生设备节点,JNI负责打开操作这个设备,APK直接调用JNI控制就OK了.
呵呵,纯技术坛子感觉比杂乱的52RD好
不错,知道学习!
悲剧,上层JAVA这块不怎么懂,还得加快学习中,向群主和各位大佬们学习
不错,说白了就这样。