Android app->Framework->Jni->Hal->Linux driver通路(硬件访问服务的通路)

Android 的硬件访问服务是基于C/S架构实现的。整个框架如下:

硬件访问服务框架

  1. service manager负责管理注册到系统的所有硬件服务(放入链表)。(service_manager.c)
  2. SystemServer进程完成对所有硬件服务的注册。(SystemServer.java)
    SystemServer.java的调用过程:
    a. 加载c库(会触发JNI_OnLoad()函数的调用)
    System.loadLibrary(“android_servers”); //加载libandroid_servers.so库,该库是由onload.cpp编译得到
    b. 添加服务(如:SerialService,LightsService,PowerManagerService,VibratorService等)
    此处以LedService为例:
    /* 类LedService是我们自己编写(LedService.java),它继承自ILedService.Stub,ILedService是由ILedService.aidl编译自动生成的。ILedService.aidl文件是我们自己编写的。LedService类内部会声明本地方法,这些方法与2.a中加载的c库中的JNI方法相对应 */
    LedService led = null;
    led = new LedService(context);
    ServiceManager.addService(“led”, led);
  3. onload.cpp
    该文件实现了JNI_OnLoad()函数,函数内部又调用各种硬件服务的注册函数:
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
	    JNIEnv* env = NULL;
	    jint result = -1;
	    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
		        ALOGE("GetEnv failed!");
		        return result;
   	 	}
    	ALOG_ASSERT(env, "Could not retrieve the env!");

	    register_android_server_ActivityManagerService(env);
	    register_android_server_PowerManagerService(env);
	    register_android_server_SerialService(env);
	    register_android_server_InputApplicationHandle(env);
	    register_android_server_InputWindowHandle(env);
	    register_android_server_InputManager(env);
	    register_android_server_LightsService(env);
	    register_android_server_AlarmManagerService(env);
	    register_android_server_UsbDeviceManager(env);
	    register_android_server_UsbMidiDevice(env);
	    register_android_server_UsbHostManager(env);
	    register_android_server_VibratorService(env);
	    register_android_server_SystemServer(env);
	    register_android_server_location_GpsLocationProvider(env);
	    register_android_server_location_FlpHardwareProvider(env);
	    register_android_server_connectivity_Vpn(env);
	    register_android_server_AssetAtlasService(env);
	    register_android_server_ConsumerIrService(env);
	    register_android_server_BatteryStatsService(env);
	    register_android_server_hdmi_HdmiCecController(env);
	    register_android_server_tv_TvInputHal(env);
	    register_android_server_PersistentDataBlockService(env);
	    register_android_server_Watchdog(env);
	    //我们为LedService添加
	    register_android_server_LedService(env);
	
	    return JNI_VERSION_1_4;
 }
  1. register_android_server_LedService(env);(com_android_server_LedService.cpp)
#define LOG_TAG "LedService"
		
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"

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

#include <stdio.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <hardware/led_hal.h>


namespace android
{

static led_device_t* led_device;

jint ledOpen(JNIEnv *env, jobject cls)
{
	jint err;
    hw_module_t* module;
	hw_device_t* device;

	ALOGI("native ledOpen ...");

	/* 1. hw_get_module --- JNI调用Hal层代码的固定格式 ,获得hw_get_module结构体*/
    err = hw_get_module("led", (hw_module_t const**)&module);
    if (err == 0) {
		/* 2. 通过hw_module_t的open函数将hw_device_t结构传过来 */
	    err = module->methods->open(module, NULL, &device);
	    if (err == 0) {
			/* 3. 自定义设备结构体的第一个成员是hw_device_t结构体类型,该结构在2中已获得,通过2中的指针可以获得自定义结构体led_device_t的指针,进而调用led_device_t中的函数 */
	        led_device = (led_device_t *)device;
			return led_device->led_open(led_device);
	    } else {
	        return -1;
    	}
    }
	
    return -1;	
}

void ledClose(JNIEnv *env, jobject cls)
{
	//ALOGI("native ledClose ...");
	//close(fd);
}


jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
{
	ALOGI("native ledCtrl %d, %d", which, status);
	return led_device->led_ctrl(led_device, which, status);
}


static const JNINativeMethod methods[] = {
	{"native_ledOpen", "()I", (void *)ledOpen},
	{"native_ledClose", "()V", (void *)ledClose},
	{"native_ledCtrl", "(II)I", (void *)ledCtrl},
};
	
int register_android_server_LedService(JNIEnv *env)
{
    return jniRegisterNativeMethods(env, "com/android/server/LedService", methods, NELEM(methods));
}

}
  1. Hal层的实现
    Hal的实现也遵循固定的格式,
#define LOG_TAG "LedHal"
		
/* 1. 实现一个名为HMI的hw_module_t结构体 */

/* 2. 实现一个open函数, 它返回led_device_t结构体 */

/* 3. 实现led_device_t结构体 */

/* 参考 hardware\libhardware\modules\vibrator\vibrator.c
 */

#include <hardware/vibrator.h>
#include <hardware/hardware.h>

#include <cutils/log.h>

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include <hardware/led_hal.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <utils/Log.h>

static int fd;

/** Close this device */
static int led_close(struct hw_device_t* device)
{
	close(fd);
	return 0;
}

static int led_open(struct led_device_t* dev)
{
	fd = open("/dev/leds", O_RDWR);
	ALOGI("led_open : %d", fd);
	if (fd >= 0)
		return 0;
	else
		return -1;
}

static int led_ctrl(struct led_device_t* dev, int which, int status)
{
	int ret = ioctl(fd, status, which);
	ALOGI("led_ctrl : %d, %d, %d", which, status, ret);
	return ret;
}

static struct led_device_t led_dev = {
	.common = {
		.tag   = HARDWARE_DEVICE_TAG,
		.close = led_close,
	},
	.led_open  = led_open,
	.led_ctrl  = led_ctrl,
};

static int led_device_open(const struct hw_module_t* module, const char* id,
        struct hw_device_t** device)
{
	*device = &led_dev;
	return 0;
}


static struct hw_module_methods_t led_module_methods = {
    .open = led_device_open,
};

//"HMI",hw_get_module()函数会在动态库查找“HMI”这个符号,然后通过id匹配到想要的服务。
struct hw_module_t HAL_MODULE_INFO_SYM = {	
	.tag = HARDWARE_MODULE_TAG,
    .id = "led",
    .methods = &led_module_methods,
};

hal代码中的自定义结构led_device_t中的函数就会去调用驱动的设备文件,完成对硬件的访问。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值