该系列文章总纲链接: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系统如何添加一个全新模块的流程。