Android system :灯光系统_HAL_lights

一、android灯光系统框架:

Java: frameworks/base/services/core/java/com/android/server/lights/LightsService.java
JNI: frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp
Hal: lights.c

默认配色:frameworks/base/core/res/res/values/config.xml
电池灯:frameworks/base/services/core/java/com/android/server/BatteryService.java
通知灯:frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java

怎么写LIGHTS HAL
a. 实现一个名为HMI的hw_module_t结构体
b. 实现一个open函数, 它会根据name返回一个light_device_t结构体
c. 实现多个light_device_t结构体,每一个对应一个DEVICE
light_device_t结构体里第1个成员是hw_device_t结构体, 紧接着一个set_light函数

二、代码lights.c:

/*
 * Copyright (C) 2008 The Android Open Source Project
 * Copyright (C) 2011 Diogo Ferreira <[email protected]>
 * Copyright (C) 2012 Andreas Makris <[email protected]>
 * Copyright (C) 2012 The CyanogenMod Project <http://www.cyanogenmod.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_NDEBUG 0
#define LOG_TAG "lights"
#include <cutils/log.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <hardware/lights.h>

char const*const RED_LED_FILE             = "/sys/class/leds/led1/brightness";
char const*const GREEN_LED_FILE         = "/sys/class/leds/led2/brightness";
char const*const BLUE_LED_FILE             = "/sys/class/leds/led3/brightness";
char const*const RED_LED_FILE_TRIGGER    = "/sys/class/leds/led1/trigger";
char const*const GREEN_LED_FILE_TRIGGER    = "/sys/class/leds/led2/trigger";
char const*const BLUE_LED_FILE_TRIGGER    = "/sys/class/leds/led3/trigger";
char const*const RED_LED_FILE_DELAYON    = "/sys/class/leds/led1/delay_on";
char const*const GREEN_LED_FILE_DELAYON    = "/sys/class/leds/led2/delay_on";
char const*const BLUE_LED_FILE_DELAYON    = "/sys/class/leds/led3/delay_on";
char const*const RED_LED_FILE_DELAYOFF    = "/sys/class/leds/led1/delay_off";
char const*const GREEN_LED_FILE_DELAYOFF= "/sys/class/leds/led2/delay_off";
char const*const BLUE_LED_FILE_DELAYOFF    = "/sys/class/leds/led3/delay_off";
char const*const LCD_BACKLIGHT_FILE     = "/dev/backlight-1wire";

/* Synchronization primities */
static pthread_once_t g_init = PTHREAD_ONCE_INIT;
static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
/* Mini-led state machine */
static struct light_state_t g_notification;
static struct light_state_t g_battery;

static int write_int (const char *path, int value) {
    int fd;
    static int already_warned = 0;
    fd = open(path, O_RDWR);
    if (fd < 0) {
        if (already_warned == 0) {
            ALOGE("write_int failed to open %s\n", path);
            already_warned = 1;
        }
        return -errno;
    }
    char buffer[20];
    int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
    int written = write (fd, buffer, bytes);
    close(fd);
    return written == -1 ? -errno : 0;
}
static int write_string (const char *path, const char *value) {
    int fd;
    static int already_warned = 0;
    fd = open(path, O_RDWR);
    if (fd < 0) {
        if (already_warned == 0) {
            ALOGE("write_string failed to open %s\n", path);
            already_warned = 1;
        }
        return -errno;
    }
    char buffer[20];
    int bytes = snprintf(buffer, sizeof(buffer), "%s\n", value);
    int written = write (fd, buffer, bytes);
    close(fd);
    return written == -1 ? -errno : 0;
}
/* Color tools */
static int is_lit (struct light_state_t const* state) {
    return state->color & 0x00ffffff;
}
static int rgb_to_brightness (struct light_state_t const* state) {
    int color = state->color & 0x00ffffff;
    return ((77*((color>>16)&0x00ff))
            + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
}
/* The actual lights controlling section */
static int set_light_backlight (struct light_device_t *dev, struct light_state_t const *state) {
    int brightness = rgb_to_brightness(state);
    ALOGV("%s brightness=%d color=0x%08x", __func__,brightness,state->color);
    pthread_mutex_lock(&g_lock);

    /* brightness 0-255 */
    /* LCD_BACKLIGHT_FILE能接收是0-127 */

    write_int (LCD_BACKLIGHT_FILE, brightness/2);

    pthread_mutex_unlock(&g_lock);
    return 0;
}
static void set_shared_light_locked (struct light_device_t *dev, struct light_state_t *state) {
    int r, g, b;
    int delayOn,delayOff;
    r = (state->color >> 16) & 0xFF;
    g = (state->color >> 8) & 0xFF;
    b = (state->color) & 0xFF;
    delayOn = state->flashOnMS;
    delayOff = state->flashOffMS;
    if (state->flashMode != LIGHT_FLASH_NONE) {
        write_string (RED_LED_FILE_TRIGGER, "timer");
        write_string (GREEN_LED_FILE_TRIGGER, "timer");
        write_string (BLUE_LED_FILE_TRIGGER, "timer");
        write_int (RED_LED_FILE_DELAYON, delayOn);
        write_int (GREEN_LED_FILE_DELAYON, delayOn);
        write_int (BLUE_LED_FILE_DELAYON, delayOn);
        write_int (RED_LED_FILE_DELAYOFF, delayOff);
        write_int (GREEN_LED_FILE_DELAYOFF, delayOff);
        write_int (BLUE_LED_FILE_DELAYOFF, delayOff);
    } else {
        write_string (RED_LED_FILE_TRIGGER, "none");
        write_string (GREEN_LED_FILE_TRIGGER, "none");
        write_string (BLUE_LED_FILE_TRIGGER, "none");
    }
    write_int (RED_LED_FILE, r);
    write_int (GREEN_LED_FILE, g);
    write_int (BLUE_LED_FILE, b);
}
static void handle_shared_battery_locked (struct light_device_t *dev) {
    if (is_lit (&g_notification)) {
        set_shared_light_locked (dev, &g_notification);
    } else {
        set_shared_light_locked (dev, &g_battery);
    }
}
static int set_light_battery (struct light_device_t *dev, struct light_state_t const* state) {

    ALOGV("%s flashMode=%d onMS = %d offMS = %d color=0x%08x", __func__,state->flashMode,state->flashOnMS,state->flashOffMS,state->color);

    pthread_mutex_lock (&g_lock);
    g_battery = *state;
    handle_shared_battery_locked(dev);
    pthread_mutex_unlock (&g_lock);
    return 0;
}
static int set_light_notifications (struct light_device_t *dev, struct light_state_t const* state) {
    ALOGV("%s flashMode=%d onMS = %d offMS = %d color=0x%08x", __func__,state->flashMode,state->flashOnMS,state->flashOffMS,state->color);
    pthread_mutex_lock (&g_lock);
    g_notification = *state;
    handle_shared_battery_locked(dev);
    pthread_mutex_unlock (&g_lock);
    return 0;
}
/* Initializations */
void init_globals () {
    pthread_mutex_init (&g_lock, NULL);
}
/* Glueing boilerplate */
static int close_lights (struct light_device_t *dev) {
    if (dev)
        free(dev);
    return 0;
}
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_BATTERY, name)) {
        set_light = set_light_battery;
    }
    else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
        set_light = set_light_notifications;
    }
    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;
}
static struct hw_module_methods_t lights_module_methods = {
    .open = open_lights,
};
struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .version_major = 1,
    .version_minor = 0,
    .id = LIGHTS_HARDWARE_MODULE_ID,
    .name = "Sony lights module",
    .author = "Diogo Ferreira <[email protected]>, Andreas Makris <[email protected]>",
    .methods = &lights_module_methods,
};

三、Android.mk

# Copyright (C) 2012 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := lights.tiny4412

# HAL module implementation stored in
# hw/<VIBRATOR_HARDWARE_MODULE_ID>.default.so
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_C_INCLUDES := hardware/libhardware
LOCAL_SRC_FILES := lights.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := eng

include $(BUILD_SHARED_LIBRARY)
时间: 2024-08-03 03:30:19

Android system :灯光系统_HAL_lights的相关文章

The behavior of App killed or restored by Android System or by users

What's the behavior of App killed or restored by Android System or by users? First, user kills the app by swiping out the screen The DEMO process is killed and activity stack is cleared. And the system will relaunch the DEMO process automatically.  W

Android System分区大小异常

平台:Freescale / Android 4.2.2 问题描述: 用 df 命令,看到/system分区大小275M. 用 busybox fdisk -l /dev/block/mmcblk0p5,看到 536M. Freescale的刷机工具是Mfgtool,分区的动作在mksdcard-android.sh里面完成. SYSTEM_ROM_SIZE=512 dd if=/dev/zero of=${node} bs=1024 count=1 sfdisk --force -uM ${n

Forms Android System Download

1 不用自己写下载文件的功能,直接调用系统下载服务 2 forms 接口 3 4 using System; 5 using System.Collections; 6 using System.Collections.Generic; 7 8 namespace 9 { 10 public interface ISystemDownloadFile 11 { 12 //下载文件 13 void DownloadThread (string strUrl,string str1); 14 } 1

Android System Property 解析

一 System Property 今天在折腾HDMI 显示这块的时候,为Setting提供接口时候,遇到很多跟Android系统属性相关的问题.因此,顺便分析和总结一些. android的代码中大量存在:SystemProperties.set()/SystemProperties.get():通过这两个接口可以对系统的属性进行读取/设置, 顾名思义系统属性,肯定对整个系统全局共享.通常程序的执行以进程为单位各自相互独立,如何实现全局共享呢? System Properties是怎么一回事,又

Android System ANR caused SWT restart issue

一.问题现象 1.用户直观看到的现象是System先ANR. 2.ANR之后系统重启. 测试方法: 在录音的界面不停的滑动音量进度条,同时座机给测试机打电话,电话没有接通,只见界面冻结,弹出ANR,接着系统重启. Platform:MT6732 Android版本:4.4.4KK BuildType:user 系统软件版本:SWA3A+UMA0 系统RAM:1GB 问题概率:≈2% 参考机行为: 1.低概率问题,暂无参考机行为. 二.解决方案 通过初步分析.深入分析(具体分析过程.关键代码和lo

android system service 系统服务列表

1 public abstract Object getSystemService(String name); 2 3 /** 4 * Use with {@link #getSystemService} to retrieve a 5 * {@link android.os.PowerManager} for controlling power management, 6 * including "wake locks," which let you keep the device

Android System trace分析

Systrace的原理:它的思想很朴素,在系统的一些关键链路(比如System Service,虚拟机,Binder驱动)插入一些信息(我这里称之为Label),通过Label的开始和结束来确定某个核心过程的执行时间,然后把这些Label信息收集起来得到系统关键路径的运行时间信息,进而得到整个系统的运行性能信息.Android Framework里面一些重要的模块都插入了Label信息(Java层的通过android.os.Trace类完成,native层通过ATrace宏完成),用户App中可

【工利其器】工具使用之(三)Android System Trace篇

systrace工具打开路径 以AndroidStudio(后面简写为AS),在顶部菜单栏中 Tools>Android>Android Device Monitor 打开后看到如下界面,鼠标停在红框图标上,会显示“Capture system wide trace using Android systrace”,这个图标即Android systrace的入口. 或者点击下图的倒三角,会显示下拉列表,红框中“Capture System Wide Trace"这一项,和上面一样,也

【工利其器】工具使用之(四)Android System Trace篇(1)官网翻译

前言 Android 开发者官网中对该工具有专门的介绍,本篇文章作为System Trace系列的开头,笔者先不做任何介绍,仅仅翻译一下官网的介绍.在后续的文章中再整理一份学习教程,以及笔者的实践经历.官网中对System Trace的介绍文档路径为[https://developer.android.google.cn/studio/command-line/systrace?hl=en#java].或者在进入到官网的首页后,按照Android Studio > USER GUIDE > C