222

一次从无到有的led灯控制

三色灯模块总结

模块需求

提示灯、夜间灯光、调色板亮灯、灯光表盘

背景

由于芯片原因,三色灯的硬件被挂在在adsp中,OEM管理。这边一般用作常驻的sensor之类的。鉴于之前的安卓系统,灯光的驱动直接挂载kernel侧,通过读写节点文件即可实现控制灯的颜色、亮度等。现在的挂载modem侧之后,没有之前的完整的流程来可进行对灯的调整。传感器的原理是,开机的时候开启,一直运行,当需要传感器数据的时候,发送通知打开向上层传递,也就是说传感器的开闭是系统层面的管控,应用内对于传感器的使用只是对于通道开闭来获取数据使用。且芯片的原有功能只支持在modem写死数据,无法在底层保持对原始数据的修改。需要有一条新的通路针对控制可以及时修改灯效并执行灯效。

模块分为4个阶段

1、ap侧向modem侧写数据,芯片读取数据i2c(I方c)串口写入硬件

2、将三色灯作为一种sensor类型挂载到light hal层模块,添加selinux权限

3、hal层与framework层的对接 (原有的lightmanagerservice作为抽象类使用 并没有开放接口至系统为lightmanger,与此同时系统需要另一个系统service来接收所有的灯光指令集中处理(获取灯效、灯光冲突、执行灯效等))添加service权限

4、传递service至三色灯app处理灯效、应用层调用系统层的manager接口来控制灯的亮灭。

三色灯app主要由一个service构成,为其设置persist属性使其开一开机自动运行,需具有sysenui id完成流畅的与系统层api使用。

安卓light流程

framework层

framework的light的控制类在LightsService中,没有开放给应用的api来使用service,只能在framework 通过systemserver下获取方法来控制。设置一些状态值来控制灯

int light(灯的类型), int color(灯的颜色), int mode(灯的模式分闪烁和常亮),int onMS(闪烁时亮的间隔), int offMS(闪烁时灭), int brightnessMode(明暗模式)

最终通过jni和hal层交互,light的唯一方法传递

    static native void setLight_native(int light, int color, int mode, int onMS, int offMS, int brightnessMode);

使用方法:

在server层获取方法,其他地方获取不到暂时

获取到light对象之后可以直接调用方法设置属性

jni层:

hal层:selinux权限

关联类(静态变量,已注册可被上层调用的方法)

直接的链接驱动管理类,截图的路径与芯片定制强相关(主要是硬件上是否支持其他灯类型如 键盘、蓝牙灯等逻辑灯),主要的代码在lights.c 中。

根据名字获取不同的方法

其中原生的框架基本上都是对应一个物理灯,也就说batteryservei控制的battery灯,powermanager控制的attention灯,notification控制的notification灯最终控制的都是一个灯,在有充电灯的情况下优先响应充电灯。

其他的则自控件灯效处理,例如控制背屏、键盘灯、控制的基本具体细节按照kenerl中控制节点文件的方式下发。

如下是基于通知、充电的共用物理灯读写节点文件

166static int
167set_speaker_light_locked(struct light_device_t* dev,
168       struct light_state_t const* state)
169{
170   int red, green, blue;
171   int blink;
172   int onMS, offMS;
173   unsigned int colorRGB;
174
175   if(!dev) {
176       return -1;
177   }
178
179   switch (state->flashMode) {
180       case LIGHT_FLASH_TIMED:
181           onMS = state->flashOnMS;
182           offMS = state->flashOffMS;
183           break;
184       case LIGHT_FLASH_NONE:
185       default:
186           onMS = 0;
187           offMS = 0;
188           break;
189   }
190
191   colorRGB = state->color;
192
193#if 0
194   ALOGD("set_speaker_light_locked mode %d, colorRGB=%08X, onMS=%d, offMS=%d\n",
195           state->flashMode, colorRGB, onMS, offMS);
196#endif
197
198   red = (colorRGB >> 16) & 0xFF;
199   green = (colorRGB >> 8) & 0xFF;
200   blue = colorRGB & 0xFF;
201
202   if (onMS > 0 && offMS > 0) {
203       /*
204         * if ON time == OFF time
205         *   use blink mode 2
206         * else
207         *   use blink mode 1
208         */
209       if (onMS == offMS)
210           blink = 2;
211       else
212           blink = 1;
213   } else {
214       blink = 0;
215   }
216
217   if (blink) {
218       if (red) {
219           if (write_int(RED_BLINK_FILE, blink))
220               write_int(RED_LED_FILE, 0);
221}
222       if (green) {
223           if (write_int(GREEN_BLINK_FILE, blink))
224               write_int(GREEN_LED_FILE, 0);
225}
226       if (blue) {
227           if (write_int(BLUE_BLINK_FILE, blink))
228               write_int(BLUE_LED_FILE, 0);
229}
230   } else {
231       write_int(RED_LED_FILE, red);
232       write_int(GREEN_LED_FILE, green);
233       write_int(BLUE_LED_FILE, blue);
234   }
235
236   return 0;
237}

这些基础的节点文件都可以通过adb命令来查看拉起。

基于新作的功能我们的处理方案就是截取设置节点文件的数据,将数据封装与封装的灯sensor类型相绑定,通过qmi传输数据至adsp来下发灯效。其中有几个点1、原有的lightmanager 无法获取数组流,新增方法时涉及众多权限问题

2、sensor类型 与 sensor的传递中,无法直接传递大数据

3、改善过程中使用 qmi 通讯来下发 数据,单次最大255字节。当数据大于该状态时需要分级,并且底层接收时要根据拼接的数据信息组装数据。

4、为抽象方法lightmanager 添加 实体控制类。同时注册新的systemserver 、以及manager类作为全局的灯效控制类。

posted on 2022-02-25 17:31  归臻  阅读(602)  评论(0编辑  收藏  举报

导航