android背光系统架构

来源:互联网 发布:淘宝主动打招呼 编辑:程序博客网 时间:2024/04/30 12:27

Mg Android中背光系统架构

Email:wei7758@126.com

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 plaincopyprint?
  1. #include <unistd.h>   
  2.   
  3. #include <stdio.h>   
  4.   
  5. #include <stdlib.h>   
  6.   
  7. #include <fcntl.h>   
  8.   
  9. #include <sys/types.h>   
  10.   
  11. #include <sys/stat.h>   
  12.   
  13. //#include <dirent.h>     
  14.   
  15. //#include <jni.h>   
  16.   
  17. #include <string.h>   
  18.   
  19. #include <android/log.h>   
  20.   
  21.    
  22.   
  23. #include "com_yecon_CtlBL_CtlBLActivity.h"  
  24.   
  25.    
  26.   
  27. #define  LOG_TAG    "ctlbl.c"  
  28.   
  29. #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)  
  30.   
  31. //#define DEV_PATH "/sys/class/leds/lcd-backlight/brightness"  
  32.   
  33. //#define DEV_PATH "/sys/devices/platform/leds-mt65xx/leds/lcd-backlight/brightness"  
  34.   
  35.    
  36.   
  37. /** 
  38.  
  39.  * native method 
  40.  
  41.  */  
  42.   
  43. //JNIEXPORT jobjectArray JNICALL Java_com_yecon_CtlBL_CtlBLActivity_ctlbl(JNIEnv * env, jobject obj)  
  44.   
  45. JNIEXPORT jint JNICALL Java_com_yecon_CtlBL_CtlBLActivity_ctlbl(JNIEnv * env, jobject obj)  
  46.   
  47. {  
  48.   
  49.    
  50.   
  51.    
  52.   
  53.     int fd;  
  54.   
  55.     int err;  
  56.   
  57.     char *p;  
  58.   
  59.     char ctl[10]={"20"};  
  60.   
  61.     LOGI("HELLO!\n");  
  62.   
  63.     //__android_log_print("");  
  64.   
  65.     //printf("call ctlbl function succ!\n");  
  66.   
  67.     fd = open("/sys/class/leds/lcd-backlight/brightness",O_RDWR);  
  68.   
  69.     if(fd < 0)  
  70.   
  71.     {  
  72.   
  73.         //fprintf(stderr,"error: open %s\n",DEV_PATH);  
  74.   
  75.         LOGI("error: open!\n");  
  76.   
  77.         exit(1);  
  78.   
  79.     }  
  80.   
  81. #if 0   
  82.   
  83.     err = read(fd,ctl,1);  
  84.   
  85.     if(err != 1)  
  86.   
  87.     {  
  88.   
  89.         //fprintf(stderr,"error: write %d!\n",err);  
  90.   
  91.           
  92.   
  93.         exit(1);  
  94.   
  95.     }else{  
  96.   
  97.         //printf("the data is %s\n",ctl[0]);  
  98.   
  99.     }  
  100.   
  101. #endif   
  102.   
  103.     err=write(fd,ctl,2);  
  104.   
  105.     //printf("%s\n",ctl);   
  106.   
  107.     if(err != 2)  
  108.   
  109.     {  
  110.   
  111.         //fprintf(stderr,"error: write %d!\n",err);  
  112.   
  113.         LOGI("error: write !\n");  
  114.   
  115.         exit(1);  
  116.   
  117.     }  
  118.   
  119.       
  120.   
  121.     close(fd);  
  122.   
  123.    
  124.   
  125.     return 0;  
  126.   
  127.       
  128.   
  129.     //return (*env)->NewStringUTF(env, "Hello ww JNI !");  
  130.   
  131.       
  132.   
  133. }  


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

[java] view plaincopyprint?
  1. package com.yecon.CtlBL;  
  2.   
  3.    
  4.   
  5. import android.app.Activity;  
  6.   
  7. import android.os.Bundle;  
  8.   
  9. import android.view.View;  
  10.   
  11. import android.view.View.OnClickListener;  
  12.   
  13. import android.widget.Button;  
  14.   
  15. import android.widget.TextView;  
  16.   
  17.    
  18.   
  19. //import com.yecon.CtlBL.ctlbljni;  
  20.   
  21.    
  22.   
  23. public class CtlBLActivity extends Activity {  
  24.   
  25.     Button b  = null;  
  26.   
  27.      
  28.   
  29. //    ctl = new ctlbljni();   
  30.   
  31.     private OnClickListener clickListener = new OnClickListener(){  
  32.   
  33.    
  34.   
  35.         @Override  
  36.   
  37.         public void onClick(View v) {  
  38.   
  39.             // TODO Auto-generated method stub  
  40.   
  41.  //           ctl.ctlbl();   
  42.   
  43.               ctlbl();  
  44.   
  45.         }  
  46.   
  47.     };  
  48.   
  49.             
  50.   
  51.     /** Called when the activity is first created. */  
  52.   
  53.     @Override  
  54.   
  55.     public void onCreate(Bundle savedInstanceState) {  
  56.   
  57.         super.onCreate(savedInstanceState);  
  58.   
  59.         setContentView(R.layout.main);  
  60.   
  61.         b = (Button) this.findViewById(R.id.BtnCancel);  
  62.   
  63.         b.setOnClickListener(clickListener);  
  64.   
  65. //        TextView  tv = new TextView(this);  
  66.   
  67.  //       tv.setText( ctlbl() );  
  68.   
  69.  //       setContentView(tv);   
  70.   
  71.     }  
  72.   
  73.       
  74.   
  75.     public native int ctlbl();//本地方法  
  76.   
  77.       
  78.   
  79.     static {  
  80.   
  81.         System.loadLibrary("ctlbl");//载入so库  
  82.   
  83.     }  
  84.   
  85. }  


 

看上去,没几行代码,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 plaincopyprint?
  1. public void setBacklightBrightness (int brightness) {  
  2.   
  3.         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);  
  4.   
  5.         // Don't let applications turn the screen all the way off  
  6.   
  7.         synchronized (mLocks) {  
  8.   
  9.             brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);  
  10.   
  11.             mLcdLight.setBrightness(brightness);  
  12.   
  13.             //We won't adjust Button/Keyboard BKL here for the time being, see CR[ALPS00132847]  
  14.   
  15.             //mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);  
  16.   
  17.             //mButtonLight.setBrightness(brightness);  
  18.   
  19.             long identity = Binder.clearCallingIdentity();  
  20.   
  21.             try {  
  22.   
  23.                 mBatteryStats.noteScreenBrightness(brightness);  
  24.   
  25.             } catch (RemoteException e) {  
  26.   
  27.                 Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);  
  28.   
  29.             } finally {  
  30.   
  31.                 Binder.restoreCallingIdentity(identity);  
  32.   
  33.             }  
  34.   
  35.    
  36.   
  37.             // update our animation state  
  38.   
  39.             synchronized (mLocks) {  
  40.   
  41.                 mScreenBrightness.targetValue = brightness;  
  42.   
  43.                 mScreenBrightness.jumpToTargetLocked();  
  44.   
  45.             }  
  46.   
  47.         }  
  48.   
  49.     }  

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

    private LightsService.Light mLcdLight;

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

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

 

[java] view plaincopyprint?
  1. public void setBrightness(int brightness) {  
  2.   
  3.             setBrightness(brightness, BRIGHTNESS_MODE_USER);  
  4.   
  5.         }  
  6.   
  7.    
  8.   
  9.         public void setBrightness(int brightness, int brightnessMode) {  
  10.   
  11.             synchronized (this) {  
  12.   
  13.                 int color = brightness & 0x000000ff;  
  14.   
  15.                 color = 0xff000000 | (color << 16) | (color << 8) | color;  
  16.   
  17.                 setLightLocked(color, LIGHT_FLASH_NONE, 00, brightnessMode);  
  18.   
  19.             }  
  20.   
  21.         }  


 

这里又调用了setLightLocked()

[java] view plaincopyprint?
  1. private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {  
  2.   
  3.             if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {  
  4.   
  5.                 mColor = color;  
  6.   
  7.                 mMode = mode;  
  8.   
  9.                 mOnMS = onMS;  
  10.   
  11.                 mOffMS = offMS;  
  12.   
  13.                 setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);  
  14.   
  15.             }  
  16.   
  17.         }  


 

革命的曙光来啦,看到没,这里调用了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 plaincopyprint?
  1. static void setLight_native(JNIEnv *env, jobject clazz, int ptr,  
  2.   
  3.         int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode)  
  4.   
  5. {  
  6.   
  7.     Devices* devices = (Devices*)ptr;  
  8.   
  9.     light_state_t state;  
  10.   
  11.    
  12.   
  13.     if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {  
  14.   
  15.         return ;  
  16.   
  17.     }  
  18.   
  19.    
  20.   
  21.     memset(&state, 0, sizeof(light_state_t));  
  22.   
  23.     state.color = colorARGB;  
  24.   
  25.     state.flashMode = flashMode;  
  26.   
  27.     state.flashOnMS = onMS;  
  28.   
  29.     state.flashOffMS = offMS;  
  30.   
  31.     state.brightnessMode = brightnessMode;  
  32.   
  33.    
  34.   
  35.     devices->lights[light]->set_light(devices->lights[light], &state);  
  36.   
  37. }  
  38.   
  39.    
  40.   
  41. static JNINativeMethod method_table[] = {  
  42.   
  43.     { "init_native""()I", (void*)init_native },  
  44.   
  45.     { "finalize_native""(I)V", (void*)finalize_native },  
  46.   
  47.     { "setLight_native""(IIIIIII)V", (void*)setLight_native },  
  48.   
  49. };  


 

哇,高手就是高手啊。看看,一个函数人家处理的不只是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 plaincopyprint?
  1. /** 
  2.  
  3.  * module methods 
  4.  
  5.  */  
  6.   
  7.    
  8.   
  9. /** Open a new instance of a lights device using name */  
  10.   
  11. static int open_lights(const struct hw_module_t* module, char const* name,  
  12.   
  13.         struct hw_device_t** device)  
  14.   
  15. {  
  16.   
  17.     int (*set_light)(struct light_device_t* dev,  
  18.   
  19.             struct light_state_t const* state);  
  20.   
  21.    
  22.   
  23.     if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {  
  24.   
  25.         set_light = set_light_backlight;  
  26.   
  27.     }  
  28.   
  29.     else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {  
  30.   
  31.         set_light = set_light_keyboard;  
  32.   
  33.     }  
  34.   
  35.     else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {  
  36.   
  37.         set_light = set_light_buttons;  
  38.   
  39.     }  
  40.   
  41.     else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {  
  42.   
  43.         set_light = set_light_battery;  
  44.   
  45.     }  
  46.   
  47.     else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {  
  48.   
  49.         set_light = set_light_notifications;  
  50.   
  51.     }  
  52.   
  53.     else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {  
  54.   
  55.         set_light = set_light_attention;  
  56.   
  57.     }  
  58.   
  59.     else {  
  60.   
  61.         return -EINVAL;  
  62.   
  63.     }  
  64.   
  65.    
  66.   
  67.     pthread_once(&g_init, init_globals);  
  68.   
  69.    
  70.   
  71.     struct light_device_t *dev = malloc(sizeof(struct light_device_t));  
  72.   
  73.     memset(dev, 0, sizeof(*dev));  
  74.   
  75.    
  76.   
  77.     dev->common.tag = HARDWARE_DEVICE_TAG;  
  78.   
  79.     dev->common.version = 0;  
  80.   
  81.     dev->common.module = (struct hw_module_t*)module;  
  82.   
  83.     dev->common.close = (int (*)(struct hw_device_t*))close_lights;  
  84.   
  85.     dev->set_light = set_light;  
  86.   
  87.    
  88.   
  89.     *device = (struct hw_device_t*)dev;  
  90.   
  91.     return 0;  
  92.   
  93. }  


 

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

[html] view plaincopyprint?
  1. static int  
  2.   
  3. set_light_backlight(struct light_device_t* dev,  
  4.   
  5.         struct light_state_t const* state)  
  6.   
  7. {  
  8.   
  9.     int err = 0;  
  10.   
  11.     int brightness = rgb_to_brightness(state);  
  12.   
  13.     pthread_mutex_lock(&g_lock);  
  14.   
  15.     LOGD("%s: brightness=%d start+++\n", __func__, brightness);  
  16.   
  17.     g_backlight = brightness;  
  18.   
  19.     err = write_int(LCD_FILE, brightness);  
  20.   
  21.     if (g_haveTrackballLight) {  
  22.   
  23.         handle_trackball_light_locked(dev);  
  24.   
  25.     }  
  26.   
  27.     pthread_mutex_unlock(&g_lock);  
  28.   
  29.     return err;  
  30.   
  31. }  


 

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

 

 

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

原创粉丝点击