ADROID 2.1 架构解析 3 亮度设置

2024-01-02 18:58

本文主要是介绍ADROID 2.1 架构解析 3 亮度设置,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

3 亮度设置

3.1 应用设计

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

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;

}

这篇关于ADROID 2.1 架构解析 3 亮度设置的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/563355

相关文章

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门

Spring三级缓存解决循环依赖的解析过程

《Spring三级缓存解决循环依赖的解析过程》:本文主要介绍Spring三级缓存解决循环依赖的解析过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、循环依赖场景二、三级缓存定义三、解决流程(以ServiceA和ServiceB为例)四、关键机制详解五、设计约

Redis实现分布式锁全解析之从原理到实践过程

《Redis实现分布式锁全解析之从原理到实践过程》:本文主要介绍Redis实现分布式锁全解析之从原理到实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、背景介绍二、解决方案(一)使用 SETNX 命令(二)设置锁的过期时间(三)解决锁的误删问题(四)Re

CentOS和Ubuntu系统使用shell脚本创建用户和设置密码

《CentOS和Ubuntu系统使用shell脚本创建用户和设置密码》在Linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设置密码,本文写了一个shell... 在linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

Python利用ElementTree实现快速解析XML文件

《Python利用ElementTree实现快速解析XML文件》ElementTree是Python标准库的一部分,而且是Python标准库中用于解析和操作XML数据的模块,下面小编就来和大家详细讲讲... 目录一、XML文件解析到底有多重要二、ElementTree快速入门1. 加载XML的两种方式2.

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

java解析jwt中的payload的用法

《java解析jwt中的payload的用法》:本文主要介绍java解析jwt中的payload的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解析jwt中的payload1. 使用 jjwt 库步骤 1:添加依赖步骤 2:解析 JWT2. 使用 N