指示灯代码逻辑查看与定义:
默认当低电量时候,指示灯亮灭是1s-1s 的切换; 根据产品定义反馈,切换的太过频繁,需要调整修改。
当电量较多时候,不处于低电量时候,系统处于正常的battery实现逻辑中,而当电量低于15之后,电量切换为setBrightness和setColor模式下,出现了闪光灯一直切换的情况。所以其闪烁未按照现有的软件逻辑执行。
LightsService.java
private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
if (shouldBeInLowPersistenceMode()) {
brightnessMode = BRIGHTNESS_MODE_LOW_PERSISTENCE;
} else if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
brightnessMode = mLastBrightnessMode;
}
if (!mInitialized || color != mColor || mode != mMode || onMS != mOnMS ||
offMS != mOffMS || mBrightnessMode != brightnessMode) {
if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
+ Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
mInitialized = true;
mLastColor = mColor;
mColor = color;
mMode = mode;
mOnMS = onMS;
mOffMS = offMS;
mBrightnessMode = brightnessMode;
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
+ Integer.toHexString(color) + ")");
try {
setLight_native(mId, color, mode, onMS, offMS, brightnessMode);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
}
设置执行的主要函数是:setLight_native
static native void setLight_native(int light, int color, int mode,
int onMS, int offMS, int brightnessMode);
根据Jni函数设置找到对应的文件:
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;
}
//连接LightHal节点
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 LightState constructState(
jint colorARGB,
jint flashMode,
jint onMS,
jint offMS,
jint brightnessMode){
Flash flash = static_cast<Flash>(flashMode);
Brightness brightness = static_cast<Brightness>(brightnessMode);
LightState state{};
if (brightness == Brightness::LOW_PERSISTENCE) {
state.flashMode = Flash::NONE;
} else {
// Only set non-brightness settings when not in low-persistence mode
state.flashMode = flash;
state.flashOnMs = onMS;
state.flashOffMs = offMS;
}
state.color = colorARGB;
state.brightnessMode = brightness;
return state;
}
此处插一句:刚刚总是查找android.hardware.light.V2_0.Flash和android.hardware/light.V2_0.Brightnes
import android.hardware.light.V2_0.Flash;
import android.hardware.light.V2_0.Brightness;
此文件的定义在jni中也同样找到:
using Brightness = ::android::hardware::light::V2_0::Brightness;
using Flash = ::android::hardware::light::V2_0::Flash;
using ILight = ::android::hardware::light::V2_0::ILight;
using LightState = ::android::hardware::light::V2_0::LightState;
using Status = ::android::hardware::light::V2_0::Status;
using Type = ::android::hardware::light::V2_0::Type;
找到匹配文件点:
hardware/interfaces/light/2.0/types.hal
enum Flash : int32_t {
/**
* Keep the light steady on or off.
*/
NONE,
/**
* Flash the light at specified rate.
*/
TIMED,
/**
* Flash the light using hardware assist.
*/
HARDWARE,
};
其对应的外部接口函数为:hardware\interfaces\light\2.0\ILight.hal
package android.hardware.light@2.0;
interface ILight {
/**
* Set the provided lights to the provided values.
*
* @param type logical light to set
* @param state describes what the light should look like.
* @return status result of applying state transformation.
*/
setLight(Type type, LightState state) generates (Status status);
/**
* Discover what indicator lights are available.
*
* @return types list of available lights
*/
getSupportedTypes() generates (vec<Type> types);
};
在\hardware\interfaces\light\2.0\default\Light.cpp文件中的实现过程是:
// Methods from ::android::hardware::light::V2_0::ILight follow.
Return<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);
switch (ret) {
case -ENOSYS:
return Status::BRIGHTNESS_NOT_SUPPORTED;
case 0:
return Status::SUCCESS;
default:
return Status::UNKNOWN;
}
}
在lights.c文件hardware/qcom/display/liblight/lights.c:
不同的模式下的闪光灯赋予均赋予给set_light 处理;
/******************************************************************************/
/**
* module methods
*/
/** 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;
} 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)) {
if (!access(BUTTON_FILE, F_OK)) {
// enable light button when the file is present
set_light = set_light_buttons;
} else {
return -EINVAL;
}
}
else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
set_light = set_light_attention;
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 = LIGHTS_DEVICE_API_VERSION_2_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;
}
而我们现在主要是查找关于battery电量的闪烁:
static void
handle_speaker_battery_locked(struct light_device_t* dev)
{
if (is_lit(&g_battery)) {
set_speaker_light_locked(dev, &g_battery);
} else {
set_speaker_light_locked(dev, &g_notification);
}
}
static int
set_light_battery(struct light_device_t* dev,
struct light_state_t const* state)
{
pthread_mutex_lock(&g_lock);
g_battery = *state;
handle_speaker_battery_locked(dev);
pthread_mutex_unlock(&g_lock);
return 0;
}
static int
set_light_notifications(struct light_device_t* dev,
struct light_state_t const* state)
{
pthread_mutex_lock(&g_lock);
g_notification = *state;
handle_speaker_battery_locked(dev);
pthread_mutex_unlock(&g_lock);
return 0;
}
进而直接可以找到其实现过程:
static int
set_speaker_light_locked(struct light_device_t* dev,
struct light_state_t const* state)
{
int red, green, blue;
int blink;
int onMS, offMS;
unsigned int colorRGB;
if(!dev) {
return -1;
}
switch (state->flashMode) {
case LIGHT_FLASH_TIMED:
onMS = state->flashOnMS;
offMS = state->flashOffMS;
break;
case LIGHT_FLASH_NONE:
default:
onMS = 0;
offMS = 0;
break;
}
colorRGB = state->color;
#if 0
ALOGD("set_speaker_light_locked mode %d, colorRGB=%08X, onMS=%d, offMS=%d\n",
state->flashMode, colorRGB, onMS, offMS);
#endif
red = (colorRGB >> 16) & 0xFF;
green = (colorRGB >> 8) & 0xFF;
blue = colorRGB & 0xFF;
if (onMS > 0 && offMS > 0) {
/*
* if ON time == OFF time
* use blink mode 2
* else
* use blink mode 1
*/
if (onMS == offMS)
blink = 2;
else
blink = 1;
} else {
blink = 0;
}
if (blink) {
if (red) {
if (write_int(RED_BLINK_FILE, blink))
write_int(RED_LED_FILE, 0);
}
if (green) {
if (write_int(GREEN_BLINK_FILE, blink))
write_int(GREEN_LED_FILE, 0);
}
if (blue) {
if (write_int(BLUE_BLINK_FILE, blink))
write_int(BLUE_LED_FILE, 0);
}
} else {
write_int(RED_LED_FILE, red);
write_int(GREEN_LED_FILE, green);
write_int(BLUE_LED_FILE, blue);
}
return 0;
}
如果不是按照时间闪烁,则直接on/off 时间直接均赋予为0.
那么可以知道现在指示灯闪烁基本是芯片默认设置。