下拉菜单中自动亮度调节

来源:互联网 发布:淘宝手机版订单回收站 编辑:程序博客网 时间:2024/05/17 08:46


frameworks\base\packages\SystemUI\AndroidManifest.xml

<activity    android:name=".settings.BrightnessDialog"    android:label="@string/quick_settings_brightness_dialog_title"    android:theme="@android:style/Theme.DeviceDefault.Dialog"    android:finishOnCloseSystemDialogs="true"    android:launchMode="singleInstance"    android:excludeFromRecents="true"    android:exported="true">    <intent-filter>        <action android:name="android.intent.action.SHOW_BRIGHTNESS_DIALOG" />        <category android:name="android.intent.category.DEFAULT" />    </intent-filter></activity>

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 

@Overridepublic 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

原创粉丝点击