1. 燈光硬體抽象層(HAL):
有關LED HAL的定義在android_source\hardware\libhardware\include\hardware\lights.h的檔案中,在該檔案中可以看到定義struct light_state_t的資料結構,來儲存燈光的狀態。另一個資料結構struct light_device_t則定義set_light的函式,其完整的定如下:
struct light_device_t {
struct hw_device_t common;
/**
* Set the provided lights to the provided values.
*
* Returns: 0 on succes, error code on failure.
*/
int (*set_light)(struct light_device_t* dev,
struct light_state_t const* state);
};
2. 實作燈號系統函式庫(.so):在android_source\hardware\msm7k\liblights\目錄下可以看到lights.c及Android.mk兩個檔案,前者是實現硬體抽象層的系統檔案,而後者則提供編譯資訊。我們以處理追蹤球燈號為例,其原始程式如下:
static int
handle_trackball_light_locked(struct light_device_t* dev)
{
int mode = g_attention;
if (mode == 7 && g_backlight) {
mode = 0;
}
LOGV("%s g_backlight = %d, mode = %d, g_attention = %d\n",
__func__, g_backlight, mode, g_attention);
// If the value isn't changing, don't set it, because this
// can reset the timer on the breathing mode, which looks bad.
if (g_trackball == mode) {
return 0;
}
return write_int(TRACKBALL_FILE, mode);
}
上述程式中會呼叫write_int函式來和底層驅動溝通,利用open函式來開啟驅動並用write函式來進行控制。
static int
write_int(char const* path, int value)
{
int fd;
static int already_warned = 0;
fd = open(path, O_RDWR);
if (fd >= 0) {
char buffer[20];
int bytes = sprintf(buffer, "%d\n", value);
int amt = write(fd, buffer, bytes);
close(fd);
return amt == -1 ? -errno : 0;
} else {
if (already_warned == 0) {
LOGE("write_int failed to open %s\n", path);
already_warned = 1;
}
return -errno;
}
}
何時會點亮追蹤球燈號呢?當手機有通知事件要通知使用者時,我們可以用set_light_notifications函式來設定追蹤球燈號。
static int
set_light_notifications(struct light_device_t* dev,
struct light_state_t const* state)
{
pthread_mutex_lock(&g_lock);
g_notification = *state;
LOGV("set_light_notifications g_trackball=%d color=0x%08x",
g_trackball, state->color);
if (g_haveTrackballLight) {
handle_trackball_light_locked(dev);
}
handle_speaker_battery_locked(dev);
pthread_mutex_unlock(&g_lock);
return 0;
}
以上的程式是說明定義在硬體抽象層中的set_light如何和系統函式庫相互連結。
static int open_lights(const struct hw_module_t* module, char const* name,
struct hw_device_t** device)
{
int (*set_light)(struct light_device_t* dev,
struct light_state_t const* state);
if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
set_light = set_light_backlight;
}
else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {
set_light = set_light_keyboard;
}
else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
set_light = set_light_buttons;
}
else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {
set_light = set_light_battery;
}
else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
set_light = set_light_notifications;
}
else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {
set_light = set_light_attention;
}
else {
return -EINVAL;
}
pthread_once(&g_init, init_globals);
struct light_device_t *dev = malloc(sizeof(struct light_device_t));
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t*)module;
dev->common.close = (int (*)(struct hw_device_t*))close_lights;
dev->set_light = set_light;
*device = (struct hw_device_t*)dev;
return 0;
}
3. Java/C JNI介面函式:在android_source\frameworks\base\services\jni目錄下,可以找到com_android_server_HardwareService.cpp檔案,您可以發現JNINativeMethod method_table陣列及register_android_server_HardwareService函式,利用此兩項資訊來註冊硬體相關服務。
static JNINativeMethod method_table[] = {
{ "init_native", "()I", (void*)init_native },
{ "finalize_native", "(I)V", (void*)finalize_native },
{ "setLight_native", "(IIIIIII)V", (void*)setLight_native },
{ "vibratorOn", "(J)V", (void*)vibratorOn },
{ "vibratorOff", "()V", (void*)vibratorOff }
};
int register_android_server_HardwareService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/HardwareService",
method_table, NELEM(method_table));
}
在上述資訊中,我們可以看到setLight_native函式,其程式列表如下:
static void setLight_native(JNIEnv *env, jobject clazz, int ptr,
int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode)
{
Devices* devices = (Devices*)ptr;
light_state_t state;
if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
return ;
}
memset(&state, 0, sizeof(light_state_t));
state.color = colorARGB;
state.flashMode = flashMode;
state.flashOnMS = onMS;
state.flashOffMS = offMS;
state.brightnessMode = brightnessMode;
devices->lights[light]->set_light(devices->lights[light], &state);
}
上述的set_light就定義在硬體抽象層中。
4. Java服務軟體實作:在android_source\frameworks\base\services\java\com\android\server目錄下,HardwareService.java實作硬體服務的程式,該程式定義HardwareService並繼承IHardwareService.Stub介面,在該程式中可以呼叫setLight_native函式來連結JNI層的軟體。
public class HardwareService extends IHardwareService.Stub {
private static final String TAG = "HardwareService";
:
:
private static native int init_native();
private static native void finalize_native(int ptr);
private static native void setLight_native(int ptr, int light, int color, int mode,
int onMS, int offMS, int brightnessMode);
}
以上簡略說明從底層硬體抽象層、系統函式庫層、JNI介面層、及Java服務層,相信您對如何在Google Android平台中控制硬體已有初步的瞭解。
有關LED HAL的定義在android_source\hardware\libhardware\include\hardware\lights.h的檔案中
回覆刪除這檔案哪裡有提供??
Google 提供的 Android Source Code, http://source.android.com/source/downloading.html
回覆刪除