自动背光调节




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">true</bool>
亮屏时是否重舍弃上次灭屏时的采集值。true 表示舍弃,这个时候采集 config_lightSensorWarmupTime 这个时间后 马上计算出当前环境值,波动性较大

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

<!-- Amount of time it takes for the light sensor to warm up in milliseconds.
     For this time after the screen turns on, the Power Manager
     will not debounce light sensor readings -->
<integer name="config_lightSensorWarmupTime">0</integer>

<!-- Period of time in which to consider light samples in milliseconds. -->
<integer name="config_autoBrightnessAmbientLightHorizon">10000</integer>
采样周期

<!-- Light sensor event rate in milliseconds for automatic brightness control. -->
<integer name="config_autoBrightnessLightSensorRate">250</integer>
light-sensor 采样率


<integer name="config_autoBrightnessBrighteningLightDebounce">4000</integer>

变亮持续时间

<integer name="config_autoBrightnessDarkeningLightDebounce">8000</integer>

变暗持续时间



    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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值