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);
    }
}

系统在这里对电量灯和通知灯做了区分,有电量指示灯时通知灯的设置是无效的。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值