博客
关于我
android系统核心机制 基础(09)Android 添加新模块
阅读量:522 次
发布时间:2019-03-07

本文共 24847 字,大约阅读时间需要 82 分钟。

该系列文章总纲链接:


本章关键点总结 & 说明:

这里主要关注➕右下角部分 添加新模块即可。本章节详细解读了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 
#include
#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 
#include
#include
#include
#include
#include
#include
#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_addsource "drivers/wds_hello/Kconfig"endmenu

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

## Makefile for the Linux kernel device drivers.## 15 Sep 2000, Christoph Hellwig 
# Rewritten to use lists instead of if-statements.## GPIO must come after pinctrl as gpios may need to mux pins etcobj-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 addobj-$(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 18CONFIG_KEYBOARD_LOE=yCONFIG_FOR_EVT=y#CONFIG_FOR_EVB is not set#config the VGA display for watch strap connect the debug board#CONFIG_FOR_VGA=yCONFIG_AVERAGE=y#CONFIG_FOR_EVT3=y#wds addCONFIG_WDS_HELLO=y

Kconifg实现如下:

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

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

1.3 编译代码

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

2 编写驱动测试程序(源码见wds_hello_driver),添加流程如下:

2.1 添加代码
测试代码这里对应位置代码-->external/wds_test

代码实现如下:

#include 
#include
#include
#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 := optionalLOCAL_MODULE := wds_helloLOCAL_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 
__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 
#include
#include
#include
#include
#include
#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 := optionalLOCAL_PRELINK_MODULE := falseLOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hwLOCAL_SHARED_LIBRARIES := liblog libcutilsLOCAL_SRC_FILES := wds_hello.cLOCAL_MODULE := wds_hello.defaultinclude $(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 
#include
#include
#include
#include
#define LOG_TAG "wdsHelloService" namespace android { /*在硬件抽象层中定义的硬件访问结构体,参考
*/ 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文件如下所示:

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

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optionalLOCAL_SRC_FILES := $(call all-subdir-java-files)LOCAL_PACKAGE_NAME := wds_Helloinclude $(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系统如何添加一个全新模块的流程。

转载地址:http://tpnnz.baihongyu.com/

你可能感兴趣的文章
mysql 权限整理记录
查看>>
mysql 权限登录问题:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)
查看>>
MYSQL 查看最大连接数和修改最大连接数
查看>>
MySQL 查看有哪些表
查看>>
mysql 查看锁_阿里/美团/字节面试官必问的Mysql锁机制,你真的明白吗
查看>>
MySql 查询以逗号分隔的字符串的方法(正则)
查看>>
MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT 、分页查询的优化、合理使用连接、子查询的优化)(上)
查看>>
mysql 查询,正数降序排序,负数升序排序
查看>>
MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)...
查看>>
mysql 死锁 Deadlock found when trying to get lock; try restarting transaction
查看>>
mysql 死锁(先delete 后insert)日志分析
查看>>
MySQL 死锁了,怎么办?
查看>>
MySQL 深度分页性能急剧下降,该如何优化?
查看>>
MySQL 深度分页性能急剧下降,该如何优化?
查看>>
MySQL 添加列,修改列,删除列
查看>>
mysql 添加索引
查看>>
MySQL 添加索引,删除索引及其用法
查看>>
MySQL 用 limit 为什么会影响性能?
查看>>
MySQL 用 limit 为什么会影响性能?有什么优化方案?
查看>>
MySQL 用户权限管理:授权、撤销、密码更新和用户删除(图文解析)
查看>>