安卓充电灯更新逻辑:
1.灯相关变量定义:
frameworks/base/core/res/res/values/symbols.xml
<java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
<java-symbol type="integer" name="config_notificationsBatteryLedOff" />
<java-symbol type="integer" name="config_notificationsBatteryLedOn" />
<java-symbol type="integer" name="config_notificationsBatteryLowARGB" />
<java-symbol type="integer" name="config_notificationsBatteryMediumARGB" />
2.定义值
frameworks/base/core/res/res/values/config.xml
<!-- Default color for notification LED. -->
<color name="config_defaultNotificationColor">#ffffffff</color>
<!-- Default LED on time for notification LED in milliseconds. -->
<integer name="config_defaultNotificationLedOn">500</integer>
<!-- Default LED off time for notification LED in milliseconds. -->
<integer name="config_defaultNotificationLedOff">2000</integer>
<!-- Default value for led color when battery is low on charge -->
<integer name="config_notificationsBatteryLowARGB">0xFFFF0000</integer>
<!-- Default value for led color when battery is medium charged -->
<integer name="config_notificationsBatteryMediumARGB">0xFFFFFF00</integer>
<!-- Default value for led color when battery is fully charged -->
<integer name="config_notificationsBatteryFullARGB">0xFF00FF00</integer>
3.充电灯状态更新逻辑:
frameworks/base/services/java/com/android/server/BatteryService.java
private final class Led {
private final LightsService.Light mBatteryLight;
private final int mBatteryLowARGB;
private final int mBatteryMediumARGB;
private final int mBatteryFullARGB;
private final int mBatteryLedOn;
private final int mBatteryLedOff;
public Led(Context context, LightsService lights) {
mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY);
mBatteryLowARGB = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryLowARGB);
mBatteryMediumARGB = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryMediumARGB);
mBatteryFullARGB = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryFullARGB);
mBatteryLedOn = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryLedOn);
mBatteryLedOff = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryLedOff);
}
/**
* Synchronize on BatteryService.
*/
public void updateLightsLocked() {
final int level = mBatteryProps.batteryLevel;
final int status = mBatteryProps.batteryStatus;
if (level < mLowBatteryWarningLevel) {
if (status == BatteryManager.BATTERY_STATUS_CHARGING) { //当处于低电量时,调用setColor()
// Solid red when battery is charging
mBatteryLight.setColor(mBatteryLowARGB);
} else {
// Flash red when battery is low and not charging
mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED,
mBatteryLedOn, mBatteryLedOff);
}
} else if (status == BatteryManager.BATTERY_STATUS_CHARGING
|| status == BatteryManager.BATTERY_STATUS_FULL) {
if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) { //电量大于百分90或状态为FULL时
// Solid green when full or charging and nearly full
mBatteryLight.setColor(mBatteryFullARGB);
} else { //电量小于90 且 非低电量时。
// Solid orange when charging and halfway full
mBatteryLight.setColor(mBatteryMediumARGB);
}
} else {
// No lights if not charging and not low
mBatteryLight.turnOff();
}
}
4.安卓lightservice灯相关的操作接口:
frameworks/base/services/java/com/android/server/LightsService.java
public void setBrightness(int brightness) {
setBrightness(brightness, BRIGHTNESS_MODE_USER);
}
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);
}
}
public void setColor(int color) {
synchronized (this) {
//setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);
setLightLocked(color, LIGHT_FLASH_TIMED, 500, 500, BRIGHTNESS_MODE_USER);
}
}
public void setFlashing(int color, int mode, int onMS, int offMS) {
synchronized (this) {
setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
}
}
public void pulse() {
pulse(0x00ffffff, 7);
}
public void pulse(int color, int onMS) {
synchronized (this) {
if (mColor == 0 && !mFlashing) {
setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER);
mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
}
}
}
public void turnOff() {
synchronized (this) {
setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);
}
}
private void stopFlashing() {
synchronized (this) {
setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER);
}
}
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;
setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
}
}
lightsService 注册:
路径:frameworks/base/services/java/com/android/server/SystemServer.java
// Manages LEDs and display backlight so we need it to bring up the display.
traceBeginAndSlog("StartLightsService");
mSystemServiceManager.startService(LightsService.class);
traceEnd();
lights服务代码
frameworks/base/services/core/java/com/android/server/lights/LightsService.java
在这个服务中,对led灯所有操作都是通过下面这个接口实现的:
static native void setLight_native(int light, int color, int mode,
int onMS, int offMS, int brightnessMode);
}
lights jni层代码:
主要作用是在O版及之后衔接hidl层和注册本地方法到这个类:com/android/server/lights/LightsService
路径:frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp
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);
{
android::base::Timer t;
Return<Status> ret = hal->setLight(type, state);
processReturn(ret, type, state);
if (t.duration() > 50ms) ALOGD("Excessive delay setting light");
}
}
static const JNINativeMethod method_table[] = {
{ "setLight_native", "(IIIIII)V", (void*)setLight_native },
};
int register_android_server_LightsService(JNIEnv *env) {
return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
method_table, NELEM(method_table));
}
hidl 层(分为直通式:兼容之前的旧框架,直接使用dlopen和binder式:还未了解):
-> 直通式:安卓O及之后版本,不在是直接在jni处调用hw_get_module直接jni处调用,而是在hidl出调用,
->bingder式:还未了解
路径:/hardware/interfaces/light/
/here to add a lights interface by zwl
const static std::map<Type, const char*> kLogicalLights = {
{Type::BACKLIGHT, LIGHT_ID_BACKLIGHT},
{Type::KEYBOARD, LIGHT_ID_KEYBOARD},
{Type::BUTTONS, LIGHT_ID_BUTTONS},
{Type::BATTERY, LIGHT_ID_BATTERY},
{Type::NOTIFICATIONS, LIGHT_ID_NOTIFICATIONS},
{Type::ATTENTION, LIGHT_ID_ATTENTION},
{Type::BLUETOOTH, LIGHT_ID_BLUETOOTH},
{Type::WIFI, LIGHT_ID_WIFI}
};
light_device_t* getLightDevice(const char* name) {
light_device_t* lightDevice;
const hw_module_t* hwModule = NULL;
int ret = hw_get_module (LIGHTS_HARDWARE_MODULE_ID, &hwModule); //call the .so //dlopen直通式
if (ret == 0) {
ret = hwModule->methods->open(hwModule, name,
reinterpret_cast<hw_device_t**>(&lightDevice));
if (ret != 0) {
ALOGE("light_open %s %s failed: %d", LIGHTS_HARDWARE_MODULE_ID, name, ret);
}
} else {
ALOGE("hw_get_module %s %s failed: %d", LIGHTS_HARDWARE_MODULE_ID, name, ret);
}
if (ret == 0) {
return lightDevice;
} else {
ALOGE("Light passthrough failed to load legacy HAL.");
return nullptr;
}
}
ILight* HIDL_FETCH_ILight(const char* /* name */) {
std::map<Type, light_device_t*> lights;
for(auto const &pair : kLogicalLights) {
Type type = pair.first;
const char* name = pair.second;
light_device_t* light = getLightDevice(name);
if (light != nullptr) {
lights[type] = light;
}
}
if (lights.size() == 0) {
// Log information, but still return new Light.
// Some devices may not have any lights.
ALOGI("Could not open any lights.");
}
return new Light(std::move(lights));
}
vendor层:
实现HAL_MODULE_INFO_SYM符号so库,和实现调用方法。
路径:vendor/mediatek/proprietary/hardware/liblights
/** Open a new instance of a lights device using name */
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;
if (access(LCD_FILE, F_OK) < 0)
return -errno;
}
else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {
set_light = set_light_keyboard;
if (access(KEYBOARD_FILE, F_OK) < 0)
return -errno;
}
else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
set_light = set_light_buttons;
if (access(BUTTON_FILE, F_OK) < 0)
return -errno;
}
else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {
set_light = set_light_battery;
if (access(RED_LED_FILE, F_OK) < 0)
return -errno;
if (access(GREEN_LED_FILE, F_OK) < 0)
return -errno;
if (access(BLUE_LED_FILE, F_OK) < 0)
return -errno;
}
else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
set_light = set_light_notifications;
if (access(RED_LED_FILE, F_OK) < 0)
return -errno;
if (access(GREEN_LED_FILE, F_OK) < 0)
return -errno;
if (access(BLUE_LED_FILE, F_OK) < 0)
return -errno;
}
else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {
set_light = set_light_attention;
if (access(RED_LED_FILE, F_OK) < 0)
return -errno;
if (access(GREEN_LED_FILE, F_OK) < 0)
return -errno;
if (access(BLUE_LED_FILE, F_OK) < 0)
return -errno;
}
else {
return -EINVAL;
}
pthread_once(&g_init, init_globals);
struct light_device_t *dev = malloc(sizeof(struct light_device_t));
if (!dev)
return -ENOMEM;
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 struct hw_module_methods_t lights_module_methods = {
.open = open_lights,
};
/*
* The lights Module
*/
struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
//.version_major = 1,
//.version_minor = 0,
.id = LIGHTS_HARDWARE_MODULE_ID,
.name = "MTK lights Module",
.author = "MediaTek",
.methods = &lights_module_methods,
};
kernel层:
kernel-4.9/drivers/misc/mediatek/leds