Android中背光系統架構

來源:互聯網
上載者:User

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介面的源碼如下:

 

#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>//#include <dirent.h>  //#include <jni.h>#include <string.h>#include <android/log.h> #include "com_yecon_CtlBL_CtlBLActivity.h" #define  LOG_TAG    "ctlbl.c"#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)//#define DEV_PATH "/sys/class/leds/lcd-backlight/brightness"//#define DEV_PATH "/sys/devices/platform/leds-mt65xx/leds/lcd-backlight/brightness" /** * native method *///JNIEXPORT jobjectArray JNICALL Java_com_yecon_CtlBL_CtlBLActivity_ctlbl(JNIEnv * env, jobject obj)JNIEXPORT jint JNICALL Java_com_yecon_CtlBL_CtlBLActivity_ctlbl(JNIEnv * env, jobject obj){      int fd;    int err;    char *p;    char ctl[10]={"20"};    LOGI("HELLO!\n");    //__android_log_print("");    //printf("call ctlbl function succ!\n");    fd = open("/sys/class/leds/lcd-backlight/brightness",O_RDWR);    if(fd < 0)    {        //fprintf(stderr,"error: open %s\n",DEV_PATH);        LOGI("error: open!\n");        exit(1);    }#if 0    err = read(fd,ctl,1);    if(err != 1)    {        //fprintf(stderr,"error: write %d!\n",err);                exit(1);    }else{        //printf("the data is %s\n",ctl[0]);    }#endif    err=write(fd,ctl,2);    //printf("%s\n",ctl);    if(err != 2)    {        //fprintf(stderr,"error: write %d!\n",err);        LOGI("error: write !\n");        exit(1);    }        close(fd);     return 0;        //return (*env)->NewStringUTF(env, "Hello ww JNI !");    }

上層Java調用的源碼如下:(只是實現了一個Button,點擊,有一個訊息響應,將背光調到20)

package com.yecon.CtlBL; import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView; //import com.yecon.CtlBL.ctlbljni; public class CtlBLActivity extends Activity {    Button b  = null;   //    ctl = new ctlbljni();    private OnClickListener clickListener = new OnClickListener(){         @Override        public void onClick(View v) {            // TODO Auto-generated method stub //           ctl.ctlbl();              ctlbl();        }    };              /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        b = (Button) this.findViewById(R.id.BtnCancel);        b.setOnClickListener(clickListener);//        TextView  tv = new TextView(this); //       tv.setText( ctlbl() ); //       setContentView(tv);    }        public native int ctlbl();//本地方法        static {        System.loadLibrary("ctlbl");//載入so庫    }}

 

看上去,沒幾行代碼,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中。

public void setBacklightBrightness (int brightness) {        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);        // Don't let applications turn the screen all the way off        synchronized (mLocks) {            brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);            mLcdLight.setBrightness(brightness);            //We won't adjust Button/Keyboard BKL here for the time being, see CR[ALPS00132847]            //mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);            //mButtonLight.setBrightness(brightness);            long identity = Binder.clearCallingIdentity();            try {                mBatteryStats.noteScreenBrightness(brightness);            } catch (RemoteException e) {                Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);            } finally {                Binder.restoreCallingIdentity(identity);            }             // update our animation state            synchronized (mLocks) {                mScreenBrightness.targetValue = brightness;                mScreenBrightness.jumpToTargetLocked();            }        }    }

看著看著又模糊啦,這裡怎麼又調用了setBrightness()哦,此setBrightness非BrightnessPreference.java中的setBrightness。其類屬於:

    private LightsService.Light mLcdLight;

革命尚未成功,你說咋辦,那好吧,為了革命的勝利,再進去看看這個類中setBrightness()的實現吧。源碼路徑為:

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

 

public void setBrightness(int brightness) {            setBrightness(brightness, BRIGHTNESS_MODE_USER);        }         public void setBrightness(int brightness, int brightnessMode) {            synchronized (this) {                int color = brightness & 0x000000ff;                color = 0xff000000 | (color << 16) | (color << 8) | color;                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);            }        }

 

這裡又調用了setLightLocked()

private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {            if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {                mColor = color;                mMode = mode;                mOnMS = onMS;                mOffMS = offMS;                setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);            }        }

 

革命的曙光來啦,看到沒,這裡調用了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層

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);} static JNINativeMethod method_table[] = {    { "init_native", "()I", (void*)init_native },    { "finalize_native", "(I)V", (void*)finalize_native },    { "setLight_native", "(IIIIIII)V", (void*)setLight_native },};

 

哇,高手就是高手啊。看看,一個函數人家處理的不只是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中啊。真是罪孽啊~~

/** * module methods */ /** 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;}

 

看看吧,其實我們需要找的就是set_light_backlight。

static intset_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);    LOGD("%s: brightness=%d start+++\n", __func__, brightness);    g_backlight = brightness;    err = write_int(LCD_FILE, brightness);    if (g_haveTrackballLight) {        handle_trackball_light_locked(dev);    }    pthread_mutex_unlock(&g_lock);    return err;}

 

當你認真看完lights.c會發現其基本思想跟之前的設想一樣,只是人家是高手,我是菜鳥,人家看到赤裸裸的美女不是表面,而是藝術~~~~!!

 

 

通過這個分析,可以延伸瞭解到led燈的結構。

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.