安卓硬件服务程序框架

参考Vibrator来写:

1、.aidl程序

形如:

package android.os;

interface ILedsService {
     int ledCtrl(int which, int status);
}

这是应用程序需要用到的函数,应用程序不需要open

2、将ILedsService.aidl放到/work/android-5.0.2/frameworks/base/core/java/android/os目录下

     修改base/Android.mk:

添加:core/java/android/os/ILedsService.aidl \

执行mm命令之前一定要先编译安卓系统

执行命令: mm   编译当前目录下的模块,当前目录要有Android.mk文件

mmm <dir>   编译指定目录下的模块,指定目录下要有Android.mk文件

得到ILedsService.java代码

3、应用程序

修改SystemServer.java,添加: 

             Slog.i(TAG, "Leds Service");
             ServiceManager.addService("leds", new LedsService());

新建LedsService.java:

package com.android.server;
import android.os.ILedsService;
public class LedsService extends ILedsService.Stub
         {
    private static final String TAG = "LedsService";

    public LedsService() {
          native_ledOpen();
    }
    public int ledCtrl(int which, int status)throws android.os.RemoteException{
           return naitve_ledCtrl(which, status);
    }
    public native int native_ledOpen();
    public native void native_ledClose();
    public native int naitve_ledCtrl(int which, int status);
};

4、JNI接口(向上提供本地函数和加载HAL并调用HAL里的函数):

#define LOG_TAG "LedsService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/Leds.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <hardware/leds_hal.h>
namespace android
{
 jnit err;
 
 struct leds_device_t* led_dev;
 jint ledOpen(JNIEnv *env, jobject cls)
 {
     struct hw_module_t *module;
  struct hw_device_t* dev;
  err = hw_get_module("leds", (const struct hw_module_t **)&module);
  if (err == 0)
   err = module->methods->open(module,NULL,&dev);
      if (err == 0) {
                 led_dev = (struct leds_device_t*)dev;
     err = led_dev->led_open(led_dev);
       
   }
    
  return err;
 }
 
 jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
 {
      return led_dev->led_ctrl(led_dev, status, which);
 }
 
 void ledClose(JNIEnv *env, jobject cls)
 {
  
 }
 
 static JNINativeMethod gMethods[] ={
  {"native_ledCtrl", "(II)I", (void *)ledCtrl},
  {"native_ledOpen", "()I", (void *)ledOpen},
  {"native_ledClose", "()V", (void *)ledClose},
 };

int register_android_server_LedsService(JNIEnv *env)
{
    return jniRegisterNativeMethods(env, "com/android/server/LedsService",
            gMethods, NELEM(gMethods));
}
};

5、HAL(硬件抽象层:负责访问驱动程序执行硬件操作)

#include <hardware/hardware.h>
#include <cutils/log.h>
#include <android/log.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <hardware/leds_hal.h>
//#define LOG_TAG "Led_Hal" static int fd; int led_close(struct leds_device_t* device) { close(fd); ALOGI("native ledClose\n"); return 0; } int led_open(struct leds_device_t* device) { fd = open("/dev/LED0", O_RDWR); if (fd < 0) return -1; ALOGI("native ledOpen\n"); return 0; } int led_ctrl(struct leds_device_t* device, int which, int status) { int ret = ioctl(fd, status, which); if (ret < 0) return -1; ALOGI("native ledCtrl: %d %d\n", which, status); return 0; } struct leds_device_t led_dev = { .common = { .close = led_close, }, .led_open = led_open, .led_ctrl = led_ctrl, }; int leds_device_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device) { *device = &led_dev; return 0; } static struct hw_module_methods_t led_module_methods = { .open = leds_device_open, }; struct hw_module_t HAL_MODULE_INFO_SYM = { .id = "leds", .methods = &led_module_methods, };
#ifndef _LEDS_HAL_H
#define _LEDS_HAL_H

#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <hardware/hardware.h>

__BEDIN_DECLS struct leds_device_t { struct hw_device_t common; int (*led_open)(struct leds_device_t *dev); int (*led_ctrl)(struct leds_device_t *dev, int which, int status); }; __END_DECLS #endif

6、修改Onload.cpp:

 添加: int register_android_server_LedsService(JNIEnv *env); 以及

register_android_server_LedsService(env);

编译android-5.0.2(mmm frameworks/base/services      ./gen-img.sh),得到system.img映像文件

7、APP

以上修改的都是系统,APP在Android Studio 里面编写,需要import Android.os.ILedsService

private ILedsService iLedsService;

iLedsService = ILedsService.stab.asInterface(ServiceManager.getService("leds"));

调用iLedsService.ledCrtl(which,status);

但Android Studio并不知道有ILedsService这个接口,所以需要包含out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar

target Java: framework (out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes)

 在build.gradle下添加:

dexOptions {
javaMaxHeapSize"4g"
}
defaultConfig {
applicationId "com.example.zhu.zhu_first"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
+ multiDexEnabled true
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:22.1.1'
compile project(':classes')
+ compile 'com.android.support:multidex:1.0.0'
}
在AndroidManifest.xml里添加:android:name="android.support.multidex.MultiDexApplication"
dex文件是Android平台上可执行文件的类型,Android Studio 会对包含的jar文件转换成dex文件,而当DEX文件里面的方法超过
65535时(DEX文件里的方法数目是用short类型索引的,short类型最多65535),就得用multidex了。
对于Android DEX文件进行优化,需要注意的一点是DEX文件的结构是紧凑的,
但是我们还是要想方设法的进行提高程序的运行速度,我们就仍然需要对DEX文件进行进一步优化
调整所有字段的字节序(LITTLE_ENDIAN)和对齐结构中的每一个域 验证DEX文件中的所有类 对一些特定的类进行优化,对方法里的操作码进行优化 。
优化后的文件大小会有所增加,应该是原Android DEX文件的1-4倍。 优化发生的时机有两个:对于预置应用,可以在系统编译后,生成优化文件,以ODEX结尾
这样做可以加快软件的启动速度,预先提取,减少对RAM的占用,因为没有odex的话,系统要从apk包中提取dex再运行

8、底层驱动

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
 
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>

static int major;
static struct class *led_class;

static int led_gpios[] = {
    EXYNOS4212_GPM4(0),
    EXYNOS4212_GPM4(1),
    EXYNOS4212_GPM4(2),
    EXYNOS4212_GPM4(3),
};

static int PIN_NUM = sizeof(led_gpios)/sizeof(led_gpios[0]);

static int leds_open(struct inode *inode, struct file *file)
{
   int i;
   for (i = 0; i < 4; i++) {
        s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);
   }
   return 0;
}


static long leds_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
{       
        if (cmd != 0 && cmd !=1)
            return EINVAL;
        if (arg > 3)
            return EINVAL;
        gpio_set_value(led_gpios[arg], !cmd);
        return 0;
}

struct file_operations leds_ops = {
        .owner = THIS_MODULE,
        .open = leds_open,
        .unlocked_ioctl = leds_ioctl,
};

int leds_init(void)
{
   major = register_chrdev(0, "led", &leds_ops);
   led_class = class_create(THIS_MODULE, "led");
   device_create(led_class, NULL, MKDEV(major,0), 0, "LED0");
   
   return 0;
}

void leds_exit(void)
{
    device_destroy(led_class, MKDEV(major,0));
    class_destroy(led_class);
}

module_init(leds_init);
module_exit(leds_exit);

MODULE_LICENSE("GPL");

放入linux内核drivers/char下,修改Makefile

编译出zImage: make zImage

9、程序执行过程:

SystemServer.java里的main方法-->run方法-->

// Initialize native services.
        System.loadLibrary("android_servers");    -->加载C库,调用onload.cpp

 

posted @ 2019-03-06 20:54  一条水煮鱼  阅读(376)  评论(0编辑  收藏  举报