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

更多相关文章

  1. [置顶] Android实用代码集
  2. Android打电话,挂电话
  3. R.stamp Error 1
  4. Android(安卓)应用程序主动请求Vsync
  5. Android菜鸟笔记-获取设备信息
  6. Android开发常见问题 不定期更新。开发环境Android(安卓)Studio
  7. android http中请求访问添加 cookie
  8. Android(安卓)反射获得控件对象
  9. Android(安卓)添加菜单

随机推荐

  1. android 中android:id="@android:id/list
  2. html5 开发 android 注意点
  3. android 计算器简单加法实现
  4. Android(安卓)Application
  5. android中自带的主题(theme)的集
  6. Android计算器开发实例
  7. android设置头像
  8. TextView跑马灯效果
  9. Android显示图片(非绑定)
  10. android官方资料