上篇博客我们分析了,PowerManagerService和DisplayPowerController这两个类,我也提到了和android5.1的变化,把背光这块放到了DisplayManagerService中了,之前这块没有分析过,今天分析下DisplayManagerService和背光的关系。
看了DisplayManagerService的注释,发现现在所以的显示设备都放在DisplayManagerService管理,wifiDisplay,defaultDisplay(背光)。
一、DisplayManagerService注册localDisplay的适配层
我们先来看构造函数:
- public DisplayManagerService(Context context) {
- super(context);
- mContext = context;
- mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());//消息处理
- mUiHandler = UiThread.getHandler();
- mDisplayAdapterListener = new DisplayAdapterListener();//display适配层监视器
- mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
- PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();//成员变量屏幕亮度
- }
我们再来看onStart函数,publish了一个BinderService和LocalService,还有发送了一个消息。
- @Override
- public void onStart() {
- mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
- publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
- true /*allowIsolated*/);
- publishLocalService(DisplayManagerInternal.class, new LocalService());
- }
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
- registerDefaultDisplayAdapter();
- break;
registerDefaultDisplayAdapter函数
- private void registerDefaultDisplayAdapter() {
- // Register default display adapter.
- synchronized (mSyncRoot) {
- registerDisplayAdapterLocked(new LocalDisplayAdapter(
- mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
- }
- }
再来看看registerDisplayAdapterLocked
- private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
- mDisplayAdapters.add(adapter);
- adapter.registerLocked();
- }
这里就是register了DefaultDisplay的适配层,就是和背光相关的。在新建LocalDisplayAdapter的时候我们把mDisplayAdapterListener传过去了。
二、LocalDisplayAdapter & LocalDisplayDevice
LocalDisplayAdapter构造函数调用了父类的,而父类也就是保存了变量
- public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
- Context context, Handler handler, Listener listener) {
- super(syncRoot, context, handler, listener, TAG);
- }
上面又紧跟着调用了registerLocked函数
- public void registerLocked() {
- super.registerLocked();
- mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
- for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
- tryConnectDisplayLocked(builtInDisplayId);
- }
- }
tryConnectDisplayLocked函数,先是看传入的builtInDisplayId是否支持,一个是main,一个是hdmi的。
- private void tryConnectDisplayLocked(int builtInDisplayId) {
- IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
- if (displayToken != null) {
- SurfaceControl.PhysicalDisplayInfo[] configs =
- SurfaceControl.getDisplayConfigs(displayToken);
- if (configs == null) {
- // There are no valid configs for this device, so we can't use it
- Slog.w(TAG, "No valid configs found for display device " +
- builtInDisplayId);
- return;
- }
- int activeConfig = SurfaceControl.getActiveConfig(displayToken);
- if (activeConfig < 0) {
- // There is no active config, and for now we don't have the
- // policy to set one.
- Slog.w(TAG, "No active config found for display device " +
- builtInDisplayId);
- return;
- }
- LocalDisplayDevice device = mDevices.get(builtInDisplayId);
- if (device == null) {
- // Display was added.
- device = new LocalDisplayDevice(displayToken, builtInDisplayId,
- configs, activeConfig);
- mDevices.put(builtInDisplayId, device);
- sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
- } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig)) {
- // Display properties changed.
- sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
- }
- } else {
- // The display is no longer available. Ignore the attempt to add it.
- // If it was connected but has already been disconnected, we'll get a
- // disconnect event that will remove it from mDevices.
- }
- }
然后再去查找这个LocalDisplayDevice,如果是找到了需要更新下configs,没找到需要新建一个LocalDisplayDevice。最后都调用了sendDisplayDeviceEventLocked函数。
我们再来看LocalDisplayDevice,如果传入的是BUILT_IN_DISPLAY_ID_MAIN就是背光的,我们获取背光的Light,保存在mBackLight变量。
- public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
- SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo) {
- super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId);
- mBuiltInDisplayId = builtInDisplayId;
- updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo);
- if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
- LightsManager lights = LocalServices.getService(LightsManager.class);
- mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
- } else {
- mBacklight = null;
- }
- }
然后上面函数调用了sendDisplayDeviceEventLocked函数,就是调用了传入的参数DisplayAdapterListener
- protected final void sendDisplayDeviceEventLocked(
- final DisplayDevice device, final int event) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mListener.onDisplayDeviceEvent(device, event);
- }
- });
- }
如果是新建就调用了handleDisplayDeviceAdded函数,
- private final class DisplayAdapterListener implements DisplayAdapter.Listener {
- @Override
- public void onDisplayDeviceEvent(DisplayDevice device, int event) {
- switch (event) {
- case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
- handleDisplayDeviceAdded(device);
- break;
- case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
- handleDisplayDeviceChanged(device);
- break;
- case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
- handleDisplayDeviceRemoved(device);
- break;
- }
- }
- @Override
- public void onTraversalRequested() {
- synchronized (mSyncRoot) {
- scheduleTraversalLocked(false);
- }
- }
- }
我们先来看看handleDisplayDeviceAdded,最后将device保存在了mDisplayDevices中。
- private void handleDisplayDeviceAdded(DisplayDevice device) {
- synchronized (mSyncRoot) {
- handleDisplayDeviceAddedLocked(device);
- }
- }
- private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
- DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
- if (mDisplayDevices.contains(device)) {
- Slog.w(TAG, "Attempted to add already added display device: " + info);
- return;
- }
- Slog.i(TAG, "Display device added: " + info);
- device.mDebugLastLoggedDeviceInfo = info;
- mDisplayDevices.add(device);
- addLogicalDisplayLocked(device);
- Runnable work = updateDisplayStateLocked(device);
- if (work != null) {
- work.run();
- }
- scheduleTraversalLocked(false);
- }
三、设置背光
现在我们在上篇博客不是说背光的调制最后是在DisplayManagerService中,是在下面函数的requestGlobalDisplayStateInternal中调用的
- 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);
- }
- }
我们再来看看requestGlobalDisplayStateInternal函数:
- 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函数,最后遍历device调用updateDisplayStateLocked函数
- 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);
- }
- }
- }
updateDisplayStateLocked函数调用device的requestDisplayStateLocked返回是Runnable,最后放在workQueue队列中
- 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;
- }
我们再来看看LocalDisplayDevice的requestDisplayStateLocked函数
- 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
- }
- }
- // 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 setDisplayState(int state) {
- if (DEBUG) {
- Slog.d(TAG, "setDisplayState("
- + "id=" + displayId
- + ", state=" + Display.stateToString(state) + ")");
- }
- Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayState("
- + "id=" + displayId
- + ", state=" + Display.stateToString(state) + ")");
- try {
- final int mode = getPowerModeForState(state);
- SurfaceControl.setDisplayPowerMode(token, mode);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_POWER);
- }
- }
- 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);
- }
- }
- };
- }
- return null;
- }
上面函数返回一个Runnable放在workQueue,在Runnable 中会调用mBacklight.setBrightness设置背光。
之前是将Runnable接口都放在了mTempDisplayStateWorkQueue中,然后遍历调用了run函数。最后就调用到了LocalDisplayDevice的Runnable接口中设置背光了。
- 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();
- }
四、背光hal层
我们先来看看LightsService
- public class LightsService extends SystemService {
- static final String TAG = "LightsService";
- static final boolean DEBUG = false;
- final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];
- private final class LightImpl extends Light {
- private LightImpl(int id) {
- mId = id;
- }
- @Override
- public void setBrightness(int brightness) {
- setBrightness(brightness, BRIGHTNESS_MODE_USER);
- }
- @Override
- public void setBrightness(int brightness, int brightnessMode) {
- synchronized (this) {
- int color = brightness & 0x000000ff;
- color = 0xff000000 | (color << 16) | (color << 8) | color;
- setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
- }
- }
setLightLocked中最后调用了setLight_native函数。
- private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
- if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
- if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
- + Integer.toHexString(color));
- mColor = color;
- mMode = mode;
- mOnMS = onMS;
- mOffMS = offMS;
- Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
- + Integer.toHexString(color) + ")");
- try {
- setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_POWER);
- }
- }
- }
setLight_native函数如下,其主要也是依赖上面传下来的ptr,作为devices的指针。
- static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
- jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
- {
- Devices* devices = (Devices*)ptr;
- light_state_t state;
- if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
- return ;
- }
- memset(&state, 0, sizeof(light_state_t));
- state.color = colorARGB;
- state.flashMode = flashMode;
- state.flashOnMS = onMS;
- state.flashOffMS = offMS;
- state.brightnessMode = brightnessMode;
- {
- ALOGD_IF_SLOW(50, "Excessive delay setting light");
- devices->lights[light]->set_light(devices->lights[light], &state);
- }
- }
而mNativePointer也是调用了init_native函数
- static jlong init_native(JNIEnv* /* env */, jobject /* clazz */)
- {
- int err;
- hw_module_t* module;
- Devices* devices;
- devices = (Devices*)malloc(sizeof(Devices));
- err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
- if (err == 0) {
- devices->lights[LIGHT_INDEX_BACKLIGHT]
- = get_device(module, LIGHT_ID_BACKLIGHT);
- devices->lights[LIGHT_INDEX_KEYBOARD]
- = get_device(module, LIGHT_ID_KEYBOARD);
- devices->lights[LIGHT_INDEX_BUTTONS]
- = get_device(module, LIGHT_ID_BUTTONS);
- devices->lights[LIGHT_INDEX_BATTERY]
- = get_device(module, LIGHT_ID_BATTERY);
- devices->lights[LIGHT_INDEX_NOTIFICATIONS]
- = get_device(module, LIGHT_ID_NOTIFICATIONS);
- devices->lights[LIGHT_INDEX_ATTENTION]
- = get_device(module, LIGHT_ID_ATTENTION);
- devices->lights[LIGHT_INDEX_BLUETOOTH]
- = get_device(module, LIGHT_ID_BLUETOOTH);
- devices->lights[LIGHT_INDEX_WIFI]
- = get_device(module, LIGHT_ID_WIFI);
- } else {
- memset(devices, 0, sizeof(Devices));
- }
- return (jlong)devices;
- }
这就到驱动了,最终到hardware目录下有个lights.c文件有下面函数
- static int open_lights(const struct hw_module_t *module, char const *name,
- struct hw_device_t **device)
- {
- 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_NOTIFICATIONS, name))
- set_light = set_light_leds_notifications;
- else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
- set_light = set_light_leds_attention;
- else if (0 == strcmp(LIGHT_ID_BATTERY,name))
- set_light = set_light_leds_battery;
- else if (0 == strcmp(LIGHT_ID_BUTTONS,name))
- set_light = set_light_keyboard;
- else
- return -EINVAL;
- pthread_once(&g_init, init_g_lock);
- struct light_device_t *dev = malloc(sizeof(struct light_device_t));
- memset(dev, 0, sizeof(*dev));
- dev->common.tag = HARDWARE_DEVICE_TAG;
- dev->common.version = 0;
- dev->common.module = (struct hw_module_t *)module;
- dev->common.close = (int (*)(struct hw_device_t *))close_lights;
- dev->set_light = set_light;
- *device = (struct hw_device_t *)dev;
- return 0;
- }
- static int
- set_light_backlight(struct light_device_t* dev,
- struct light_state_t const* state)
- {
- int err = 0;
- int brightness = rgb_to_brightness(state);
- if(!dev) {
- return -1;
- }
- pthread_mutex_lock(&g_lock);
- err = write_int(LCD_FILE, brightness);
- pthread_mutex_unlock(&g_lock);
- return err;
- }
其中
- char const*const LCD_FILE
- = "/sys/class/leds/lcd-backlight/brightness";
这样最后设置背光就是往这个节点里面写值,我们可以看下这个节点值。
- root@lte26007:/sys/class/leds/lcd-backlight # cat brightness
- 102
五、总结
这篇博客我们主要分析了,DisplayMangerService是如何设置背光节点的,以及一些hal层的代码。
博文转自:https://blog.csdn.net/kc58236582/article/details/51584381