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 <android/hardware/vibrator/1.0/types.h>
#include <android/hardware/vibrator/1.1/types.h>
#include <android/hardware/vibrator/1.2/IVibrator.h>
#include <android/hardware/vibrator/1.2/types.h>
#include <hardware/hardware.h>

#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "android_runtime/AndroidRuntime.h"

#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/vibrator.h>

#include <inttypes.h>
#include <stdio.h>

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;
	*/u
	struct 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 <cutils/log.h>
#include <hardware/hardware.h>
#include <sys/ioctl>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
/* 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.so
LOCAL_MODULE:=myled.default
#指定生成的.so文件存放的路径androidM/out/target/product/astar-fs733/system/lib/hw
LOCAL_MODULE_RELATIVE:= hw
LOCAL_SRC_FILES:=HelloService_HAL.c
#LOCAL_MODULE_PATH:=$(LOCAL_PATH)
#添加eng
LOCAL_SHARED_LIBRARIES:=liblog eng
include $(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;
	
	@override
	protected 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()){
			@override
			public 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);
				}
			}
			
		}
	}
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值