Android4.0 LCD和键盘 背光亮度设置

亮度设置
应用设计
1.1 设置进度条范围
背光设置是在:设置->声音和显示->亮度,通过进度条来设置的。

文件:
packages/apps/Settings/src/com/Android/settings/BrightnessPreference.java
private static final int MINIMUM_BACKLIGHT = Android.os.Power.BRIGHTNESS_DIM + 10;
private static final int MAXIMUM_BACKLIGHT = Android.os.Power.BRIGHTNESS_ON;

mSeekBar.setMax(MAXIMUM_BACKLIGHT - MINIMUM_BACKLIGHT);

设置进度条的范围,BRIGHTNESS_DIM = 20  BRIGHTNESS_ON=255,它们的定义在:

frameworks/base/core/java/Android/os/Power.java

1.2 设置亮度
文件:packages/apps/Settings/src/com/Android/settings/BrightnessPreference.java
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

       setMode(isChecked ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC

                : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);

        if (!isChecked) {

            setBrightness(mSeekBar.getProgress() + MINIMUM_BACKLIGHT);

        }

    }

private void setBrightness(int brightness) {

        try {

            IPowerManager power = IPowerManager.Stub.asInterface(

                    ServiceManager.getService("power"));

            if (power != null) {

                power.setBacklightBrightness(brightness);

            }

        } catch (RemoteException doe) {

           

        }       

}

由以上代码可知,brightness的范围是:20~255;代码通过服务管理器(ServiceManager)获得power服务,然后通过power服务设置亮度。

power.setBacklightBrightness的定义在:

rameworks/base/core/java/Android/os/IPowerManager.aidl.java

frameworks/base/core/java/Android/os/PowerManager.java

2, Power服务
文件:frameworks/base/core/java/Android/os/Power.java

/**

     * Brightness value for dim backlight

     */

    public static final int BRIGHTNESS_DIM = 20;

    /**

     * Brightness value for fully on

     */

public static final int BRIGHTNESS_ON = 255;

文件:frameworks/base/core/java/Android/os/PowerManager.java
/**

     * sets the brightness of the backlights (screen, keyboard, button).

     *

     * @param brightness value from 0 to 255

     *

     * {@hide}

     */

    public void setBacklightBrightness(int brightness)

    {

        try {

            mService.setBacklightBrightness(brightness);

        } catch (RemoteException e) {

        }

}

电源管理器(powermager)将brightness转给电源服务,该服务位置如下:

文件:frameworks/base/services/java/com/android/server/PowerManagerService.java +2934
public void setBacklightBrightness(int brightness) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
        // Don't let applications turn the screen all the way off
        synchronized (mLocks) {
            brightness = Math.max(brightness, mScreenBrightnessDim);
            mLcdLight.setBrightness(brightness);
            mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
            mButtonLight.setBrightness(brightness);
            long identity = Binder.clearCallingIdentity();
            try {
                mBatteryStats.noteScreenBrightness(brightness);
            } catch (RemoteException e) {
                Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }

            // update our animation state
            synchronized (mLocks) {
                mScreenBrightness.targetValue = brightness;
                mScreenBrightness.jumpToTargetLocked();
            }
        }
    }


由以上代码可知,同时设置了背光、键盘、按钮的亮度。mHardware 是硬件服务,通过该服务调用底层与设备打交道的C\C++代码,setLightBrightness_UNCHECKED原型如下:

文件:frameworks/base/services/java/com/android/server/LightsService.java

        public void setBrightness(int brightness, int brightnessMode) {
            synchronized (this) {
                Resources resources = mContext.getResources();
                int mScreenBrightnessDim = resources.getInteger(
                        com.android.internal.R.integer.config_screenBrightnessDim);
                brightness = Math.max(brightness, mScreenBrightnessDim);

                int color = brightness & 0x000000ff;
                color = 0xff000000 | (color << 16) | (color << 8) | color;
                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
            }
        }


参数说明:int light 表示类型,选项如下:

static final int LIGHT_ID_BACKLIGHT = 0;

    static final int LIGHT_ID_KEYBOARD = 1;

    static final int LIGHT_ID_BUTTONS = 2;
    static final int LIGHT_ID_BATTERY = 3;

    static final int LIGHT_ID_NOTIFICATIONS = 4;

static final int LIGHT_ID_ATTENTION = 5;

int brightness 表示亮度值

int brightnessMode 表示亮度的控制模式,选项如下:

/**

     * Light brightness is managed by a user setting.

     */

    static final int BRIGHTNESS_MODE_USER = 0;

    /**

     * Light brightness is managed by a light sensor.

     */

static final int BRIGHTNESS_MODE_SENSOR = 1;

由代码:

int b = brightness & 0x000000ff;

        b = 0xff000000 | (b << 16) | (b << | b;

可知,亮度值在此进行了修改,即亮度值的格式变成:FFRRGGBB,FF是没有的,RR、GG、BB分别是256色的红绿蓝,并且红绿蓝的值都是一样的亮度值。

3 硬件调用
3.1获取硬件
文件:frameworks/base/services/jni/com_android_server_LightsService.cpp +129
static jint init_native(JNIEnv *env, jobject clazz)
{
    int err;
    hw_module_t* module;
    Devices* devices;

    devices = (Devices*)malloc(sizeof(Devices));

    err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
    if (err == 0) {
        devices->lights[LIGHT_INDEX_BACKLIGHT]
                = get_device(module, LIGHT_ID_BACKLIGHT);
        devices->lights[LIGHT_INDEX_KEYBOARD]
                = get_device(module, LIGHT_ID_KEYBOARD);
        devices->lights[LIGHT_INDEX_BUTTONS]
                = get_device(module, LIGHT_ID_BUTTONS);
        devices->lights[LIGHT_INDEX_BATTERY]
                = get_device(module, LIGHT_ID_BATTERY);
        devices->lights[LIGHT_INDEX_NOTIFICATIONS]
                = get_device(module, LIGHT_ID_NOTIFICATIONS);
        devices->lights[LIGHT_INDEX_ATTENTION]
                = get_device(module, LIGHT_ID_ATTENTION);
        devices->lights[LIGHT_INDEX_BLUETOOTH]
                = get_device(module, LIGHT_ID_BLUETOOTH);
        devices->lights[LIGHT_INDEX_WIFI]
                = get_device(module, LIGHT_ID_WIFI);
    } else {
        memset(devices, 0, sizeof(Devices));
    }

    return (jint)devices;
}


用hw_get_module获取ID为LIGHTS_HARDWARE_MODULE_ID的硬件模块,该模块含有6个不同类型的亮度控制。

hw_get_module 的实现原理,如下:

文件:hardware/libhardware/Hardware.c
#define HAL_LIBRARY_PATH "/system/lib/hw"

static const char *variant_keys[] = {

    "ro.hardware",  /* This goes first so that it can pick up a different

                       file on the emulator. */

    "ro.product.board",

    "ro.board.platform",

    "ro.arch"

};

static const int HAL_VARIANT_KEYS_COUNT =

    (sizeof(variant_keys)/sizeof(variant_keys[0]));

int hw_get_module_by_class(const char *class_id, const char *inst,
                           const struct hw_module_t **module)
{
    int status;
    int i;
    const struct hw_module_t *hmi = NULL;
    char prop[PATH_MAX];
    char path[PATH_MAX];
    char name[PATH_MAX];

    if (inst)
        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
    else
        strlcpy(name, class_id, PATH_MAX);

    /*
     * Here we rely on the fact that calling dlopen multiple times on
     * the same .so will simply increment a refcount (and not load
     * a new copy of the library).
     * We also assume that dlopen() is thread-safe.
     */

    /* Loop through the configuration variants looking for a module */
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
        if (i < HAL_VARIANT_KEYS_COUNT) {
            if (property_get(variant_keys[i], prop, NULL) == 0) {
                continue;
            }
            snprintf(path, sizeof(path), "%s/%s.%s.so",
                     HAL_LIBRARY_PATH2, name, prop);
            if (access(path, R_OK) == 0) break;

            snprintf(path, sizeof(path), "%s/%s.%s.so",
                     HAL_LIBRARY_PATH1, name, prop);
            if (access(path, R_OK) == 0) break;
        } else {
            snprintf(path, sizeof(path), "%s/%s.default.so",
                     HAL_LIBRARY_PATH1, name);
            if (access(path, R_OK) == 0) break;
        }
    }

    status = -ENOENT;
    if (i < HAL_VARIANT_KEYS_COUNT+1) {
        /* load the module, if this fails, we're doomed, and we should not try
         * to load a different variant. */
        status = load(class_id, path, module);
    }

    return status;
}

int hw_get_module(const char *id, const struct hw_module_t **module)
{
    return hw_get_module_by_class(id, NULL, module);
}

}

property_get(variant_keys[i], prop, NULL) 会按如下顺序去获取如下变量所对应的值,然后返回给prop:

"ro.hardware",  /* This goes first so that it can pick up a different

                       file on the emulator. */

    "ro.product.board",

    "ro.board.platform",

"ro.arch"

它们对应的变量为:

"ro.product.board=$TARGET_BOOTLOADER_BOARD_NAME"

"ro.board.platform=$TARGET_BOARD_PLATFORM"

如vendor/htc/dream-open/BoardConfig.mk里定义的TARGET_BOARD_PLATFORM := msm7k,则prop返回” msm7k ”,所以path = /system/lib/hw/lights. msm7k.so,也就是说要获取的硬件模块为lights. msm7k.so。

3.2调用硬件

setLight_native对应的jni C/C++代码是:

文件:frameworks/base/frameworks/base/services/jni/com_android_server_LightsService.cpp

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);
}


通过light标识找到对应的light设备,然后再设置亮度。

3.3 硬件原型
msm7k的lights对应的硬件原型是在:hardware/msm7k/liblights

文件:hardware/msm7k/liblights/Android.mk

LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw

LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)

也就是生成模块:/system/lib/hw/lights. msm7k.so

文件:device/softwinner/crane-common/hardware/libhardware/lights/lights.c
/** Open a new instance of a lights device using name */
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);

    LOGD("open_lights!name = %s\n",name);
    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_context_t *dev = (struct light_context_t *)malloc(sizeof(struct light_context_t));
    memset(dev, 0, sizeof(struct light_context_t));

    LOGD("light set back linghts!name = %s\n",name);

        if(0 == strcmp(LIGHT_ID_BACKLIGHT, name))
    {
        dev->fd = open("/dev/disp", O_RDONLY);
        if (dev->fd < 0)
        {
            LOGE("Failed to open display device dev->fd = %x\n",dev->fd);
        }
    }

    dev->device.common.tag = HARDWARE_DEVICE_TAG;
    dev->device.common.version = 0;
    dev->device.common.module = (struct hw_module_t*)module;
    dev->device.common.close = (int (*)(struct hw_device_t*))close_lights;
    dev->device.set_light = set_light;

    *device = (struct hw_device_t*)dev;

    return 0;

error:
    free(dev);

    return -EINVAL;
}


static struct hw_module_methods_t lights_module_methods = {

    .open =  open_lights,

};

以上代码对应的是:

devices->lights[LIGHT_INDEX_BACKLIGHT]

                = get_device(module, LIGHT_ID_BACKLIGHT);

        devices->lights[LIGHT_INDEX_KEYBOARD]

                = get_device(module, LIGHT_ID_KEYBOARD);

        devices->lights[LIGHT_INDEX_BUTTONS]

                = get_device(module, LIGHT_ID_BUTTONS);

        devices->lights[LIGHT_INDEX_BATTERY]

                = get_device(module, LIGHT_ID_BATTERY);

        devices->lights[LIGHT_INDEX_NOTIFICATIONS]

                = get_device(module, LIGHT_ID_NOTIFICATIONS);

        devices->lights[LIGHT_INDEX_ATTENTION]

                = get_device(module, LIGHT_ID_ATTENTION);

也就是说,对不同的亮度设置给予了不同的设置函数。

举例,背光设置,背光对应的代码如下:
static int
rgb_to_brightness(struct light_state_t const* state)
{
    int color = state->color & 0x00ffffff;
    int bright;

    bright = ((77*((color>>16)&0x00ff)) + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;

    //support backlight 0-255
//    bright = bright >> 4;


        /* fix bright value >=5 , for HW reason*/
        if(bright < 5)
                bright = 5;

    return bright;
}



static int
set_light_backlight(struct light_device_t* dev,
        struct light_state_t const* state)
{
    struct light_context_t      *ctx;

    int err = 0;

    int brightness = rgb_to_brightness(state);

    pthread_mutex_lock(&g_lock);
    g_backlight = brightness;
    ctx = (struct light_context_t *)dev;
    unsigned long  args[3];

        args[0]  = 0;
        args[1]  = brightness;
        args[2]  = 0;
        err = ioctl(ctx->fd,DISP_CMD_LCD_SET_BRIGHTNESS,args);

        if(err == 0)
        {
                g_backlight = brightness;
        }

    pthread_mutex_unlock(&g_lock);

    return err;
}



然后驱动层
vendor/softwinner/linux-3.0/drivers/video/sun4i/disp/dev_disp.c

vendor/softwinner/linux-3.0/drivers/video/sun4i/disp/de_bsp/de/disp_lcd.c +1739



写寄存器


__s32 pwm_set_duty_ns(__u32 channel, __u32 duty_ns)
{
    __u32 active_cycle = 0;
    __u32 tmp;

    active_cycle = (duty_ns * gdisp.pwm[channel].entire_cycle + (gdisp.pwm[channel].period_ns/2)) / gdisp.pwm[channel].period_ns;

    if(channel == 0)
    {
            tmp = pwm_read_reg(0x204);
        pwm_write_reg(0x204,(tmp & 0xffff0000) | active_cycle);
    }
    else
    {
            tmp = pwm_read_reg(0x208);
        pwm_write_reg(0x208,(tmp & 0xffff0000) | active_cycle);
    }

    gdisp.pwm[channel].duty_ns = duty_ns;

    DE_INF("%d,%d,%d,%d\n", duty_ns, gdisp.pwm[channel].period_ns, active_cycle, gdisp.pwm[channel].entire_cycle);
    return 0;
}


//.....

static __s32 pwm_write_reg(__u32 offset, __u32 value)
{
    sys_put_wvalue(gdisp.init_para.base_pwm+offset, value);

    LCD_delay_ms(20);

    return 0;
}





你可能感兴趣的:(c,android,jni)