android button light 流程分析(三) — framework

一、初始化信息

首先看看Android中的幾種電源狀態定義,這幾個值定義了不同的led開閉狀態以及lcd背光的不同亮度模式:

  1. // flags for setPowerState  
  2. private static final int SCREEN_ON_BIT          = 0x00000001;  
  3. private static final int SCREEN_BRIGHT_BIT      = 0x00000002;  
  4. private static final int BUTTON_BRIGHT_BIT      = 0x00000004;  
  5. private static final int KEYBOARD_BRIGHT_BIT    = 0x00000008;  
  6. private static final int BATTERY_LOW_BIT        = 0x00000010;  
  7.   
  8. // values for setPowerState  
  9.   
  10. // SCREEN_OFF == everything off  
  11. private static final int SCREEN_OFF         = 0x00000000;  
  12.   
  13. // SCREEN_DIM == screen on, screen backlight dim  
  14. private static final int SCREEN_DIM         = SCREEN_ON_BIT;  
  15.   
  16. // SCREEN_BRIGHT == screen on, screen backlight bright  
  17. private static final int SCREEN_BRIGHT      = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;  
  18.   
  19. // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright  
  20. private static final int SCREEN_BUTTON_BRIGHT  = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;  
  21.   
  22. // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright  
  23. private static final int ALL_BRIGHT         = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;  
  24.   
  25. // used for noChangeLights in setPowerState()  
  26. private static final int LIGHTS_MASK        = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;  
    // flags for setPowerState
    private static final int SCREEN_ON_BIT          = 0x00000001;
    private static final int SCREEN_BRIGHT_BIT      = 0x00000002;
    private static final int BUTTON_BRIGHT_BIT      = 0x00000004;
    private static final int KEYBOARD_BRIGHT_BIT    = 0x00000008;
    private static final int BATTERY_LOW_BIT        = 0x00000010;

    // values for setPowerState

    // SCREEN_OFF == everything off
    private static final int SCREEN_OFF         = 0x00000000;

    // SCREEN_DIM == screen on, screen backlight dim
    private static final int SCREEN_DIM         = SCREEN_ON_BIT;

    // SCREEN_BRIGHT == screen on, screen backlight bright
    private static final int SCREEN_BRIGHT      = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;

    // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
    private static final int SCREEN_BUTTON_BRIGHT  = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;

    // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
    private static final int ALL_BRIGHT         = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;

    // used for noChangeLights in setPowerState()
    private static final int LIGHTS_MASK        = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;

在frameworks/base/core/res/res/values/config.xml中配置自動背光的總開關mUseSoftwareAutoBrightness以及自動背光模式下的背光數值,如果沒有lightsensor用於自動背光調整,則需要將mUseSoftwareAutoBrightness配置爲false,配置項如下:

  1. <bool name="config_automatic_brightness_available">true</bool>  
  2.   
  3. <!-- Array of light sensor LUX values to define our levels for auto backlight brightness support.  
  4.      The N entries of this array define N + 1 zones as follows:  
  5.   
  6.      Zone 0:        0 <= LUX < array[0]  
  7.      Zone 1:        array[0] <= LUX < array[1]  
  8.      ...  
  9.      Zone N:        array[N - 1] <= LUX < array[N]  
  10.      Zone N + 1:    array[N] <= LUX < infinity  
  11.   
  12.      Must be overridden in platform specific overlays -->  
  13. <integer-array name="config_autoBrightnessLevels">  
  14.     <item>3</item>  
  15.     <item>10</item>  
  16.     <item>40</item>  
  17.     <item>65</item>  
  18.     <item>145</item>  
  19.     <item>300</item>  
  20.     <item>550</item>  
  21.     <item>930</item>  
  22.     <item>1250</item>  
  23. </integer-array>  
  24.   
  25. <!-- Array of output values for LCD backlight corresponding to the LUX values  
  26.      in the config_autoBrightnessLevels array.  This array should have size one greater  
  27.      than the size of the config_autoBrightnessLevels array.  
  28.      This must be overridden in platform specific overlays -->  
  29. <integer-array name="config_autoBrightnessLcdBacklightValues">  
  30.     <item>101</item>  
  31.     <item>117</item>  
  32.     <item>142</item>  
  33.     <item>183</item>  
  34.     <item>195</item>  
  35.     <item>216</item>  
  36.     <item>234</item>  
  37.     <item>245</item>  
  38.     <item>250</item>  
  39.     <item>250</item>  
  40. </integer-array>  
  41.   
  42. <!-- Array of output values for button backlight corresponding to the LUX values  
  43.      in the config_autoBrightnessLevels array.  This array should have size one greater  
  44.      than the size of the config_autoBrightnessLevels array.  
  45.      This must be overridden in platform specific overlays -->  
  46. <integer-array name="config_autoBrightnessButtonBacklightValues">  
  47.     <item>255</item>  
  48.     <item>255</item>  
  49.     <item>255</item>  
  50.     <item>0</item>  
  51.     <item>0</item>  
  52.     <item>0</item>  
  53.     <item>0</item>  
  54.     <item>0</item>  
  55.     <item>0</item>  
  56.     <item>0</item>  
  57. </integer-array>  
  58.   
  59. <!-- Array of output values for keyboard backlight corresponding to the LUX values  
  60.      in the config_autoBrightnessLevels array.  This array should have size one greater  
  61.      than the size of the config_autoBrightnessLevels array.  
  62.      This must be overridden in platform specific overlays -->  
  63. <integer-array name="config_autoBrightnessKeyboardBacklightValues">  
  64. </integer-array>  
    <bool name="config_automatic_brightness_available">true</bool>

    <!-- Array of light sensor LUX values to define our levels for auto backlight brightness support.
         The N entries of this array define N + 1 zones as follows:

         Zone 0:        0 <= LUX < array[0]
         Zone 1:        array[0] <= LUX < array[1]
         ...
         Zone N:        array[N - 1] <= LUX < array[N]
         Zone N + 1:    array[N] <= LUX < infinity

         Must be overridden in platform specific overlays -->
    <integer-array name="config_autoBrightnessLevels">
        <item>3</item>
        <item>10</item>
        <item>40</item>
        <item>65</item>
        <item>145</item>
        <item>300</item>
        <item>550</item>
        <item>930</item>
        <item>1250</item>
    </integer-array>

    <!-- Array of output values for LCD backlight corresponding to the LUX values
         in the config_autoBrightnessLevels array.  This array should have size one greater
         than the size of the config_autoBrightnessLevels array.
         This must be overridden in platform specific overlays -->
    <integer-array name="config_autoBrightnessLcdBacklightValues">
        <item>101</item>
        <item>117</item>
        <item>142</item>
        <item>183</item>
        <item>195</item>
        <item>216</item>
        <item>234</item>
        <item>245</item>
        <item>250</item>
        <item>250</item>
    </integer-array>

    <!-- Array of output values for button backlight corresponding to the LUX values
         in the config_autoBrightnessLevels array.  This array should have size one greater
         than the size of the config_autoBrightnessLevels array.
         This must be overridden in platform specific overlays -->
    <integer-array name="config_autoBrightnessButtonBacklightValues">
        <item>255</item>
        <item>255</item>
        <item>255</item>
        <item>0</item>
        <item>0</item>
        <item>0</item>
        <item>0</item>
        <item>0</item>
        <item>0</item>
        <item>0</item>
    </integer-array>

    <!-- Array of output values for keyboard backlight corresponding to the LUX values
         in the config_autoBrightnessLevels array.  This array should have size one greater
         than the size of the config_autoBrightnessLevels array.
         This must be overridden in platform specific overlays -->
    <integer-array name="config_autoBrightnessKeyboardBacklightValues">
    </integer-array>

在初始化的時候會調用如下代碼獲取配置信息:

  1. // 獲取系統默認配置  
  2. Resources resources = mContext.getResources();  
  3. // 屏幕動畫是否開啓  
  4. mAnimateScreenLights = resources.getBoolean(  
  5.         com.android.internal.R.bool.config_animateScreenLights);  
  6.   
  7. mUnplugTurnsOnScreen = resources.getBoolean(  
  8.         com.android.internal.R.bool.config_unplugTurnsOnScreen);  
  9. // 軟件自動背光調整是否打開  
  10. mUseSoftwareAutoBrightness = resources.getBoolean(  
  11.         com.android.internal.R.bool.config_automatic_brightness_available);  
  12. // 讀取自動背光參考值  
  13. if (mUseSoftwareAutoBrightness) {  
  14.     mAutoBrightnessLevels = resources.getIntArray(  
  15.             com.android.internal.R.array.config_autoBrightnessLevels);  
  16.     mLcdBacklightValues = resources.getIntArray(  // lcd背光值  
  17.             com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);  
  18.     mButtonBacklightValues = resources.getIntArray(  // button背光值  
  19.             com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);  
  20.     mKeyboardBacklightValues = resources.getIntArray(  // keyboard背光值  
  21.             com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);  
  22.     mLightSensorWarmupTime = resources.getInteger(  
  23.             com.android.internal.R.integer.config_lightSensorWarmupTime);  
  24. }  
        // 獲取系統默認配置
        Resources resources = mContext.getResources();
        // 屏幕動畫是否開啓
        mAnimateScreenLights = resources.getBoolean(
                com.android.internal.R.bool.config_animateScreenLights);

        mUnplugTurnsOnScreen = resources.getBoolean(
                com.android.internal.R.bool.config_unplugTurnsOnScreen);
        // 軟件自動背光調整是否打開
        mUseSoftwareAutoBrightness = resources.getBoolean(
                com.android.internal.R.bool.config_automatic_brightness_available);
        // 讀取自動背光參考值
        if (mUseSoftwareAutoBrightness) {
            mAutoBrightnessLevels = resources.getIntArray(
                    com.android.internal.R.array.config_autoBrightnessLevels);
            mLcdBacklightValues = resources.getIntArray(  // lcd背光值
                    com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
            mButtonBacklightValues = resources.getIntArray(  // button背光值
                    com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
            mKeyboardBacklightValues = resources.getIntArray(  // keyboard背光值
                    com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
            mLightSensorWarmupTime = resources.getInteger(
                    com.android.internal.R.integer.config_lightSensorWarmupTime);
        }

二、代碼流程分析

在Android中,如果framework層接收到輸入事件就會調用PowerManagerService裏面的userActivity()去設置系統的下一個電源狀態,流程圖如下:


當調用userActivity()之後,將進行一些事件類型和狀態的判斷並先後調用setPowerState()設置新的狀態、setTimeoutLocked()設置新狀態超時後的狀態,代碼分析如下:

  1. private void userActivity(long time, long timeoutOverride, boolean noChangeLights,  
  2.         int eventType, boolean force) {  
  3.     // 檢測是否忽略CHEEK_EVENT事件  
  4.     if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)  
  5.             && (eventType == CHEEK_EVENT)) {  
  6.         if (false) {  
  7.             Slog.d(TAG, "dropping cheek event mPokey=0x" + Integer.toHexString(mPokey));  
  8.         }  
  9.         return;  
  10.     }  
  11.     // 檢測是否忽略CHEEK_EVENT與TOUCH事件  
  12.     if (((mPokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0)  
  13.             && (eventType == TOUCH_EVENT || eventType == TOUCH_UP_EVENT  
  14.                 || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT)) {  
  15.         if (false) {  
  16.             Slog.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));  
  17.         }  
  18.         return;  
  19.     }  
  20.   
  21.     if (false) {  
  22.         if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {  
  23.             Slog.d(TAG, "userActivity !!!");//, new RuntimeException());  
  24.         } else {  
  25.             Slog.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey));  
  26.         }  
  27.     }  
  28.   
  29.     synchronized (mLocks) {  
  30.         if (mSpew) {  
  31.             Slog.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time  
  32.                     + " mUserActivityAllowed=" + mUserActivityAllowed  
  33.                     + " mUserState=0x" + Integer.toHexString(mUserState)  
  34.                     + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)  
  35.                     + " mProximitySensorActive=" + mProximitySensorActive  
  36.                     + " timeoutOverride=" + timeoutOverride  
  37.                     + " force=" + force  
  38.                     + " eventType=" + eventType);  
  39.         }  
  40.         // 如果當前屏幕爲關閉狀態則不處理  
  41.         if (isScreenTurningOffLocked()) {  
  42.             Slog.d(TAG, "ignoring user activity while turning off screen");  
  43.             return;  
  44.         }  
  45.         // 如果正在等待距離傳感器爲負值時用戶按下power鍵則關閉距離傳感器功能  
  46.         if (mProximitySensorActive && mProximityWakeLockCount == 0) {  
  47.             mProximitySensorActive = false;  
  48.         }  
  49.         if (mLastEventTime <= time || force) {  // 判斷事件是否爲最新的  
  50.             mLastEventTime = time;  
  51.             if ((mUserActivityAllowed && !mProximitySensorActive) || force) {  
  52.                 // 在用戶點擊觸摸屏或者虛擬按鍵並且不是自動背光狀態時設置下一個狀態爲全亮  
  53.                 if ((eventType == BUTTON_EVENT || eventType == TOUCH_EVENT  
  54.                     || eventType == TOUCH_UP_EVENT || eventType == LONG_TOUCH_EVENT)  
  55.                         && (!mUseSoftwareAutoBrightness || !mAutoBrightessEnabled)) {  
  56.                     mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);  
  57.                 } else {  
  58.                     // 設置系統下一個狀態爲SCREEN_BRIGHT,並保留上次狀態  
  59.                     mUserState |= SCREEN_BRIGHT;  
  60.                 }  
  61.   
  62.                 int uid = Binder.getCallingUid();  
  63.                 long ident = Binder.clearCallingIdentity();  
  64.                 try {  
  65.                     mBatteryStats.noteUserActivity(uid, eventType);  
  66.                 } catch (RemoteException e) {  
  67.                     // Ignore  
  68.                 } finally {  
  69.                     Binder.restoreCallingIdentity(ident);  
  70.                 }  
  71.                 // 獲取當前WakeLock狀態  
  72.                 mWakeLockState = mLocks.reactivateScreenLocksLocked();  
  73.                 // 設置下一個狀態  
  74.                 setPowerState(mUserState | mWakeLockState, noChangeLights,  
  75.                         WindowManagerPolicy.OFF_BECAUSE_OF_USER);  
  76.                 // 設置超時後的狀態  
  77.                 setTimeoutLocked(time, timeoutOverride, SCREEN_BRIGHT);  
  78.             }  
  79.         }  
  80.     }  
  81.   
  82.     if (mPolicy != null) {  
  83.         mPolicy.userActivity();  
  84.     }  
  85. }  
    private void userActivity(long time, long timeoutOverride, boolean noChangeLights,
            int eventType, boolean force) {
        // 檢測是否忽略CHEEK_EVENT事件
        if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)
                && (eventType == CHEEK_EVENT)) {
            if (false) {
                Slog.d(TAG, "dropping cheek event mPokey=0x" + Integer.toHexString(mPokey));
            }
            return;
        }
        // 檢測是否忽略CHEEK_EVENT與TOUCH事件
        if (((mPokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0)
                && (eventType == TOUCH_EVENT || eventType == TOUCH_UP_EVENT
                    || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT)) {
            if (false) {
                Slog.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
            }
            return;
        }

        if (false) {
            if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {
                Slog.d(TAG, "userActivity !!!");//, new RuntimeException());
            } else {
                Slog.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey));
            }
        }

        synchronized (mLocks) {
            if (mSpew) {
                Slog.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
                        + " mUserActivityAllowed=" + mUserActivityAllowed
                        + " mUserState=0x" + Integer.toHexString(mUserState)
                        + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
                        + " mProximitySensorActive=" + mProximitySensorActive
                        + " timeoutOverride=" + timeoutOverride
                        + " force=" + force
                        + " eventType=" + eventType);
            }
            // 如果當前屏幕爲關閉狀態則不處理
            if (isScreenTurningOffLocked()) {
                Slog.d(TAG, "ignoring user activity while turning off screen");
                return;
            }
            // 如果正在等待距離傳感器爲負值時用戶按下power鍵則關閉距離傳感器功能
            if (mProximitySensorActive && mProximityWakeLockCount == 0) {
                mProximitySensorActive = false;
            }
            if (mLastEventTime <= time || force) {  // 判斷事件是否爲最新的
                mLastEventTime = time;
                if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
                    // 在用戶點擊觸摸屏或者虛擬按鍵並且不是自動背光狀態時設置下一個狀態爲全亮
                    if ((eventType == BUTTON_EVENT || eventType == TOUCH_EVENT
                        || eventType == TOUCH_UP_EVENT || eventType == LONG_TOUCH_EVENT)
                            && (!mUseSoftwareAutoBrightness || !mAutoBrightessEnabled)) {
                        mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
                    } else {
                        // 設置系統下一個狀態爲SCREEN_BRIGHT,並保留上次狀態
                        mUserState |= SCREEN_BRIGHT;
                    }

                    int uid = Binder.getCallingUid();
                    long ident = Binder.clearCallingIdentity();
                    try {
                        mBatteryStats.noteUserActivity(uid, eventType);
                    } catch (RemoteException e) {
                        // Ignore
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                    // 獲取當前WakeLock狀態
                    mWakeLockState = mLocks.reactivateScreenLocksLocked();
                    // 設置下一個狀態
                    setPowerState(mUserState | mWakeLockState, noChangeLights,
                            WindowManagerPolicy.OFF_BECAUSE_OF_USER);
                    // 設置超時後的狀態
                    setTimeoutLocked(time, timeoutOverride, SCREEN_BRIGHT);
                }
            }
        }

        if (mPolicy != null) {
            mPolicy.userActivity();
        }
    }

  1. private void setTimeoutLocked(long now, final long originalTimeoutOverride, int nextState) {  
  2.     long timeoutOverride = originalTimeoutOverride;  // 超時時間  
  3.     if (mBootCompleted) {  // 判斷系統是否啓動完成  
  4.         synchronized (mLocks) {  
  5.             long when = 0;  
  6.             if (timeoutOverride <= 0) {  
  7.                 switch (nextState)  
  8.                 {  
  9.                     case SCREEN_BRIGHT:  
  10.                         when = now + mKeylightDelay;  // 關閉按鍵燈的時間  
  11.                         break;  
  12.                     case SCREEN_DIM:  
  13.                         if (mDimDelay >= 0) {  
  14.                             when = now + mDimDelay;  // 屏幕亮度降低的時間  
  15.                             break;  
  16.                         } else {  
  17.                             Slog.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");  
  18.                         }  
  19.                    case SCREEN_OFF:  
  20.                         synchronized (mLocks) {  
  21.                             when = now + mScreenOffDelay;  // 關閉屏幕時間  
  22.                         }  
  23.                         break;  
  24.                     default:  
  25.                         when = now;  
  26.                         break;  
  27.                 }  
  28.             } else {  // 如果指定了originalTimeoutOverride  
  29.                 override: {  
  30.                     if (timeoutOverride <= mScreenOffDelay) {  
  31.                         when = now + timeoutOverride;  
  32.                         nextState = SCREEN_OFF;  
  33.                         break override;  
  34.                     }  
  35.                     timeoutOverride -= mScreenOffDelay;  
  36.   
  37.                     if (mDimDelay >= 0) {  
  38.                          if (timeoutOverride <= mDimDelay) {  
  39.                             when = now + timeoutOverride;  
  40.                             nextState = SCREEN_DIM;  
  41.                             break override;  
  42.                         }  
  43.                         timeoutOverride -= mDimDelay;  
  44.                     }  
  45.   
  46.                     when = now + timeoutOverride;  
  47.                     nextState = SCREEN_BRIGHT;  
  48.                 }  
  49.             }  
  50.             if (mSpew) {  
  51.                 Slog.d(TAG, "setTimeoutLocked now=" + now  
  52.                         + " timeoutOverride=" + timeoutOverride  
  53.                         + " nextState=" + nextState + " when=" + when);  
  54.             }  
  55.   
  56.             mHandler.removeCallbacks(mTimeoutTask);  // 清除超時任務  
  57.             mTimeoutTask.nextState = nextState;  // 設置超時後的狀態  
  58.             mTimeoutTask.remainingTimeoutOverride = timeoutOverride > 0  
  59.                     ? (originalTimeoutOverride - timeoutOverride)  
  60.                     : -1;  
  61.             mHandler.postAtTime(mTimeoutTask, when);  // 啓動超時任務  
  62.             mNextTimeout = when; // for debugging  
  63.         }  
  64.     }  
  65. }  
    private void setTimeoutLocked(long now, final long originalTimeoutOverride, int nextState) {
        long timeoutOverride = originalTimeoutOverride;  // 超時時間
        if (mBootCompleted) {  // 判斷系統是否啓動完成
            synchronized (mLocks) {
                long when = 0;
                if (timeoutOverride <= 0) {
                    switch (nextState)
                    {
                        case SCREEN_BRIGHT:
                            when = now + mKeylightDelay;  // 關閉按鍵燈的時間
                            break;
                        case SCREEN_DIM:
                            if (mDimDelay >= 0) {
                                when = now + mDimDelay;  // 屏幕亮度降低的時間
                                break;
                            } else {
                                Slog.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
                            }
                       case SCREEN_OFF:
                            synchronized (mLocks) {
                                when = now + mScreenOffDelay;  // 關閉屏幕時間
                            }
                            break;
                        default:
                            when = now;
                            break;
                    }
                } else {  // 如果指定了originalTimeoutOverride
                    override: {
                        if (timeoutOverride <= mScreenOffDelay) {
                            when = now + timeoutOverride;
                            nextState = SCREEN_OFF;
                            break override;
                        }
                        timeoutOverride -= mScreenOffDelay;

                        if (mDimDelay >= 0) {
                             if (timeoutOverride <= mDimDelay) {
                                when = now + timeoutOverride;
                                nextState = SCREEN_DIM;
                                break override;
                            }
                            timeoutOverride -= mDimDelay;
                        }

                        when = now + timeoutOverride;
                        nextState = SCREEN_BRIGHT;
                    }
                }
                if (mSpew) {
                    Slog.d(TAG, "setTimeoutLocked now=" + now
                            + " timeoutOverride=" + timeoutOverride
                            + " nextState=" + nextState + " when=" + when);
                }

                mHandler.removeCallbacks(mTimeoutTask);  // 清除超時任務
                mTimeoutTask.nextState = nextState;  // 設置超時後的狀態
                mTimeoutTask.remainingTimeoutOverride = timeoutOverride > 0
                        ? (originalTimeoutOverride - timeoutOverride)
                        : -1;
                mHandler.postAtTime(mTimeoutTask, when);  // 啓動超時任務
                mNextTimeout = when; // for debugging
            }
        }
    }

  1. private class TimeoutTask implements Runnable  
  2. {  
  3.     int nextState; // access should be synchronized on mLocks  
  4.     long remainingTimeoutOverride;  
  5.     public void run()  
  6.     {  
  7.         synchronized (mLocks) {  
  8.             if (mSpew) {  
  9.                 Slog.d(TAG, "user activity timeout timed out nextState=" + this.nextState);  
  10.             }  
  11.   
  12.             if (nextState == -1) {  
  13.                 return;  
  14.             }  
  15.   
  16.             mUserState = this.nextState;  // 設置全局變量  
  17.             setPowerState(this.nextState | mWakeLockState);  // 設置電源狀態  
  18.   
  19.             long now = SystemClock.uptimeMillis();  
  20.   
  21.             switch (this.nextState)  // 設置超時後的下一個狀態  
  22.             {  
  23.                 case SCREEN_BRIGHT:  // 如果當前屏幕全亮則下一狀態爲暗屏  
  24.                     if (mDimDelay >= 0) {  
  25.                         setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_DIM);  
  26.                         break;  
  27.                     }  
  28.                 case SCREEN_DIM:  // 如果當前屏幕爲暗屏則下一狀態爲熄屏  
  29.                     setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_OFF);  
  30.                     break;  
  31.             }  
  32.         }  
  33.     }  
  34. }  
    private class TimeoutTask implements Runnable
    {
        int nextState; // access should be synchronized on mLocks
        long remainingTimeoutOverride;
        public void run()
        {
            synchronized (mLocks) {
                if (mSpew) {
                    Slog.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
                }

                if (nextState == -1) {
                    return;
                }

                mUserState = this.nextState;  // 設置全局變量
                setPowerState(this.nextState | mWakeLockState);  // 設置電源狀態

                long now = SystemClock.uptimeMillis();

                switch (this.nextState)  // 設置超時後的下一個狀態
                {
                    case SCREEN_BRIGHT:  // 如果當前屏幕全亮則下一狀態爲暗屏
                        if (mDimDelay >= 0) {
                            setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_DIM);
                            break;
                        }
                    case SCREEN_DIM:  // 如果當前屏幕爲暗屏則下一狀態爲熄屏
                        setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_OFF);
                        break;
                }
            }
        }
    }

在setPowerState()中如果leds有變化則調用updateLightsLocked()更新leds的狀態,如果lcd新狀態和當前狀態不同,則可能需要調用setScreenStateLocked()處理系統的休眠和喚醒流程,代碼分析如下:

  1. private void setPowerState(int newState, boolean noChangeLights, int reason)  
  2. {  
  3.     synchronized (mLocks) {  
  4.         int err;  
  5.   
  6.         if (mSpew) {  
  7.             Slog.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)  
  8.                     + " newState=0x" + Integer.toHexString(newState)  
  9.                     + " noChangeLights=" + noChangeLights  
  10.                     + " reason=" + reason);  
  11.         }  
  12.   
  13.         if (noChangeLights) {  // 如果不改變light狀態,則保持上次light狀態  
  14.             newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);  
  15.         }  
  16.         if (mProximitySensorActive) {  // 如果距離傳感器鎖定則關閉lcd背光  
  17.             // don't turn on the screen when the proximity sensor lock is held  
  18.             newState = (newState & ~SCREEN_BRIGHT);  
  19.         }  
  20.   
  21.         if (batteryIsLow()) {  // 如果當前低電則添加低電狀態  
  22.             newState |= BATTERY_LOW_BIT;  
  23.         } else {  
  24.             newState &= ~BATTERY_LOW_BIT;  
  25.         }  
  26.         if (newState == mPowerState) {  // 如果本次狀態和上次狀態一致則直接返回  
  27.             return;  
  28.         }  
  29.         // 如果正在啓動並且沒有設置自動背光則爲全亮  
  30.         if (!mBootCompleted && !mUseSoftwareAutoBrightness) {  
  31.             newState |= ALL_BRIGHT;  
  32.         }  
  33.   
  34.         boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;  // 當前屏幕狀態  
  35.         boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;  // 下次屏幕狀態  
  36.   
  37.         if (mSpew) {  
  38.             Slog.d(TAG, "setPowerState: mPowerState=" + mPowerState  
  39.                     + " newState=" + newState + " noChangeLights=" + noChangeLights);  
  40.             Slog.d(TAG, "  oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)  
  41.                      + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));  
  42.             Slog.d(TAG, "  oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)  
  43.                      + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));  
  44.             Slog.d(TAG, "  oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)  
  45.                      + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));  
  46.             Slog.d(TAG, "  oldScreenOn=" + oldScreenOn  
  47.                      + " newScreenOn=" + newScreenOn);  
  48.             Slog.d(TAG, "  oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)  
  49.                      + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));  
  50.         }  
  51.   
  52.         if (mPowerState != newState) {  // 判斷狀態是否改變  
  53.             updateLightsLocked(newState, 0);  // 更新按鍵燈狀態  
  54.             mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);  
  55.         }  
  56.   
  57.         if (oldScreenOn != newScreenOn) {  // 判斷屏幕狀態是否不同  
  58.             if (newScreenOn) {  // 如果要點亮屏幕  
  59.                 // When the user presses the power button, we need to always send out the  
  60.                 // notification that it's going to sleep so the keyguard goes on.  But  
  61.                 // we can't do that until the screen fades out, so we don't show the keyguard  
  62.                 // too early.  
  63.                 if (mStillNeedSleepNotification) {  
  64.                     sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);  
  65.                 }  
  66.   
  67.                 // Turn on the screen UNLESS there was a prior  
  68.                 // preventScreenOn(true) request.  (Note that the lifetime  
  69.                 // of a single preventScreenOn() request is limited to 5  
  70.                 // seconds to prevent a buggy app from disabling the  
  71.                 // screen forever; see forceReenableScreen().)  
  72.                 boolean reallyTurnScreenOn = true;  
  73.                 if (mSpew) {  
  74.                     Slog.d(TAG, "- turning screen on...  mPreventScreenOn = "  
  75.                           + mPreventScreenOn);  
  76.                 }  
  77.   
  78.                 if (mPreventScreenOn) {  // 是否阻止屏幕點亮  
  79.                     if (mSpew) {  
  80.                         Slog.d(TAG, "- PREVENTING screen from really turning on!");  
  81.                     }  
  82.                     reallyTurnScreenOn = false;  
  83.                 }  
  84.                 if (reallyTurnScreenOn) {  
  85.                     err = setScreenStateLocked(true);  // 喚醒系統,點亮屏幕  
  86.                     long identity = Binder.clearCallingIdentity();  
  87.                     try {  
  88.                         mBatteryStats.noteScreenBrightness(getPreferredBrightness());  
  89.                         mBatteryStats.noteScreenOn();  
  90.                     } catch (RemoteException e) {  
  91.                         Slog.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);  
  92.                     } finally {  
  93.                         Binder.restoreCallingIdentity(identity);  
  94.                     }  
  95.                 } else {  
  96.                     setScreenStateLocked(false);  // 休眠系統  
  97.                     // But continue as if we really did turn the screen on...  
  98.                     err = 0;  
  99.                 }  
  100.   
  101.                 mLastTouchDown = 0;  
  102.                 mTotalTouchDownTime = 0;  
  103.                 mTouchCycles = 0;  
  104.                 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason,  
  105.                         mTotalTouchDownTime, mTouchCycles);  
  106.                 if (err == 0) {  
  107.                     mPowerState |= SCREEN_ON_BIT;  
  108.                     sendNotificationLocked(true, -1);  
  109.                 }  
  110.             } else {  // 如果要關閉屏幕  
  111.                 // cancel light sensor task  
  112.                 mHandler.removeCallbacks(mAutoBrightnessTask);  // 取消背光自動調整任務  
  113.                 mScreenOffTime = SystemClock.elapsedRealtime();  // 獲取關閉時間  
  114.                 long identity = Binder.clearCallingIdentity();  
  115.                 try {  
  116.                     mBatteryStats.noteScreenOff();  
  117.                 } catch (RemoteException e) {  
  118.                     Slog.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);  
  119.                 } finally {  
  120.                     Binder.restoreCallingIdentity(identity);  
  121.                 }  
  122.                 mPowerState &= ~SCREEN_ON_BIT;  // 設置狀態位  
  123.                 mScreenOffReason = reason;  
  124.                 if (!mScreenBrightness.animating) {  // 判斷是否打開關屏動畫  
  125.                     err = screenOffFinishedAnimatingLocked(reason);  
  126.                 } else {  
  127.                     err = 0;  
  128.                     mLastTouchDown = 0;  
  129.                 }  
  130.             }  
  131.         }  
  132.           
  133.         updateNativePowerStateLocked();  // 更新HAL層狀態  
  134.     }  
  135. }  
    private void setPowerState(int newState, boolean noChangeLights, int reason)
    {
        synchronized (mLocks) {
            int err;

            if (mSpew) {
                Slog.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
                        + " newState=0x" + Integer.toHexString(newState)
                        + " noChangeLights=" + noChangeLights
                        + " reason=" + reason);
            }

            if (noChangeLights) {  // 如果不改變light狀態,則保持上次light狀態
                newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
            }
            if (mProximitySensorActive) {  // 如果距離傳感器鎖定則關閉lcd背光
                // don't turn on the screen when the proximity sensor lock is held
                newState = (newState & ~SCREEN_BRIGHT);
            }

            if (batteryIsLow()) {  // 如果當前低電則添加低電狀態
                newState |= BATTERY_LOW_BIT;
            } else {
                newState &= ~BATTERY_LOW_BIT;
            }
            if (newState == mPowerState) {  // 如果本次狀態和上次狀態一致則直接返回
                return;
            }
            // 如果正在啓動並且沒有設置自動背光則爲全亮
            if (!mBootCompleted && !mUseSoftwareAutoBrightness) {
                newState |= ALL_BRIGHT;
            }

            boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;  // 當前屏幕狀態
            boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;  // 下次屏幕狀態

            if (mSpew) {
                Slog.d(TAG, "setPowerState: mPowerState=" + mPowerState
                        + " newState=" + newState + " noChangeLights=" + noChangeLights);
                Slog.d(TAG, "  oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
                         + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
                Slog.d(TAG, "  oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
                         + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
                Slog.d(TAG, "  oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
                         + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
                Slog.d(TAG, "  oldScreenOn=" + oldScreenOn
                         + " newScreenOn=" + newScreenOn);
                Slog.d(TAG, "  oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
                         + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
            }

            if (mPowerState != newState) {  // 判斷狀態是否改變
                updateLightsLocked(newState, 0);  // 更新按鍵燈狀態
                mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
            }

            if (oldScreenOn != newScreenOn) {  // 判斷屏幕狀態是否不同
                if (newScreenOn) {  // 如果要點亮屏幕
                    // When the user presses the power button, we need to always send out the
                    // notification that it's going to sleep so the keyguard goes on.  But
                    // we can't do that until the screen fades out, so we don't show the keyguard
                    // too early.
                    if (mStillNeedSleepNotification) {
                        sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
                    }

                    // Turn on the screen UNLESS there was a prior
                    // preventScreenOn(true) request.  (Note that the lifetime
                    // of a single preventScreenOn() request is limited to 5
                    // seconds to prevent a buggy app from disabling the
                    // screen forever; see forceReenableScreen().)
                    boolean reallyTurnScreenOn = true;
                    if (mSpew) {
                        Slog.d(TAG, "- turning screen on...  mPreventScreenOn = "
                              + mPreventScreenOn);
                    }

                    if (mPreventScreenOn) {  // 是否阻止屏幕點亮
                        if (mSpew) {
                            Slog.d(TAG, "- PREVENTING screen from really turning on!");
                        }
                        reallyTurnScreenOn = false;
                    }
                    if (reallyTurnScreenOn) {
                        err = setScreenStateLocked(true);  // 喚醒系統,點亮屏幕
                        long identity = Binder.clearCallingIdentity();
                        try {
                            mBatteryStats.noteScreenBrightness(getPreferredBrightness());
                            mBatteryStats.noteScreenOn();
                        } catch (RemoteException e) {
                            Slog.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
                        } finally {
                            Binder.restoreCallingIdentity(identity);
                        }
                    } else {
                        setScreenStateLocked(false);  // 休眠系統
                        // But continue as if we really did turn the screen on...
                        err = 0;
                    }

                    mLastTouchDown = 0;
                    mTotalTouchDownTime = 0;
                    mTouchCycles = 0;
                    EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason,
                            mTotalTouchDownTime, mTouchCycles);
                    if (err == 0) {
                        mPowerState |= SCREEN_ON_BIT;
                        sendNotificationLocked(true, -1);
                    }
                } else {  // 如果要關閉屏幕
                    // cancel light sensor task
                    mHandler.removeCallbacks(mAutoBrightnessTask);  // 取消背光自動調整任務
                    mScreenOffTime = SystemClock.elapsedRealtime();  // 獲取關閉時間
                    long identity = Binder.clearCallingIdentity();
                    try {
                        mBatteryStats.noteScreenOff();
                    } catch (RemoteException e) {
                        Slog.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
                    } finally {
                        Binder.restoreCallingIdentity(identity);
                    }
                    mPowerState &= ~SCREEN_ON_BIT;  // 設置狀態位
                    mScreenOffReason = reason;
                    if (!mScreenBrightness.animating) {  // 判斷是否打開關屏動畫
                        err = screenOffFinishedAnimatingLocked(reason);
                    } else {
                        err = 0;
                        mLastTouchDown = 0;
                    }
                }
            }
            
            updateNativePowerStateLocked();  // 更新HAL層狀態
        }
    }
在updateLightsLocked()裏面將會進行一系列的狀態處理, 比如調用applyButtonState()獲取button led的相關數據和狀態,然後調用setLightBrightness()設置leds,代碼分析如下:
  1. private void updateLightsLocked(int newState, int forceState) {  
  2.     final int oldState = mPowerState;  
  3.     if ((newState & SCREEN_ON_BIT) != 0) {  // 如果屏幕打開則設置按鍵燈  
  4.         newState = applyButtonState(newState);  // 請求button燈狀態  
  5.         newState = applyKeyboardState(newState);  // 請求keyboard燈狀態  
  6.     }  
  7.     final int realDifference = (newState ^ oldState);  // 判斷狀態是否相同,取得不同的位  
  8.     final int difference = realDifference | forceState;  // 是否強制更新狀態  
  9.     if (difference == 0) {  
  10.         return;  
  11.     }  
  12.   
  13.     int offMask = 0;  
  14.     int dimMask = 0;  
  15.     int onMask = 0;  
  16.   
  17.     int preferredBrightness = getPreferredBrightness();  // 獲取參考亮度  
  18.   
  19.     if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {  // 如果keyboard有變化  
  20.         if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {  
  21.             offMask |= KEYBOARD_BRIGHT_BIT;  
  22.         } else {  
  23.             onMask |= KEYBOARD_BRIGHT_BIT;  
  24.         }  
  25.     }  
  26.   
  27.     if ((difference & BUTTON_BRIGHT_BIT) != 0) {  // 如果button有變化  
  28.         if ((newState & BUTTON_BRIGHT_BIT) == 0) {  
  29.             offMask |= BUTTON_BRIGHT_BIT;  
  30.         } else {  
  31.             onMask |= BUTTON_BRIGHT_BIT;  
  32.         }  
  33.     }  
  34.     // 如果狀態不同且forceState有效或者屏幕狀態變化  
  35.     if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {  
  36.         int nominalCurrentValue = -1;  
  37.         // If there was an actual difference in the light state, then  
  38.         // figure out the "ideal" current value based on the previous  
  39.         // state.  Otherwise, this is a change due to the brightness  
  40.         // override, so we want to animate from whatever the current  
  41.         // value is.  
  42.         // 如果屏幕狀態變化  
  43.         if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {  
  44.             switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {  // 判斷當前屏幕狀態  
  45.                 case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:  // 屏幕全亮狀態  
  46.                     nominalCurrentValue = preferredBrightness;  
  47.                     break;  
  48.                 case SCREEN_ON_BIT:  // 屏幕DIM狀態  
  49.                     nominalCurrentValue = Power.BRIGHTNESS_DIM;  
  50.                     break;  
  51.                 case 0:  // 屏幕關閉狀態  
  52.                     nominalCurrentValue = Power.BRIGHTNESS_OFF;  
  53.                     break;  
  54.                 case SCREEN_BRIGHT_BIT:  
  55.                 default:  
  56.                     // not possible  
  57.                     nominalCurrentValue = (int)mScreenBrightness.curValue;  
  58.                     break;  
  59.             }  
  60.         }  
  61.         int brightness = preferredBrightness;  
  62.         int steps = ANIM_STEPS;  // 動畫步數  
  63.         if ((newState & SCREEN_BRIGHT_BIT) == 0) {  // 下一個狀態爲DIM或者OFF  
  64.             // dim or turn off backlight, depending on if the screen is on  
  65.             // the scale is because the brightness ramp isn't linear and this biases  
  66.             // it so the later parts take longer.  
  67.             final float scale = 1.5f;  
  68.             // 每次變化比例  
  69.             float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);  
  70.             if (ratio > 1.0f) ratio = 1.0f;  
  71.             if ((newState & SCREEN_ON_BIT) == 0) {  // 下一個狀態爲OFF  
  72.                 if ((oldState & SCREEN_BRIGHT_BIT) != 0) {  
  73.                     // was bright  
  74.                     steps = ANIM_STEPS;  
  75.                 } else {  
  76.                     // was dim  
  77.                     steps = (int)(ANIM_STEPS*ratio*scale);  
  78.                 }  
  79.                 brightness = Power.BRIGHTNESS_OFF;  // 設置brightness  
  80.             } else {  // 下一個狀態爲DIM  
  81.                 if ((oldState & SCREEN_ON_BIT) != 0) {  
  82.                     // was bright  
  83.                     steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);  
  84.                 } else {  
  85.                     // was dim  
  86.                     steps = (int)(ANIM_STEPS*ratio);  
  87.                 }  
  88.                 if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {  
  89.                     // If the "stay on while plugged in" option is  
  90.                     // turned on, then the screen will often not  
  91.                     // automatically turn off while plugged in.  To  
  92.                     // still have a sense of when it is inactive, we  
  93.                     // will then count going dim as turning off.  
  94.                     mScreenOffTime = SystemClock.elapsedRealtime();  
  95.                 }  
  96.                 brightness = Power.BRIGHTNESS_DIM;  
  97.             }  
  98.         }  
  99.         long identity = Binder.clearCallingIdentity();  
  100.         try {  
  101.             mBatteryStats.noteScreenBrightness(brightness);  
  102.         } catch (RemoteException e) {  
  103.             // Nothing interesting to do.  
  104.         } finally {  
  105.             Binder.restoreCallingIdentity(identity);  
  106.         }  
  107.         mScreenBrightness.setTargetLocked(brightness, steps,  // 設置背光亮度  
  108.                 INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);  
  109.     }  
  110.   
  111.     if (mSpew) {  
  112.         Slog.d(TAG, "offMask=0x" + Integer.toHexString(offMask)  
  113.                 + " dimMask=0x" + Integer.toHexString(dimMask)  
  114.                 + " onMask=0x" + Integer.toHexString(onMask)  
  115.                 + " difference=0x" + Integer.toHexString(difference)  
  116.                 + " realDifference=0x" + Integer.toHexString(realDifference)  
  117.                 + " forceState=0x" + Integer.toHexString(forceState)  
  118.                 );  
  119.     }  
  120.   
  121.     if (offMask != 0) {  // 如果有燈要關閉  
  122.         if (mSpew) Slog.i(TAG, "Setting brightess off: " + offMask);  
  123.         setLightBrightness(offMask, Power.BRIGHTNESS_OFF);  
  124.     }  
  125.     if (dimMask != 0) {  
  126.         int brightness = Power.BRIGHTNESS_DIM;  
  127.         if ((newState & BATTERY_LOW_BIT) != 0 &&  
  128.                 brightness > Power.BRIGHTNESS_LOW_BATTERY) {  
  129.             brightness = Power.BRIGHTNESS_LOW_BATTERY;  
  130.         }  
  131.         if (mSpew) Slog.i(TAG, "Setting brightess dim " + brightness + ": " + dimMask);  
  132.         setLightBrightness(dimMask, brightness);  // 設置leds  
  133.     }  
  134.     if (onMask != 0) {  // 如果有燈要打開  
  135.         int brightness = getPreferredBrightness();  // 獲取亮度值,包括按鍵燈的亮度值,都是從用戶設置中獲取  
  136.         if ((newState & BATTERY_LOW_BIT) != 0 &&  
  137.                 brightness > Power.BRIGHTNESS_LOW_BATTERY) {  
  138.             brightness = Power.BRIGHTNESS_LOW_BATTERY;  
  139.         }  
  140.         if (mSpew) Slog.i(TAG, "Setting brightess on " + brightness + ": " + onMask);  
  141.         setLightBrightness(onMask, brightness);  // 設置leds  
  142.     }  
  143. }  
    private void updateLightsLocked(int newState, int forceState) {
        final int oldState = mPowerState;
        if ((newState & SCREEN_ON_BIT) != 0) {  // 如果屏幕打開則設置按鍵燈
            newState = applyButtonState(newState);  // 請求button燈狀態
            newState = applyKeyboardState(newState);  // 請求keyboard燈狀態
        }
        final int realDifference = (newState ^ oldState);  // 判斷狀態是否相同,取得不同的位
        final int difference = realDifference | forceState;  // 是否強制更新狀態
        if (difference == 0) {
            return;
        }

        int offMask = 0;
        int dimMask = 0;
        int onMask = 0;

        int preferredBrightness = getPreferredBrightness();  // 獲取參考亮度

        if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {  // 如果keyboard有變化
            if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
                offMask |= KEYBOARD_BRIGHT_BIT;
            } else {
                onMask |= KEYBOARD_BRIGHT_BIT;
            }
        }

        if ((difference & BUTTON_BRIGHT_BIT) != 0) {  // 如果button有變化
            if ((newState & BUTTON_BRIGHT_BIT) == 0) {
                offMask |= BUTTON_BRIGHT_BIT;
            } else {
                onMask |= BUTTON_BRIGHT_BIT;
            }
        }
        // 如果狀態不同且forceState有效或者屏幕狀態變化
        if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
            int nominalCurrentValue = -1;
            // If there was an actual difference in the light state, then
            // figure out the "ideal" current value based on the previous
            // state.  Otherwise, this is a change due to the brightness
            // override, so we want to animate from whatever the current
            // value is.
            // 如果屏幕狀態變化
            if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
                switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {  // 判斷當前屏幕狀態
                    case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:  // 屏幕全亮狀態
                        nominalCurrentValue = preferredBrightness;
                        break;
                    case SCREEN_ON_BIT:  // 屏幕DIM狀態
                        nominalCurrentValue = Power.BRIGHTNESS_DIM;
                        break;
                    case 0:  // 屏幕關閉狀態
                        nominalCurrentValue = Power.BRIGHTNESS_OFF;
                        break;
                    case SCREEN_BRIGHT_BIT:
                    default:
                        // not possible
                        nominalCurrentValue = (int)mScreenBrightness.curValue;
                        break;
                }
            }
            int brightness = preferredBrightness;
            int steps = ANIM_STEPS;  // 動畫步數
            if ((newState & SCREEN_BRIGHT_BIT) == 0) {  // 下一個狀態爲DIM或者OFF
                // dim or turn off backlight, depending on if the screen is on
                // the scale is because the brightness ramp isn't linear and this biases
                // it so the later parts take longer.
                final float scale = 1.5f;
                // 每次變化比例
                float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
                if (ratio > 1.0f) ratio = 1.0f;
                if ((newState & SCREEN_ON_BIT) == 0) {  // 下一個狀態爲OFF
                    if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
                        // was bright
                        steps = ANIM_STEPS;
                    } else {
                        // was dim
                        steps = (int)(ANIM_STEPS*ratio*scale);
                    }
                    brightness = Power.BRIGHTNESS_OFF;  // 設置brightness
                } else {  // 下一個狀態爲DIM
                    if ((oldState & SCREEN_ON_BIT) != 0) {
                        // was bright
                        steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
                    } else {
                        // was dim
                        steps = (int)(ANIM_STEPS*ratio);
                    }
                    if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
                        // If the "stay on while plugged in" option is
                        // turned on, then the screen will often not
                        // automatically turn off while plugged in.  To
                        // still have a sense of when it is inactive, we
                        // will then count going dim as turning off.
                        mScreenOffTime = SystemClock.elapsedRealtime();
                    }
                    brightness = Power.BRIGHTNESS_DIM;
                }
            }
            long identity = Binder.clearCallingIdentity();
            try {
                mBatteryStats.noteScreenBrightness(brightness);
            } catch (RemoteException e) {
                // Nothing interesting to do.
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
            mScreenBrightness.setTargetLocked(brightness, steps,  // 設置背光亮度
                    INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
        }

        if (mSpew) {
            Slog.d(TAG, "offMask=0x" + Integer.toHexString(offMask)
                    + " dimMask=0x" + Integer.toHexString(dimMask)
                    + " onMask=0x" + Integer.toHexString(onMask)
                    + " difference=0x" + Integer.toHexString(difference)
                    + " realDifference=0x" + Integer.toHexString(realDifference)
                    + " forceState=0x" + Integer.toHexString(forceState)
                    );
        }

        if (offMask != 0) {  // 如果有燈要關閉
            if (mSpew) Slog.i(TAG, "Setting brightess off: " + offMask);
            setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
        }
        if (dimMask != 0) {
            int brightness = Power.BRIGHTNESS_DIM;
            if ((newState & BATTERY_LOW_BIT) != 0 &&
                    brightness > Power.BRIGHTNESS_LOW_BATTERY) {
                brightness = Power.BRIGHTNESS_LOW_BATTERY;
            }
            if (mSpew) Slog.i(TAG, "Setting brightess dim " + brightness + ": " + dimMask);
            setLightBrightness(dimMask, brightness);  // 設置leds
        }
        if (onMask != 0) {  // 如果有燈要打開
            int brightness = getPreferredBrightness();  // 獲取亮度值,包括按鍵燈的亮度值,都是從用戶設置中獲取
            if ((newState & BATTERY_LOW_BIT) != 0 &&
                    brightness > Power.BRIGHTNESS_LOW_BATTERY) {
                brightness = Power.BRIGHTNESS_LOW_BATTERY;
            }
            if (mSpew) Slog.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
            setLightBrightness(onMask, brightness);  // 設置leds
        }
    }

  1. private int applyButtonState(int state) {  
  2.     int brightness = -1;  
  3.     if ((state & BATTERY_LOW_BIT) != 0) {  
  4.         // 如果電池電量低則不覆蓋亮度值  
  5.         return state;  
  6.     }  
  7.     if (mButtonBrightnessOverride >= 0) {  // 判斷亮度值是否有效  
  8.         brightness = mButtonBrightnessOverride;  
  9.     } else if (mLightSensorButtonBrightness >= 0 && mUseSoftwareAutoBrightness) {  
  10.         // 根據lightsensor設置亮度值  
  11.         // 這裏有android系統的一個bug,如果開啓自動背光後再關閉自動背光  
  12.         // 會導致mLightSensorButtonBrightness爲之前自動背光時的值,如果爲0按鍵燈就不會再被點亮了  
  13.         brightness = mLightSensorButtonBrightness;  
  14.     }  
  15.     if (brightness > 0) {  
  16.         return state | BUTTON_BRIGHT_BIT;  // 如果亮度值大於0則返回狀態  
  17.     } else if (brightness == 0) {  
  18.         return state & ~BUTTON_BRIGHT_BIT;  
  19.     } else {  
  20.         return state;  
  21.     }  
  22. }  
    private int applyButtonState(int state) {
        int brightness = -1;
        if ((state & BATTERY_LOW_BIT) != 0) {
            // 如果電池電量低則不覆蓋亮度值
            return state;
        }
        if (mButtonBrightnessOverride >= 0) {  // 判斷亮度值是否有效
            brightness = mButtonBrightnessOverride;
        } else if (mLightSensorButtonBrightness >= 0 && mUseSoftwareAutoBrightness) {
            // 根據lightsensor設置亮度值
            // 這裏有android系統的一個bug,如果開啓自動背光後再關閉自動背光
            // 會導致mLightSensorButtonBrightness爲之前自動背光時的值,如果爲0按鍵燈就不會再被點亮了
            brightness = mLightSensorButtonBrightness;
        }
        if (brightness > 0) {
            return state | BUTTON_BRIGHT_BIT;  // 如果亮度值大於0則返回狀態
        } else if (brightness == 0) {
            return state & ~BUTTON_BRIGHT_BIT;
        } else {
            return state;
        }
    }

在setLightBrightness()中將根據標誌依次調用JNI接口去設置leds,代碼分析如下:

  1. private void setLightBrightness(int mask, int value) {  
  2.     int brightnessMode = (mAutoBrightessEnabled  
  3.                         ? LightsService.BRIGHTNESS_MODE_SENSOR  
  4.                         : LightsService.BRIGHTNESS_MODE_USER);  // 設置背光模式  
  5.     if ((mask & SCREEN_BRIGHT_BIT) != 0) {  
  6.         mLcdLight.setBrightness(value, brightnessMode);  // 調用JNI接口設置lcd亮度  
  7.     }  
  8.     if ((mask & BUTTON_BRIGHT_BIT) != 0) {  
  9.         mButtonLight.setBrightness(value);  // 調用JNI接口設置button燈  
  10.     }  
  11.     if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {  
  12.         mKeyboardLight.setBrightness(value);  // 調用JNI接口設置keyboard燈  
  13.     }  
  14. }  
    private void setLightBrightness(int mask, int value) {
        int brightnessMode = (mAutoBrightessEnabled
                            ? LightsService.BRIGHTNESS_MODE_SENSOR
                            : LightsService.BRIGHTNESS_MODE_USER);  // 設置背光模式
        if ((mask & SCREEN_BRIGHT_BIT) != 0) {
            mLcdLight.setBrightness(value, brightnessMode);  // 調用JNI接口設置lcd亮度
        }
        if ((mask & BUTTON_BRIGHT_BIT) != 0) {
            mButtonLight.setBrightness(value);  // 調用JNI接口設置button燈
        }
        if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
            mKeyboardLight.setBrightness(value);  // 調用JNI接口設置keyboard燈
        }
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章