Android 通知灯设置
Posted 虫师魁拔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 通知灯设置相关的知识,希望对你有一定的参考价值。
系统通知灯相关文件
frameworks/base/services/core/java/com/android/server/lights/LightsManager.java
frameworks/base/services/core/java/com/android/server/lights/LogicalLight.java
frameworks/base/services/core/java/com/android/server/lights/LightsService.java
frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp
hardware/interfaces/light/2.0/default/Light.cpp
hardware/qcom/display/liblight/lights.c
一、LightsManager.java
主要定义各种灯类型和一个 getLight 抽象函数
public abstract class LightsManager
public static final int LIGHT_ID_BACKLIGHT = Type.BACKLIGHT; //背光灯
public static final int LIGHT_ID_KEYBOARD = Type.KEYBOARD; //键盘灯
public static final int LIGHT_ID_BUTTONS = Type.BUTTONS; //按键灯
public static final int LIGHT_ID_BATTERY = Type.BATTERY; //电池指示灯
public static final int LIGHT_ID_NOTIFICATIONS = Type.NOTIFICATIONS; //通知灯
public static final int LIGHT_ID_ATTENTION = Type.ATTENTION; //重要灯
public static final int LIGHT_ID_BLUETOOTH = Type.BLUETOOTH; //蓝牙
public static final int LIGHT_ID_WIFI = Type.WIFI; //WIFI灯
public static final int LIGHT_ID_COUNT = Type.COUNT; //这个表示灯类型数量
public abstract LogicalLight getLight(int id);
二、LogicalLight.java
定义调用接口,供系统使用,其实现在 LightsService$LightImpl 中
三、LightsService.java
系统服务,实际实现led控制功能,往下调用 jni native函数
@Override
public void onStart()
publishLocalService(LightsManager.class, mService);
publishBinderService(Context.LIGHTS_SERVICE, mManagerService);
... ...
private final LightsManager mService = new LightsManager()
@Override
public LogicalLight getLight(int lightType)
if (mLightsByType != null && 0 <= lightType && lightType < mLightsByType.length)
return mLightsByType[lightType];
else
return null;
;
内部主要是使用一个 LightsService$LightImpl(LogicalLight 实现类)数组 mLightsByType ,保存所有类型灯的对象,通过 getSystemService 获取 LightsManager 需要根据不同灯的类型去获取对应的对象。
LightImpl 中是所有led相关操作上层接口的实现,例如设置灯打开、关闭、颜色、亮度、闪烁等。
@Override
public void setColor(int color)
synchronized (this)
// 设置颜色灯是常亮的,使用 LIGHT_FLASH_NONE
setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);
@Override
public void setFlashing(int color, int mode, int onMS, int offMS)
synchronized (this)
setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
mode 有三种:
/** * 常亮或者常灭 */ public static final int LIGHT_FLASH_NONE = Flash.NONE; /** * 以指定的速率闪烁灯光 */ public static final int LIGHT_FLASH_TIMED = Flash.TIMED; /** * 使用硬件辅助闪烁指示灯,闪烁时间一般是固定 */ public static final int LIGHT_FLASH_HARDWARE = Flash.HARDWARE;
四、com_android_server_lights_LightsService.cpp
系统 jni 层,调用 HIDL 服务端接口
Return<Status> ret = hal->setLight(type, state);
五、hardware/interfaces/light/2.0/default/Light.cpp
HIDL 服务端接口,继续调用系统的 HAL 库函数
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;
mLights 也是根据不同的灯 id 类型保存了一个数组
六、hardware/qcom/display/liblight/lights.c
系统的 HAL 库代码文件,直接操作系统节点,实现 led 控制
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;
/** 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))
g_has_persistence_node = !access(PERSISTENCE_FILE, F_OK);
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;
... ...
根据不同灯的类型执行不同函数,以通知灯电量灯为例,最后执 handle_speaker_battery_locked
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);
系统在这里对电量灯和通知灯做了区分,有电量指示灯时通知灯的设置是无效的。
以上是关于Android 通知灯设置的主要内容,如果未能解决你的问题,请参考以下文章