自动背光调节




AAL与CABC背光选择(两种方式控制背光):
参考[FAQ05966]
89平台支持BB端CABC(即AAL)或LCM端CABC方式控制背光,两种方式使用方法如下
【BB端CABC(即AAL)】
   - 打开功能,向MTK申请patch,并在ProjectConfig.mk中打开MTK_AAL_SUPPORT = yes
【LCM端CABC】
- 对于Video Mode,ALPS.JB2.MP.V1.3(包括1.3)之前的版本,请向MTK申请patch
     - lcm driver中实现set_backlight接口
     - cust_leds.c(包括lk与kernel中的两支文件)设置如下


config_automatic_brightness_available  自动亮度调节控制开关

BRIGHTENING_LIGHT_HYSTERESIS    ---变得更亮,只有达到比上个lux值高出这个百分比才认为是valid
DARKENING_LIGHT_HYSTERESIS       ---变得更暗,只有比上个lux值低出这个百分比才认为是valid

<bool name="config_autoBrightnessResetAmbientLuxAfterWarmUp">truebool>
亮屏时是否重舍弃上次灭屏时的采集值。true 表示舍弃,这个时候采集 config_lightSensorWarmupTime 这个时间后 马上计算出当前环境值,波动性较大

false 表示重新根据 BRIGHTENING_LIGHT_HYSTERESIS、DARKENING_LIGHT_HYSTERESIS计算满足阈值条件值,这样较平滑,需要花些时间才能调节到当前环境值。


<integer name="config_lightSensorWarmupTime">0integer>


<integer name="config_autoBrightnessAmbientLightHorizon">10000integer>
采样周期


<integer name="config_autoBrightnessLightSensorRate">250integer>
light-sensor 采样率


4000

变亮持续时间

8000

变暗持续时间



    private final SensorEventListener mLightSensorListener = new SensorEventListener() {
        // Mediatek AAL support
        private long mPrevLogTime = 0L;
        private float mPrevLogLux = 0.0f;

        @Override
        public void onSensorChanged(SensorEvent event) {
            if (DEBUG) Slog.d(TAG, "onSensorChanged: mLightSensorEnabled=" + mLightSensorEnabled +
                ", mAmbientLuxValid=" + mAmbientLuxValid);

            if (mLightSensorEnabled) {
                final long time = SystemClock.uptimeMillis();
                final float lux = event.values[0];
                handleLightSensorEvent(time, lux);

                // Mediatek AAL support : long period and significant lux changed
                if (time - mPrevLogTime >= 500L ||
                    mPrevLogLux * 1.2f <= lux || lux * 1.2f <= mPrevLogLux) {
                    if (DEBUG) Slog.d(TAG, "onSensorChanged: lux = " + lux);
                    mPrevLogTime = time;
                    mPrevLogLux = lux;
                }
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // Not used.
        }
    };

//light sensor 监听器


 private boolean setLightSensorEnabled(boolean enable) {
        if (enable != mLightSensorEnabled) {
            Slog.d(TAG, "setLightSensorEnabled: enable=" + enable +
                ", mLightSensorEnabled=" + mLightSensorEnabled +
                ", mAmbientLuxValid=" + mAmbientLuxValid +
                ", mResetAmbientLuxAfterWarmUpConfig=" + mResetAmbientLuxAfterWarmUpConfig);
        }
        if (enable) {
            if (!mLightSensorEnabled) {
                mLightSensorEnabled = true;
                mLightSensorEnableTime = SystemClock.uptimeMillis();
                mSensorManager.registerListener(mLightSensorListener, mLightSensor,
                        mLightSensorRate * 1000, mHandler);
                return true;
            }
        } else {
            if (mLightSensorEnabled) {
                mLightSensorEnabled = false;
                mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig;
                mRecentLightSamples = 0;
                mAmbientLightRingBuffer.clear();
                mInitialHorizonAmbientLightRingBuffer.clear();
                mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
                mSensorManager.unregisterListener(mLightSensorListener);
            }
        }
        return false;
    }

//注册light  sensor,其中采样率 为 < integer name= "config_autoBrightnessLightSensorRate" >250 integer >



//light sensor 监听到背光事件处理

final long time = SystemClock.uptimeMillis();
final float lux = event.values[0];
handleLightSensorEvent(time, lux);
 
  
 
  
    private void handleLightSensorEvent(long time, float lux) {
        mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);

        applyLightSensorMeasurement(time, lux);
        updateAmbientLux(time);
    }


//背光采集的数据插入数组
    private void applyLightSensorMeasurement(long time, float lux) {
        mRecentLightSamples++;
        // Store all of the light measurements for the intial horizon period. This is to help
        // diagnose dim wake ups and slow responses in b/27951906.
        if (time <= mLightSensorEnableTime + mAmbientLightHorizon) {
            mInitialHorizonAmbientLightRingBuffer.push(time, lux);
        }
        mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
        mAmbientLightRingBuffer.push(time, lux);

        // Remember this sample value.
        mLastObservedLux = lux;
        mLastObservedLuxTime = time;
    }



mInitialHorizonAmbientLightRingBuffer.push(time, lux);

从自动背光enable开始10s采集到的环境光线值复制给mInitialHorizonAmbientLightRingBuffer

 mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon); 就是去掉当前比采样周期mAmbientLightHorizon早的数据,并确定插入有效数组位置
 mAmbientLightRingBuffer.push 将值插入有效数组位置
 其中mAmbientLightRingBuffer对象可以简单认为是一个循环数组,大小为通常
mCapacity = (int) Math.ceil(ambientLightHorizon * BUFFER_SLACK / lightSensorRate);   即采样周期内采样次数的一个比例(1.5)放大


 
  
 
  
//处理采样的数组值并获得lux
 
  
 private void updateAmbientLux(long time) {
        if (DEBUG) Slog.d(TAG, "updateAmbientLux: mAmbientLuxValid=" + mAmbientLuxValid +
            ", AAL=" + DisplayPowerController.MTK_AAL_SUPPORT);
        // If the light sensor was just turned on then immediately update our initial
        // estimate of the current ambient light level.
        if (!mAmbientLuxValid) {  //config_autoBrightnessResetAmbientLuxAfterWarmUp 为false
            final long timeWhenSensorWarmedUp =
                mLightSensorWarmUpTimeConfig + mLightSensorEnableTime;
            if (time < timeWhenSensorWarmedUp) {//config_lightSensorWarmupTime   warmUP time,即重置等待采样时间
                if (DEBUG) {
                    Slog.d(TAG, "updateAmbientLux: Sensor not  ready yet: "
                            + "time=" + time
                            + ", timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp);
                }
                mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX,
                        timeWhenSensorWarmedUp);
                return;
            }
            setAmbientLux(calculateAmbientLux(time));//config_lightSensorWarmupTime  采样时间到计算获取lux值
            mAmbientLuxValid = true;
            if (DEBUG) {
                Slog.d(TAG, "updateAmbientLux: Initializing: "
                        + "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer
                        + ", mAmbientLux=" + mAmbientLux);
            }
            updateAutoBrightness(true);//更新背光亮度
        }

        long nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
        long nextDarkenTransition = nextAmbientLightDarkeningTransition(time);
        float ambientLux = calculateAmbientLux(time);

        if (DisplayPowerController.MTK_AAL_SUPPORT) {
            Slog.d(TAG, "updateAmbientLux: ambientLux=" + ambientLux
                        + ", timeToBrighten=" + (nextBrightenTransition - time)
                        + ", timeToDarken=" + (nextDarkenTransition - time)
                        + ", current=" + mAmbientLux);
        }

        if (ambientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time
                || ambientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) {
            setAmbientLux(ambientLux);
            if (DEBUG) {
                Slog.d(TAG, "updateAmbientLux: "
                        + ((ambientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
                        + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
                        + ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer
                        + ", mAmbientLux=" + mAmbientLux);
            }
            updateAutoBrightness(true);
            nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
            nextDarkenTransition = nextAmbientLightDarkeningTransition(time);
        }
        long nextTransitionTime = Math.min(nextDarkenTransition, nextBrightenTransition);
        // If one of the transitions is ready to occur, but the total weighted ambient lux doesn't
        // exceed the necessary threshold, then it's possible we'll get a transition time prior to
        // now. Rather than continually checking to see whether the weighted lux exceeds the
        // threshold, schedule an update for when we'd normally expect another light sample, which
        // should be enough time to decide whether we should actually transition to the new
        // weighted ambient lux or not.
        nextTransitionTime =
                nextTransitionTime > time ? nextTransitionTime : time + mLightSensorRate;
        if (DEBUG) {
            Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for "
                    + nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime));
        }
        mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime);
    }


 long nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
 long nextDarkenTransition = nextAmbientLightDarkeningTransition(time);

mAmbientLightRingBuffer中从晚到早找到达到变得更亮的阈值的亮度时间点,这里是说计算出的下一次达到稳定的时间,如果这个时间比当前时间早,说明已经超出了变亮或者变暗的时间。即已经达到了config_autoBrightnessBrighteningLightDebounce 、config_autoBrightnessDarkeningLightDebounce要求的时间

mAmbientLightRingBuffer中从晚到早找到达到变得更暗的阈值的亮度时间点

float ambientLux = calculateAmbientLux(time);

根据当前时间获取一个lux值

         if (ambientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time
                || ambientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) {
            setAmbientLux(ambientLux);

                  updateAutoBrightness(true);
                  nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
                  nextDarkenTransition = nextAmbientLightDarkeningTransition(time);
            }

如果获取的lux值达到变亮(暗)阈值且时间达到稳定的时间,小于当前时间就是说明达到了config_autoBrightnessBrighteningLightDebounce 、config_autoBrightnessDarkeningLightDebounce要求的时间。这个时候就认为计算出的lux值是有效的,就设置lux值,并setAmbientLux重新计算得出阈值。紧接着更新背光亮度,这个时候由于重新获取了阈值,并重新算出下一次。

private void setAmbientLux(float lux) {
    mAmbientLux = lux;
    mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
    mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);

    DisplayPowerController.nativeSetDebouncedAmbientLight((int) lux);
}


 mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime);

下一次更新的时间消息。


    private float calculateAmbientLux(long now) {
        final int N = mAmbientLightRingBuffer.size();
        if (N == 0) {
            Slog.e(TAG, "calculateAmbientLux: No ambient light readings available");
            return -1;
        }
        float sum = 0;
        float totalWeight = 0;
        long endTime = AMBIENT_LIGHT_PREDICTION_TIME_MILLIS;
        for (int i = N - 1; i >= 0; i--) {
            long startTime = (mAmbientLightRingBuffer.getTime(i) - now);
            // Mediatek AAL support
            if (DisplayPowerController.MTK_AAL_SUPPORT) {
                if (startTime < -MTK_AAL_AMBIENT_LIGHT_HORIZON && totalWeight > 0)
                    break;
            }
            float weight = calculateWeight(startTime, endTime);
            float lux = mAmbientLightRingBuffer.getLux(i);
            if (DEBUG) {
                Slog.d(TAG, "calculateAmbientLux: [" +
                        (startTime) + ", " +
                        (endTime) + "]: lux=" + lux + ", weight=" + weight);
            }
            totalWeight += weight;
            sum += mAmbientLightRingBuffer.getLux(i) * weight;
            endTime = startTime;
        }
        if (DEBUG) {
            Slog.d(TAG, "calculateAmbientLux: totalWeight=" + totalWeight +
                    ", newAmbientLux=" + (sum / totalWeight));
        }
        return sum / totalWeight;
    }

long startTime = (mAmbientLightRingBuffer.getTime(i) - now);
就是获取与当前时间的时间负差

float weight = calculateWeight(startTime, endTime);
float lux = mAmbientLightRingBuffer.getLux(i);

根据两个时间点计算出一个比重,再获取lux值

totalWeight += weight;
sum += mAmbientLightRingBuffer.getLux(i) * weight;
endTime = startTime;
根据比重计算出lux,并从新设置时间点


Android 系统 屏幕背光流程分析

http://blog.csdn.net/u011311586/article/details/59480408

AAL框架

http://www.cnblogs.com/lexuele/p/5131396.html


/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;

越大越快


调节开关控制

MTK_AAL_SUPPORT
MTK_ULTRA_DIMMING_SUPPORT


adb shell dumpsys AAL --function 1   关闭AAL ,及关闭背光上报模块


config_screenBrightnessSettingMinimum  屏膜最小亮度


config_autoBrightnessLcdBacklightValues




frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java

控制display 的power 状态

处理距离、灯传感器、及动画

与PMS 其它部分独立,仅仅通过异步回调通知PMS状态改变

事件都是在它的handler中处理

PMS保证在显示准备好之前它一直持有suspend blocker 

final class DisplayPowerController implements AutomaticBrightnessController.Callbacks
    实现了接口

public void updateBrightness() {
    sendUpdatePowerState();
}

this这个接口作为mAutomaticBrightnessController = new AutomaticBrightnessController(this    ....的回调




frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java

管理和通知系统显示 依赖于DisplayAdapter

private final class LocalService extends DisplayManagerInternal {
    @Override
    public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
            SensorManager sensorManager) {
        synchronized (mSyncRoot) {
            DisplayBlanker blanker = new DisplayBlanker() {
                @Override
                public void requestDisplayState(int state, int brightness) {
                    // The order of operations is important for legacy reasons.
                    if (state == Display.STATE_OFF) {
                        requestGlobalDisplayStateInternal(state, brightness);
                    }

                    callbacks.onDisplayStateChange(state);

                    if (state != Display.STATE_OFF) {
                        requestGlobalDisplayStateInternal(state, brightness);
                    }
                }
            };
            mDisplayPowerController = new DisplayPowerController(
                    mContext, callbacks, handler, sensorManager, blanker);
        }
    }

DMS 通过 DisplayPowerController 实现显示状态控制,DisplayPowerCallbacks 用于回调回PMS

/**
 * Interface used to update the actual display state.
 */
public interface DisplayBlanker {
    void requestDisplayState(int state, int brightness);
}



frameworks\base\services\core\java\com\android\server\display\AutomaticBrightnessController.java

光传感器

    private final SensorEventListener mLightSensorListener = new SensorEventListener() {
        // Mediatek AAL support
        private long mPrevLogTime = 0L;
        private float mPrevLogLux = 0.0f;

        @Override
        public void onSensorChanged(SensorEvent event) {
            if (DEBUG) Slog.d(TAG, "onSensorChanged: mLightSensorEnabled=" + mLightSensorEnabled +
                ", mAmbientLuxValid=" + mAmbientLuxValid);

            if (mLightSensorEnabled) {
                final long time = SystemClock.uptimeMillis();
                final float lux = event.values[0];
                handleLightSensorEvent(time, lux);

                // Mediatek AAL support : long period and significant lux changed
                if (time - mPrevLogTime >= 500L ||
                    mPrevLogLux * 1.2f <= lux || lux * 1.2f <= mPrevLogLux) {
                    if (DEBUG) Slog.d(TAG, "onSensorChanged: lux = " + lux);
                    mPrevLogTime = time;
                    mPrevLogLux = lux;
                }
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // Not used.
        }
    };






frameworks\base\services\core\java\com\android\server\display\AutomaticBrightnessController.java

光传感器

    private final SensorEventListener mLightSensorListener = new SensorEventListener() {
        // Mediatek AAL support
        private long mPrevLogTime = 0L;
        private float mPrevLogLux = 0.0f;

        @Override
        public void onSensorChanged(SensorEvent event) {
            if (DEBUG) Slog.d(TAG, "onSensorChanged: mLightSensorEnabled=" + mLightSensorEnabled +
                ", mAmbientLuxValid=" + mAmbientLuxValid);

            if (mLightSensorEnabled) {
                final long time = SystemClock.uptimeMillis();
                final float lux = event.values[0];
                handleLightSensorEvent(time, lux);

                // Mediatek AAL support : long period and significant lux changed
                if (time - mPrevLogTime >= 500L ||
                    mPrevLogLux * 1.2f <= lux || lux * 1.2f <= mPrevLogLux) {
                    if (DEBUG) Slog.d(TAG, "onSensorChanged: lux = " + lux);
                    mPrevLogTime = time;
                    mPrevLogLux = lux;
                }
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // Not used.
        }
    };

AAL与CABC背光选择(两种方式控制背光):
参考[FAQ05966]
89平台支持BB端CABC(即AAL)或LCM端CABC方式控制背光,两种方式使用方法如下
【BB端CABC(即AAL)】
   - 打开功能,向MTK申请patch,并在ProjectConfig.mk中打开MTK_AAL_SUPPORT = yes
【LCM端CABC】
- 对于Video Mode,ALPS.JB2.MP.V1.3(包括1.3)之前的版本,请向MTK申请patch
     - lcm driver中实现set_backlight接口
     - cust_leds.c(包括lk与kernel中的两支文件)设置如下


private void setAmbientLux(float lux) {
    mAmbientLux = lux;
    mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
    mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);

    DisplayPowerController.nativeSetDebouncedAmbientLight((int) lux);
}

BRIGHTENING_LIGHT_HYSTERESIS    ---变得更亮,只有达到
DARKENING_LIGHT_HYSTERESIS      ---变得更暗

private void setAmbientLux(float lux) {
    mAmbientLux = lux;
    mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
    mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);

    DisplayPowerController.nativeSetDebouncedAmbientLight((int) lux);
}

你可能感兴趣的:(android)