第十期 基于模拟器的Helloworld Framework接口 《手机就是开发板》
2016-12-11 22:08
525 查看
这一期我们在Android系统的Application Frameworks层提供Java接口的硬件服务,结合上一期添加的JNI方法来调用底层硬件。
下面提到的代码保存在https://github.com/aggresss/PHDemo.git 的Code目录的hello_Framework文件中,也可以直接访问:
https://github.com/aggresss/PHDemo/tree/master/Code/hello_Framework
在Android系统中,硬件服务一般是运行在一个独立的进程中为各种应用程序提供服务。因此,调用这些硬件服务的应用程序与这些硬件服务之间的通信需要通过代理来进行。为此,我们要先定义好通信接口。进入到frameworks/base/core/java/android/os目录,新增IHelloService.aidl接口定义文件:
然后进入 frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IHelloService.aidl源文件:
LOCAL_SRC_FILES += /
....................................................................
core/java/android/os/IVibratorService.aidl /
core/java/android/os/IHelloService.aidl /
core/java/android/service/urlrenderer/IUrlRendererService.aidl /
.....................................................................
执行 mmm frameworks/base 这样,就会根据IHelloService.aidl生成相应的IHelloService.Stub接口。
进入到frameworks/base/services/java/com/android/server目录,新增HelloService.java文件:
修改同目录的SystemServer.java文件,在ServerThread::run函数中增加加载HelloService的代码:
@Override
public void run() {
....................................................................................
try {
Slog.i(TAG, "DiskStats Service");
ServiceManager.addService("diskstats", new DiskStatsService(context));
} catch (Throwable e) {
Slog.e(TAG, "Failure starting DiskStats Service", e);
}
try {
Slog.i(TAG, "Hello Service");
ServiceManager.addService("hello", new HelloService());
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Hello Service", e);
}
......................................................................................
}
执行 mmm frameworks/base/services/java
然后 make snod 重新生成system.img
重新打包后的system.img系统镜像文件就在Application Frameworks层中包含了我们自定义的硬件服务HelloService了,并且会在系统启动的时候,自动加载HelloService。这时,应用程序就可以通过Java接口来访问Hello硬件服务了。
=======================分割线==========================
但是从android5.0以后的系统引入了SELinux,SELinux定义了系统中每个用户,进程,应用和文件的访问和转变的权限,然后它使用一个安全策略来控制这些实体(用户、进程、应用和文件)之间的交互,安全策略指定如何严格或宽松地进行检查。
Android 5.0以后,因为采取了SEAndroid/SElinux的安全机制,即使拥有root权限,或者对某内核节点设置为777的权限,仍然无法在JNI层访问。要想让JNI可以成功的访问/dev/hello硬件就必须修改SELinux的策略,否则Android系统再启动是就是出现
add_service ('hello',4e) uid=1000 - PERMISSION DENIED 的错误信息。
这里有两篇参考的博客,里面详细的讲解了怎么修改SELinux策略:
http://blog.csdn.net/eliot_shao/article/details/51770558
http://blog.csdn.net/wh_19910525/article/details/45170755
AOSP中,SELinux相关的策略配置文件保存在 /external/sepolicy/中,为了完成我们这次实验,需要修改5个 .te 文件,可通过访问https://github.com/aggresss/PHDemo/tree/master/Code/hello_Framework/sepolicy
获得
具体的文件改动,都在 #add by aggresss 标签下。
为了确保修改后的 .te 文件被成功的编译进system.img 建议执行一次 make update-api ,然后重新执行 make 进行编译。
=======================分割线==========================
上面的步骤完成后,我们来验证一下 HelloService 是否启动成功,因为只有验证成功后我们才可以进行下一步,如果每完成一步都不验证,到最后实验出现问题时,一层一层的分析起来太复杂了。
我们验证的方式是查看android启动时的打印信息,因为我们的HelloService的源码内都设置有调试信息,启动成功和失败都会有信息输出,在Android中,当系统内核启动后,所有的打印信息都通过logcat机制进行输出,所以只要获取到logcat信息就可以对已启动的Android系统进行调试分析,这里我们使用android studio 内集成的功能,在开启模拟器前先启动android
studio ,选择 Android Monitor 。然后启动模拟器,当内核加载成功进入到Andorid系统后,logcat便会收到系统信息。因为信息非常多,所以我们进行一下筛选,在filter内输出 "hello" ,当andorid系统完全启动后,就能搜索到和hello 相关的信息,如下图所示:
当出现 Hello JNI: hello device is open. 的信息后就说明我们添加的HelloService服务已经成功运行。
下面提到的代码保存在https://github.com/aggresss/PHDemo.git 的Code目录的hello_Framework文件中,也可以直接访问:
https://github.com/aggresss/PHDemo/tree/master/Code/hello_Framework
在Android系统中,硬件服务一般是运行在一个独立的进程中为各种应用程序提供服务。因此,调用这些硬件服务的应用程序与这些硬件服务之间的通信需要通过代理来进行。为此,我们要先定义好通信接口。进入到frameworks/base/core/java/android/os目录,新增IHelloService.aidl接口定义文件:
package android.os; interface IHelloService { void setVal(int val); int getVal(); }
然后进入 frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IHelloService.aidl源文件:
LOCAL_SRC_FILES += /
....................................................................
core/java/android/os/IVibratorService.aidl /
core/java/android/os/IHelloService.aidl /
core/java/android/service/urlrenderer/IUrlRendererService.aidl /
.....................................................................
执行 mmm frameworks/base 这样,就会根据IHelloService.aidl生成相应的IHelloService.Stub接口。
进入到frameworks/base/services/java/com/android/server目录,新增HelloService.java文件:
package com.android.server; import android.content.Context; import android.os.IHelloService; import android.util.Slog; public class HelloService extends IHelloService.Stub { private static final String TAG = "HelloService"; HelloService() { init_native(); } public void setVal(int val) { setVal_native(val); } public int getVal() { return getVal_native(); } private static native boolean init_native(); private static native void setVal_native(int val); private static native int getVal_native(); };
修改同目录的SystemServer.java文件,在ServerThread::run函数中增加加载HelloService的代码:
@Override
public void run() {
....................................................................................
try {
Slog.i(TAG, "DiskStats Service");
ServiceManager.addService("diskstats", new DiskStatsService(context));
} catch (Throwable e) {
Slog.e(TAG, "Failure starting DiskStats Service", e);
}
try {
Slog.i(TAG, "Hello Service");
ServiceManager.addService("hello", new HelloService());
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Hello Service", e);
}
......................................................................................
}
执行 mmm frameworks/base/services/java
然后 make snod 重新生成system.img
重新打包后的system.img系统镜像文件就在Application Frameworks层中包含了我们自定义的硬件服务HelloService了,并且会在系统启动的时候,自动加载HelloService。这时,应用程序就可以通过Java接口来访问Hello硬件服务了。
=======================分割线==========================
但是从android5.0以后的系统引入了SELinux,SELinux定义了系统中每个用户,进程,应用和文件的访问和转变的权限,然后它使用一个安全策略来控制这些实体(用户、进程、应用和文件)之间的交互,安全策略指定如何严格或宽松地进行检查。
Android 5.0以后,因为采取了SEAndroid/SElinux的安全机制,即使拥有root权限,或者对某内核节点设置为777的权限,仍然无法在JNI层访问。要想让JNI可以成功的访问/dev/hello硬件就必须修改SELinux的策略,否则Android系统再启动是就是出现
add_service ('hello',4e) uid=1000 - PERMISSION DENIED 的错误信息。
这里有两篇参考的博客,里面详细的讲解了怎么修改SELinux策略:
http://blog.csdn.net/eliot_shao/article/details/51770558
http://blog.csdn.net/wh_19910525/article/details/45170755
AOSP中,SELinux相关的策略配置文件保存在 /external/sepolicy/中,为了完成我们这次实验,需要修改5个 .te 文件,可通过访问https://github.com/aggresss/PHDemo/tree/master/Code/hello_Framework/sepolicy
获得
具体的文件改动,都在 #add by aggresss 标签下。
为了确保修改后的 .te 文件被成功的编译进system.img 建议执行一次 make update-api ,然后重新执行 make 进行编译。
=======================分割线==========================
上面的步骤完成后,我们来验证一下 HelloService 是否启动成功,因为只有验证成功后我们才可以进行下一步,如果每完成一步都不验证,到最后实验出现问题时,一层一层的分析起来太复杂了。
我们验证的方式是查看android启动时的打印信息,因为我们的HelloService的源码内都设置有调试信息,启动成功和失败都会有信息输出,在Android中,当系统内核启动后,所有的打印信息都通过logcat机制进行输出,所以只要获取到logcat信息就可以对已启动的Android系统进行调试分析,这里我们使用android studio 内集成的功能,在开启模拟器前先启动android
studio ,选择 Android Monitor 。然后启动模拟器,当内核加载成功进入到Andorid系统后,logcat便会收到系统信息。因为信息非常多,所以我们进行一下筛选,在filter内输出 "hello" ,当andorid系统完全启动后,就能搜索到和hello 相关的信息,如下图所示:
当出现 Hello JNI: hello device is open. 的信息后就说明我们添加的HelloService服务已经成功运行。
相关文章推荐
- 第八期 基于模拟器的Helloworld HAL接口 《手机就是开发板》
- 第九期 基于模拟器的Helloworld JNI方法 《手机就是开发板》
- 第五期 基于模拟器上的实践和学习规划 《手机就是开发板》
- 第七期 基于模拟器的Helloworld 可执行程序 《手机就是开发板》
- 第六期 基于模拟器的Helloworld 内核驱动 《手机就是开发板》
- 第十一期 基于模拟器的Helloworld APP 访问硬件服务 《手机就是开发板》
- 第二十四期 OpenWrt ipk helloworld 《路由器就是开发板》
- 第十九期 基于HG255d_U-Boot的uIP移植《路由器就是开发板》
- 实现一个基于串口的手机AT信令模拟器
- 实现一个基于串口的手机AT信令模拟器
- 最简单的基于FFmpeg的移动端例子:Windows Phone HelloWorld
- Spring 3 MVC Framework Based Hello World Web Application Example Using Maven, Eclipse IDE And Tomcat
- play framework HelloWorld
- 实现一个基于串口的手机AT信令模拟器
- SAP接口编程-RFC系列01 : RFC Hello World
- Spring 4 MVC hello world 教程-完全基于XML(带项目源码)【超赞】
- 构建基于Javascript的移动web CMS——Hello,World
- 实现一个基于串口的手机AT信令模拟器
- 全民付手机接口开发生产环境error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
- 我的第一个程序:hello_world(基于at91sam9g20)