图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 plaincopy

在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. privateintmScreenBrightnessDim =
  5. getContext().getResources().getInteger(com.android.internal.R.integer.config_screenBrightnessDim);
  6. privatestaticfinalintMAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON;
  7. @Override
  8. protectedvoidonBindDialogView(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 plaincopy

在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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. /**
  2. * Brightness value for fully off
  3. */
  4. publicstaticfinalintBRIGHTNESS_OFF =0;
  5. /**
  6. * Brightness value for dim backlight
  7. */
  8. publicstaticfinalintBRIGHTNESS_DIM =20;
  9. /**
  10. * Brightness value for fully on
  11. */
  12. publicstaticfinalintBRIGHTNESS_ON =255;
  13. /**
  14. * Brightness value to use when battery islow
  15. */
  16. publicstaticfinalintBRIGHTNESS_LOW_BATTERY =10;




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

1.2   设置背光亮度

[java] view plaincopy

在CODE上查看代码片派生到我的代码片

  1. publicvoidonProgressChanged(SeekBar seekBar,intprogress,
  2. booleanfromTouch) {
  3. setBrightness(progress +mScreenBrightnessDim);
  4. }
  5. progress表示滑动条的值。
  6. privatevoidsetBrightness(intbrightness) {
  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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. privatevoidloadSystemSettings(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 plaincopy

在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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. interfaceIPowerManager
  2. {
  3. ……
  4. // sets the brightness of thebacklights (screen, keyboard, button) 0-255
  5. voidsetBacklightBrightness(intbrightness);
  6. voidsetBacklightBrightnessOff(booleanenable);
  7. voidsetMaxBrightness(intbrightness);
  8. ……….
  9. }


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

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

[plain] view plaincopy

在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 plaincopy

在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. publicvoidsetBacklightBrightness(intbrightness)
  9. {
  10. try{
  11. mService.setBacklightBrightness(brightness);
  12. catch(RemoteException e) {
  13. }


这里调用PowerManagerService的接口,

[java] view plaincopy

在CODE上查看代码片派生到我的代码片

  1. frameworks\base\services\java\com\android\server\PowerManagerService.java,如下:
  2. publicvoidsetBacklightBrightness(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. longidentity =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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. …………..
  2. staticfinalintLIGHT_ID_BACKLIGHT =0;
  3. staticfinalintLIGHT_ID_KEYBOARD =1;
  4. staticfinalintLIGHT_ID_BUTTONS =2;
  5. staticfinalintLIGHT_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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. privatestaticnativeintinit_native();
  2. privatestaticnativevoidfinalize_native(intptr);
  3. privatestaticnativevoidsetLight_native(intptr,intlight,intcolor,intmode,
  4. intonMS,intoffMS, intbrightnessMode);


这些本地方法在

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

[cpp] view plaincopy

在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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. typedefstruct{
  2. constchar* name;
  3. constchar*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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. staticjintinit_native(JNIEnv *env, jobject clazz)
  2. {
  3. interr;
  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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. inthw_get_module(constchar*id,conststructhw_module_t **module);


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

[cpp] view plaincopy

在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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. staticvoidfinalize_native(JNIEnv *env, jobject clazz,intptr)
  2. {
  3. Devices* devices = (Devices*)ptr;
  4. if(devices == NULL) {
  5. return;
  6. }
  7. free(devices);
  8. }


(3)  setLight_native()

[cpp] view plaincopy

在CODE上查看代码片派生到我的代码片

  1. staticvoidsetLight_native(JNIEnv *env, jobject clazz,intptr,
  2. intlight,intcolorARGB, intflashMode,intonMS,intoffMS,intbrightnessMode)
  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 plaincopy

在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 intcolor;
  23. /**
  24. * See the LIGHT_FLASH_* constants
  25. */
  26. intflashMode;
  27. intflashOnMS;
  28. intflashOffMS;
  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. intbrightnessMode;
  34. };


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

(1)  flashMode成员

[cpp] view plaincopy

在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 plaincopy

在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 plaincopy

在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. typedefstructhw_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. constchar*id;
  21. /**Name of this module */
  22. constchar*name;
  23. /** Author/owner/implementor of the module*/
  24. constchar*author;
  25. /** Modules methods */
  26. structhw_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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. typedefstructhw_module_methods_t {
  2. /** Open a specific device */
  3. int(*open)(conststructhw_module_t*module,constchar* id,
  4. structhw_device_t** device);
  5. }hw_module_methods_t;


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

hw_device_t结构体的定义如下:

[cpp] view plaincopy

在CODE上查看代码片派生到我的代码片

  1. /**
  2. * Every device data structure must begin withhw_device_t
  3. * followed by module specific public methodsand attributes.
  4. */
  5. typedefstructhw_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. structhw_module_t* module;
  12. /** padding reserved for future use */
  13. uint32_t reserved[12];
  14. /** Close this device */
  15. int(*close)(structhw_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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. structlight_device_t {
  2. structhw_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)(structlight_device_t*dev,
  9. structlight_state_tconst* state);
  10. };


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

[cpp] view plaincopy

在CODE上查看代码片派生到我的代码片

  1. /**
  2. * module methods
  3. */
  4. /** Open a newinstance of a lights device using name */
  5. staticintopen_lights(conststructhw_module_t* module,charconst* name,
  6. structhw_device_t** device)
  7. {
  8. int(*set_light)(structlight_device_t*dev,
  9. structlight_state_tconst* 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. elseif(0 == strcmp(LIGHT_ID_BUTTONS,name)) {
  17. set_light = set_light_buttons;
  18. }
  19. elseif(0 == strcmp(LIGHT_ID_BATTERY,name)) {
  20. set_light = set_light_battery;
  21. }
  22. elseif(0 ==strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
  23. set_light = set_light_notifications;
  24. }
  25. elseif(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. structlight_device_t *dev =malloc(sizeof(structlight_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 = (structhw_device_t*)dev;
  40. return0;
  41. }
  42. staticstructhw_module_methods_t lights_module_methods = {
  43. .open = open_lights,
  44. };
  45. /*
  46. * The lights Module
  47. */
  48. conststructhw_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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. /* LCD BACKLIGHT*/
  2. charconst*constLCD_FILE
  3. "/sys/class/leds/lcd-backlight/brightness";
  4. staticint
  5. set_light_backlight(structlight_device_t* dev,
  6. structlight_state_tconst* state)
  7. {
  8. interr = 0;
  9. intbrightness = 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. returnerr;
  19. }


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

[cpp] view plaincopy

在CODE上查看代码片派生到我的代码片

  1. staticint
  2. write_int(charconst* path, intvalue)
  3. {
  4. intfd;
  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. charbuffer[20];
  11. intbytes = sprintf(buffer,"%d\n", value);
  12. intamt = write(fd, buffer, bytes);
  13. close(fd);
  14. returnamt == -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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. staticstructdevice_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. staticint__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. return0;
  18. }
  19. staticvoid__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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. g_leds_data[i]->cdev.brightness_set= mt65xx_led_set;

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

[cpp] view plaincopy

在CODE上查看代码片派生到我的代码片

  1. staticvoidmt65xx_led_set(structled_classdev *led_cdev,enumled_brightness level)
  2. {
  3. structmt65xx_led_data *led_data =
  4. container_of(led_cdev,structmt65xx_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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. structPWM_config
  2. {
  3. intclock_source;
  4. intdiv;
  5. intlow_duration;
  6. intHigh_duration;
  7. };
  8. structcust_mt65xx_led {
  9. char*name;
  10. enummt65xx_led_mode  mode;
  11. intdata;
  12. structPWM_config config_data;
  13. };
  14. staticstructcust_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. returncust_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 plaincopy

在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. }elseif(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 plaincopy

在CODE上查看代码片派生到我的代码片

  1. unsigned intbrightness_mapping(unsignedintlevel)
  2. {
  3. unsigned intmapped_level;
  4. mapped_level = level;
  5. returnmapped_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 系统(20)---背光灯相关推荐

  1. Ubuntu系统键盘背光灯不亮解决办法

    今天新装了Ubuntu系统,突然发现之前买的彩光灯键盘背光 灯不亮了,作为Linux系统小白,这可急坏了我,这搜索那查查, 终于找到了解决方案,特此记录一下,分享给大家: 1.开启背光灯的方法: 在终 ...

  2. 第四章:Android灯光系统(6)-背光灯

    上小节我们实现了对通知灯控制,该小节我们讲解怎么实现对背光灯的控制,一般来说,操作是比较简单的,我们只需要往数据库中写入亮度就可以了,那么为什么会这么简单,当然是有其他的程序(ContentObser ...

  3. Android 利润,惊人利润:Android系统免费背后影藏的巨大利润

    Android用户群体的庞大数量有目共睹,并且Android一直以免费为噱头,如果是一直免费,那么Android背后庞大的团队是靠什么经济来源支撑着Android一代又一代的更新?近日有网友披露谷歌的 ...

  4. Android背光灯控制实现

    Android中所有系统灯光的定义:lights.h #define LIGHT_ID_BACKLIGHT "backlight" JNI: com_android_server_ ...

  5. android 背光灯分析,Android灯光系统--深入理解背光灯

    Android灯光系统--深入理解背光灯 一.怎么控制背光灯(简述) APP将亮度值写入数据库 线程检测数据库的值是否发生变化 这种机制成为"内容观察者"--contentObse ...

  6. android 背光灯分析,android - LCD背光灯不再工作:Android - 堆栈内存溢出

    按下Android电源按钮时,LCD背光灯会打开和关闭. 但是从过去的一天开始,我的LCD背光灯没有打开. 按下15至20次后,背光灯会亮起几分钟,然后再次熄灭. 当我执行电源按钮按下操作时,我发现它 ...

  7. 机械键盘插入linux系统中,机械键盘背光灯不亮,并且键盘快捷键无作用

    Linux问题解决专栏 第四篇:机械键盘插入linux系统中,机械键盘背光灯不亮,并且键盘快捷键无作用. 一.问题描述:在笔记本或者台式机中使用外接键盘的时候,键盘的LED灯总是不亮,不论是虚拟机或者 ...

  8. Android灯光系统背光灯

    一.背光灯的实现目标 实现一个滑块,滑动滑块可以进行背光的控制 二.程序编写 1.实现滑块功能 <SeekBarandroid:layout_width="fill_parent&qu ...

  9. android 背光灯分析,Android-Android 触摸屏按键背光灯控制

    终于把这个问题解决了,跟了好久的log,在PowerManagerService.java的userActivity()里面有如下代码: if (eventType == BUTTON_EVENT & ...

最新文章

  1. 斐波那契数列及青蛙跳台阶问题
  2. [UWP小白日记-1]判断APP是否是第一次运行初始化SQLITE数据库
  3. 2020年周记(2/50)
  4. 程序员必备的10大健康装备!——我们要工作更要健康!
  5. 计算(a+b)*c的值
  6. Liferay MinifierFilter的研究
  7. java 解决死锁_如何解决java中的死锁问题
  8. java 读取mysql日志_如何在MySQL中查看日志文件?
  9. 如何识别计算机病毒,怎样识别计算机病毒
  10. 微信小程序云开发-时间存储、转换、比较
  11. E20170603-ts
  12. 《Java并发编程实战》 读书勘误
  13. 软件测试基础知识 + 面试理论(超详细)
  14. Linux安全加固手册
  15. 《疯狂Python讲义》数字转人民币大写完整代码
  16. pythoneducoder苹果梨子煮水的功效_梨子煮水真的有润肺止咳化痰的功效吗?
  17. 腾讯员工税后收入 250 万,年终奖是100个月工资?在大厂工作究竟有多赚钱?
  18. 男神体 骚包体 快乐体 手拙体 好身体(haha),你知道这些字体的英文名字吗?
  19. 计算机专业java餐厅点餐系统,Java实现餐厅点餐系统的实例代码.pdf
  20. 【Appium踩坑】关闭inspector后打开weditor,uiautomator2.exceptions.NullPointerExceptionError: -32001 Jsonrpc er

热门文章

  1. SVD 与 PCA 的直观解释(1): 线性变换
  2. oracle中distinct和group by的区别
  3. wpf异常:指定的 Visual 不是此 Visual 的上级问题处理解析
  4. java 获取音频文件时长
  5. Redis与Memcache的区别
  6. ThinkPHP5如何引用新建的配置文件?
  7. Oracle GoldenGate 12c中的协同交付(Coordinated Delivery)
  8. 编写Javascript时的注意事项
  9. Objective-C中的反射和反射工厂
  10. python获取Linux发行版名称