一次从无到有的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类作为全局的灯效控制类。