Android中背光系统架构

分类: Adroid开发 Linux操作系统 嵌入式Linux驱动 1650人阅读 评论(6) 收藏 举报 android struct frameworks jni notifications module

Mg Android中背光系统架构

Email:[email protected]

Blog:http://blog.csdn.net/yinwei520

Author:Yww

Time:2011-9-24

Update:

(转载请注明出处,谢谢)

不知不觉喜欢上了写Blog,这还是一种不错的休闲方式,所噶~~,会不会也害怕过周末呢?因为寂寞~~啥样儿的生活才让觉得舒适哦~单身好~哈哈。搞了两天,还是姚哥一语惊醒梦中人啊~忽略了Linux下的权限问题,让我纠结了好几个小时啊。首先说明一下,这次学习中让我学到的东西:

最主要的莫过于是了解了Android中jni编程,游荡整个Android源码,可以看到很多直接操作底层驱动接口,封装成so库,供Java调用的例子哦。

这次学习,也正是出于这样的想法,没想到这个设想高手们早就实现了哦,菜鸟现在也只能算是验证了。诶,菜鸟就是菜鸟,有虫子吃,就兴奋的不得了。

驱动架构略,这里只讨论jni接口的实现。

一、我的设想

其实设想很简单,找到背光驱动提供给上层的API接口,人家Android还不是一样需要一层一层的抽象(HAL、Framework),高手们考虑的东东很多,所以才一层层抽象封装,既然这样,咱菜鸟不就一根筋,有虫吃就是王道啊,我为什么不能直接将这个驱动接口封装成jni提供给Java呢?其实这想法很早就有了,只是到现在才验证,确实可以啊。其实Android中还是有N多这样的例子的。

背光驱动提供的接口是:/sys/class/leds/lcd-backlight/brightness。至于这个接口是怎么来的??那就要去看驱动结构了。驱动注册此接口的源码位于:

Kernel/driver/leds/led-class.c中。

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

二、设想验证

这里关键就是要清楚jni的接口实现规则咯,不过环境搭建也比较麻烦(ndk编译环境)。

环境搭建另外给出日志。

Jni接口的源码如下:

[cpp] view plain copy print ?
  1. #include<unistd.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<fcntl.h>
  5. #include<sys/types.h>
  6. #include<sys/stat.h>
  7. //#include<dirent.h>
  8. //#include<jni.h>
  9. #include<string.h>
  10. #include<android/log.h>
  11. #include"com_yecon_CtlBL_CtlBLActivity.h"
  12. #defineLOG_TAG"ctlbl.c"
  13. #defineLOGI(...)__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
  14. //#defineDEV_PATH"/sys/class/leds/lcd-backlight/brightness"
  15. //#defineDEV_PATH"/sys/devices/platform/leds-mt65xx/leds/lcd-backlight/brightness"
  16. /**
  17. *nativemethod
  18. */
  19. //JNIEXPORTjobjectArrayJNICALLJava_com_yecon_CtlBL_CtlBLActivity_ctlbl(JNIEnv*env,jobjectobj)
  20. JNIEXPORTjintJNICALLJava_com_yecon_CtlBL_CtlBLActivity_ctlbl(JNIEnv*env,jobjectobj)
  21. {
  22. intfd;
  23. interr;
  24. char*p;
  25. charctl[10]={"20"};
  26. LOGI("HELLO!\n");
  27. //__android_log_print("");
  28. //printf("callctlblfunctionsucc!\n");
  29. fd=open("/sys/class/leds/lcd-backlight/brightness",O_RDWR);
  30. if(fd<0)
  31. {
  32. //fprintf(stderr,"error:open%s\n",DEV_PATH);
  33. LOGI("error:open!\n");
  34. exit(1);
  35. }
  36. #if0
  37. err=read(fd,ctl,1);
  38. if(err!=1)
  39. {
  40. //fprintf(stderr,"error:write%d!\n",err);
  41. exit(1);
  42. }else{
  43. //printf("thedatais%s\n",ctl[0]);
  44. }
  45. #endif
  46. err=write(fd,ctl,2);
  47. //printf("%s\n",ctl);
  48. if(err!=2)
  49. {
  50. //fprintf(stderr,"error:write%d!\n",err);
  51. LOGI("error:write!\n");
  52. exit(1);
  53. }
  54. close(fd);
  55. return0;
  56. //return(*env)->NewStringUTF(env,"HellowwJNI!");
  57. }


上层Java调用的源码如下:(只是实现了一个Button,点击,有一个消息响应,将背光调到20)

[java] view plain copy print ?
  1. packagecom.yecon.CtlBL;
  2. importandroid.app.Activity;
  3. importandroid.os.Bundle;
  4. importandroid.view.View;
  5. importandroid.view.View.OnClickListener;
  6. importandroid.widget.Button;
  7. importandroid.widget.TextView;
  8. //importcom.yecon.CtlBL.ctlbljni;
  9. publicclassCtlBLActivityextendsActivity{
  10. Buttonb=null;
  11. //ctl=newctlbljni();
  12. privateOnClickListenerclickListener=newOnClickListener(){
  13. @Override
  14. publicvoidonClick(Viewv){
  15. //TODOAuto-generatedmethodstub
  16. //ctl.ctlbl();
  17. ctlbl();
  18. }
  19. };
  20. /**Calledwhentheactivityisfirstcreated.*/
  21. @Override
  22. publicvoidonCreate(BundlesavedInstanceState){
  23. super.onCreate(savedInstanceState);
  24. setContentView(R.layout.main);
  25. b=(Button)this.findViewById(R.id.BtnCancel);
  26. b.setOnClickListener(clickListener);
  27. //TextViewtv=newTextView(this);
  28. //tv.setText(ctlbl());
  29. //setContentView(tv);
  30. }
  31. publicnativeintctlbl();//本地方法
  32. static{
  33. System.loadLibrary("ctlbl");//载入so库
  34. }
  35. }


看上去,没几行代码,so easy!!看看高手们的实现吧!!

三、Android中背光系统实现

以往,我经常都是从底层往上看,这次从上层往下找找吧,同样的眼睛,不一样的视角,会别有一番风景哦~~其实,美女也要应该这样欣赏。

玩玩Android机子,其实知道背光调节就是在“设置”中的那个seekBar,那我们就去setting中去找源码吧.其源码路径为:

packages\apps\Settings\src\com\android\settings\ BrightnessPreference.java

打开看看吧~宽衣解带是最让人兴奋的啊。你会看到这样几行注释:

// Backlight range is from 0 - 255. Need to make sure that user

// doesn't set the backlight to 0 and get stuck

private static final intMINIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_DIM + 10;

private static final int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON;

背光的调节范围是0-255啊~~

继续解带吧~会看到一个很亲切的函数:

public void UpdateBrightness()

{

if(mIsActive)

{

setBrightness(mSeekBar.getProgress() +MINIMUM_BACKLIGHT);

}

}

更新背光亮度,太亲切了,这不慢慢接近目标了吗?其调用了setBrightness()函数,跳进去看看其实现哦~~

private void setBrightness(int brightness) {

try {

IPowerManager power = IPowerManager.Stub.asInterface(

ServiceManager.getService("power"));

if (power !=null) {

power.setBacklightBrightness(brightness);

}

} catch (RemoteException doe) {

}

}

这不就是韩哥给出的那几行代码嘛~~呵呵~终于找到要点了吧,所谓打蛇要打七寸,不就是这样吗?这个IPowerManager类中有个setBacklightBrightness函数啊,那它又是怎么实现的啊?找来找去只找到了一个申明啊:

public void setBacklightBrightness(int brightness)throws android.os.RemoteException;

找不到其实现怎么办呢??这是个棘手的问题啊~还好Eclipse很恶心啊~~搜搜就又出来了,这个函数的实现在:

frameworks\base\services\java\com\android\server\PowerManagerService.java中。

[java] view plain copy print ?
  1. publicvoidsetBacklightBrightness(intbrightness){
  2. mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,null);
  3. //Don'tletapplicationsturnthescreenallthewayoff
  4. synchronized(mLocks){
  5. brightness=Math.max(brightness,Power.BRIGHTNESS_DIM);
  6. mLcdLight.setBrightness(brightness);
  7. //Wewon'tadjustButton/KeyboardBKLhereforthetimebeing,seeCR[ALPS00132847]
  8. //mKeyboardLight.setBrightness(mKeyboardVisible?brightness:0);
  9. //mButtonLight.setBrightness(brightness);
  10. longidentity=Binder.clearCallingIdentity();
  11. try{
  12. mBatteryStats.noteScreenBrightness(brightness);
  13. }catch(RemoteExceptione){
  14. Slog.w(TAG,"RemoteExceptioncallingnoteScreenBrightnessonBatteryStatsService",e);
  15. }finally{
  16. Binder.restoreCallingIdentity(identity);
  17. }
  18. //updateouranimationstate
  19. synchronized(mLocks){
  20. mScreenBrightness.targetValue=brightness;
  21. mScreenBrightness.jumpToTargetLocked();
  22. }
  23. }
  24. }

看着看着又模糊啦,这里怎么又调用了setBrightness()哦,此setBrightness非BrightnessPreference.java中的setBrightness。其类属于:

private LightsService.Light mLcdLight;

革命尚未成功,你说咋办,那好吧,为了革命的胜利,再进去看看这个类中setBrightness()的实现吧。源码路径为:

frameworks\base\services\java\com\android\server\LightsService.java

[java] view plain copy print ?
  1. publicvoidsetBrightness(intbrightness){
  2. setBrightness(brightness,BRIGHTNESS_MODE_USER);
  3. }
  4. publicvoidsetBrightness(intbrightness,intbrightnessMode){
  5. synchronized(this){
  6. intcolor=brightness&0x000000ff;
  7. color=0xff000000|(color<<16)|(color<<8)|color;
  8. setLightLocked(color,LIGHT_FLASH_NONE,0,0,brightnessMode);
  9. }
  10. }


这里又调用了setLightLocked()

[java] view plain copy print ?
  1. privatevoidsetLightLocked(intcolor,intmode,intonMS,intoffMS,intbrightnessMode){
  2. if(color!=mColor||mode!=mMode||onMS!=mOnMS||offMS!=mOffMS){
  3. mColor=color;
  4. mMode=mode;
  5. mOnMS=onMS;
  6. mOffMS=offMS;
  7. setLight_native(mNativePointer,mId,color,mode,onMS,offMS,brightnessMode);
  8. }
  9. }


革命的曙光来啦,看到没,这里调用了setLight_native这个本地接口,

private static native void setLight_native(int ptr,int light,int color,int mode,

int onMS,int offMS,int brightnessMode);

皇天不负有心人啊,胜利的曙光照耀着我们啊,终于就快脱光光啦~~!难以按捺住这颗激动的心啊。

可是这个setLight_native又是在哪里呢??经过一番苦苦搜索,它并不在灯火阑珊处,而是在:

frameworks\base\services\jni\ com_android_server_LightsService.cpp

宽衣,看看:

四、JNI层

[cpp] view plain copy print ?
  1. staticvoidsetLight_native(JNIEnv*env,jobjectclazz,intptr,
  2. intlight,intcolorARGB,intflashMode,intonMS,intoffMS,intbrightnessMode)
  3. {
  4. Devices*devices=(Devices*)ptr;
  5. light_state_tstate;
  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. }
  17. staticJNINativeMethodmethod_table[]={
  18. {"init_native","()I",(void*)init_native},
  19. {"finalize_native","(I)V",(void*)finalize_native},
  20. {"setLight_native","(IIIIIII)V",(void*)setLight_native},
  21. };


哇,高手就是高手啊。看看,一个函数人家处理的不只是backlight,还有flash,color哦。惭愧啊~

到此,一个美女就这样被你看完啦~~当然,还有三点哦~~还想要激情的吗??激情就在底层了哦。想单刀直入吗?那还得看你本事了哦~~

devices->lights[light]->set_light(devices->lights[light], &state);

这句将带你穿梭进赤裸裸的XX。

五、HAL层

太神奇啦,这里直接给出HAL层的源码路劲,如下:

\mediatek\source\hardware\liblights\ lights.c

\hardware\libhardware\include\hardware\ lights.h

你会看到引你越过道德边缘的set_light的申明就在lights.h中啊。真是罪孽啊~~

[cpp] view plain copy print ?
  1. /**
  2. *modulemethods
  3. */
  4. /**Openanewinstanceofalightsdeviceusingname*/
  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. }


看看吧,其实我们需要找的就是set_light_backlight。

[html] view plain copy print ?
  1. staticint
  2. set_light_backlight(structlight_device_t*dev,
  3. structlight_state_tconst*state)
  4. {
  5. interr=0;
  6. intbrightness=rgb_to_brightness(state);
  7. pthread_mutex_lock(&g_lock);
  8. LOGD("%s:brightness=%dstart+++\n",__func__,brightness);
  9. g_backlight=brightness;
  10. err=write_int(LCD_FILE,brightness);
  11. if(g_haveTrackballLight){
  12. handle_trackball_light_locked(dev);
  13. }
  14. pthread_mutex_unlock(&g_lock);
  15. returnerr;
  16. }


当你认真看完lights.c会发现其基本思想跟之前的设想一样,只是人家是高手,我是菜鸟,人家看到赤裸裸的美女不是表面,而是艺术~~~~!!

通过这个分析,可以延伸了解到led灯的结构。


更多相关文章

  1. [Android]Toolbar使用详解(三)——源码解析
  2. Android(安卓)Universal Image Loader 源码分析(转载)
  3. xe5 android 控制蓝牙
  4. android用户界面之Widget教程实例汇总
  5. Android(安卓)- ToDoList(fragment) 详解
  6. 修改android 默认设置
  7. 15款小应用源码
  8. Android(安卓)- 使用AIDL设计远程接口
  9. 《Android开发从零开始》——9.Activity高级学习

随机推荐

  1. android button light 流程分析(二) — H
  2. 开源项目之Android(安卓)推送框架(androi
  3. AndTask v2.2 安安任务管理器 发布
  4. android: 大量开源项目源代码分享
  5. Android 得到连接热点的ip的方法
  6. Android为Layout设置最大宽度
  7. 萝卜小姐-Handler之系列sendMessage学习
  8. Android收起虚拟键盘
  9. android 云标签,文字墙(文字随机排列效果)
  10. Android SDK 1.5 "--core-library" build