先来看MTK官方给出的Lights(光)架构图:

图1

这是MTK 2011年的图,下面给出MT6575/6577中此部分的框架图:

图2

再来看更体现一些细节的框架图:

图3

由此可见光系统从上到下依次分为java APP层、java 框架层、本地层和驱动层。下面就来看APP层,先给出调节背光的应用界面:

图4

此功能在settings--->display--->brightness下面,可知有自动调节和手动调节背光亮度的功能,其中手动是通过进度条(slider)来调节的,此应用对应的布局文件为\packages\apps\Settings\res\layout\preference_dialog_brightness.xml

1.     Lights应用层

1.1   设置背光亮度调节范围

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. \packages\apps\Settings\src\com\android\settings\BrightnessPreference.java
  2. // Backlight range is from 0 - 255. Need tomake sure that user
  3. // doesn't set the backlight to 0 and getstuck
  4. private int mScreenBrightnessDim =
  5. getContext().getResources().getInteger(com.android.internal.R.integer.config_screenBrightnessDim);
  6. private staticfinal int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON;
  7. @Override
  8. protected void onBindDialogView(View view){
  9. super.onBindDialogView(view);
  10. mSeekBar = getSeekBar(view);
  11. mSeekBar.setMax(MAXIMUM_BACKLIGHT -mScreenBrightnessDim);
  12. mOldBrightness = getBrightness(0);
  13. mSeekBar.setProgress(mOldBrightness -mScreenBrightnessDim);
  14. mCheckBox =(CheckBox)view.findViewById(R.id.automatic_mode);
  15. if (mAutomaticAvailable) {
  16. mCheckBox.setOnCheckedChangeListener(this);
  17. mOldAutomatic =getBrightnessMode(0);
  18. mCheckBox.setChecked(mOldAutomatic!= 0);
  19. else {
  20. mCheckBox.setVisibility(View.GONE);
  21. }
  22. mSeekBar.setOnSeekBarChangeListener(this);
  23. }

(1)         getContext().getResources().getInteger(com.android.internal.R.integer.config_screenBrightnessDim)的值

在\frameworks\base\core\res\res\values\config.xml下赋值,如下:

[html] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <!-- Minimumscreen brightness allowed by the power manager. -->
  2. <integernameintegername="config_screenBrightnessDim">20</integer>

可见背光亮度最小值是20,不能设置为0,否则会关闭背光的显示。

(2)          android.os.Power.BRIGHTNESS_ON的值

在\frameworks\base\core\java\android\os\Power.java中定义:

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /**
  2. * Brightness value for fully off
  3. */
  4. public static final int BRIGHTNESS_OFF = 0;
  5. /**
  6. * Brightness value for dim backlight
  7. */
  8. public static final int BRIGHTNESS_DIM =20;
  9. /**
  10. * Brightness value for fully on
  11. */
  12. public static final int BRIGHTNESS_ON =255;
  13. /**
  14. * Brightness value to use when battery islow
  15. */
  16. public staticfinal int BRIGHTNESS_LOW_BATTERY = 10;

由此可见设置的背光亮度调节范围为20~255。

1.2   设置背光亮度

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public voidonProgressChanged(SeekBar seekBar, int progress,
  2. boolean fromTouch) {
  3. setBrightness(progress +mScreenBrightnessDim);
  4. }
  5. progress表示滑动条的值。
  6. private void setBrightness(int brightness) {
  7. try {
  8. IPowerManager power =IPowerManager.Stub.asInterface(
  9. ServiceManager.getService("power"));
  10. //Only set backlight value whenscreen is on
  11. if (power != null &&power.isScreenOn()) {
  12. power.setBacklightBrightness(brightness);
  13. }
  14. catch (RemoteException doe) {
  15. }
  16. }

通过ServiceManager获得power服务,然后通过power服务设置背光亮度

1.3   背光亮度初始值

frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private voidloadSystemSettings(SQLiteDatabase db) {
  2. SQLiteStatement stmt = null;
  3. try {
  4. ……….
  5. loadIntegerSetting(stmt,Settings.System.SCREEN_BRIGHTNESS,
  6. R.integer.def_screen_brightness);
  7. loadBooleanSetting(stmt,Settings.System.SCREEN_BRIGHTNESS_MODE,
  8. R.bool.def_screen_brightness_automatic_mode);
  9. ……………..
  10. finally {
  11. if (stmt != null) stmt.close();
  12. }
  13. }

def_screen_brightness的值在下面定义:

\frameworks\base\packages\SettingsProvider\res\values\ defaults.xml

[html] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <integernameintegername="def_screen_brightness">102</integer>
  2. <boolnameboolname="def_screen_brightness_automatic_mode">false</bool>

可知默认亮度值为102

2.     Lights框架层(java框架层和antive框架层)

接着1.2节,设备背光亮度的power.setBacklightBrightness() 在文件

\frameworks\base\core\java\android\os\IPowerManager.aidl中定义,如下:

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. interfaceIPowerManager
  2. {
  3. ……
  4. // sets the brightness of thebacklights (screen, keyboard, button) 0-255
  5. void setBacklightBrightness(intbrightness);
  6. void setBacklightBrightnessOff(booleanenable);
  7. void setMaxBrightness(int brightness);
  8. ……….
  9. }

IPowerManager.aidl,android系统提供了一种描述语言来定义具有跨进程访问能力的服务接口,这种描述语言称为Android接口描述语言(Android Interface Definition Language, AIDL)。以AIDL定义的服务接口文件以aidl为后缀名,在编译是,编译系统会将它们转换成java文件,这是需要在\frameworks\base\Android.mk

文件中添加对应的aidl文件,才会转换为java文件的,如:

[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. LOCAL_SRC_FILES +=\
  2. ……………
  3. core/java/android/os/IPermissionController.aidl\
  4. core/java/android/os/IPowerManager.aidl\
  5. core/java/android/os/IRemoteCallback.aidl\
  6. …………….

然后再对它们进行编译。通常用于访问硬件的服务接口定义在\frameworks\base\core\java\android\os下。

IPowerManager只是提供服务的接口,具体的实在

frameworks\base\core\java\android\os\PowerManager.java中,如下:

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /**
  2. * sets the brightness of the backlights(screen, keyboard, button).
  3. *
  4. * @param brightness value from 0 to 255
  5. *
  6. * {@hide}
  7. */
  8. public void setBacklightBrightness(intbrightness)
  9. {
  10. try {
  11. mService.setBacklightBrightness(brightness);
  12. catch (RemoteException e) {
  13. }

这里调用PowerManagerService的接口,

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. frameworks\base\services\java\com\android\server\PowerManagerService.java,如下:
  2. public void setBacklightBrightness(intbrightness) {
  3. mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,null);
  4. // Don't let applications turn thescreen all the way off
  5. synchronized (mLocks) {
  6. brightness = Math.max(brightness,mScreenBrightnessDim);
  7. if (mMaxBrightness > 0) {
  8. if (brightness >mMaxBrightness) {
  9. brightness =mMaxBrightness;
  10. }
  11. }
  12. mLcdLight.setBrightness(brightness);
  13. //We won't adjust Button/KeyboardBKL here for the time being, see CR[ALPS00132847]
  14. //mKeyboardLight.setBrightness(mKeyboardVisible? brightness : 0);
  15. //mButtonLight.setBrightness(brightness);
  16. long identity =Binder.clearCallingIdentity();
  17. try {
  18. mBatteryStats.noteScreenBrightness(brightness);
  19. catch (RemoteException e) {
  20. Slog.w(TAG,"RemoteException calling noteScreenBrightness onBatteryStatsService", e);
  21. finally {
  22. Binder.restoreCallingIdentity(identity);
  23. }
  24. // update our animation state
  25. synchronized (mLocks) {
  26. mScreenBrightness.targetValue =brightness;
  27. mScreenBrightness.jumpToTargetLocked();
  28. }
  29. }
  30. }

(1)  mLcdLight赋值

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. …………..
  2. static final int LIGHT_ID_BACKLIGHT = 0;
  3. static final intLIGHT_ID_KEYBOARD = 1;
  4. static final intLIGHT_ID_BUTTONS = 2;
  5. static final intLIGHT_ID_BATTERY = 3;
  6. mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT);

(2)  setBrightness()

此函数位于frameworks\base\services\java\com\android\server\LightsService.java下,调用setBrightness()--->setLightLocked()--->setLight_native()。

LightsService.java声明的本地方法,也就是JNI接口函数有:

[java] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private staticnative int init_native();
  2. private static native voidfinalize_native(int ptr);
  3. private static native void setLight_native(intptr, int light, int color, int mode,
  4. int onMS, int offMS, intbrightnessMode);

这些本地方法在

frameworks\base\services\jni\com_android_server_LightsService.cpp下实现,先来看Andorid Java 和 C 函数的映射表数组:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. staticJNINativeMethod method_table[] = {
  2. "init_native""()I",(void*)init_native },
  3. "finalize_native","(I)V", (void*)finalize_native },
  4. "setLight_native","(IIIIIII)V", (void*)setLight_native },
  5. };

JNINativeMethod结构体在dalvik\libnativehelper\include\nativehelper\jni.h

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. typedef struct {
  2. const char* name;
  3. const char*signature;
  4. void* fnPtr;
  5. } JNINativeMethod;

第一个变量name是Java中函数的名字。

第二个变量signature,用字符串是描述了函数的参数和返回值

第三个变量fnPtr是函数指针,指向C/C++函数。

其中比较难以理解的是第二个参数,例如

"()V"

"(II)V"

"(Ljava/lang/String;Ljava/lang/String;)V"

实际上这些字符是与函数的参数类型一一对应的。

"()" 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();

"(II)V" 表示 void Func(int, int);

详细可参考:http://blog.csdn.net/loongembedded/article/details/41355353

由此可见Java函数对应的CPP函数名字是一样的,在

frameworks\base\services\jni\com_android_server_LightsService.cpp中定义:

(1)  init_native()

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static jintinit_native(JNIEnv *env, jobject clazz)
  2. {
  3. int err;
  4. hw_module_t* module;
  5. Devices* devices;
  6. devices =(Devices*)malloc(sizeof(Devices));
  7. err =hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
  8. if (err == 0) {
  9. devices->lights[LIGHT_INDEX_BACKLIGHT]
  10. = get_device(module,LIGHT_ID_BACKLIGHT);
  11. devices->lights[LIGHT_INDEX_KEYBOARD]
  12. = get_device(module,LIGHT_ID_KEYBOARD);
  13. devices->lights[LIGHT_INDEX_BUTTONS]
  14. = get_device(module,LIGHT_ID_BUTTONS);
  15. devices->lights[LIGHT_INDEX_BATTERY]
  16. = get_device(module,LIGHT_ID_BATTERY);
  17. devices->lights[LIGHT_INDEX_NOTIFICATIONS]
  18. = get_device(module,LIGHT_ID_NOTIFICATIONS);
  19. devices->lights[LIGHT_INDEX_ATTENTION]
  20. = get_device(module,LIGHT_ID_ATTENTION);
  21. devices->lights[LIGHT_INDEX_BLUETOOTH]
  22. = get_device(module,LIGHT_ID_BLUETOOTH);
  23. devices->lights[LIGHT_INDEX_WIFI]
  24. = get_device(module,LIGHT_ID_WIFI);
  25. else {
  26. memset(devices, 0, sizeof(Devices));
  27. }
  28. return (jint)devices;
  29. }

这里重点介绍hw_get_module()函数,声明如下:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int hw_get_module(const char *id, const struct hw_module_t **module);

id是输入参数,表示要加载的硬件抽象层模块ID;module是输出参数,如加载成功,它指向一个自定义的硬件抽象层模块结构体。函数返回值为0表示加载成功。

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #defineHAL_LIBRARY_PATH1 "/system/lib/hw"
  2. #defineHAL_LIBRARY_PATH2 "/vendor/lib/hw"
  3. #defineHAL_LIBRARY_PATH3 "/system/lib"

此函数回到这些路径下查找lights硬件抽象层模块lights.default.so并加载。

(2)  finalize_native()

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static voidfinalize_native(JNIEnv *env, jobject clazz, int ptr)
  2. {
  3. Devices* devices = (Devices*)ptr;
  4. if (devices == NULL) {
  5. return;
  6. }
  7. free(devices);
  8. }

(3)  setLight_native()

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static voidsetLight_native(JNIEnv *env, jobject clazz, int ptr,
  2. int light, int colorARGB, intflashMode, int onMS, int offMS, int brightnessMode)
  3. {
  4. Devices* devices = (Devices*)ptr;
  5. light_state_t state;
  6. if (light < 0 || light >= LIGHT_COUNT|| devices->lights[light] == NULL) {
  7. return ;
  8. }
  9. memset(&state, 0,sizeof(light_state_t));
  10. state.color = colorARGB;
  11. state.flashMode = flashMode;
  12. state.flashOnMS = onMS;
  13. state.flashOffMS = offMS;
  14. state.brightnessMode = brightnessMode;
  15. devices->lights[light]->set_light(devices->lights[light],&state);
  16. }

devices->lights[light]->set_light(devices->lights[light],&state);这里就是调用HAL层的函数。

3.     Lights硬件抽象层(HAL)

先来介绍这部分比较重要的结构体

3.1   light_state_t结构体

在hardware\libhardware\include\hardware\lights.h下定义:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /**
  2. * The parameters that can be set for a givenlight.
  3. *
  4. * Not all lights must support allparameters.  If you
  5. * can do something backward-compatible, youshould.
  6. */
  7. structlight_state_t {
  8. /**
  9. * The color of the LED in ARGB.
  10. *
  11. * Do your best here.
  12. *  - If your light can only do red or green, if they ask for blue,
  13. *    you should do green.
  14. *  - If you can only do a brightness ramp, then use this formula:
  15. *     unsigned char brightness = ((77*((color>>16)&0x00ff))
  16. *              +(150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
  17. *  - If you can only do on or off, 0 is off, anything else is on.
  18. *
  19. * The high byte should be ignored.  Callers will set it to 0xff (which
  20. * would correspond to 255 alpha).
  21. */
  22. unsigned int color;
  23. /**
  24. * See the LIGHT_FLASH_* constants
  25. */
  26. int flashMode;
  27. int flashOnMS;
  28. int flashOffMS;
  29. /**
  30. * Policy used by the framework to managethe light's brightness.
  31. * Currently the values areBRIGHTNESS_MODE_USER and BRIGHTNESS_MODE_SENSOR.
  32. */
  33. int brightnessMode;
  34. };

这里每个成员都有详细的解释,这里指强调几点:

(1)  flashMode成员

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /*************************************************************************
  2. * Flash modes for the flashMode field oflight_state_t.
  3. */
  4. #defineLIGHT_FLASH_NONE            0
  5. /**
  6. * To flash the light at a given rate, setflashMode to LIGHT_FLASH_TIMED,
  7. * and then flashOnMS should be set to thenumber of milliseconds to turn
  8. * the light on, followed by the number ofmilliseconds to turn the light
  9. * off.
  10. */
  11. #defineLIGHT_FLASH_TIMED           1
  12. /**
  13. * To flash the light using hardware assist,set flashMode to
  14. * the hardware mode.
  15. */
  16. #defineLIGHT_FLASH_HARDWARE        2

表示LED等闪的模式,如果不需要闪烁为LIGHT_FLASH_NONE;如果需要软件来控制闪烁为LIGHT_FLASH_TIMED,这时也需要适当flashOnMS和flashOffMS的值;如果由硬件来控制闪烁的效果则为LIGHT_FLASH_HARDWARE。

(2)  brightnessMode成员

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /**
  2. * Light brightness is managed by a usersetting.
  3. */
  4. #defineBRIGHTNESS_MODE_USER        0
  5. /**
  6. * Light brightness is managed by a lightsensor.
  7. */
  8. #defineBRIGHTNESS_MODE_SENSOR      1

BRIGHTNESS_MODE_USER表示由用户来设置背光,BRIGHTNESS_MODE_SENSOR表示有光传感器来自动调节背光,对应图4的Automatic brightness。

3.2   hw_module_t

在hardware\libhardware\include\hardware\hardware.h下定义:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /*
  2. * Value for the hw_module_t.tag field
  3. */
  4. #defineMAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C)<< 8) | (D))
  5. #defineHARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')
  6. #defineHARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')
  7. /**
  8. * Every hardware module must have a datastructure named HAL_MODULE_INFO_SYM
  9. * and the fields of this data structure mustbegin with hw_module_t
  10. * followed by module specific information.
  11. */
  12. typedef structhw_module_t {
  13. /** tag must be initialized toHARDWARE_MODULE_TAG */
  14. uint32_t tag;
  15. /** major version number for the module */
  16. uint16_t version_major;
  17. /** minor version number of the module */
  18. uint16_t version_minor;
  19. /** Identifier of module */
  20. const char *id;
  21. /**Name of this module */
  22. const char *name;
  23. /** Author/owner/implementor of the module*/
  24. const char *author;
  25. /** Modules methods */
  26. struct hw_module_methods_t* methods;
  27. /** module's dso */
  28. void* dso;
  29. /** padding to 128 bytes, reserved forfuture use */
  30. uint32_t reserved[32-7];
  31. } hw_module_t;

需要重点注意几点:

(1)  每个硬件抽象层都必须有个名为HAL_MODULE_INFO_SYM的结构体,而且它的第1个成员变量类型必须是hw_module_t。

(2)  结构体hw_module_t的成员变量dso用来保存加载硬件抽象层模块后得到的句柄值。前面提到,每一个硬件抽象层模块都对应有一个动态链接库文件。加载硬件抽象层模块的过程实际上就是调用dlopen函数来加载与其对应的动态链接库文件的过程。在调用dlclose函数来卸载这个硬件抽象层模块时,要用到这个句柄值,因此,我们在加载时需要将它保存起来。

(3)  methods

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. typedef structhw_module_methods_t {
  2. /** Open a specific device */
  3. int (*open)(const struct hw_module_t*module, const char* id,
  4. struct hw_device_t** device);
  5. }hw_module_methods_t;

Open函数指针用来打开硬件抽象层模块的设备,参数module表示要打开的设备所在的模块;参数id表示要打开的设备的ID;参数device是一个输出参数,用来描述已经打开的设备。因为一个硬件抽象层模块可能包含多个设备,因为此在调用open的时候需要执行它的ID。

hw_device_t结构体的定义如下:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /**
  2. * Every device data structure must begin withhw_device_t
  3. * followed by module specific public methodsand attributes.
  4. */
  5. typedef structhw_device_t {
  6. /** tag must be initialized toHARDWARE_DEVICE_TAG */
  7. uint32_t tag;
  8. /** version number for hw_device_t */
  9. uint32_t version;
  10. /** reference to the module this devicebelongs to */
  11. struct hw_module_t* module;
  12. /** padding reserved for future use */
  13. uint32_t reserved[12];
  14. /** Close this device */
  15. int (*close)(struct hw_device_t* device);
  16. } hw_device_t;

需要注意几点:

1)     硬件抽象层模块中的每个设备都必须自定义一个设备结构体,而人气它的第1个成员变量类型必须是hw_device_t。

2)     close用来关闭一个设备。

根据上面结构体的定义可知,硬件抽象层中的设备是由其所在的模块提供的接口open来打开的,而关闭是由设备本身结构体提供的close接口来完成的。

3.3   light_device_t

在hardware\libhardware\include\hardware\lights.h下定义:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. structlight_device_t {
  2. struct hw_device_t common;
  3. /**
  4. * Set the provided lights to the providedvalues.
  5. *
  6. * Returns: 0 on succes, error code onfailure.
  7. */
  8. int (*set_light)(struct light_device_t*dev,
  9. struct light_state_t const* state);
  10. };

下面给出mediatek\source\hardware\liblights\lights.c中相关的部分:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /**
  2. * module methods
  3. */
  4. /** Open a newinstance of a lights device using name */
  5. static intopen_lights(const struct hw_module_t* module, char const* name,
  6. struct hw_device_t** device)
  7. {
  8. int (*set_light)(struct light_device_t*dev,
  9. struct light_state_t const* state);
  10. if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)){
  11. set_light =set_light_backlight;
  12. }
  13. elseif (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {
  14. set_light = set_light_keyboard;
  15. }
  16. else if (0 == strcmp(LIGHT_ID_BUTTONS,name)) {
  17. set_light = set_light_buttons;
  18. }
  19. else if (0 == strcmp(LIGHT_ID_BATTERY,name)) {
  20. set_light = set_light_battery;
  21. }
  22. else if (0 ==strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
  23. set_light = set_light_notifications;
  24. }
  25. else if (0 == strcmp(LIGHT_ID_ATTENTION,name)) {
  26. set_light = set_light_attention;
  27. }
  28. else {
  29. return -EINVAL;
  30. }
  31. pthread_once(&g_init, init_globals);
  32. struct light_device_t *dev =malloc(sizeof(struct light_device_t));
  33. memset(dev, 0, sizeof(*dev));
  34. dev->common.tag = HARDWARE_DEVICE_TAG;
  35. dev->common.version = 0;
  36. dev->common.module = (structhw_module_t*)module;
  37. dev->common.close = (int (*)(structhw_device_t*))close_lights;
  38. dev->set_light = set_light;
  39. *device = (struct hw_device_t*)dev;
  40. return 0;
  41. }
  42. static structhw_module_methods_t lights_module_methods = {
  43. .open = open_lights,
  44. };
  45. /*
  46. * The lights Module
  47. */
  48. const structhw_module_t HAL_MODULE_INFO_SYM = {
  49. .tag = HARDWARE_MODULE_TAG,
  50. .version_major = 1,
  51. .version_minor = 0,
  52. .id = LIGHTS_HARDWARE_MODULE_ID,
  53. .name = "MTK lights Module",
  54. .author = "MediaTek",
  55. .methods = &lights_module_methods,
  56. };

结合第2节的setLight_native()--->set_light (),对应调用的是set_light_backlight来设置背光。

3.4   set_light_backlight()

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* LCD BACKLIGHT*/
  2. char const*constLCD_FILE
  3. "/sys/class/leds/lcd-backlight/brightness";
  4. static int
  5. set_light_backlight(structlight_device_t* dev,
  6. struct light_state_t const* state)
  7. {
  8. int err = 0;
  9. int brightness = rgb_to_brightness(state);// 将rgb亮度转化为亮度
  10. pthread_mutex_lock(&g_lock);
  11. g_backlight = brightness;
  12. //将数值写入sys文件系统的brightness文件
  13. err = write_int(LCD_FILE, brightness);
  14. if (g_haveTrackballLight) {
  15. handle_trackball_light_locked(dev);
  16. }
  17. pthread_mutex_unlock(&g_lock);
  18. return err;
  19. }

此函数主要是把新的背光亮度值brightness写入到/sys/class/leds/lcd-backlight/brightness文件中,比如103,然后LED驱动再读取此值,然后调节背光。

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static int
  2. write_int(charconst* path, int value)
  3. {
  4. int fd;
  5. #ifdefLIGHTS_INFO_ON
  6. LOGD("write %d to %s",value, path);
  7. #endif
  8. fd = open(path, O_RDWR);
  9. if (fd >= 0) {
  10. char buffer[20];
  11. int bytes = sprintf(buffer,"%d\n", value);
  12. int amt = write(fd, buffer, bytes);
  13. close(fd);
  14. return amt == -1 ? -errno : 0;
  15. else {
  16. return -errno;
  17. }
  18. }

我们也可以通过echo(写)和cat(读)来设置背光亮度,如下图:

图5

4.     Lights驱动层

mediatek\config\hsimobile77_ics2\ProjectConfig.mkCUSTOM_KERNEL_LEDS=mt65xx

对于MTK平台,

根据上面的介绍,背光驱动提供的用于调节亮度接口是:/sys/class/leds/lcd-backlight/brightness。这个接口有LED驱动注册得来的的,源码位于Kernel/driver/leds/led-class.c中,下面给出其中一部分:

表示leds class的属性文件、权限和支持的操作

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static struct device_attributeled_class_attrs[] = {
  2. __ATTR(brightness,0644, led_brightness_show, led_brightness_store),
  3. __ATTR(max_brightness, 0444,led_max_brightness_show, NULL),
  4. #ifdefCONFIG_LEDS_TRIGGERS
  5. __ATTR(trigger, 0644,led_trigger_show, led_trigger_store),
  6. #endif
  7. __ATTR_NULL,
  8. };
  9. static int __initleds_init(void)
  10. {
  11. leds_class =class_create(THIS_MODULE, "leds");
  12. if (IS_ERR(leds_class))
  13. returnPTR_ERR(leds_class);
  14. leds_class->suspend =led_suspend;
  15. leds_class->resume =led_resume;
  16. leds_class->dev_attrs =led_class_attrs;
  17. return 0;
  18. }
  19. static void __exitleds_exit(void)
  20. {
  21. class_destroy(leds_class);
  22. }
  23. subsys_initcall(leds_init);
  24. module_exit(leds_exit);

这里主要是通过subsys_initcall来进行各种子系统的初始化。

Led-class.c文件只是实现了提供上层的接口,至于真正操作硬件的驱动程序,可以给出其源码路径为:(硬件操作其实就是脉宽调制(PWM)),mediatek\source\kernel\drivers\leds\leds.c

3.4节的set_light_backlight()通过write()把背光值写入到/sys/class/leds/lcd-backlight/brightness文件后,会触发调用led_brightness_store函数,经过led_brightness_store()--->led_set_brightness()--->led_cdev->brightness_set(led_cdev,value)的调用流程,最后调用到mt65xx_led_set(),这是通过mt65xx_leds_probe()的赋值语句知道的:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. g_leds_data[i]->cdev.brightness_set= mt65xx_led_set;

这样我们就来看mt65xx_led_set()函数

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static voidmt65xx_led_set(struct led_classdev *led_cdev, enum led_brightness level)
  2. {
  3. struct mt65xx_led_data *led_data =
  4. container_of(led_cdev,struct mt65xx_led_data, cdev);
  5. // do something only when level ischanged
  6. if (led_data->level != level) {
  7. led_data->level= level;
  8. if(strcmp(led_data->cust.name,"lcd-backlight"))
  9. {
  10. schedule_work(&led_data->work);
  11. }else
  12. {
  13. LEDS_DEBUG("[LED]SetBacklight directly %d at time %lu\n",led_data->level,jiffies);
  14. mt65xx_led_set_cust(&led_data->cust,led_data->level);
  15. }
  16. }
  17. }

调用mt65xx_led_set_cust()来实现,此函数的参数led_data->cust

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. struct PWM_config
  2. {
  3. int clock_source;
  4. int div;
  5. int low_duration;
  6. int High_duration;
  7. };
  8. structcust_mt65xx_led {
  9. char                 *name;
  10. enum mt65xx_led_mode  mode;
  11. int                   data;
  12. struct PWM_config config_data;
  13. };
  14. static structcust_mt65xx_led cust_led_list[MT65XX_LED_TYPE_TOTAL] = {
  15. {"red",               MT65XX_LED_MODE_NONE, -1,{0}},
  16. {"green",             MT65XX_LED_MODE_NONE, -1,{0}},
  17. {"blue",              MT65XX_LED_MODE_NONE, -1,{0}},
  18. {"jogball-backlight", MT65XX_LED_MODE_NONE,-1,{0}},
  19. {"keyboard-backlight",MT65XX_LED_MODE_NONE,-1,{0}},
  20. {"button-backlight",  MT65XX_LED_MODE_PMIC,MT65XX_LED_PMIC_BUTTON,{0}},
  21. //           {"lcd-backlight",     MT65XX_LED_MODE_CUST,(int)Cust_SetBacklight,{0}},
  22. {"lcd-backlight",     MT65XX_LED_MODE_PWM,PWM1,{0}},
  23. };
  24. structcust_mt65xx_led *get_cust_led_list(void)
  25. {
  26. return cust_led_list;
  27. }

参数led_data->level就是当前要设置的背光值。

mt65xx_led_set_cust()--->backlight_set_pwm()--->pwm_set_spec_config()

在调试过程遇到的问题:

(1)  cust_mt65xx_ledcust_led_list全局结构体数组的修改

修改之前:{"lcd-backlight",     MT65XX_LED_MODE_GPIO,GPIO84,{0}},

因为我们是采用CPU的PWM1来控制背光的的,所以修改为:

{"lcd-backlight",     MT65XX_LED_MODE_PWM,PWM1,{0}},

可是进入系统后直接就是黑屏,为什么呢?根据调试信息知道/sys/class/leds/lcd-backlight/brightness文件的值为255,255是最大值,应该是最亮才对啊,但为什么是255就会黑屏呢?

看backlight_set_pwm()函数体下面的部分:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. if(level>0&& level <= 32)
  2. {
  3. pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0=  (1 << level) - 1 ;
  4. pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA1= 0 ;
  5. pwm_set_spec_config(&pwm_setting);
  6. }else if(level>32 &&level <=64)
  7. {
  8. level -= 32;
  9. pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0=  0xFFFFFFFF ;
  10. pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA1= (1 << level) - 1;
  11. pwm_set_spec_config(&pwm_setting);
  12. }else
  13. {
  14. LEDS_DEBUG("[LED]Errorlevel in backlight\n");
  15. mt_set_pwm_disable(pwm_setting.pwm_no);
  16. mt_power_off(pwm_setting.pwm_no);
  17. }

因为level=255,所以就直接执行了关屏的动作,如果要搞清楚为什么level>64就要关屏,就要详细看MT6577的PWM部分了。

(2)  修改brightness_mapping()

上面出现在leve=255关屏的情况,为解决此问题就需要修改brightness_mapping()函数,看了为了确保上层设置0~255的情况下,是需要brightness_mapping函数的映射的,下面给出其实现部分:

[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. unsigned intbrightness_mapping(unsigned int level)
  2. {
  3. unsigned int mapped_level;
  4. mapped_level = level;
  5. return mapped_level;
  6. }

很简单吧,为了解决此问题,我们改为:

mapped_level =level/4;

5.     Lights硬件层

参考我之前介绍的部分:

http://blog.csdn.net/loongembedded/article/details/38540297

6.     编译

./mk n ub、 ./mk n k和./mk bootimage,然后更新uboot_hsimobile77_ics2.bin和boot.img即可

参考:

mtk led

http://blog.csdn.net/mcgrady_tracy/article/details/41285213

android系统开发(七)-背光模块

http://blog.csdn.net/jiajie961/article/details/6030405

【从应用层到Framework】android LCD、键盘灯的背光亮度设置

http://blog.sina.com.cn/s/blog_40d475e901014wkt.html

Android中背光系统架构

http://blog.csdn.net/yinwei520/article/details/6817528

Android LCD和键盘背光亮度数据流分析

http://blog.csdn.net/wealoong/article/details/7759178

lights从上到下的流程

http://blog.csdn.net/zhangchiytu/article/details/7958513

android背光设置相关推荐

  1. Android 系统背光设置

    一.一般设置 1.手动设置背光API // 修改当前Activity界面的窗口亮度 private void setScreenLight(int brightness) {WindowManager ...

  2. android背光系统,Android 的背光控制

    Android 背光的控制: 屏幕背光设置 packages/apps/Settings/src/com/android/settings/BrightnessPreference.java 背光设置 ...

  3. android修改自动背光,android 背光控制

    echo 23 > /sys/devices/platform/atmel_lcdfb.0/backlight/backlight/brightness android 源代码 http://b ...

  4. android 自动背光闪烁,Android 背光流程小结

    android背光控制小结,从上到下: ----android---- DisplayPowerController.java--> DisplayPowerState.java:SCREEN_ ...

  5. Android中设置TextView的颜色setTextColor

    tv.setTextColor(Color.parseColor("#FFFFFF")); tv.setTextColor(Color.WHITE); tv.setTextColo ...

  6. android 动态设置padding,Android动态设置控件大小以及设定margin以及padding值

    http://www.aichengxu.com/Java/73893.htm Android动态设置控件大小以及设定margin以及padding值,有需要的朋友可以参考下. 一.概述 在andro ...

  7. android studio 设置 ndk 路径

    ndk下载路径: https://developer.android.google.cn/ndk/downloads android studio 设置 ndk 路径 在项目的根目录下面,有个配置文件 ...

  8. android字体行距,android textview设置字体的行距和字间距

    字间距 textView有一个属性android:textScaleX是调节字间距的,它的值是一个float型.查看源代码,默认textView 此属性是使用的是: android.internal. ...

  9. android 自启动列表,Android 机型设置自启动的跳转界面

    Android 机型设置自启动的跳转界面 由于之前版本号把23,6.0误写成26,8.0了,导致一些判断是错的,并且在catch中没有重新对intent更新,导致会有崩溃问题,现已修复. 简书怎么传附 ...

最新文章

  1. BOOL,int,float,指针变量与零值比较的if语句
  2. mysql期中考试题及答案_MySQL练习题及答案
  3. ActiveMQ消息队列的使用及应用
  4. objective c 语法
  5. MySQL 请选择合适的列!
  6. Fiddler 跟踪数据包
  7. Kali环境下安装python3
  8. 训练日志 2018.10.11
  9. 浅谈OpenCL之API分类
  10. Android View体系‘铁三角‘
  11. 两者结合在一起看SphereFace
  12. configure: error: MySQL library not found ,Not found mysqlclient library
  13. 预言梦可能破坏质能守恒定律
  14. html怎么调用jq和js,js的outerHTML 与jquery的prop()的用法
  15. 从HttpClient3迁移到HttpClient4
  16. 在Mac和PC之间共享鼠标键盘(拥有多台电脑者必看)
  17. 华为鸿蒙os logo,华为鸿蒙OS Logo揭秘:Powered by HarmonyOS
  18. Java家庭收支记账程序
  19. Multi-Layered Gradient Boosting Decision Trees
  20. 2021年 全网最细大数据学习笔记(二):Hadoop 伪分布式安装

热门文章

  1. Linux操作系统之—所有端口详解大全手册
  2. Spring boot 缓存学习笔记
  3. Objective-C 编程语言官网文档(四)-协议
  4. PowerDesigner快速建表使用方法
  5. 投资的过程:进行高质量的研究
  6. 学生用计算机的电流是多少,220V家用电源的电流是多少mA?
  7. 医学图像领域,是时候用视觉Transformer替代CNN了吗?
  8. 基于JAVA体育城场地预定系统后台计算机毕业设计源码+数据库+lw文档+系统+部署
  9. explain ref_用 Explain 命令分析 MySQL 的 SQL 执行
  10. sql语句异常 You have an error in your SQL syntax; check the manual that corresponds to your.......