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;

    }

  • 相关阅读:
    OpenCV使用边缘提取、腐蚀、轮廓进行车牌定位
    How To Move Or Rebuild A Lob Partition
    Hadoop入门进阶步步高(三)-配置Hadoop
    [学习笔记]整体DP
    leetcode404
    leetcode349
    leetcode383
    leetcode453
    leetcode455
    leetcode167
  • 原文地址:https://www.cnblogs.com/liang123/p/6325486.html
Copyright © 2011-2022 走看看