android系统核心机制 基础(09)Android 添加新模块

115 篇文章 94 订阅

该系列文章总纲链接:android 系统核心机制基础 系列文章目录


本章关键点总结 & 说明:

这里主要关注➕右下角部分 添加新模块即可。本章节详细解读了android新模块从驱动层、HAL层、framework层、APP层的流程。上面的图添加新模块部分可能会看不清,这里单独截取该部分,如下所示:

这样就清晰多了。本章节主要描述了android系统从上到下添加一个模块的流程,因为仅针对流程,所以关于其使用的原理本部分不会涉及,但在binder以及其他章节中会有所涉及。

1 添加驱动程序(源码见wds_hello_driver)

添加流程如下:

1.1 添加代码

对应代码位置-->kernel/drivers/wds_hello,驱动层代码如下:

@1 wds_hello.h

#ifndef _WDS_HELLO_ANDROID_H_  
#define _WDS_HELLO_ANDROID_H_  

#include <linux/cdev.h>  
#include <linux/semaphore.h>  

#define WDS_HELLO_DEVICE_NODE_NAME  "wds_hello"  
#define WDS_HELLO_DEVICE_FILE_NAME  "wds_hello"  
#define WDS_HELLO_DEVICE_PROC_NAME  "wds_hello"  
#define WDS_HELLO_DEVICE_CLASS_NAME "wds_hello"  

struct wds_hello_android_dev {  
	int val;  
	struct semaphore sem;  
	struct cdev dev;  
};  

#endif  

@2 wds_hello.c

#include <linux/init.h>  
#include <linux/module.h>  
#include <linux/types.h>  
#include <linux/fs.h>  
#include <linux/proc_fs.h>  
#include <linux/device.h>  
#include <asm/uaccess.h>  

#include "wds_hello.h"  

/*主设备和从设备号变量*/  
static int wds_hello_major = 0;  
static int wds_hello_minor = 0;  

/*设备类别和设备变量*/  
static struct class* wds_hello_class = NULL;  
static struct wds_hello_android_dev* wds_hello_dev = NULL;  

/*传统的设备文件操作方法*/  
static int wds_hello_open(struct inode* inode, struct file* filp);  
static int wds_hello_release(struct inode* inode, struct file* filp);  
static ssize_t wds_hello_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos);  
static ssize_t wds_hello_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos);  

/*设备文件操作方法表*/  
static struct file_operations wds_hello_fops = {  
	.owner = THIS_MODULE,  
	.open = wds_hello_open,  
	.release = wds_hello_release,  
	.read = wds_hello_read,  
	.write = wds_hello_write,   
};  

/*访问设置属性方法*/  
static ssize_t wds_hello_val_show(struct device* dev, struct device_attribute* attr,  char* buf);  
static ssize_t wds_hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);  

/*定义设备属性*/  
static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, wds_hello_val_show, wds_hello_val_store);  

///
/*打开设备方法*/  
static int wds_hello_open(struct inode* inode, struct file* filp) {  
	struct wds_hello_android_dev* dev;          

	/*将自定义设备结构体保存在文件指针的私有数据域中,以便访问设备时拿来用*/  
	dev = container_of(inode->i_cdev, struct wds_hello_android_dev, dev);  
	filp->private_data = dev;  

	return 0;  
}  

/*设备文件释放时调用,空实现*/  
static int wds_hello_release(struct inode* inode, struct file* filp) {  
	return 0;  
}  

/*读取设备的寄存器val的值*/  
static ssize_t wds_hello_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos) {  
	ssize_t err = 0;  
	struct wds_hello_android_dev* dev = filp->private_data;          

	/*同步访问*/  
	if(down_interruptible(&(dev->sem))) {  
		return -ERESTARTSYS;  
	}  

	if(count < sizeof(dev->val)) {  
		goto out;  
	}          

	/*将寄存器val的值拷贝到用户提供的缓冲区*/  
	if(copy_to_user(buf, &(dev->val), sizeof(dev->val))) {  
		err = -EFAULT;  
		goto out;  
	}  

	err = sizeof(dev->val);  

out:  
	up(&(dev->sem));  
	return err;  
}  

/*写设备的寄存器值val*/  
static ssize_t wds_hello_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) {  
	struct wds_hello_android_dev* dev = filp->private_data;  
	ssize_t err = 0;          

	/*同步访问*/  
	if(down_interruptible(&(dev->sem))) {  
		return -ERESTARTSYS;          
	}          

	if(count != sizeof(dev->val)) {  
		goto out;          
	}          

	/*将用户提供的缓冲区的值写到设备寄存器去*/  
	if(copy_from_user(&(dev->val), buf, count)) {  
		err = -EFAULT;  
		goto out;  
	}  

	err = sizeof(dev->val);  

out:  
	up(&(dev->sem));  
	return err;  
}

///
/*读取寄存器val的值到缓冲区buf中,内部使用*/  
static ssize_t __wds_hello_get_val(struct wds_hello_android_dev* dev, char* buf) {  
	int val = 0;          

	/*同步访问*/  
	if(down_interruptible(&(dev->sem))) {                  
		return -ERESTARTSYS;          
	}          

	val = dev->val;          
	up(&(dev->sem));          

	return snprintf(buf, PAGE_SIZE, "%d\n", val);  
}  

/*把缓冲区buf的值写到设备寄存器val中去,内部使用*/  
static ssize_t __wds_hello_set_val(struct wds_hello_android_dev* dev, const char* buf, size_t count) {  
	int val = 0;          

	/*将字符串转换成数字*/          
	val = simple_strtol(buf, NULL, 10);          

	/*同步访问*/          
	if(down_interruptible(&(dev->sem))) {                  
		return -ERESTARTSYS;          
	}          

	dev->val = val;          
	up(&(dev->sem));  

	return count;  
}  

/*读取设备属性val*/  
static ssize_t wds_hello_val_show(struct device* dev, struct device_attribute* attr, char* buf) {  
	struct wds_hello_android_dev* hdev = (struct wds_hello_android_dev*)dev_get_drvdata(dev);          

	return __wds_hello_get_val(hdev, buf);  
}  

/*写设备属性val*/  
static ssize_t wds_hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {   
	struct wds_hello_android_dev* hdev = (struct wds_hello_android_dev*)dev_get_drvdata(dev);    

	return __wds_hello_set_val(hdev, buf, count);  
}    

///
/*读取设备寄存器val的值,保存在page缓冲区中*/  
static ssize_t wds_hello_proc_read(char* page, char** start, off_t off, int count, int* eof, void* data) {  
	if(off > 0) {  
		*eof = 1;  
		return 0;  
	}  

	return __wds_hello_get_val(wds_hello_dev, page);  
}  

/*把缓冲区的值buff保存到设备寄存器val中去*/  
static ssize_t wds_hello_proc_write(struct file* filp, const char __user *buff, unsigned long len, void* data) {  
	int err = 0;  
	char* page = NULL;  

	if(len > PAGE_SIZE) {  
		printk(KERN_ALERT"The buff is too large: %lu.\n", len);  
		return -EFAULT;  
	}  

	page = (char*)__get_free_page(GFP_KERNEL);  
	if(!page) {                  
		printk(KERN_ALERT"Failed to alloc page.\n");  
		return -ENOMEM;  
	}          

	/*先把用户提供的缓冲区值拷贝到内核缓冲区中去*/  
	if(copy_from_user(page, buff, len)) {  
		printk(KERN_ALERT"Failed to copy buff from user.\n");                  
		err = -EFAULT;  
		goto out;  
	}  

	err = __wds_hello_set_val(wds_hello_dev, page, len);  
out:  
	free_page((unsigned long)page);  
	return err;  
}  

/*创建/proc/hello文件*/  
static void wds_hello_create_proc(void) {  
	struct proc_dir_entry* entry;  

	entry = create_proc_entry(WDS_HELLO_DEVICE_PROC_NAME, 0, NULL);  
	if(entry) {  
		//entry->owner = THIS_MODULE; //wds modify 
		entry->read_proc = wds_hello_proc_read;  
		entry->write_proc = wds_hello_proc_write;  
	}  
}  

/*删除/proc/hello文件*/  
static void wds_hello_remove_proc(void) {  
	remove_proc_entry(WDS_HELLO_DEVICE_PROC_NAME, NULL);  
}
  
///
/*初始化设备*/  
static int  __wds_hello_setup_dev(struct wds_hello_android_dev* dev) {  
	int err;  
	dev_t devno = MKDEV(wds_hello_major, wds_hello_minor);  

	memset(dev, 0, sizeof(struct wds_hello_android_dev));  

	cdev_init(&(dev->dev), &wds_hello_fops);  
	dev->dev.owner = THIS_MODULE;  
	dev->dev.ops = &wds_hello_fops;          

	/*注册字符设备*/  
	err = cdev_add(&(dev->dev),devno, 1);  
	if(err) {  
		return err;  
	}          

	/*初始化信号量和寄存器val的值*/  
	//init_MUTEX(&(dev->sem));  
	sema_init(&(dev->sem),1);  //wds modify

	dev->val = 0;  

	return 0;  
}  

/*模块加载方法*/  
static int __init wds_hello_init(void){   
	int err = -1;  
	dev_t dev = 0;  
	struct device* temp = NULL;  

	printk(KERN_ALERT"Initializing wds_hello device.\n");          

	/*动态分配主设备和从设备号*/  
	err = alloc_chrdev_region(&dev, 0, 1, WDS_HELLO_DEVICE_NODE_NAME);  
	if(err < 0) {  
		printk(KERN_ALERT"Failed to alloc char dev region.\n");  
		goto fail;  
	}  

	wds_hello_major = MAJOR(dev);  
	wds_hello_minor = MINOR(dev);          

	/*分配helo设备结构体变量*/  
	wds_hello_dev = kmalloc(sizeof(struct wds_hello_android_dev), GFP_KERNEL);  
	if(!wds_hello_dev) {  
		err = -ENOMEM;  
		printk(KERN_ALERT"Failed to alloc hello_dev.\n");  
		goto unregister;  
	}          

	/*初始化设备*/  
	err = __wds_hello_setup_dev(wds_hello_dev);  
	if(err) {  
		printk(KERN_ALERT"Failed to setup dev: %d.\n", err);  
		goto cleanup;  
	}          

	/*在/sys/class/目录下创建设备类别目录hello*/  
	wds_hello_class = class_create(THIS_MODULE, WDS_HELLO_DEVICE_CLASS_NAME);  
	if(IS_ERR(wds_hello_class)) {  
		err = PTR_ERR(wds_hello_class);  
		printk(KERN_ALERT"Failed to create hello class.\n");  
		goto destroy_cdev;  
	}          

	/*在/dev/目录和/sys/class/hello目录下分别创建设备文件hello*/  
	temp = device_create(wds_hello_class, NULL, dev, "%s", WDS_HELLO_DEVICE_FILE_NAME);  
	if(IS_ERR(temp)) {  
		err = PTR_ERR(temp);  
		printk(KERN_ALERT"Failed to create hello device.");  
		goto destroy_class;  
	}          

	/*在/sys/class/hello/hello目录下创建属性文件val*/  
	err = device_create_file(temp, &dev_attr_val);  
	if(err < 0) {  
		printk(KERN_ALERT"Failed to create attribute val.");                  
		goto destroy_device;  
	}  

	dev_set_drvdata(temp, wds_hello_dev);          

	/*创建/proc/hello文件*/  
	wds_hello_create_proc();  

	printk(KERN_ALERT"Succedded to initialize hello device.\n");  
	return 0;  

destroy_device:  
	device_destroy(wds_hello_class, dev);  

destroy_class:  
	class_destroy(wds_hello_class);  

destroy_cdev:  
	cdev_del(&(wds_hello_dev->dev));  

cleanup:  
	kfree(wds_hello_dev);  

unregister:  
	unregister_chrdev_region(MKDEV(wds_hello_major, wds_hello_minor), 1);  

fail:  
	return err;  
}  

/*模块卸载方法*/  
static void __exit wds_hello_exit(void) {  
	dev_t devno = MKDEV(wds_hello_major, wds_hello_minor);  

	printk(KERN_ALERT"Destroy hello device.\n");          

	/*删除/proc/hello文件*/  
	wds_hello_remove_proc();          

	/*销毁设备类别和设备*/  
	if(wds_hello_class) {  
		device_destroy(wds_hello_class, MKDEV(wds_hello_major, wds_hello_minor));  
		class_destroy(wds_hello_class);  
	}          

	/*删除字符设备和释放设备内存*/  
	if(wds_hello_dev) {  
		cdev_del(&(wds_hello_dev->dev));  
		kfree(wds_hello_dev);  
	}          

	/*释放设备号*/  
	unregister_chrdev_region(devno, 1);  
}  

MODULE_LICENSE("GPL");  
MODULE_DESCRIPTION("First Android Driver");  

module_init(wds_hello_init);  
module_exit(wds_hello_exit);  

@3 创建Makefile文件并添加一行:

obj-$(CONFIG_WDS_HELLO) += wds_hello.o

@4 创建Kconfig配置文件并添加一行:

config WDS_HELLO
           tristate "wds First Android Driver wds_hello"
           default n
           help
           This is the first android driver

1.2 配置代码

同时,配置对应代码-->kernel/drivers/Kconfig 与 kernel/drivers/Makefile

@1 Kconfig代码添加如下:

menu "Device Drivers"

source "drivers/base/Kconfig"
#...

source "drivers/sensors/Kconfig"
#wds_add
source "drivers/wds_hello/Kconfig"

endmenu

@2 Makefile代码配置添加如下:

#
# Makefile for the Linux kernel device drivers.
#
# 15 Sep 2000, Christoph Hellwig <hch@infradead.org>
# Rewritten to use lists instead of if-statements.
#

# GPIO must come after pinctrl as gpios may need to mux pins etc
obj-y				+= pinctrl/
obj-y				+= gpio/
obj-$(CONFIG_PCI)		+= pci/
obj-$(CONFIG_PARISC)		+= parisc/
obj-$(CONFIG_RAPIDIO)		+= rapidio/
#...
obj-$(CONFIG_CORESIGHT)		+= coresight/

obj-$(CONFIG_BIF)		+= bif/
obj-$(CONFIG_SENSORS)		+= sensors/
#wds add
obj-$(CONFIG_WDS_HELLO)		+= wds_hello/

接下来的配置对应代码-->arch/arm/configs/msm8226-config 与 arch/arm/Kconfig
注:后面的配置主要跟平台有关,上面的是高通平台的修改方案,其余平台参照其内核的编译配置即可

@3 msm8226_defconfig的添加如下:

#...
CONFIG_MSM_RDBG=m 
#carl add for touchpad gesture input 2014 7 18
CONFIG_KEYBOARD_LOE=y
CONFIG_FOR_EVT=y
#CONFIG_FOR_EVB is not set
#config the VGA display for watch strap connect the debug board
#CONFIG_FOR_VGA=y
CONFIG_AVERAGE=y
#CONFIG_FOR_EVT3=y
#wds add
CONFIG_WDS_HELLO=y

Kconifg实现如下:

#...
source "lib/Kconfig"
#wds add
source "drivers/wds_hello/Kconfig"

这里的配置文件和平台关系很大,这里仅给出msm8226平台作为参考。

1.3 编译代码

make bootimage,确保这里无误后才可以继续写demo测试程序

2 编写驱动测试程序(源码见wds_hello_driver)

添加流程如下:

2.1 添加代码

测试代码这里对应位置代码-->external/wds_test,代码实现如下:

#include <stdio.h>  
#include <stdlib.h>  
#include <fcntl.h>  

#define DEVICE_NAME "/dev/wds_hello"  

int main(int argc, char** argv)
{  
	int fd = -1;  
	int val = 0;  
	fd = open(DEVICE_NAME, O_RDWR);  
	if(fd == -1) {  
		printf("Failed to open device %s.\n", DEVICE_NAME);  
		return -1;  
	}  

	printf("Read original value:\n");  
	read(fd, &val, sizeof(val));  
	printf("%d.\n\n", val);  

	if(argc == 2){
		val = atoi(argv[1]);  
	}else{
		val = 3;
	}
	
	printf("Write value %d to %s.\n\n", val, DEVICE_NAME);  
	write(fd, &val, sizeof(val));  

	printf("Read the value again:\n");  
	read(fd, &val, sizeof(val));  
	printf("%d.\n\n", val);  

	close(fd);  
	return 0;  
}  

同时Android.mk实现如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := wds_hello
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)

2.2 编译代码

mmm external/wds_hello

3 编写HAL层代码(源码见wds_hello_hal)

3.1 添加代码

hal_include<--对应代码-->hardware/libhardware/include,代码实现如下:

#ifndef ANDROID_WDS_HELLO_INTERFACE_H  
#define ANDROID_WDS_HELLO_INTERFACE_H  

#include <hardware/hardware.h>  

__BEGIN_DECLS  

/*定义模块ID*/  
#define WDS_HELLO_HARDWARE_MODULE_ID "wds_hello"  

/*硬件模块结构体*/  
struct wds_hello_module_t {  
	struct hw_module_t common;  
};  

/*硬件接口结构体*/  
struct wds_hello_device_t {  
	struct hw_device_t common;  
	int fd;  
	int (*set_val)(struct wds_hello_device_t* dev, int val);  
	int (*get_val)(struct wds_hello_device_t* dev, int* val);  
};  

__END_DECLS  

#endif  

hal_module_wds_hello<--对应代码-->hardware/libhardware/modules/wds_hello/

wds_hello.c代码实现如下:

#define LOG_TAG "WDS_HelloStub"  

#include <hardware/hardware.h>  
#include <hardware/wds_hello.h>  
#include <fcntl.h>  
#include <errno.h>  
#include <cutils/log.h>  
#include <cutils/atomic.h>  

#define DEVICE_NAME "/dev/wds_hello"  
#define MODULE_NAME "wds_hello"  
#define MODULE_AUTHOR "DS-AGS"  

/*设备打开和关闭接口*/  
static int wds_hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);  
static int wds_hello_device_close(struct hw_device_t* device);  

/*设备访问接口*/  
static int wds_hello_set_val(struct wds_hello_device_t* dev, int val);  
static int wds_hello_get_val(struct wds_hello_device_t* dev, int* val);  

/*模块方法表*/  
static struct hw_module_methods_t wds_hello_module_methods = {
	open: wds_hello_device_open
};  

/*模块实例变量*/  
struct wds_hello_module_t HAL_MODULE_INFO_SYM = {  
	common: {  
	tag: HARDWARE_MODULE_TAG,  
	     version_major: 1,  
	     version_minor: 0,  
	     id: WDS_HELLO_HARDWARE_MODULE_ID,  
	     name: MODULE_NAME,  
	     author: MODULE_AUTHOR,  
	     methods: &wds_hello_module_methods,  
	}  
};  
///

static int wds_hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {
	struct wds_hello_device_t* dev;
	dev = (struct wds_hello_device_t*)malloc(sizeof(struct wds_hello_device_t));

	if(!dev) {  
		ALOGE("Hello Stub: failed to alloc space");
		return -EFAULT;
	}

	memset(dev, 0, sizeof(struct wds_hello_device_t));
	dev->common.tag = HARDWARE_DEVICE_TAG;  
	dev->common.version = 0;  
	dev->common.module = (hw_module_t*)module;  
	dev->common.close = wds_hello_device_close;
	dev->set_val = wds_hello_set_val;
	dev->get_val = wds_hello_get_val;

	if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {  
		ALOGE("Hello Stub: failed to open /dev/hello -- %s.", strerror(errno));
		free(dev);
		return -EFAULT;
	}  

	*device = &(dev->common);
	ALOGI("WDS_Hello Stub: open /dev/wds_hello successfully.");

	return 0;  
}  
///

static int wds_hello_device_close(struct hw_device_t* device) {  
	struct wds_hello_device_t* wds_hello_device = (struct wds_hello_device_t*)device;  

	if(wds_hello_device) {  
		close(wds_hello_device->fd);  
		free(wds_hello_device);  
	}  

	return 0;  
}  

static int wds_hello_set_val(struct wds_hello_device_t* dev, int val) {
	ALOGI("WDS_Hello Stub: set value %d to device.", val);
	write(dev->fd, &val, sizeof(val));

	return 0;
}

static int wds_hello_get_val(struct wds_hello_device_t* dev, int* val) {  
	if(!val) {  
		ALOGE("WDS_Hello Stub: error val pointer");  
		return -EFAULT;  
	}  
	read(dev->fd, val, sizeof(*val));  
	ALOGI("WDS_Hello Stub: get value %d from device", *val);  
	return 0;  
}  

同时Android.mk 代码实现如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_SRC_FILES := wds_hello.c
LOCAL_MODULE := wds_hello.default
include $(BUILD_SHARED_LIBRARY)

3.2 配置代码

system_core_rootdir_ueventd_rc<--对应代码--> system/core/rootdir/uevent.rc,uevent.rc代码添加如下:

/dev/null                 0666   root       root
/dev/zero                 0666   root       root
/dev/full                 0666   root       root
/dev/ptmx                 0666   root       root
/dev/tty                  0666   root       root
/dev/random               0666   root       root
/dev/urandom              0666   root       root
/dev/ashmem               0666   root       root
/dev/binder               0666   root       root
/dev/wds_hello			  0666   root		root	//wds add
/dev/touchpad_mode_switch                     0666   root       root // root permission
/dev/touchpanel_switch                        0666   root       root  // permission
//...

3.3 编译代码

mmm hardware/libhardware/modules/wds_hello/;
make snod;

4 编写framework层代码(源码见wds_hello_framework)

添加流程如下:

4.1 添加与修改代码

framework_base_services_jni<--对应代码-->framework/base/services/jni

@1 com_android_server_WDS_HelloService.c代码实现如下:

#include "jni.h"  
#include "JNIHelp.h"  
#include "android_runtime/AndroidRuntime.h"  
#include <utils/misc.h>  
#include <utils/Log.h>  
#include <hardware/hardware.h>  
#include <hardware/wds_hello.h>  
#include <stdio.h>  

#define LOG_TAG "wdsHelloService"  

namespace android  
{  
	/*在硬件抽象层中定义的硬件访问结构体,参考<hardware/hello.h>*/  
	struct wds_hello_device_t* wds_hello_device = NULL;  

	/*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/  
	static void wds_hello_setVal(JNIEnv* env, jobject clazz, jint value) {  
		int val = value;  
		ALOGI("Hello JNI: set value %d to device.", val);  
		if(!wds_hello_device) {  
			ALOGI("Hello JNI: device is not open.");  
			return;  
		}  

		wds_hello_device->set_val(wds_hello_device, val);  
	}  

	/*通过硬件抽象层定义的硬件访问接口读取硬件寄存器val的值*/  
	static jint wds_hello_getVal(JNIEnv* env, jobject clazz) {  
		int val = 0;  
		if(!wds_hello_device) {  
			ALOGI("Hello JNI: device is not open.");  
			return val;  
		}  
		wds_hello_device->get_val(wds_hello_device, &val);

		ALOGI("Hello JNI: get value %d from device.", val);  

		return val;  
	}  
	/*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/  
	static inline int wds_hello_device_open(const hw_module_t* module, struct wds_hello_device_t** device) {
		return module->methods->open(module, WDS_HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device); 
	}  
	/*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/  
	static jboolean wds_hello_init(JNIEnv* env, jclass clazz) {  
		wds_hello_module_t* module;  

		ALOGI("WDS_Hello JNI: initializing......");  
		if(hw_get_module(WDS_HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {  
			ALOGI("WDS_Hello JNI: hello Stub found.");  
			if(wds_hello_device_open(&(module->common), &wds_hello_device) == 0) {  
				ALOGI("WDS_Hello JNI: hello device is open.");  
				return 0;  
			}  
			ALOGE("WDS_Hello JNI: failed to open hello device.");  
			return -1;  
		}  
		ALOGE("WDS_Hello JNI: failed to get hello stub module.");  
		return -1;        
	}  

	/*JNI方法表*/  
	static const JNINativeMethod method_table[] = {  
		{"init_native", "()Z", (void*)wds_hello_init},  
		{"setVal_native", "(I)V", (void*)wds_hello_setVal},  
		{"getVal_native", "()I", (void*)wds_hello_getVal},  
	};  

	/*注册JNI方法*/  
	int register_android_server_WDS_HelloService(JNIEnv *env) {  
		return jniRegisterNativeMethods(env, "com/android/server/WDS_HelloService", method_table, NELEM(method_table));  
	}  
};  

@2 onload.cpp代码添加如下:

#include "JNIHelp.h"
#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"

namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_ConsumerIrService(JNIEnv *env);
//...
int register_android_server_WDS_HelloService(JNIEnv *env);//wds add
};

using namespace android;

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_PowerManagerService(env);
    register_android_server_SerialService(env);
    //...
    register_android_server_WDS_HelloService(env); //wds add
    return JNI_VERSION_1_4;
}

Android.mk代码添加如下:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
    com_android_server_AlarmManagerService.cpp \
    #...
    com_android_server_WDSHelloService.cpp \
    onload.cpp
#...

framework_base_core_java_android_os<--对应代码-->framework/base/core/java/android/os

IWDSHelloService.aidl的实现如下所示:

package android.os;  

interface IWDSHelloService {  
	void setVal(int val);  
	int getVal();  
}  

@3 framework_base<--对应代码-->framework/base/Android.mk

代码添加如下:

LOCAL_SRC_FILES += \
	core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
#...	
	core/java/android/os/IWDSHelloService.aidl \
#...

4.2 编译代码生成stub类

mmm framework/base/services/jni;
mmm framework/base/core/java/android/os;
mmm framework/base;
make snod;

4.3 添加代码

framework_base_services_java<--对应代码-->framework/base/services/java,生成的service如下所示:

package com.android.server;  

import android.content.Context;  
import android.os.IWDSHelloService;  
import android.util.Slog;  

public class WDSHelloService extends IWDSHelloService.Stub {  
	private static final String TAG = "WDSHelloService";
  
	WDSHelloService() {  
		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中添加代码:

//...
			try {
				Slog.i(TAG, "Print Service");
				printManager = new PrintManagerService(context);
				ServiceManager.addService(Context.PRINT_SERVICE, printManager);
			} catch (Throwable e) {
				reportWtf("starting Print Service", e);
			}

			if (!disableNonCoreServices) {
				try {
					Slog.i(TAG, "Media Router Service");
					mediaRouter = new MediaRouterService(context);
					ServiceManager.addService(Context.MEDIA_ROUTER_SERVICE, mediaRouter);
				} catch (Throwable e) {
					reportWtf("starting MediaRouterService", e);
				}
			}

			try {
				Slog.i(TAG, "WDS_Hello Service");
				ServiceManager.addService("wds_hello", new WDSHelloService());
			} catch (Throwable e) {
				Slog.e(TAG, "Failure starting WDS Hello Service", e);
			}
		}
//...

因为每个版本代码是不一样的,只要在服务启动项中添加 即可。

4.4 整体编译

 make snod

5 编写APP demo测试服务(源码见wds_hello_APP)

5.1 android studio中添加代码

wds_hello_APP<--对应代码-->packages/apps/wds_hello

package com.ags.wds;

//import com.ags.wds.R;
import android.app.Activity;
import android.os.ServiceManager; 
import android.os.IWDSHelloService; 
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {
	private final static String LOG_TAG = "com.ags.wds_Hello";

	private IWDSHelloService wdshelloService = null;

	private EditText valueText = null;
	private Button readButton = null;
	private Button writeButton = null;
	private Button clearButton = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		wdshelloService = IWDSHelloService.Stub.asInterface(ServiceManager.getService("wds_hello"));

		valueText = (EditText) findViewById(R.id.edit_value);
		readButton = (Button) findViewById(R.id.button_read);
		writeButton = (Button) findViewById(R.id.button_write);
		clearButton = (Button) findViewById(R.id.button_clear);

		readButton.setOnClickListener(this);
		writeButton.setOnClickListener(this);
		clearButton.setOnClickListener(this);

		Log.i(LOG_TAG, "WDS Hello Activity Created");
	}

	@Override
	public void onClick(View v) {
		if (v.equals(readButton)) {
			try {
				int val = wdshelloService.getVal();
				String text = String.valueOf(val);
				valueText.setText(text);
			} catch (RemoteException e) {
				Log.e(LOG_TAG,"Remote Exception while reading value from device.");
			}
		} else if (v.equals(writeButton)) {
			try {
				String text = valueText.getText().toString();
				int val = Integer.parseInt(text);
				wdshelloService.setVal(val);
			} catch (RemoteException e) {
				Log.e(LOG_TAG,"Remote Exception while writing value to device.");
			}
		} else if (v.equals(clearButton)) {
			String text = "";
			valueText.setText(text);
		}
	}
}

同时activity_main.xml文件如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/value" >
        </TextView>

        <EditText
            android:id="@+id/edit_value"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/hint" >
        </EditText>
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/button_read"
            style="?android:attr/buttonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/read" >
        </Button>

        <Button
            android:id="@+id/button_write"
            style="?android:attr/buttonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/write" >
        </Button>

        <Button
            android:id="@+id/button_clear"
            style="?android:attr/buttonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/clear" >
        </Button>
    </LinearLayout>

</LinearLayout>

这里 Android.mk文件实现如下:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := wds_Hello
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))

同时APP demo其他文件自动生成。

5.2 编译代码

mmm packages/apps/wds_hello

6 总结

工程整体框架如下所示://wds_modules in android
├── wds_hello_APP
│   ├── AndroidManifest.xml
│   ├── Android.mk
│   ├── ic_launcher-web.png
│   ├── proguard-project.txt
│   ├── project.properties
│   ├── res
│   │   ├── drawable-hdpi
│   │   │   └── ic_launcher.png
│   │   ├── drawable-ldpi
│   │   ├── drawable-mdpi
│   │   │   └── ic_launcher.png
│   │   ├── drawable-xhdpi
│   │   │   └── ic_launcher.png
│   │   ├── drawable-xxhdpi
│   │   │   └── ic_launcher.png
│   │   ├── layout
│   │   │   └── activity_main.xml
│   │   ├── menu
│   │   │   └── main.xml
│   │   ├── values
│   │   │   ├── dimens.xml
│   │   │   ├── strings.xml
│   │   │   └── styles.xml
│   │   ├── values-v11
│   │   │   └── styles.xml
│   │   ├── values-v14
│   │   │   └── styles.xml
│   │   └── values-w820dp
│   │       └── dimens.xml
│   └── src
│       └── com
│           └── ags
│               └── wds
│                   └── MainActivity.java
├── wds_hello_framework
│   ├── framework_base
│   │   └── Android.mk
│   ├── framework_base_core_java_android_os
│   │   └── IWDSHelloService.aidl
│   ├── framework_base_services_java
│   │   ├── SystemServer.java
│   │   └── WDS_HelloService.java
│   └── framework_base_services_jni
│       ├── Android.mk
│       ├── com_android_server_WDS_HelloService.cpp
│       └── onload.cpp
├── wds_hello_hal
│   ├── hal_include
│   │   └── wds_hello.h
│   ├── hal_module_wds_hello
│   │   ├── Android.mk
│   │   └── wds_hello.c
│   └── system_core_rootdir_ueventd_rc
│        └── ueventd.rc
└── wds_hello_driver
    ├── cfg_arch_arm_Kconfig_msm8226-config
    │   ├── Kconfig
    │   └── msm8226_defconfig
    ├── cfg_drivers_Kconfig_Makefile
    │   ├── Kconfig
    │   └── Makefile
    ├── driver_wds_hello
    │   ├── Kconfig
    │   ├── Makefile
    │   ├── wds_hello.c
    │   └── wds_hello.h
    └── driver_wds_test
        ├── Android.mk
        └── wds_hello.c

本文主要以实用为主,主要描述了Android系统如何添加一个全新模块的流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值