P 上背光调节:
https://blog.csdn.net/FightFightFight/article/details/85797336
frameworks\base\packages\SystemUI\AndroidManifest.xml
frameworks\base\packages\SystemUI\src\com\android\systemui\settings\BrightnessDialog.java
/** A dialog that provides controls for adjusting the screen brightness. */
public class BrightnessDialog extends Activity {
private BrightnessController mBrightnessController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Window window = getWindow();
window.setGravity(Gravity.TOP);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.requestFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.quick_settings_brightness_dialog);
final ImageView icon = (ImageView) findViewById(R.id.brightness_icon_on);
final ToggleSlider slider = (ToggleSlider) findViewById(R.id.brightness_slider);
mBrightnessController = new BrightnessController(this, icon, slider);
}
@Override
protected void onStart() {
super.onStart();
mBrightnessController.registerCallbacks();
MetricsLogger.visible(this, MetricsEvent.BRIGHTNESS_DIALOG);
}
@Override
protected void onStop() {
super.onStop();
MetricsLogger.hidden(this, MetricsEvent.BRIGHTNESS_DIALOG);
mBrightnessController.unregisterCallbacks();
}
}
// BrightnessController 实现了ToggleSlider监听的类,其内部对象类是赋值传入的slider,从而与ToggleSlider 关联起来
// mBrightnessController.registerCallbacks(); 将BrightnessController 设置为slider 的监听器,同时设置对数据库的监BrightnessController
frameworks\base\packages\SystemUI\src\com\android\systemui\settings\BrightnessController.java
public class BrightnessController implements ToggleSlider.Listener {
public interface BrightnessStateChangeCallback {
public void onBrightnessLevelChanged();
}
/** ContentObserver to watch brightness **/
private class BrightnessObserver extends ContentObserver {
private final Uri BRIGHTNESS_MODE_URI =
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);
private final Uri BRIGHTNESS_URI =
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
private final Uri BRIGHTNESS_ADJ_URI =
Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ);
}
public void registerCallbacks() {
if (mListening) {
return;
}
mBrightnessObserver.startObserving();
mUserTracker.startTracking();
// Update the slider and mode before attaching the listener so we don't
// receive the onChanged notifications for the initial values.
updateMode();
updateSlider();
mControl.setOnChangedListener(this);
mListening = true;
}
}
// 当注册数据库监听器与ToggleSlider的监听器后,如果数据库改变,onChange 就会更新ToggleSlider ,如果ToggleSlider 改变了,这回调用其onChange函数,这个时候会更新数据库项,反过来由于数据库项变了,就会更新ToggleSlider 到对应的进度位置。
frameworks\base\packages\SystemUI\src\com\android\systemui\settings\ToggleSlider.java
mToggle = (CompoundButton) findViewById(R.id.toggle); mToggle.setOnCheckedChangeListener(mCheckListener); mSlider = (ToggleSeekBar) findViewById(R.id.slider); mSlider.setOnSeekBarChangeListener(mSeekListener);
private final OnCheckedChangeListener mCheckListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton toggle, boolean checked) {
mSlider.setEnabled(!checked);
if (mListener != null) {
mListener.onChanged(
ToggleSlider.this, mTracking, checked, mSlider.getProgress(), false);
}
if (mMirror != null) {
mMirror.mToggle.setChecked(checked);
}
}
};
private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mListener != null) {
mListener.onChanged(
ToggleSlider.this, mTracking, mToggle.isChecked(), progress, false);
}
}
ToggleSlider 是由多个控件组成的,这里一个是check控件、一个是进度条控件,并分别绑定对应的监听器。
private ToggleSlider mMirror;
private BrightnessMirrorController mMirrorController;
ToggleSlider 这两个成员用于下拉设置中设置与隐藏亮度进度条。
public void setMirror(ToggleSlider toggleSlider) {
mMirror = toggleSlider;
if (mMirror != null) {
mMirror.setChecked(mToggle.isChecked());
mMirror.setMax(mSlider.getMax());
mMirror.setValue(mSlider.getProgress());
}
}
public void setMirrorController(BrightnessMirrorController c) {
mMirrorController = c;
}
这里将 mToggle、mSlider 值设置到 mMirror
frameworks\base\packages\SystemUI\src\com\android\systemui\qs\QSPanel.java
public void setBrightnessMirror(BrightnessMirrorController c) { mBrightnessMirrorController = c; ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider); ToggleSlider mirror = (ToggleSlider) c.getMirror().findViewById(R.id.brightness_slider); brightnessSlider.setMirror(mirror); brightnessSlider.setMirrorController(c); }
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBar.java
mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
这里 mBrightnessMirrorController控制 ToggleSlider mirror其在下拉菜单中的显示与隐藏,而其值由 mToggle、mSlider 的值设置。
frameworks\base\packages\SystemUI\src\com\android\systemui\settings\BrightnessController.java
public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value, boolean stopTracking) { updateIcon(mAutomatic); if (mExternalChange) return; if (!mAutomatic) { final int val = value + mMinimumBacklight; if (stopTracking) { MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val); } setBrightness(val); if (!tracking) { AsyncTask.execute(new Runnable() { public void run() { Settings.System.putIntForUser(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, val, UserHandle.USER_CURRENT); } }); } } else { final float adj = value / (BRIGHTNESS_ADJ_RESOLUTION / 2f) - 1; if (stopTracking) { MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS_AUTO, value); } setBrightnessAdj(adj); if (!tracking) { AsyncTask.execute(new Runnable() { public void run() { Settings.System.putFloatForUser(mContext.getContentResolver(), Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adj, UserHandle.USER_CURRENT); } }); } } for (BrightnessStateChangeCallback cb : mChangeCallbacks) { cb.onBrightnessLevelChanged(); } }
mAutomaticAvailable = context.getResources().getBoolean( com.android.internal.R.bool.config_automatic_brightness_available);
自动亮度是否支持,设置Settings.System.SCREEN_BRIGHTNESS_MODE
public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
支持则设置为Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC ,否则设置为 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL
这里监听进度条改变,并记录到数据库中,并调用PMS设置亮度
private class BrightnessObserver extends ContentObserver { private final Uri BRIGHTNESS_MODE_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE); private final Uri BRIGHTNESS_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS); private final Uri BRIGHTNESS_ADJ_URI = Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ); public BrightnessObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { onChange(selfChange, null); } @Override public void onChange(boolean selfChange, Uri uri) { if (selfChange) return; try { mExternalChange = true; if (BRIGHTNESS_MODE_URI.equals(uri)) { updateMode(); updateSlider();
同时systemUI 中BrightnessController会注册监听器监听数据库改变从而改变进度条的位置
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
关闭自动背光:
setBrightness(val);-》
mPower.setTemporaryScreenBrightnessSettingOverride(brightness);设置 mTemporaryScreenBrightnessSettingOverride 为当前进度条值,同时会设置 Settings.System.SCREEN_BRIGHTNESS 值为val,但是这个时候值是一样的,所以
SCREEN_BRIGHTNESS 不会变化,紧接着会再次调用这个函数,设置的值为用户点击位置的值,从而马上更新SCREEN_BRIGHTNESS ,
这个时候PMS 监听数据库值Settings.System.SCREEN_BRIGHTNESS 改变,并执行以下
mScreenBrightnessSetting = Settings.System.getIntForUser(resolver, Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault,
if (oldScreenBrightnessSetting != mScreenBrightnessSetting) { mTemporaryScreenBrightnessSettingOverride = -1; }
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked(); //这个时候亮度值不一样,从而调节亮度。
当用户点击进度条到不同位置时,
1、进度条会调用setBrightness(val),但是值还是当前进度条的值。这样会调用如下方法:
setBrightness(val); //设置 mTemporaryScreenBrightnessSettingOverride 为当前进度条的值。
mDirty |= DIRTY_SETTINGS; //设置标记,这样才会调用updatePowerStateLocked(); updatePowerStateLocked(); //更新设置屏膜亮度,但是由于设置的为当前进度条的值,即前后亮度一致,所以这次并不会改变屏膜亮度。
2、这个时候进度条更新到用户设置的值,这个时候会重复1、
3、PMS中监听到SCREEN_BRIGHTNESS 数据库改变,从而将mTemporaryScreenAutoBrightnessAdjustmentSettingOverride 改为 -1,这个时候从数据库中
读取的 SCREEN_BRIGHTNESS 更上次保存的不一样,从而调用
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
将亮度调到用户设置的亮度值。
如果打开自动背光:与手动一样
阶段1
setBrightnessAdj(adj); --》
mPower.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(adj);-》
mDirty |= DIRTY_SETTINGS; updatePowerStateLocked(); // 这个时候并没有改变亮度,用于设置的是当前进度条的值
阶段2
设置mTemporaryScreenAutoBrightnessAdjustmentSettingOverride 为adj,同时设置 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ
这个时候会监听数据库值 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ
final float oldScreenAutoBrightnessAdjustmentSetting =
mScreenAutoBrightnessAdjustmentSetting;
mScreenAutoBrightnessAdjustmentSetting = Settings.System.getFloatForUser(resolver,
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f,
UserHandle.USER_CURRENT);
if (oldScreenAutoBrightnessAdjustmentSetting != mScreenAutoBrightnessAdjustmentSetting) {
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN;
}
//监听
private final class SettingsObserver extends ContentObserver { public SettingsObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange, Uri uri) { synchronized (mLock) { handleSettingsChangedLocked(); } } }
private void handleSettingsChangedLocked() { updateSettingsLocked(); updatePowerStateLocked(); }
阶段1
setBrightnessAdj(adj); --》
mPower.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(adj);-》
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
--》
// Phase 2: Update display power state.
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
这个时候 有 DIRTY_SETTINGS 并且 mTemporaryScreenAutoBrightnessAdjustmentSettingOverride 是有效值,否则取
mScreenAutoBrightnessAdjustmentSetting
这里赋值mDisplayPowerRequest
// Update display power request.
mDisplayPowerRequest.screenBrightness = screenBrightness; ---屏膜亮度
mDisplayPowerRequest.screenAutoBrightnessAdjustment = ---自动进度条值,现在是mTemporaryScreenAutoBrightnessAdjustmentSettingOverride
screenAutoBrightnessAdjustment;
mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
mDisplayPowerRequest.useAutoBrightness = autoBrightness; ---自动调节值
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress;
mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight;
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
实现在
frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
return mDisplayPowerController.requestPowerState(request,
waitForNegativeProximity);
}
这个时候判断 mPendingRequestLocked 与 request可以知道是否changed,从而是否调用sendUpdatePowerStateLocked,并进入请求标识mPendingRequestChangedLocked
if (changed && !mPendingRequestChangedLocked) {
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked();
}
if (changed) {
mDisplayReadyLocked = false; ---如果changed没准备好
}
==》
private void sendUpdatePowerStateLocked() {
if (!mPendingUpdatePowerStateLocked) {
mPendingUpdatePowerStateLocked = true;
Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
进入请求mPendingUpdatePowerStateLocked
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_POWER_STATE:
updatePowerState();
break;
case MSG_PROXIMITY_SENSOR_DEBOUNCED:
debounceProximitySensor();
break;
case MSG_SCREEN_ON_UNBLOCKED:
if (mPendingScreenOnUnblocker == msg.obj) {
unblockScreenOn();
updatePowerState();
}
break;
case MSG_PROTECT_LOW_DIMMING:
handleProtectLowDimming();
break;
}
}
==》
updatePowerState();
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;
if (mPendingRequestLocked == null) {
return; // wait until first actual power request
}
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mustInitialize = true;
} else if (mPendingRequestChangedLocked) {
autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
!= mPendingRequestLocked.screenAutoBrightnessAdjustment);
mPowerRequest.copyFrom(mPendingRequestLocked);
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
}
这个时候构造 mPowerRequest
updateAutoBrightness()
根据光感应出一个值(算法),由这个值算出一个屏膜亮度newScreenAutoBrightness,
并与mScreenAutoBrightness比较,如果不一样就会updateBrightness
自动背光亮度mScreenAutoBrightness
mAppliedAutoBrightness
mScreenBrightness
手动模式
这个时候进度条对应的值是亮度值 SCREEN_BRIGHTNESS 0~255
自动模式下的亮度
这个时候进度条对应的值是[-1,1],即缩放比例mScreenAutoBrightnessAdjustment,根据这个比例来得到一个亮度值
自动模式下的自动动背光调节
自动背光传感器会自动感应光强度,并通过算法获得一个亮度值mScreenAutoBrightness,与当前屏膜亮度mScreenBrightness比较,
变化则会自动调节屏膜亮度。或者这个时候调节进度条会导致mScreenAutoBrightnessAdjustment变化,从而调节亮度。
问题:
1、手动与自动切换时,会出现进度条不一样,并且也会出些亮度不一样
---这是由于手动模式对应的是上一次SCREEN_BRIGHTNESS ,而自动模式对应的是上一次mScreenAutoBrightnessAdjustment,这两个
值没有必然联系,仅仅记录了上一次对应的亮度的位置及亮度,从而出现这种现象。
2、自动模式,会出现亮度变化但是进度条不变
---这是由于自动背光传感器及对应的算法会根据环境算出一个亮度mScreenAutoBrightness,从而跟目前亮度比较发生变化就会调节到
mScreenAutoBrightness亮度,但是不会影响mScreenAutoBrightnessAdjustment值,所以进度条不变化,亮度变化。如果这个时候
调节进度条会导致mScreenAutoBrightnessAdjustment变化,从而根据mScreenAutoBrightnessAdjustment重新调节亮度。
问题1、 修改
可以在手动与自动切换时将mScreenAutoBrightnessAdjustment与mScreenBrightness关联起来,做到切换时只是进度条改变,屏膜的亮度不变。
见http://www.ithao123.cn/content-11140655.html
http://blog.csdn.net/kitty_landon/article/details/64128140