zoukankan      html  css  js  c++  java
  • android backlight

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

    文件: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

    3.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

    3.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

    public void setBacklightBrightness(int brightness) {

            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);

            // Don't let applications turn the screen all the way off

            brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);

            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness,

                    HardwareService.BRIGHTNESS_MODE_USER);

            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,

                (mKeyboardVisible ? brightness : 0), HardwareService.BRIGHTNESS_MODE_USER);

            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness,

                HardwareService.BRIGHTNESS_MODE_USER);

            long identity = Binder.clearCallingIdentity();

            try {

                mBatteryStats.noteScreenBrightness(brightness);

            } catch (RemoteException e) {

                Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);

            } finally {

                Binder.restoreCallingIdentity(identity);

            }

     

            // update our animation state

            if (ANIMATE_SCREEN_LIGHTS) {

                mScreenBrightness.curValue = brightness;

                mScreenBrightness.animating = false;

                mScreenBrightness.targetValue = -1;

            }

            if (ANIMATE_KEYBOARD_LIGHTS) {

                mKeyboardBrightness.curValue = brightness;

                mKeyboardBrightness.animating = false;

                mKeyboardBrightness.targetValue = -1;

            }

            if (ANIMATE_BUTTON_LIGHTS) {

                mButtonBrightness.curValue = brightness;

                mButtonBrightness.animating = false;

                mButtonBrightness.targetValue = -1;

            }

        }

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

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

    void setLightBrightness_UNCHECKED(int light, int brightness, int brightnessMode) {

            int b = brightness & 0x000000ff;

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

            setLight_native(mNativePointer, light, b, 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 << 8) | b;

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

    3.3 硬件调用

    3.3.1获取硬件

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

    enum {

        LIGHT_INDEX_BACKLIGHT = 0,

        LIGHT_INDEX_KEYBOARD = 1,

        LIGHT_INDEX_BUTTONS = 2,

        LIGHT_INDEX_BATTERY = 3,

        LIGHT_INDEX_NOTIFICATIONS = 4,

        LIGHT_INDEX_ATTENTION = 5,

        LIGHT_COUNT

    };

     

    #define LIGHTS_HARDWARE_MODULE_ID "lights"

     

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

        } 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(const char *id, 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];

     

        /*

         * 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_PATH, id, prop);

            } else {

                snprintf(path, sizeof(path), "%s/%s.default.so",

                        HAL_LIBRARY_PATH, id);

            }

            if (access(path, R_OK)) {

                continue;

            }

            /* we found a library matching this id/variant */

            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(id, path, module);

        }

     

        return status;

    }

    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.3.2调用硬件

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

    文件:frameworks/base/services/jni/com_android_server_HardwareService.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.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

     

    文件:hardware/msm7k/liblights/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);

     

        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;

    }

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

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

    举例,背光设置,背光对应的代码如下:

    char const*const LCD_FILE

            = "/sys/class/leds/lcd-backlight/brightness";

    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;

    }

    static int

    set_light_backlight(struct light_device_t* dev,

            struct light_state_t const* state)

    {

        int err = 0;

        int brightness = rgb_to_brightness(state);

        pthread_mutex_lock(&g_lock);

        g_backlight = brightness;

        err = write_int(LCD_FILE, brightness);

        if (g_haveTrackballLight) {

            handle_trackball_light_locked(dev);

        }

        pthread_mutex_unlock(&g_lock);

        return err;

    }

    也就是往文件/sys/class/leds/lcd-backlight/brightness写入亮度值,然后驱动会根据该文件更改背光的亮度。LCD_FILE的路径根据实际情况更改,同时需要在init.rc 修改其权限,使其可写rgb_to_brightness也根据实际更改,比如要直接亮度值控制,那只要获取r,g,b其中的一个值就行了,如:

    static int

    rgb_to_brightness(struct light_state_t const* state)

    {

        int color = state->color & 0x000000ff;

        return color;

    }

  • 相关阅读:
    POJ3320 Jessica's Reading Problem
    POJ3320 Jessica's Reading Problem
    CodeForces 813B The Golden Age
    CodeForces 813B The Golden Age
    An impassioned circulation of affection CodeForces
    An impassioned circulation of affection CodeForces
    Codeforces Round #444 (Div. 2) B. Cubes for Masha
    2013=7=21 进制转换
    2013=7=15
    2013=7=14
  • 原文地址:https://www.cnblogs.com/LoongEmbedded/p/5298437.html
Copyright © 2011-2022 走看看