1. 程式人生 > >第1課第4.4節_Android硬件訪問服務編寫HAL代碼

第1課第4.4節_Android硬件訪問服務編寫HAL代碼

更新 編寫 services 指定版本 open ext which module .sh


4 編寫HAL代碼

源碼下載方法
第一次:
git clone https://github.com/weidongshan/SYS_0001_LEDDemo.git
更新:
git pull origin
取出指定版本:
git checkout v1 // 有JNI沒有HAL
git checkout v2 // 有JNI,HAL
git checkout v3 // add MODULE TAG, DEVICE TAG

技術分享

技術分享

JNI 向上提供本地函數, 向下加載HAL文件並調用HAL的函數
HAL 負責訪問驅動程序執行硬件操作

dlopen

external\chromium_org\third_party\hwcplus\src\hardware.c (參考代碼)
hw_get_module("led")

1. 模塊名==>文件名
hw_get_module_by_class("led", NULL)
name = "led"
property_get xxx是某個屬性
hw_module_exists 判斷是否存在led.xxx.so


它用來判斷"name"."subname".so文件是否存在
查找的目錄:
a. HAL_LIBRARY_PATH 環境變量

技術分享

b. /vendor/lib/hw

c. /system/lib/hw

技術分享

技術分享

/vendor/lib/hw 這個目錄下沒有文件,tiny4412所以只能去/system/lib/hw這個目錄下找

技術分享

技術分享

2. 加載
load
dlopen(filename)
dlsym("HMI") 從SO文件中獲得名為HMI的hw_module_t結構體
strcmp(id, hmi->id) 判斷名字是否一致(hmi->id, "led")

V2:
(3) JNI: 重新上傳
frameworks/base/services/core/jni/com_android_server_LedService.cpp

(4) HAL: led_hal.h
led_hal.c
把新文件上傳到服務器, 所在目錄:
hardware/libhardware/include/hardware/led_hal.h

hardware/libhardware/modules 在這個目錄下創建一個目錄led,放入led_hal.c和自己寫一個Android.mk

hardware/libhardware/modules/led/led_hal.c
hardware/libhardware/modules/led/Android.mk

Android.mk內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := led.default
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_C_INCLUDES := hardware/libhardware
LOCAL_SRC_FILES := led_hal.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := eng

include $(BUILD_SHARED_LIBRARY)


編譯:

技術分享

$ mmm frameworks/base/services
$ mmm hardware/libhardware/modules/led
$ make snod
$ ./gen-img.sh

技術分享

最終生成system.img文件


打印信息簡介:
a. 有三類打印信息: app, system, radio
程序裏使用 ALOGx, SLOGx, RLOGx來打印
b. x表示6種打印級別,有:
V Verbose
D Debug
I Info
W Warn
E Error
F Fatal

比如:
#define LOG_TAG "LedHal"
ALOGI("led_open : %d", fd);

c. 打印出來的格式為:
I/LedHal ( 1987): led_open : 65
(級別) LOG_TAG 進程號 打印信息

d. 使用 logcat 命令查看
logcat LedHal:I *:S

選出自己感興趣的信息:

技術分享

和上一個章節相比,主要修改了

com_android_server_LedService.cpp

添加了led_hal.h led_hal.c Android.mk

com_android_server_LedService.cpp

#define LOG_TAG "LedService"

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"

#include <utils/misc.h>
#include <utils/Log.h>

#include <stdio.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <hardware/led_hal.h>


namespace android
{

static led_device_t* led_device;

jint ledOpen(JNIEnv *env, jobject cls)
{
    jint err;
    hw_module_t* module;
    hw_device_t* device;

    ALOGI("native ledOpen ...");

    /* 1. hw_get_module */
    err = hw_get_module("led", (hw_module_t const**)&module);
    if (err == 0) {
        /* 2. get device : module->methods->open */
        err = module->methods->open(module, NULL, &device);
        if (err == 0) {
            /* 3. call led_open */
            led_device = (led_device_t *)device;
            return led_device->led_open(led_device);
        } else {
            return -1;
        }
    }
    
    return -1;    
}

void ledClose(JNIEnv *env, jobject cls)
{
    //ALOGI("native ledClose ...");
    //close(fd);
}


jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
{
    ALOGI("native ledCtrl %d, %d", which, status);
    return led_device->led_ctrl(led_device, which, status);
}


static const JNINativeMethod methods[] = {
    {"native_ledOpen", "()I", (void *)ledOpen},
    {"native_ledClose", "()V", (void *)ledClose},
    {"native_ledCtrl", "(II)I", (void *)ledCtrl},
};
    

int register_android_server_LedService(JNIEnv *env)
{
    return jniRegisterNativeMethods(env, "com/android/server/LedService",
            methods, NELEM(methods));
}

}

led_hal.c

#define LOG_TAG "LedHal"


/* 1. 實現一個名為HMI的hw_module_t結構體 */

/* 2. 實現一個open函數, 它返回led_device_t結構體 */

/* 3. 實現led_device_t結構體 */

/* 參考 hardware\libhardware\modules\vibrator\vibrator.c
 */

#include <hardware/vibrator.h>
#include <hardware/hardware.h>

#include <cutils/log.h>

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include <hardware/led_hal.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <utils/Log.h>


static int fd;


/** Close this device */
static int led_close(struct hw_device_t* device)
{
    close(fd);
    return 0;
}

static int led_open(struct led_device_t* dev)
{
    fd = open("/dev/leds", O_RDWR);
    ALOGI("led_open : %d", fd);
    if (fd >= 0)
        return 0;
    else
        return -1;
}

static int led_ctrl(struct led_device_t* dev, int which, int status)
{
    int ret = ioctl(fd, status, which);
    ALOGI("led_ctrl : %d, %d, %d", which, status, ret);
    return ret;
}




static struct led_device_t led_dev = {
    .common = {
        .tag   = HARDWARE_DEVICE_TAG,
        .close = led_close,
    },
    .led_open  = led_open,
    .led_ctrl  = led_ctrl,
};

static int led_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 = led_device_open,
};

struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .id = "led",
    .methods = &led_module_methods,
};

led_hal.h

#ifndef ANDROID_LED_INTERFACE_H
#define ANDROID_LED_INTERFACE_H

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

#include <hardware/hardware.h>

__BEGIN_DECLS

struct led_device_t {
    struct hw_device_t common;

    int (*led_open)(struct led_device_t* dev);
    int (*led_ctrl)(struct led_device_t* dev, int which, int status);
};


__END_DECLS

#endif  // ANDROID_LED_INTERFACE_H

第1課第4.4節_Android硬件訪問服務編寫HAL代碼