Android中所有系统灯光的定义:lights.h #define LIGHT_ID_BACKLIGHT “backlight”
JNI: com_android_server_lights_LightsService.cpp
setLight_native:调用HAL去控制背光
Service:LightsService.java 1.它是各种灯光和背光的Service,提供了对背光灯操作的所有方法 2.setLightLocked():是实际调用JNI操作背光灯的函数,所有向应用程序公开的LCD操作接口都使用synchronized (this){… setLightLocked() …} 确保互斥访问硬件。 3.onStart()中:publishLocalService(LightsManager.class, mService);
先分析DisplayPowerController.java
private void initialize() {
mPowerState = new DisplayPowerState(mBlanker,
mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT),
new ColorFade(Display.DEFAULT_DISPLAY));
...
}
- 获取LightsService中注册的LightsManager:mLights = LocalServices.getService(LightsManager.class);
- 然后在构造函数中只获取了背光灯:new DisplayPowerState(mBlanker, mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT), new ColorFade(Display.DEFAULT_DISPLAY)); 整个系统中也只有这里获取了背光灯。
查看DisplayPowerState构造函数
public DisplayPowerState(DisplayBlanker blanker, Light backlight, ColorFade electronBeam) {
77 mHandler = new Handler(true );
78 mChoreographer = Choreographer.getInstance();
79 mBlanker = blanker;
80 mBacklight = backlight;
81 mColorFade = electronBeam;
82 mPhotonicModulator = new PhotonicModulator();
83 mPhotonicModulator.start();
84
85
86
87
88
89
90
91 mScreenState = Display.STATE_ON;
92 mScreenBrightness = PowerManager.BRIGHTNESS_ON;
93 scheduleScreenUpdate();
94
95 mColorFadePrepared = false;
96 mColorFadeLevel = 1.0f;
97 mColorFadeReady = true;
98 }
构造函数中
- mBacklight = backlight //这里将上述拿到的LightImpl,赋值给mBacklight
- 创建一个线程mPhotonicModulator = new PhotonicModulator()
下面分析PhotonicModulator线程
private final class PhotonicModulator extends Thread {
341 private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF;
342 private static final int INITIAL_BACKLIGHT = -1;
343
344 private final Object mLock = new Object();
345
346 private int mPendingState = INITIAL_SCREEN_STATE;
347 private int mPendingBacklight = INITIAL_BACKLIGHT;
348 private int mActualState = INITIAL_SCREEN_STATE;
349 private int mActualBacklight = INITIAL_BACKLIGHT;
350 private boolean mChangeInProgress;
351
352 public boolean setState(int state, int backlight) {
353 synchronized (mLock) {
354 if (state != mPendingState || backlight != mPendingBacklight) {
355 if (DEBUG) {
356 Slog.d(TAG, "Requesting new screen state: state="
357 + Display.stateToString(state) + ", backlight=" + backlight);
358 }
359
360 mPendingState = state;
361 mPendingBacklight = backlight;
362
363 if (!mChangeInProgress) {
364 mChangeInProgress = true;
365 mLock.notifyAll();
366 }
367 }
368 return !mChangeInProgress;
369 }
370 }
371
384 @Override
385 public void run() {
386 for (;;) {
387
388 final int state;
389 final boolean stateChanged;
390 final int backlight;
391 final boolean backlightChanged;
392 synchronized (mLock) {
393 state = mPendingState;
394 stateChanged = (state != mActualState);
395 backlight = mPendingBacklight;
396 backlightChanged = (backlight != mActualBacklight);
397 if (!stateChanged && !backlightChanged) {
398
399 mChangeInProgress = false;
400 postScreenUpdateThreadSafe();
401 try {
402 mLock.wait();
403 } catch (InterruptedException ex) { }
404 continue;
405 }
406 mActualState = state;
407 mActualBacklight = backlight;
408 }
409
410
411 if (DEBUG) {
412 Slog.d(TAG, "Updating screen state: state="
413 + Display.stateToString(state) + ", backlight=" + backlight);
414 }
415 boolean suspending = Display.isSuspendedState(state);
416 if (stateChanged && !suspending) {
417 requestDisplayState(state);
418 }
419 if (backlightChanged) {
420 setBrightness(backlight);
421 }
422 if (stateChanged && suspending) {
423 requestDisplayState(state);
424 }
425 }
426 }
- 创建了一个PhotonicModulator 线程,此线程大部分事件是睡眠的,通过notifyAll()来唤醒,具体唤醒流程如下:
scheduleScreenUpdate()
--> postScreenUpdateThreadSafe();
postScreenUpdateThreadSafe中mHandler.post(mScreenUpdateRunnable);
//mScreenUpdateRunnable如下:
private final Runnable mScreenUpdateRunnable = new Runnable() {
mPhotonicModulator.setState(mScreenState, brightness);
}
//setState
public boolean setState(int state, int backlight) {
synchronized (mLock) {
if (state != mPendingState || backlight != mPendingBacklight) {
if (DEBUG) {
Slog.d(TAG, "Requesting new screen state: state="
+ Display.stateToString(state) + ", backlight=" + backlight);
}
mPendingState = state;
mPendingBacklight = backlight;
if (!mChangeInProgress) {
mChangeInProgress = true;
mLock.notifyAll();
}
}
return !mChangeInProgress;
}
}
由上,也就是调用scheduleScreenUpdate()来触发向消息队列中存放一个消息,消息处理函数中notifyAll()然后在上面无限循环的run()中设置背光亮度。 下面查找scheduleScreenUpdate()的地方: (1)DisplayPowerState构造方法 –> scheduleScreenUpdate (2)setScreenState –> scheduleScreenUpdate (3)setScreenBrightness –> scheduleScreenUpdate (4)setColorFadeLevel –> scheduleScreenUpdate 综上可以看出,DisplayPowerState.java有三大功能: 设置屏幕状态(setScreenState)、设置屏幕背光(setScreenBrightness)、设置colorfade(setColorFadeLevel)
在frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java的systemReady方法中: (1)注册了4个广播Receiver:
Receiver 监听的事件
BatteryReceiver ACTION_BATTERY_CHANGED
DreamReceiver ACTION_DREAMING_STARTED
UserSwitchedReceiver ACTION_USER_SWITCHED
DockReceiver ACTION_DOCK_EVENT
当收到这个广播时,都会调用到updatePowerStateLocked()方法 (2)对于背光灯还注册了1个ContentObserver resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SCREENSAVER_ENABLED), false, mSettingsObserver, UserHandle.USER_ALL); 当数据库中Settings.Secure.SCREENSAVER_ENABLED变化的时候,mSettingsObserver中的onChange()方法就会被调用。
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();
}
所以触发ContentObserver最终也会调用updatePowerStateLocked(); 下面分析一下updatePowerStateLocked
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
try {
updateIsPoweredLocked(mDirty);
updateStayOnLocked(mDirty);
updateScreenBrightnessBoostLocked(mDirty);
final long now = SystemClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
updateDreamLocked(dirtyPhase2, displayBecameReady);
finishWakefulnessChangeIfNeededLocked();
updateSuspendBlockerLocked();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
private boolean updateDisplayPowerStateLocked(int dirty) {
...
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
...
}
这里有mDisplayManagerInternal中的requestPowerState,mDisplayManagerInternal是一个抽象类,肯定有子类继承它并实现它的requestPowerState方法。 mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
private final class LocalService extends DisplayManagerInternal {
...
@Override
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
return mDisplayPowerController.requestPowerState(request,
waitForNegativeProximity);
}
}
public void onStart() {
mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
true );
publishLocalService(DisplayManagerInternal.class, new LocalService());
}
在\frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java中
-->requestPowerState
--> sendUpdatePowerStateLocked()
-->mHandler.sendMessage(msg); //它通过发送消息在Handler的handleMessage中处理
-->handleMessage(Message msg)
-->updatePowerState()
-->animateScreenBrightness(brightness, 0);
--->mScreenBrightnessRampAnimator.animateTo(target, rate) //rate表示收敛速度,要是0表示立即设为targrt值
RampAnimator.java
--->animateTo(target, rate)
--->mProperty.setValue
--->DisplayPowerState.setScreenBrightness
--->scheduleScreenUpdate()
下面分析 mScreenBrightnessRampAnimator.animateTo(target, rate)方法
private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
下面分析RampAnimator类:
public RampAnimator(T object, IntProperty<T> property) {
mObject = object;
mProperty = property;
mChoreographer = Choreographer.getInstance();
}
public boolean animateTo(int target, int rate) {
if (mFirstTime || rate <= 0) {
if (mFirstTime || target != mCurrentValue) {
mFirstTime = false;
mRate = 0;
mTargetValue = target;
mCurrentValue = target;
mProperty.setValue(mObject, target);
if (mAnimating) {
mAnimating = false;
cancelAnimationCallback();
}
if (mListener != null) {
mListener.onAnimationEnd();
}
return true;
}
return false;
}
if (!mAnimating
|| rate > mRate
|| (target <= mCurrentValue && mCurrentValue <= mTargetValue)
|| (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
mRate = rate;
}
final boolean changed = (mTargetValue != target);
mTargetValue = target;
if (!mAnimating && target != mCurrentValue) {
mAnimating = true;
mAnimatedValue = mCurrentValue;
mLastFrameTimeNanos = System.nanoTime();
postAnimationCallback();
}
return changed;
}
public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS =
new IntProperty<DisplayPowerState>("screenBrightness") {
@Override
public void setValue(DisplayPowerState object, int value) {
object.setScreenBrightness(value);
}
@Override
public Integer get(DisplayPowerState object) {
return object.getScreenBrightness();
}
};
public void setScreenBrightness(int brightness) {
if (mScreenBrightness != brightness) {
if (DEBUG) {
Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
}
mScreenBrightness = brightness;
if (mScreenState != Display.STATE_OFF) {
mScreenReady = false;
scheduleScreenUpdate();
}
}
}
setting中怎么调节亮度呢
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);
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, MetricsLogger.BRIGHTNESS_DIALOG);
}
}
public BrightnessController(Context context, ImageView icon, ToggleSlider control) {
mContext = context;
mIcon = icon;
mControl = control;
mHandler = new Handler();
mUserTracker = new CurrentUserTracker(mContext) {
@Override
public void onUserSwitched(int newUserId) {
updateMode();
updateSlider();
}
};
...
}
public void registerCallbacks() {
mControl.setOnChangedListener(this);
mListening = true;
}
@Override
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, MetricsLogger.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);
}
});
}
...
}
private void setBrightness(int brightness) {
try {
mPower.setTemporaryScreenBrightnessSettingOverride(brightness);
} catch (RemoteException ex) {
}
}
public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
synchronized (mLock) {
if (mTemporaryScreenBrightnessSettingOverride != brightness) {
mTemporaryScreenBrightnessSettingOverride = brightness;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
App测试Demo MainActivity.java
package com.example.mm.lcd_brightness;
import android.os.Bundle;
import android.provider.Settings;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SeekBar;
public class MainActivity extends AppCompatActivity {
final private int LED_NOTIFICATION_ID = 123;
private SeekBar mBacklightSeekBar = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mBacklightSeekBar = (SeekBar)findViewById(R.id.seekBar);
try {
Settings.System.putInt(getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
int brightness = android.provider.Settings.System.getInt(getContentResolver(),
android.provider.Settings.System.SCREEN_BRIGHTNESS);
mBacklightSeekBar.setProgress(brightness*100/255);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
mBacklightSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener (){
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int brightness = mBacklightSeekBar.getProgress();
brightness = brightness * 255 / 100;
android.provider.Settings.System.putInt(getContentResolver(),
android.provider.Settings.System.SCREEN_BRIGHTNESS, brightness);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
Log.d("App_Brightness: ","==============onStartTrackingTouch===============");
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Log.d("App_Brightness: ","==============onStartTrackingTouch===============");
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
|