在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口 (学习老罗的)_hal还能编译出java?-程序员宅基地

技术标签: Jounery of study android源代码  

主要是在

~/Android_4.2.2_SourceCode/frameworks/base/services/jni个夹子里面操作的。

根据老罗的方法我也是实现成功了。

但是和上一篇文章一样,同样需要将LOGI改为ALOGI,LOGE改为ALOGE。

他也写了很多知识方面的内容,但是目前还只是实现了部分,待后面JAVA方面调用的例程写好了,我串起来总结一下。。。






地址:http://blog.csdn.net/luoshengyang/article/details/6575988


在上两篇文章中,我们介绍了如何为Android系统的硬件编写驱动程序,包括如何在Linux内核空间实现内核驱动程序和在用户空间实现硬件抽象层接口。实现这两者的目的是为了向更上一层提供硬件访问接口,即为Android的Application Frameworks层提供硬件服务。我们知道,Android系统的应用程序是用Java语言编写的,而硬件驱动程序是用C语言来实现的,那么,Java接口如何去访问C接口呢?众所周知,Java提供了JNI方法调用,同样,在Android系统中,Java应用程序通过JNI来调用硬件抽象层接口。在这一篇文章中,我们将介绍如何为Android硬件抽象层接口编写JNI方法,以便使得上层的Java应用程序能够使用下层提供的硬件服务。

      一. 参照在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序一文,准备好硬件抽象层模块,确保Android系统镜像文件system.img已经包含hello.default模块。

      二. 进入到frameworks/base/services/jni目录,新建com_android_server_HelloService.cpp文件:

      USER-NAME@MACHINE-NAME:~/Android$ cd frameworks/base/services/jni

      USER-NAME@MACHINE-NAME:~/Android/frameworks/base/services/jni$ vi com_android_server_HelloService.cpp

      在com_android_server_HelloService.cpp文件中,实现JNI方法。注意文件的命令方法,com_android_server前缀表示的是包名,表示硬件服务HelloService是放在frameworks/base/services/java目录下的com/android/server目录的,即存在一个命令为com.android.server.HelloService的类。这里,我们暂时略去HelloService类的描述,在下一篇文章中,我们将回到HelloService类来。简单地说,HelloService是一个提供Java接口的硬件访问服务类。

      首先是包含相应的头文件:

  1. #define LOG_TAG "HelloService"  
  2. #include "jni.h"  
  3. #include "JNIHelp.h"  
  4. #include "android_runtime/AndroidRuntime.h"  
  5. #include <utils/misc.h>  
  6. #include <utils/Log.h>  
  7. #include <hardware/hardware.h>  
  8. #include <hardware/hello.h>  
  9. #include <stdio.h>  

      接着定义hello_init、hello_getVal和hello_setVal三个JNI方法:

  1. namespace android  
  2. {  
  3.     /*在硬件抽象层中定义的硬件访问结构体,参考<hardware/hello.h>*/  
  4.         struct hello_device_t* hello_device = NULL;  
  5.     /*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/  
  6.         static void hello_setVal(JNIEnv* env, jobject clazz, jint value) {  
  7.         int val = value;  
  8.         LOGI("Hello JNI: set value %d to device.", val);  
  9.         if(!hello_device) {  
  10.             LOGI("Hello JNI: device is not open.");  
  11.             return;  
  12.         }  
  13.           
  14.         hello_device->set_val(hello_device, val);  
  15.     }  
  16.         /*通过硬件抽象层定义的硬件访问接口读取硬件寄存器val的值*/  
  17.     static jint hello_getVal(JNIEnv* env, jobject clazz) {  
  18.         int val = 0;  
  19.         if(!hello_device) {  
  20.             LOGI("Hello JNI: device is not open.");  
  21.             return val;  
  22.         }  
  23.         hello_device->get_val(hello_device, &val);  
  24.           
  25.         LOGI("Hello JNI: get value %d from device.", val);  
  26.       
  27.         return val;  
  28.     }  
  29.         /*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/  
  30.     static inline int hello_device_open(const hw_module_t* module, struct hello_device_t** device) {  
  31.         return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);  
  32.     }  
  33.         /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/  
  34.     static jboolean hello_init(JNIEnv* env, jclass clazz) {  
  35.         hello_module_t* module;  
  36.           
  37.         LOGI("Hello JNI: initializing......");  
  38.         if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {  
  39.             LOGI("Hello JNI: hello Stub found.");  
  40.             if(hello_device_open(&(module->common), &hello_device) == 0) {  
  41.                 LOGI("Hello JNI: hello device is open.");  
  42.                 return 0;  
  43.             }  
  44.             LOGE("Hello JNI: failed to open hello device.");  
  45.             return -1;  
  46.         }  
  47.         LOGE("Hello JNI: failed to get hello stub module.");  
  48.         return -1;        
  49.     }  
  50.         /*JNI方法表*/  
  51.     static const JNINativeMethod method_table[] = {  
  52.         { "init_native""()Z", (void*)hello_init},  
  53.         { "setVal_native""(I)V", (void*)hello_setVal},  
  54.         { "getVal_native""()I", (void*)hello_getVal},  
  55.     };  
  56.         /*注册JNI方法*/  
  57.     int register_android_server_HelloService(JNIEnv *env) {  
  58.             return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));  
  59.     }  
  60. };  

      注意,在hello_init函数中,通过Android硬件抽象层提供的hw_get_module方法来加载模块ID为HELLO_HARDWARE_MODULE_ID的硬件抽象层模块,其中,HELLO_HARDWARE_MODULE_ID是在<hardware/hello.h>中定义的。Android硬件抽象层会根据HELLO_HARDWARE_MODULE_ID的值在Android系统的/system/lib/hw目录中找到相应的模块,然后加载起来,并且返回hw_module_t接口给调用者使用。在jniRegisterNativeMethods函数中,第二个参数的值必须对应HelloService所在的包的路径,即com.android.server.HelloService。

      三. 修改同目录下的onload.cpp文件,首先在namespace android增加register_android_server_HelloService函数声明:

      namespace android {

      ..............................................................................................

      int register_android_server_HelloService(JNIEnv *env);

      };

      在JNI_onLoad增加register_android_server_HelloService函数调用:
      extern "C" jint JNI_onLoad(JavaVM* vm, void* reserved)
      {
       .................................................................................................
       register_android_server_HelloService(env);
       .................................................................................................
      }
      这样,在Android系统初始化时,就会自动加载该JNI方法调用表。
      四. 修改同目录下的Android.mk文件,在LOCAL_SRC_FILES变量中增加一行:
      LOCAL_SRC_FILES:= \
      com_android_server_AlarmManagerService.cpp \
      com_android_server_BatteryService.cpp \
      com_android_server_InputManager.cpp \
      com_android_server_LightsService.cpp \
      com_android_server_PowerManagerService.cpp \
      com_android_server_SystemServer.cpp \
      com_android_server_UsbService.cpp \
      com_android_server_VibratorService.cpp \
      com_android_server_location_GpsLocationProvider.cpp \
       com_android_server_HelloService.cpp /
      onload.cpp
      五. 编译和重新找亿system.img:
       USER-NAME@MACHINE-NAME:~/Android$ mmm frameworks/base/services/jni
      USER-NAME@MACHINE-NAME:~/Android$ make snod
      这样,重新打包的system.img镜像文件就包含我们刚才编写的JNI方法了,也就是我们可以通过Android系统的Application Frameworks层提供的硬件服务HelloService来调用这些JNI方法,进而调用低层的硬件抽象层接口去访问硬件了。前面提到,在这篇文章中,我们暂时忽略了HelloService类的实现,在下一篇文章中,我们将描述如何实现硬件服务HelloService,敬请关注。
老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!
28
0
查看评论
30楼 longshijun 6天前 17:32发表 [回复]
罗老师好啊,新接触你的博客,写的太好了,按照你的方法一步步来,遇到了问题No rule to make target `out/target/product/generic/obj/lib/libhardware.so', needed by `out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so'. Stop.,我的源码编译后的工程目录smdkv210,可是默认是.so文件是在generic下,我在smdkv210下的新建system/, 把的看smdk210下的lib拷贝过去,编译没问题,生成.so文件在generic/system/lib/hw下,可是板子的product都在smdk210目录下,然后在编程镜像在板子上怎么都找不到我自己编的.so文件。。搞了几天了。。。上面老师提到的方法也用了,问题没解决 啊。老师,,求助
29楼 xinxianzhongndsc 2013-04-23 12:37发表 [回复]
编译之后模拟器起不来,求指点。去除之后再走一遍还是老样子
I/DEBUG ( 36): beaaead0 00009082 /system/bin/app_process
I/DEBUG ( 36): beaaead4 401453db /system/lib/libandroid_runtime.so
I/ServiceManager( 32): service 'media.audio_flinger' died
I/ServiceManager( 32): service 'media.player' died
I/ServiceManager( 32): service 'media.camera' died
I/ServiceManager( 32): service 'media.audio_policy' died
I/Netd ( 475): Netd 1.0 starting
E/Netd ( 475): Unable to bind netlink socket: No such file or directory
E/Netd ( 475): Unable to open quota2 logging socket
I/ ( 474): ServiceManager: 0xf958
I/AudioFlinger( 474): Loaded primary audio interface from LEGACY Audio HW HAL (audio)
I/AudioFlinger( 474): Using 'LEGACY Audio HW HAL' (audio.primary) as the primary audio interface
Re: lch1987326 2013-06-19 01:39发表 [回复]
回复xinxianzhongndsc:楼主我也碰到这个问题了,你解决了没?
Re: xinxianzhongndsc 2013-06-19 09:26发表 [回复]
回复lch1987326:没有,不知道什么原因,查找各种解决方案无果
28楼 zhangshuliai 2013-03-18 23:48发表 [回复]
大神,打扰一下,问一个问题,类似于91助手这样的连接PC和手机的程序大概是怎样做的?
27楼 woluzhi 2013-01-16 17:15发表 [回复]
01.namespace android
02.{
03. /*在硬件抽象层中定义的硬件访问结构体,参考<hardware/hello.h>*/
04. struct hello_device_t* hello_device = NULL;
05. /*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/
06. static void hello_setVal(JNIEnv* env, jobject clazz, jint value) {
07. int val = value;
08. LOGI("Hello JNI: set value %d to device.", val);
09. if(!hello_device) {
10. LOGI("Hello JNI: device is not open.");
11. return;
12. }
13.
14. hello_device->set_val(hello_device, val);
15. }
罗哥,struct hello_device_t* hello_device = NULL;
所以到 if(!hello_device) 就return出去了
下面这个 hello_device->set_val(hello_device, val);
怎么执行的呢?
Re: 罗升阳 2013-01-16 17:22发表 [回复]
回复woluzhi:要先调hello_init。
Re: woluzhi 2013-01-17 21:57发表 [回复]
回复Luoshengyang:哦,好的
26楼 yuanfen139re 2012-10-10 15:07发表 [回复]
  1. if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {    

老罗,这行代码里(const struct hw_module_t**)&module是不是写错了,我觉得应该是(const struct xx_module_t**)&module,否则的话如何实现下面的module->common?望指点,谢谢!
Re: 罗升阳 2012-10-10 15:20发表 [回复]
回复yuanfen139re:没有错,module本来就是一个类型为hello_module_t的指针,所以module->common是没有问题的。
Re: yuanfen139re 2012-10-11 15:13发表 [回复]
回复Luoshengyang:明白了,谢谢啊
25楼 gyy939774006 2012-09-27 19:27发表 [回复]
'android::register_android_server_HelloService(_JNIEnv*)'
这个函数是在哪里定义的??
Re: 罗升阳 2012-09-28 00:03发表 [回复]
回复gyy939774006:在com_android_server_HelloService.cpp文件里面,看看你的Android.mk写对了没有。
24楼 gyy939774006 2012-09-27 19:26发表 [回复]
罗老师,出现这样的问题
frameworks/base/services/jni/onload.cpp:39: error: undefined reference to 'android::register_android_server_HelloService(_JNIEnv*)'
是什么情况?
23楼 chengfengpeak001 2012-08-22 13:22发表 [回复]
没有积分了
22楼 LOVE___________YOU 2012-08-22 11:08发表 [回复]
罗老师,您好。我现在想在Android应用层直接调用Linux内核下的.so的动态库,应该在HAL层怎么写啊。只需要返回一个hello world!就可以了。我是个菜鸟,搞了快两周了,一点头绪都没有。
Re: kevinyujm 2013-03-13 12:07发表 [回复]
回复LOVE___________YOU:我想你的疑惑是java怎么调用.so里面的函数?
这其实就是Java怎么调用c/cpp库的问题,答案就是使用jni。
如果不明白,可以搜索“jni调用so库”
Re: 罗升阳 2012-08-22 11:31发表 [回复]
回复LOVE___________YOU:不是很明白你的需求,你是想写一个纯粹的so,还是想写一个HAL模块,两者还是有区别的。
Re: LOVE___________YOU 2012-08-22 13:51发表 [回复]
回复Luoshengyang:或者简单的就是我现在有个返回hello的.so动态库,现在hal层应该怎么来写,和这个动态库应该放在什么地方才能让应用层识别啊。
Re: LOVE___________YOU 2012-08-22 13:47发表 [回复]
回复Luoshengyang:就是我想将linux下的驱动,移植到android中来,可是看您写的是将驱动编译到内核中。有没有直接写个hal层然后,用这个hal层来操作.so的动态库的例子啊。
Re: LOVE___________YOU 2012-08-22 13:42发表 [回复]
回复Luoshengyang:罗老师,我就是想直接做一个linux下的动态库,然后直接在应用层调用,可是我不知道中间这层应该怎么写的。我看您这个文章都是讲驱动编译到内核里面了,我现在不想往内核里面编译,就是想直接操作动态库.so文件,应该怎么搞啊。
Re: 罗升阳 2012-08-22 14:18发表 [回复]
回复LOVE___________YOU:如果是驱动程序,那就肯定要写到内核去了,一般是不支持模块动态加载的,即使支持,应用层的程序也没有权限去做这个事情。
如果你只是想写一个纯粹的so,那就看看NDK吧,但是你想在so里面访问硬件,那就没戏了,肯定没权限,除非你的系统root过了。
21楼 houyizi313 2012-08-08 10:47发表 [回复]
罗哥:你的程序HAL层与Driver连接是通过设备文件fd;我看overlay.h/cpp没有找到跟Driver联系fd啊?一般android的HAL层封装底层linux驱动都靠什么连接???谢谢……
Re: 罗升阳 2012-08-09 01:38发表 [回复]
回复houyizi337825770:HAL层是通过设备文件来和内核层中的硬件驱动程序交互的。HAL层的overlay模块只是一个骨架,即实现规范,里面的内容是需要由厂家来定制的,因此,在这个模块里面的overlay.h和overlay.cpp里面是看不到有设备文件的。一个具体的实现可以参考hardware/ti/omap3/liboverlay模块,里面通过/dev/video1和/dev/video2设备文件来和overlay设备通信。
Re: houyizi313 2012-09-05 15:50发表 [回复]
回复Luoshengyang:谢谢罗哥:这阵子虽然也在做android,但是没时间看书了,天天在实践了,根据官网在搞pandaboard的板子;所有好久没来看罗哥的博客了;因为pandaboard也遇到了很多问题;也遇到了很多问题;现在是刚把官网的android编译通过……但是怎么都刷不到SD上……堵这了%^再慢慢解决……
20楼 tgt007 2012-08-03 14:05发表 [回复]
我按照你说的设置一下环境变量TARGET_PRODUCT=crespo,还是报错make: *** [out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so] 错误1,怎么回事楼主?
Re: waldmer 2013-05-15 09:04发表 [回复]
回复tgt007:请问:jdk的版本是多少啊。 麻烦抽时间告知一下!谢谢。。。。
19楼 huangzhenyu1983 2012-07-31 16:43发表 [回复]
有个笔误,吹毛求疵一下:)
四. 修改同目录下的Android.mk文件
.......
com_android_server_HelloService.cpp /
应该是 com_android_server_HelloService.cpp \ (反斜杠)
Re: 罗升阳 2012-07-31 17:03发表 [回复]
回复huangzhenyu1983:不知道为什么,从虚拟机拷出来的代码,所有的反斜杠都变成斜杠了,这一系列的文章都有这个问题,前面已经改了很多了。
18楼 newsten 2012-07-27 17:34发表 [回复]
楼主请问我在JNI里面直接open /dev/hello返回不是-1,但驱动的open并没有走到,用那个linux下的小程序system/bin/hello在adb shell下就可以,我在open函数里加了printk可以看到log的,请问是怎么回事啊?
Re: 罗升阳 2012-07-31 17:01发表 [回复]
回复newsten:应该是权限问题了,看看这篇文章:http://blog.csdn.net/luoshengyang/article/details/6573809
Re: newsten 2012-07-31 22:22发表 [回复]
回复Luoshengyang:我在ueventd.rc已经添加/dev/hello 0666 root root了,shell下也chmod了,open在jni里返回并不是-1,但和shell下的hello小程序返回值不一样,我在shell下用echo、cat和那个hello小程序操作/dev/hello是可以看到驱动open函数里添加的printk打印的消息,但是在jni里open就不行,我又添加了HAL层在JNI和驱动之间还是不行,好像程序并没有走到驱动里面…………
Re: 罗升阳 2012-08-01 09:31发表 [回复]
回复newsten:你可以先确认一下/dev/hello的权限,用adb工具连上模拟器,然后再ls -l /dev/hello一下看看。
Re: 罗升阳 2012-08-01 09:29发表 [回复]
回复newsten:要重新编译一下,或者重新制作一下ramdisk.img镜像,重新制作一下ramdisk.img镜像会快一些,可以网上找找资料,很多的。
17楼 zhongjihao100 2012-07-16 23:03发表 [回复]
真不错的文章
16楼 wantianpei 2012-03-17 10:23发表 [回复]
大哥,jni怎么返回“中文字符串”呀?搞了一天,试了各种方法都只能返回英文字符串,中文的就报错。
中文的这样写就可以,
jchar * newstring;
jstring ret=0;

newstring=new jchar[1];
newstring[0]=27979;//测字的unicode 码
ret=env->NewString(newstring,1);

直接搞个"测"就不行。 大哥有高招没有罗。我都整两天了也没搞定。英文的就可以,中文的不是报错就是乱码.
Re: xiaofeishou 2012-04-17 14:26发表 [回复]
回复wantianpei:返回一个byte的数组 然后上面用string的构造函数转化
15楼 mayugang 2012-02-14 23:59发表 [回复]
想请教一下博主JNI方面的内容:按照JNI的规定,native方法采用C++编写时,要用extern “C” 声明一下,可是在这个地方并没有看到类似的代码,是Android在其他地方做了处理了?
14楼 21bird 2011-12-09 09:26发表 [回复]
可以不用JNI,直接写NDK来访问HAL层吗?大概要怎么操作呢?
Re: 罗升阳 2011-12-10 19:29发表 [回复]
回复21bird:可以的,你参照JNI的方法来编写NDK就行了。
13楼 floweriswho 2011-11-23 23:29发表 [回复]
不错!
12楼 m313856126 2011-09-28 20:55发表 [回复]
楼主大神你好 请教个问题
我目前正在Android系统上添加一个支持硬件的模块
采用的是老架构 没有aidl 上层代码直接load“xxx.so”
JNI层代码放在framework\base\myJNI\下
目前需要在该目录下添加Android.mk文件
目的是执行mm时生成xxx.so
请问这个Android.mk该肿么写 我调了好久都没有编译通过
不知道楼主大神有没有这种生成动态链接库的例子
小生不胜感激 [email protected]
Re: 罗升阳 2011-09-28 23:18发表 [回复]
回复m313856126:在frameworks/base/core/jni目录下不是有一个Android.mk文件做范例了么?参考一下。
11楼 wantianpei 2011-09-08 20:55发表 [回复]
楼主:
Android.mk
com_android_server_HelloService.cpp /

应该改成:
com_android_server_HelloService.cpp \
上面所有的' / '都应该改成' \ '
Re: 罗升阳 2011-09-09 00:36发表 [回复]
回复wantianpei:又被你发现了。。。文章的硬伤看来还是不少啊,主要是写完也没有时间去检查了
10楼 yanlingzhen 2011-09-05 18:33发表 [回复]
我在c 语言封闭的库当中已经将log所用的动态库加上,并且其原型的打印函数在我的c中可以使用,但logcat 当中始终没有信息。


#include <android/log.h>
#include <utils/Log.h>

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "ProjectName", __VA_ARGS__)

我在程序当中这样调的:
LOGI("this is my first program ");
Re: 罗升阳 2011-09-05 23:34发表 [回复]
回复yanlingzhen:参考博客里面的这篇文章《浅谈Android系统开发中LOG的使用》
9楼 yanlingzhen 2011-09-03 16:53发表 [回复]
你好,如果我的c语言当中的参数含有结构体指针或其它类型的指针(如int *)JNINativeMethod 当中的第二个参怎么表示,我知道到jni.h里去找,但是没有找到,请指点一下。
Re: 百度男 2011-09-13 19:26发表 [回复]
[reply]yanlingzhen[/reply
您好,能看见我的回复吗?
Re: 罗升阳 2011-09-04 00:55发表 [回复]
回复yanlingzhen:如果参数是结构体,要在java层定义相应的类,如果参数是指针,在java层就传对象进来,网上有很多资料,找找看
8楼 yanlingzhen 2011-09-01 09:52发表 [回复]
主要是加了

register_android_server_HelloService(env);这个语句产生的。去掉就可以。我有点晕了。
Re: jqyp324 2012-02-29 18:07发表 [回复]
回复yanlingzhen:解决了吗?我也碰到这个问题了,楼主的代码有问题阿,作实验做不下去了
Re: FzChen_2012 2012-04-17 11:54发表 [回复]
回复jqyp324:我也碰到了同样的问题,不知道老兄解决了吗?
Re: 罗升阳 2011-09-01 10:06发表 [回复]
回复yanlingzhen:那检查一下register_android_server_HelloService这个函数吧,看看哪出了问题,这个函数是在系统启动的时候调用的,如果出了问题,系统是会被卡住的
7楼 yanlingzhen 2011-09-01 08:30发表 [回复]
<6>eth0: link up
<6>warning: `rild' uses 32-bit capabilities (legacy support in use)
<6>request_suspend_state: wakeup (3->0) at 31550002285 (2011-09-01 00:30:08.389096500 UTC)
<3>init: untracked pid 29 exited
<3>init: untracked pid 33 exited
<6>request_suspend_state: wakeup (0->0) at 35143873821 (2011-09-01 00:30:11.983138164 UTC)
<3>init: untracked pid 68 exited
<3>init: untracked pid 67 exited
<6>request_suspend_state: wakeup (0->0) at 39724385133 (2011-09-01 00:30:16.563648782 UTC)
<3>init: untracked pid 78 exited
<3>init: untracked pid 77 exited
<6>request_suspend_state: wakeup (0->0) at 45310642402 (2011-09-01 00:30:22.149906097 UTC)
<3>init: untracked pid 88 exited
<3>init: untracked pid 87 exited
6楼 yanlingzhen 2011-08-31 19:55发表 [回复]
我也按这样做的,但是android 启动不了,内核可以起来,不知道什么原因。
Re: 罗升阳 2011-08-31 21:07发表 [回复]
回复yanlingzhen:Android没有启动起来,你是怎么确定内核已经跑起来了的?如果能有一些日志出来,就可以分析一下了
5楼 hui05504 2011-08-14 11:05发表 [回复]
楼主,有个问题,为了方便移植,我将这个教程里新增的文件都放在源码的根目录下的一个新建的文件夹下面,所以如何修改onload.cpp文件呢,因为我的com.android.server.HelloService不是在那个文件夹下面,这个怎么处理呢?
Re: 罗升阳 2011-08-14 23:57发表 [回复]
回复hui05504:你需要去看一下jni的编写规范,com.android.server.HelloService.cpp命令就表示了HelloService.java这个类是放在com/android/server目录下面的,所以看你的HelloService.java放在哪个目录下,然后依葫芦画瓢就可以了
4楼 hui05504 2011-08-01 17:14发表 [回复]
楼主,http://blog.csdn.net/hongtao_liu/article/details/6060734这个有看过么,我下载了这个代码,发现里面的init.rc文件有一处不太明白,不知道是否和下面讨论的这个问题有关。在init.rc中:
insmod /system/lib/modules/led.ko
mknod /dev/led c 230 0
这个的意思是载入led的模块以及创建led字符设备文件。
不知道这里需要添加不?
Re: 罗升阳 2011-08-01 18:07发表 [回复]
回复hui05504:这两个命令前一个是用来动态加载led这个驱动模块,后一个是用来创建设备文件的,后面两个数字一个主设备号,一个是从设备号。或许你可以继续研究一下这个文件,看看有没有线索。据我之前的了解,设备文件权限修改的地方就是在system/core/init/init.c这个里面做的,可以好好研究一下~旧的版本的代码的确是没有ueventd这个机制,我也是偶然发现的,网络上没有找到关于这个的资料。
Re: hui05504 2011-08-01 21:38发表 [回复]
回复Luoshengyang:楼主,帮忙看下这个文章http://my.chinaunix.net/space.php?uid=20564848&amp;do=blog&id=186359,你觉得采用这个device /dev/hello 644 system system ,这样就可以修改hello的默认创建的权限,这样可行不?
Re: 罗升阳 2011-08-01 22:43发表 [回复]
回复hui05504:看起来是可以的,可以试一下
Re: hui05504 2011-08-02 11:27发表 [回复]
回复Luoshengyang:折腾啊,楼主,你那里可以运行模拟器,可以帮忙搞下这个问题不,目前比较急,都卡在这里了:(
Re: 罗升阳 2011-08-02 11:49发表 [回复]
回复hui05504:刚想起一个问题,你的源代码工程是2.2版本的吧,而你下载的内核代码是最新的,可能是跟这个有关系
Re: hui05504 2011-08-02 13:29发表 [回复]
回复Luoshengyang:不是的,都是一套的,我这里是德州仪器提供的代码,可能模拟器方面的功能是不行的,这个权限的问题还要请楼主多多帮忙啊,估计这个对楼主来说可能半个小时就搞定,但是对我来说,要花个一个星期:(麻烦了
Re: hui05504 2011-08-02 23:03发表 [回复]
回复hui05504:权限打开了。 在Init.rc这个文件下面加入下面的代码
chown system system /dev/hello
chmod 0777 /dev/hello
第一个命令的意思是修改hello的权限为system权限
第二个命令是将hello设置为所有用户可读写
因为init.rc是一个脚本,所以无需编译,如果是运行模拟器可以将它打包到ramdisk这个文件下,如果在目标板上运行的话,可以将它拷贝到out/target/指定目录/下,这样就可以在开发板上跑了,再次感谢楼主的文章:)
Re: 罗升阳 2011-08-02 23:41发表 [回复]
回复hui05504:赞!
3楼 大只辉 2011-08-01 14:50发表 [回复]
版主,loadon.cpp这个有错
register_android_server_HelloService(JNIEnv *env);
应该是
register_android_server_HelloService(env);
Re: 罗升阳 2011-08-01 15:14发表 [回复]
回复linhui568:谢谢提醒,已经修改~
2楼 hui05504 2011-07-31 20:46发表 [回复]
怎么不能连续输入3次呢,杯具,楼主,没有dev/binder这个字符呢,这个有什么建议呢,或者有文章推荐也可以
Re: 罗升阳 2011-07-31 21:04发表 [回复]
回复hui05504:又或者你是研究一下2.2里面,Binder驱动程序里面是怎么样处理/dev/binder这个文件的
Re: 罗升阳 2011-07-31 21:03发表 [回复]
回复hui05504:建议你扩大范围搜索一下代码,例如在system/core目录下找一下,肯定能发现线索的,不然用于进程间通信的/dev/binder设备文件除了root用户,其它用户也都访问不了
Re: hui05504 2011-07-31 21:31发表 [回复]
如果让app拥有root的权限,应该可以访问hello的设备吧
Re: 罗升阳 2011-07-31 22:49发表 [回复]
回复hui05504:这样做不现实,也实现不了的吧,赋予app的root功能,那就有安全问题了,app可以为所欲为了。
Re: hui05504 2011-08-01 09:37发表 [回复]
回复Luoshengyang:你网上搜下,有很多这方面的帖子,但是我没有试过,我看了2.3.3和2.2的源码都没有你说的那个文件,楼主,你这个是哪个版本的源码呢?
Re: 罗升阳 2011-08-01 10:22发表 [回复]
回复hui05504:不管是哪个版本的代码,也不管有没有那个文件,用于进程间通信的/dev/binder设备文件都是要给app使用的,所以你应该研究一下你的版本代码,/dev/binder设备文件是怎么做到这一点的。
PS:我在做这个demo的时候,网上也查不到任何资料说uevent.rc这个文件是用来做什么的
Re: hui05504 2011-08-01 13:19发表 [回复]
回复Luoshengyang:感谢楼主的辛苦付出!binder还在研究中(也在参考你的文章),还要花点时间。既然uevent.rc这个文件在源码中都没有,而且网上也没有这方面的资料,对于我们这些初学者来说还是比较郁闷的事情的,呵呵,如果楼主能写下如何根据binder来给做那就最好不过啦,哈哈!
1楼 hui05504 2011-07-28 23:09发表 [回复]
楼主,按照你上面的教程,出现了以下错误,
No rule to make target `out/target/product/generic/obj/lib/libhardware.so', needed by `out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so'. Stop.
,麻烦指导下,谢谢
Re: hui05504 2011-07-28 23:32发表 [回复]
不好意思,这个错误的出错原因估计是在out/target/product/generic/这个目录下,因为我编译源码的时候不是在generic里生成的,而是在新建的目录底下生成,但是这个命令确默认是在generic的路径,所以出错了
Re: caoyiustc 2011-12-08 10:19发表 [回复]
回复hui05504:那请问您是怎么修改这个问题的呢?我才开始接触这些东西,不知道怎么下手啊~
Re: 罗升阳 2011-12-08 21:50发表 [回复]
回复caoyiustc:设置一下环境变量TARGET_PRODUCT=crespo。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/oldmtn/article/details/9214143

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签