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);}}}}}

更多相关文章

  1. 箭头函数的基础使用
  2. Python技巧匿名函数、回调函数和高阶函数
  3. android Activity生命周期详解(图文)
  4. Android之Adapter系列之SimpleAdapter类
  5. android 2.3 电源管理
  6. Linux Kernel and Android(安卓)休眠与唤醒
  7. 开机SD卡加载过程
  8. Android(安卓)NDK中使用LOG调试C++程序
  9. Android4.4 GPS框架分析

随机推荐

  1. Android 中如何处理双击事件
  2. Html、Flex、Android、JavaGUI、IOS前端
  3. android报错——The import android.util
  4. android 多用户管理UserManager
  5. android中列表选项、单选选项、多选选项
  6. Android开发傻瓜入门-开发自己的手机短信
  7. 终于找到一个类似wince 远程桌面控制andr
  8. Android之——Surface、SurfaceView与Sur
  9. 从源码看ANDROID中SQLITE是怎么通过CURSO
  10. android检查网络连接状态的变化,无网络时