android 8.1自动背光随笔

本文简单梳理自己对自动背光涉及算法理解

主要类:

AutomaticBrightnessController.java

DisplayPowerController.java

Spline.java

1.AutomaticBrightnessController中注册SensorEventListener监听,LightSensor上报光照值回调onSensorChanged();

对上报的光照值有以下两个方法分别来处理:

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;
   
    if (USE_HUGE_DEBOUNCE) {
        int index = mScreenAutoBrightnessSpline.getIndex(lux);
        if ((mAmbientLuxIndex >= ROM_AMBIENT_LIGHT_INDEX)
            && (index < ROM_AMBIENT_LIGHT_INDEX))
        {
            setLuxThreshold(lux, true);
        }
        if (DEBUG) {
            Slog.d(TAG, "applyLightSensorMeasurement: mAmbientLux=" + mAmbientLux
                    + ", mAmbientLuxIndex=" + mAmbientLuxIndex
                    + ", lux=" + lux
                    + ", index=" + index
                    + ", [" + mDarkeningLuxThreshold + ", " + mBrighteningLuxThreshold + "]");
        }
    }

}
 
private void updateAmbientLux(long time) {
    // If the light sensor was just turned on then immediately update our initial
    // estimate of the current ambient light level.
    if (!mAmbientLuxValid) {
        final long timeWhenSensorWarmedUp =
            mLightSensorWarmUpTimeConfig + mLightSensorEnableTime;
        if (time < timeWhenSensorWarmedUp) {
            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, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS));
        mAmbientLuxValid = true;
        if (DEBUG) {
            Slog.d(TAG, "updateAmbientLux: Initializing: "
                    + "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer
                    + ", mAmbientLux=" + mAmbientLux);
        }
        updateAutoBrightness(true);
    }

    long nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
    long nextDarkenTransition = nextAmbientLightDarkeningTransition(time);
    // Essentially, we calculate both a slow ambient lux, to ensure there's a true long-term
    // change in lighting conditions, and a fast ambient lux to determine what the new
    // brightness situation is since the slow lux can be quite slow to converge.
    //
    // Note that both values need to be checked for sufficient change before updating the
    // proposed ambient light value since the slow value might be sufficiently far enough away
    // from the fast value to cause a recalculation while its actually just converging on
    // the fast value still.
    float slowAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_LONG_HORIZON_MILLIS);
    float fastAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS);
    android.util.Log.i("FM","--mBrighteningLuxThreshold is---"+mBrighteningLuxThreshold+"--nextBrightenTransition---"
            +nextBrightenTransition+"--mDarkeningLuxThreshold--"+mDarkeningLuxThreshold+"---nextDarkenTransition---"+nextDarkenTransition);

    if (slowAmbientLux >= mBrighteningLuxThreshold &&
            fastAmbientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time
            || slowAmbientLux <= mDarkeningLuxThreshold
            && fastAmbientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) {
        setAmbientLux(fastAmbientLux);
        if (DEBUG) {
            Slog.d(TAG, "updateAmbientLux: "
                    + ((fastAmbientLux > 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 + mNormalLightSensorRate;
    if (DEBUG) {
        Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for "
                + nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime));
    }
    mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime);
}
核心算法在calculateAmbientLux()中进行,即加权平均:
 
private float calculateAmbientLux(long now, long horizon) {
    if (DEBUG) {
        Slog.d(TAG, "calculateAmbientLux(" + now + ", " + horizon + ")");
    }
    final int N = mAmbientLightRingBuffer.size();
    if (N == 0) {
        Slog.e(TAG, "calculateAmbientLux: No ambient light readings available");
        return -1;
    }

    // Find the first measurement that is just outside of the horizon.
    int endIndex = 0;
    final long horizonStartTime = now - horizon;
    for (int i = 0; i < N-1; i++) {
        if (mAmbientLightRingBuffer.getTime(i + 1) <= horizonStartTime) {
            endIndex++;
        } else {
            break;
        }
    }
    if (DEBUG) {
        Slog.d(TAG, "calculateAmbientLux: selected endIndex=" + endIndex + ", point=("
                + mAmbientLightRingBuffer.getTime(endIndex) + ", "
                + mAmbientLightRingBuffer.getLux(endIndex)
                + ")");
    }
    float sum = 0;
    float totalWeight = 0;
    long endTime = AMBIENT_LIGHT_PREDICTION_TIME_MILLIS;
    for (int i = N - 1; i >= endIndex; i--) {
        long eventTime = mAmbientLightRingBuffer.getTime(i);
        if (i == endIndex && eventTime < horizonStartTime) {
            // If we're at the final value, make sure we only consider the part of the sample
            // within our desired horizon.
            eventTime = horizonStartTime;
        }
        final long startTime = eventTime - now;
        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;
}
比如:遮盖感光孔,上报的光照值会逐渐变小(由200逐渐将至0,最后一直为0),mAmbientLightRingBuffer中存进的值就会越来越小,
计算结果小于变暗阈值,且时间上大于变暗过渡时间后,就会使用Spline(存储了光照值和亮度值对应的map)对象获取对应的亮度值设置屏幕亮度。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值