Android硬件访问服务 (硬核最终篇)
Android硬件访问服务 (硬核最终篇)
一、调用关系及流程简要
SystemService.java:(调库、启动服务)
1.System.loadLibbrary(“android_servers”);
- libandroid_servers.so依赖jni文件夹下所有的com_android_server_xxx Service.cpp文件和onload.cpp文件。
- System.loadLibbrary()函数会调用JNI_OnLoad()函数。JNI_OnLoad()函数在onload.cpp.
2.Slog.i(TAG,“xxx Service”)。
3.xxx = new xxxService(context)。
4.ServiceManager.addService(“xxx”,xxx)。
onload.cpp:(实现native方法、获得env、找类)
1.JNI_OnLoad(Java vm, void /* reserver /)*
- 获得env,vm->GetEnv((void**) &env, JNI_VERSION_1_4) 。
- 找类, JNI_OnLoad()函数调用一系列register_android_server_XXXService(env)函数,进行找类。
Com_android_server_XXXService.cpp:(为onload.cpp提供register_android_server_XXXService()
1.register_android_server_XXXService(env)函数进行找类。
- jniRegisterNativeMethods(env, “com/android/server/xxxService”,method_table, NELEM(method_table))
2.JNINativeMethod methods[],自定义native修饰的 java_ioctl函数对应的 c_ioctl方法。
com/android/server/xxxService.java:
1.实现xxxService类。
- native static int java_ioctl(int which,int status)。声明native方法。
- 实现IHelloService.aidl生成IHelloService.java的生成binder机制的接口led_ioctl。
hal.c:(硬件抽象层)
1.自定义一个led_device_t结构体。
- 第一个成员为struct hw_device_t comm结构体实例。
2.定义一个struct led_device_t led_device实例。
- 填充.hal_ioctl = led_hal_ioctl。
3.int led_open(const struct hw_module_t module,const char id,struct hw_device_t** device)。**
4.struct hw_module_methods_t method。
5.struct hw_module_t HMI。
led_driver.c:(内核层驱动)
1.static struct file_operations fops。
2.static void __init。
3.static void __exit。
IHelloService.aidl:
1.package android.os。
2.interface xxxService。
- int led_ioctl(int which,int status)。
3.在androidM/frameworks/base/Android.mk加一行
- core/java/android/os/IHelloService.aidl \
IHelloService.java:
1.由aidl生成IHelloService.java。
2.生成binder机制的接口。
- public int led_ioctl(int which ,int status) throws android.os.RemoteException。
APP:
1.ServiceManager.getservice()。
2.IHelloService IHelloService.Stub.asInterface(Ibinder obj)。
二、编程示例
1.IHelloService.aidl:
package android.os;/** {@hide} */interface IHelloService{ int led_ioctrl(int which, int status);}
修改IHelloService.aidl文件对应的Android.mk文件**添加一行:
core/java/android/os/IHelloService.aidl \
执行mm命令,由IHelloService.aidl文件自动生成IHelloService.java文件。
2.IHelloService.java:
/* * This file is auto-generated. DO NOT MODIFY. * Original file: frameworks/base/./core/java/android/os/ILedService.aidl */package android.os;/** {@hide} */public interface IHelloServiceextends android.os.IInterface{ /** Local-side IPC implementation stub class. */// Stub供服务端实现public static abstract class Stub extends android.os.Binder implements android.os.ILedService{ // binder的唯一标识private static final java.lang.String DESCRIPTOR = "android.os.ILedService";/** Construct the stub at attach it to the interface. */public Stub(){ this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an android.os.IHelloServiceinterface, * generating a proxy if needed. */ // 提供给客户端:将IBinder转化成IPlusService接口public static android.os.IHelloServiceasInterface(android.os.IBinder obj){ if ((obj==null)) { return null;}// 如果是客户端跟服务端同一个进程,直接返回server端的binder对象android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof android.os.ILedService))) { return ((android.os.ILedService)iin);}// 若不同进程,则生成一个binder的代理return new android.os.ILedService.Stub.Proxy(obj);}// 底层对应BBinder@Override public android.os.IBinder asBinder(){ return this;}// 运行在服务端:客户端调用transact(),会引发服务端onTransact()// code 表示客户端请求方法标志// data 表示参数// reply 表示写入返回值// 返回值:客户端请求结果,可以做权限控制@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{ switch (code){ case INTERFACE_TRANSACTION:{ reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_led_ioctrl:{ data.enforceInterface(DESCRIPTOR);int _arg0;// 从Parcel读取客户端传过来的数据_arg0 = data.readInt();int _arg1;_arg1 = data.readInt();// 调用服务端的led_ioctrl()int _result = this.led_ioctrl(_arg0, _arg1);reply.writeNoException();// 写入返回给客户端的数据reply.writeInt(_result);return true;}}return super.onTransact(code, data, reply, flags);}// 客户端:服务的代理类private static class Proxy implements android.os.ILedService{ private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){ mRemote = remote;}// 底层对应 BinderProxy@Override public android.os.IBinder asBinder(){ return mRemote;}public java.lang.String getInterfaceDescriptor(){ return DESCRIPTOR;}// 客户端:打包数据,调用代理binder的transact(),会引发服务端transact()@Override public int led_ioctrl(int which, int status) throws android.os.RemoteException{ android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try { _data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(which);_data.writeInt(status);// 代理类,调用transact()mRemote.transact(Stub.TRANSACTION_led_ioctrl, _data, _reply, 0);_reply.readException();_result = _reply.readInt();}finally { _reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_led_ioctrl = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}// 真正实现服务的地方public int led_ioctrl(int which, int status) throws android.os.RemoteException;}
4.HelloService.java:
package com.android.server;/* 导入IHelloService.java的IHelloService */import android.os.IHelloService;import android.os.RemoteException;import android.os.IBinder;import android.os.Binder;import android.os.ServiceManager;import android.util.Slog;/* 继承IHelloservice.aidl生成的IHelloservice.java中的类IHelloService */public class HelloService extends IHelloService.Stub{ private static final String TAG = "HelloService";/* 构造函数中调用open函数 */HelloService(){ Slog.d(TAG,"this is java_open HelloService");java_open();}/* 将IHelloService.aidl生成的IHelloService.java中的此函数实现 */ public int led_ioctl(int which, int status) throws android.os.RemoteException;{ Slog.d(TAG,"this is java_ioctl HelloService");java_ioctl(which,status);return 0;} /* 声明native本地方法 */public native int java_open();public native java_ioctl(int which,int status);}
5.SystemService.java:
在SystemService.java添加内容,修改。
/* * 1.System.loadLibrary * 2.启动服务new HelloSercice * 3.添加服务addservice */ public final class SystemServer { /* Initialize native services. * 加载libandroid_servers.so文件。 * 此文件由众多com_android_server_xxx Service.cpp文件和一个onload.cpp文件编译得到 */ System.loadLibrary("android_servers"); } /* 在startOtherServices方法中添加如下内容 */private void startOtherServices() { final Context context = mSystemContext;/* 添加一行,定义HelloSercice的变量 */ HelloSercice Hellop = null; traceBeginAndSlog("StartHelloService");/* 添加一行,new出来HelloSercice的对象,此时HelloSercice的构造函数会执行java_open函数 */ Hellop = new VibratorService(context);/* 添加一行,添加服务,第一个参数服务名,第二个参数服务类的对象 */ ServiceManager.addService("HelloSercice", Hellop); traceEnd();}
6.com_android_server_HelloService.cpp:
#define LOG_TAG "HelloService"#include #include #include #include #include #include "jni.h"#include #include "android_runtime/AndroidRuntime.h"#include #include #include #include #include using android::hardware::Return;using android::hardware::vibrator::V1_0::EffectStrength;using android::hardware::vibrator::V1_0::Status;using android::hardware::vibrator::V1_1::Effect_1_1;namespace V1_0 = android::hardware::vibrator::V1_0;namespace V1_1 = android::hardware::vibrator::V1_1;namespace V1_2 = android::hardware::vibrator::V1_2;namespace android { /* hal层自定义的结构体,第一个成员为hw_device_t */struct led_device_t{ struct hw_device_t comm;int (*hal_open)();int (*hal_ioctl)(int which,int status);}/* led_device结构体是hal层自己定义的,此结构体的第一个成员就是结构体就是hw_device_t 结构体 */struct led_device *led;jint c_open(JNIEnv *env, jobject self){ /* 只有涉及native方法的jni转换设计的方法返回值和参数列表转换为jint,jchar等,其余的变量还应遵守c规则 */int ret;/* ******** hw_modile_t 结构体定义 ***********typedef struct hw_module_t {const char *id; //id是stub的身份证号struct hw_module_methods_t* methods; //操作方法} hw_module_t; ******** hw_module_methods_t结构体定义 *********** typedef struct hw_module_methods_t {int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device);} hw_module_methods_t; ********* hw_device_t 结构体定义 *********** typedef struct hw_device_t {struct hw_module_t* module;int (*close)(struct hw_device_t* device);} hw_device_t;*/ustruct hw_module_t * module;struct hw_device_t * device; ALOGI("this is c_open\n");uu /* 通过调用hw_get_module,传入id值“myled” 得到hw_module_t 结构体 module*/ret = hw_get_module("myled",(const struct hw_module_t **)&module);if(ret == 0){ /* hw_module_t 结构体的成员结构体methods的open函数返回一个hw_device_t结构体 */ret = module->methods->open(module,"myled",&device);if(ret == 0){ /* 通过上面函数返回的hw_device_t结构体得到第一个成员hw_device_t 的指针。*将hw_device_t 强转为led_device就得到自定义的led_device结构体的指针了,*从而调用其自定义的hal_open()函数了。*/led = (struct led_device *)device;led->hal_open();}}return 0;} /*在jni.h头文件中定义的typedef struct {char *name; //java中的方法名char *signature; //java中方法所对应的签名void *fnPtr; //c函数的名字} JNINativeMethod;*/static const JNINativeMethod method_table[] = { /* 准备为HelloService.java中native声明的java_open(),java_ioctl() * 与本文件com_android_server_HelloService.cpp的c_open(),c_ioctl() * 进行实现,并绑定,为注册做准备 */ { "java_open", "()I", (void*)c_open }, { "java_ioctl", "(II)I", (void*)c_ioctl },};/* 在onload.cpp文件中调用此方法 */int register_android_server_HelloService(JNIEnv *env){ /* 注册方法函数,com/android/server/HelloService.java */ return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));}};
7.onload.cpp:
在onload.cpp文件中添加函数声明和函数调用。
namespace android { /* 添加一行函数声明 */ int register_android_server_HelloService(JNIEnv *env);}using namespace android;extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved){ /* 添加一行函数调用 */ register_android_server_HelloService(env);}
8.HelloService_HAL.c:
#define LOG_TAG "HelloService"#include #include #include #include #include #include /* com_android_server_HelloService.cpp复制定义该结构体 */struct led_device_t{ struct hw_device_t comm;int (*hal_open)();int (*hal_ioctl)(int which,int status);int (*hal_close)();}int fd;int led_hal_open(){ ALOGI("this is led_hal_open"); fd = open("dev/myled0",O_RDWR); if(fd == -1) { ALOGI("open /dev/led0 is failed"); }return 0;}int led_hal_ioctl(int which,int status){ ALOGI("this is led_hal_ioctl"); ioctl(fd,which,status);return 0;}struct led_device_t led_device = { .hal_open = led_hal_open,.hal_ioctl = led_hal_ioctl,}int led_open(const struct hw_module_t* module,const char* id,struct hw_device_t** device){ /* 在native函数中通过调用hw_get_module函数,根据传进去的id。*找到结构体 hw_module_t ,通过 hw_module_t 找到 hw_module_methods_t 。*调用 hw_module_methods_t 结构体中的 open 函数 。*open 函数得到hw_device_t 结构体。*led_device_t 结构体中第一个成员就是 hw_device_t 结构体。*所以将 led_device 强转 led_device_t 得到 led_device_t 结构体指针。*从而通过led_device_t结构体访问我们自己定义的led_hal_open,led_hal_ioctl,led_hal_close。*/*device = (struct led_device_t *)&led_device;return 0;}struct hw_module_methods_t method = { .open = led_open,}/* 1.必须命名为HMI */struct hw_module_t HMI = { .id = "myled",.methods = &method,}
Android.mk:
LOCAL_PATH:=$(call my-dir)include $(CLEAR_VARS)#2.生成格式为:id.default.soLOCAL_MODULE:=myled.default#指定生成的.so文件存放的路径androidM/out/target/product/astar-fs733/system/lib/hwLOCAL_MODULE_RELATIVE:= hwLOCAL_SRC_FILES:=HelloService_HAL.c#LOCAL_MODULE_PATH:=$(LOCAL_PATH)#添加engLOCAL_SHARED_LIBRARIES:=liblog enginclude $(BUILD_SHARED_LIBARY)#注意让上层Android.mk包含此文件
在ueventd.sun8i.rc文件中添加:
/dev/myled0 0777 system system
解决权限问题。
9.应用程序MainActivity.java:
package com.company.led_service_app;import android.os.Bundle;import android.widget.ImageButton;import android.app.Activity;public class MainActivity extends Activity { private ImageButton button;private boolean status = false;/* 我们的IHelloService类由IHelloService.aidl文件生成IHelloService.java中* 在androidM/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classe.jar* 的库中存在我们的IHelloService类 */IHelloService Service;@overrideprotected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);/* ServiceManager.getservice("HelloSercice")获取服务 * 但是其返回值为IBinder类型 * 在IHelloService.aidl文件生成IHelloService.java中有一个方法用于转换 * IHelloService IHelloService.Stub.asInterface(Ibinder obj) */Service = IHelloService.Stub.asInterface(ServiceManager.getservice("HelloSercice"));ImageButton button = (ImageButton) findViewByID(R.id.imagebutton);button.setOnClickListener(new OnclickListener()){ @overridepublic void onClick(View v) { status =! status;if(status){ /* 这里就可以调用IHelloService.aidl文件生成 * Ibinder机制的IHelloService.java中声明 * 在HelloService.java实现中的函数led_ioctl() */service.led_ioctl(1,1);}else{ service.led_ioctl(1,0);}}}}}
更多相关文章
- 箭头函数的基础使用
- Python技巧匿名函数、回调函数和高阶函数
- android Activity生命周期详解(图文)
- Android之Adapter系列之SimpleAdapter类
- android 2.3 电源管理
- Linux Kernel and Android(安卓)休眠与唤醒
- 开机SD卡加载过程
- Android(安卓)NDK中使用LOG调试C++程序
- Android4.4 GPS框架分析