Android O 亮度调节相比Android N的亮度调节改变不是很大,但是以前没有分析过背光亮度调节,最近遇到了一个问题,背光亮度调节没有反应,因此把流程从上到下梳理了一下。
1.设置里设置背光亮度
packages\apps\Settings\src\com\android\settings\BrightnessPreference.java
package com.android.settings;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.support.v7.preference.Preference;
import android.util.AttributeSet;
public class BrightnessPreference extends Preference {
public BrightnessPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onClick() {
getContext().startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
UserHandle.CURRENT_OR_SELF);
}
}
可以知道这是一个隐式intent,找到ACTION_SHOW_BRIGHTNESS_DIALOG就可以了,这个Activity在SystemUI下面。
<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>
可以知道最终启动的是com.android.systemui.settings.BrightnessController类文件
private void setBrightness(int brightness) {
try { mPower.setTemporaryScreenBrightnessSettingOverride(brightness);
} catch (RemoteException ex) {
}
}
调用IPowerManager.java文件的设置亮度。通过Binder进程间通信,调用到PowerManagerService.java文件的setTemporaryScreenBrightnessSettingOverride()方法:
private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
synchronized (mLock) {
if (mTemporaryScreenBrightnessSettingOverride != brightness) {
mTemporaryScreenBrightnessSettingOverride = brightness;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
可以知道跳转到了updatePowerStateLocked()这个方法。
protected void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
if (!Thread.holdsLock(mLock)) {
Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty);
updateStayOnLocked(mDirty);
updateScreenBrightnessBoostLocked(mDirty);
// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
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;
}
}
// Phase 2: Update display power state.
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
// Phase 3: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);
// Phase 4: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked();
// Phase 5: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
这个方法是电源管理的灵魂,包括休眠、亮屏都会在这里执行。通过注释可以看出最终调用了
updateDisplayPowerStateLocked(dirtyPhase2);
这个方法:
/**
* Updates the display power state asynchronously.
* When the update is finished, mDisplayReady will be set to true. The display
* controller posts a message to tell us when the actual display power state
* has been updated so we come back here to double-check and finish up.
*
* This function recalculates the display power state each time.
*
* @return True if the display became ready.
*/
private boolean updateDisplayPowerStateLocked(int dirty) {
final boolean oldDisplayReady = mDisplayReady;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
DIRTY_QUIESCENT)) != 0) {
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
// Determine appropriate screen brightness and auto-brightness adjustments.
boolean brightnessSetByUser = true;
int screenBrightness = mScreenBrightnessSettingDefault;
float screenAutoBrightnessAdjustment = 0.0f;
boolean autoBrightness = (mScreenBrightnessModeSetting ==
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
if (!mBootCompleted) {
// Keep the brightness steady during boot. This requires the
// bootloader brightness and the default brightness to be identical.
autoBrightness = false;
brightnessSetByUser = false;
} else if (mIsVrModeEnabled) {
screenBrightness = mScreenBrightnessForVrSetting;
autoBrightness = false;
} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
screenBrightness = mScreenBrightnessOverrideFromWindowManager;
autoBrightness = false;
brightnessSetByUser = false;
} else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
screenBrightness = mTemporaryScreenBrightnessSettingOverride;
} else if (isValidBrightness(mScreenBrightnessSetting)) {
screenBrightness = mScreenBrightnessSetting;
}
if (autoBrightness) {
screenBrightness = mScreenBrightnessSettingDefault;
if (isValidAutoBrightnessAdjustment(
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {
screenAutoBrightnessAdjustment =
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;
} else if (isValidAutoBrightnessAdjustment(
mScreenAutoBrightnessAdjustmentSetting)) {
screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;
}
}
screenBrightness = Math.max(Math.min(screenBrightness,
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
screenAutoBrightnessAdjustment = Math.max(Math.min(
screenAutoBrightnessAdjustment, 1.0f), -1.0f);
// Update display power request.
mDisplayPowerRequest.screenBrightness = screenBrightness;
mDisplayPowerRequest.screenAutoBrightnessAdjustment =
screenAutoBrightnessAdjustment;
mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
&& (mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
}
mDisplayPowerRequest.dozeScreenBrightness =
mDozeScreenBrightnessOverrideFromDreamManager;
} else {
mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
}
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
if ((dirty & DIRTY_QUIESCENT) != 0) {
sQuiescent = false;
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
+ ", policy=" + mDisplayPowerRequest.policy
+ ", mWakefulness=" + mWakefulness
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", mBootCompleted=" + mBootCompleted
+ ", mScreenBrightnessBoostInProgress=" + mScreenBrightnessBoostInProgress
+ ", mIsVrModeEnabled= " + mIsVrModeEnabled
+ ", sQuiescent=" + sQuiescent);
}
}
return mDisplayReady && !oldDisplayReady;
}
看起来来确实很费劲,但是仔细看去掉一些关于自动调节等,就知道了调用了
mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
调用到了DisplayManagerInternal.java文件
public abstract boolean requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity);
这个是抽象方法,必现有类去继承和实现,继续查找最终在
/frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
这里面有个内部类去继承。
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);
}
}
@Override
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
return mDisplayPowerController.requestPowerState(request,
waitForNegativeProximity);
}
然后调用了
requestGlobalDisplayStateInternal(state, brightness);
private void requestGlobalDisplayStateInternal(int state, int brightness) {
if (state == Display.STATE_UNKNOWN) {
state = Display.STATE_ON;
}
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF;
} else if (brightness < 0) {
brightness = PowerManager.BRIGHTNESS_DEFAULT;
} else if (brightness > PowerManager.BRIGHTNESS_ON) {
brightness = PowerManager.BRIGHTNESS_ON;
}
synchronized (mTempDisplayStateWorkQueue) {
try {
// Update the display state within the lock.
// Note that we do not need to schedule traversals here although it
// may happen as a side-effect of displays changing state.
synchronized (mSyncRoot) {
if (mGlobalDisplayState == state
&& mGlobalDisplayBrightness == brightness) {
return; // no change
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
+ Display.stateToString(state)
+ ", brightness=" + brightness + ")");
mGlobalDisplayState = state;
mGlobalDisplayBrightness = brightness;
applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
}
// Setting the display power state can take hundreds of milliseconds
// to complete so we defer the most expensive part of the work until
// after we have exited the critical section to avoid blocking other
// threads for a long time.
for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
mTempDisplayStateWorkQueue.get(i).run();
}
Trace.traceEnd(Trace.TRACE_TAG_POWER);
} finally {
mTempDisplayStateWorkQueue.clear();
}
}
}
然后调用到线程
applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
final int count = mDisplayDevices.size();
for (int i = 0; i < count; i++) {
DisplayDevice device = mDisplayDevices.get(i);
Runnable runnable = updateDisplayStateLocked(device);
if (runnable != null) {
workQueue.add(runnable);
}
}
}
mTempDisplayStateWorkQueue线程为
updateDisplayStateLocked(device);
private Runnable updateDisplayStateLocked(DisplayDevice device) {
// Blank or unblank the display immediately to match the state requested
// by the display power controller (if known).
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
}
return null;
}
device为DisplayDevice 引用对象,而LocalDisplayDevice继承DisplayDevice,实现
此时最终会调用到LocalDisplayAdapter中的内部类LocalDisplayDevice的函数requestDisplayStateLocked中来调用到Light模块。
@Override
public Runnable requestDisplayStateLocked(final int state, final int brightness) {
// Assume that the brightness is off if the display is being turned off.
assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
final boolean stateChanged = (mState != state);
final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
if (stateChanged || brightnessChanged) {
final int displayId = mBuiltInDisplayId;
final IBinder token = getDisplayTokenLocked();
final int oldState = mState;
if (stateChanged) {
mState = state;
updateDeviceInfoLocked();
}
if (brightnessChanged) {
mBrightness = brightness;
}
// Defer actually setting the display state until after we have exited
// the critical section since it can take hundreds of milliseconds
// to complete.
return new Runnable() {
@Override
public void run() {
// Exit a suspended state before making any changes.
int currentState = oldState;
if (Display.isSuspendedState(oldState)
|| oldState == Display.STATE_UNKNOWN) {
if (!Display.isSuspendedState(state)) {
setDisplayState(state);
currentState = state;
} else if (state == Display.STATE_DOZE_SUSPEND
|| oldState == Display.STATE_DOZE_SUSPEND) {
setDisplayState(Display.STATE_DOZE);
currentState = Display.STATE_DOZE;
} else {
return; // old state and new state is off
}
}
// If the state change was from or to VR, then we need to tell the light
// so that it can apply appropriate VR brightness settings. This should
// happen prior to changing the brightness but also if there is no
// brightness change at all.
if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
currentState != state) {
setVrMode(state == Display.STATE_VR);
}
// Apply brightness changes given that we are in a non-suspended state.
if (brightnessChanged) {
setDisplayBrightness(brightness);
}
// Enter the final desired state, possibly suspended.
if (state != currentState) {
setDisplayState(state);
}
}
这是线程类,最终会调用
private void setDisplayBrightness(int brightness) {
if (DEBUG) {
Slog.d(TAG, "setDisplayBrightness("
+ "id=" + displayId + ", brightness=" + brightness + ")");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
+ "id=" + displayId + ", brightness=" + brightness + ")");
try {
mBacklight.setBrightness(brightness);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
设置背光 为 mBacklight.setBrightness(brightness);
mBacklight是package com.android.server.lights.light引用对象,而light.java是一个抽象类,最终调用到LightService
@Override
public void setBrightness(int brightness) {
setBrightness(brightness, BRIGHTNESS_MODE_USER);
}
@Override
public void setBrightness(int brightness, int brightnessMode) {
synchronized (this) {
/*/ [ROM-1692] added by zeusis, optimize backlight crrection
int color = brightness & 0x000000ff;
/*/
int color = brightness;
if(mId != LightsManager.LIGHT_ID_BACKLIGHT) {
color = 0xff000000 | (color << 16) | (color << 8) | color;
}
//*/
setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
}
}
然后 调用setLightLocked()方法
private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
if (!mLocked && (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
mBrightnessMode != brightnessMode)) {
if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
+ Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
mLastColor = mColor;
mColor = color;
mMode = mode;
mOnMS = onMS;
mOffMS = offMS;
mLastBrightnessMode = mBrightnessMode;
mBrightnessMode = brightnessMode;
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
+ Integer.toHexString(color) + ")");
mPerfMan.notify(HawkeyeErrno.EMS_LCD_SET_BACKLIGHT_BEGIN);
try {
setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
mPerfMan.notify(HawkeyeErrno.EMS_LCD_SET_BACKLIGHT_END);
}
}
}
接着调用setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
static native void setLight_native(long ptr, int light, int color, int mode,
int onMS, int offMS, int brightnessMode);
这个调用是jni方法
static void setLight_native(
JNIEnv* /* env */,
jobject /* clazz */,
jint light,
jint colorARGB,
jint flashMode,
jint onMS,
jint offMS,
jint brightnessMode) {
if (!validate(light, flashMode, brightnessMode)) {
return;
}
sp<ILight> hal = LightHal::associate();
if (hal == nullptr) {
return;
}
Type type = static_cast<Type>(light);
LightState state = constructState(
colorARGB, flashMode, onMS, offMS, brightnessMode);
{
ALOGD_IF_SLOW(50, "Excessive delay setting light");
Return<Status> ret = hal->setLight(type, state);
processReturn(ret, type, state);
}
}
可以看出Return ret = hal->setLight(type, state); 其中是sp hal = LightHal::associate();生成的
static sp<ILight> associate() {
if ((sLight == nullptr && !sLightInit) ||
(sLight != nullptr && !sLight->ping().isOk())) {
// will return the hal if it exists the first time.
sLight = ILight::getService();
sLightInit = true;
if (sLight == nullptr) {
ALOGE("Unable to get ILight interface.");
}
}
return sLight;
}
获取的是ILight.cpp对象,Light.cpp实现了ILight.cpp,接着调用setLight方法
eturn<Status> Light::setLight(Type type, const LightState& state) {
auto it = mLights.find(type);
if (it == mLights.end()) {
return Status::LIGHT_NOT_SUPPORTED;
}
light_device_t* hwLight = it->second;
light_state_t legacyState {
.color = state.color,
.flashMode = static_cast<int>(state.flashMode),
.flashOnMS = state.flashOnMs,
.flashOffMS = state.flashOffMs,
.brightnessMode = static_cast<int>(state.brightnessMode),
};
int ret = hwLight->set_light(hwLight, &legacyState);
ALOGE("coolpad setLight ret= %d\n", ret);
switch (ret) {
case -ENOSYS:
return Status::BRIGHTNESS_NOT_SUPPORTED;
case 0:
return Status::SUCCESS;
default:
return Status::UNKNOWN;
}
}
然后调用 int ret = hwLight->set_light(hwLight, &legacyState);方法
见light.c文件
int (*set_light)(struct light_device_t* dev,
struct light_state_t const* state);
if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
set_light = set_light_backlight;
else if (0 == strcmp(LIGHT_ID_BATTERY, name))
set_light = set_light_battery;
else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
set_light = set_light_notifications;
else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
set_light = set_light_buttons;
else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
set_light = set_light_attention;
else
return -EINVAL;
如果是背光就调用
et_light_backlight(struct light_device_t* dev,
struct light_state_t const* state)
{
int err = 0;
//int brightness = rgb_to_brightness(state);
int brightness = (int)state->color;
if(!dev) {
return -1;
}
ALOGE("coolpad brightness = %d\n", brightness);
pthread_mutex_lock(&g_lock);
err = write_int(LCD_FILE, brightness);
ALOGE("coolpad write state %d\n", err);
pthread_mutex_unlock(&g_lock);
return err;
}
其中hal层框架改了,用的是hidl语言,不过也挺容易理解。好了背光亮度从上到下介绍完了,主要是流程。