上篇博客我们分析了,PowerManagerService和DisplayPowerController这两个类,我也提到了和android5.1的变化,把背光这块放到了DisplayManagerService中了,之前这块没有分析过,今天分析下DisplayManagerService和背光的关系。
看了DisplayManagerService的注释,发现现在所以的显示设备都放在DisplayManagerService管理,wifiDisplay,defaultDisplay(背光)。
我们先来看构造函数:
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()); }我们看消息处理,就是调用了registerDefaultDisplayAdapter函数:
@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构造函数调用了父类的,而父类也就是保存了变量
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(); }
我们先来看看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; }下面我们再来看set_light_backlight函数:
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层的代码。