android系统核心机制 基础(09)Android(安卓)添加新模块
该系列文章总纲链接: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 #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 modifydev->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 rootroot//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;@Overrideprotected 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");}@Overridepublic 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系统如何添加一个全新模块的流程。
更多相关文章
- [置顶] Android实用代码集
- Android打电话,挂电话
- R.stamp Error 1
- Android(安卓)应用程序主动请求Vsync
- Android菜鸟笔记-获取设备信息
- Android开发常见问题 不定期更新。开发环境Android(安卓)Studio
- android http中请求访问添加 cookie
- Android(安卓)反射获得控件对象
- Android(安卓)添加菜单