Android4.4KK下遮盖p-sensor拨打电话无法自动灭屏的问题分析

简介: 一、问题现象先遮盖P-Sensor,然后拨打电话,90%的情况下屏幕无法自动关闭背光显示。关闭Settings-》Display-》Brightness-》Auto,然后再执行以上操作则100%能够正常关闭背光显示。


一、问题现象

先遮盖P-Sensor,然后拨打电话,90%的情况下屏幕无法自动关闭背光显示。关闭Settings-》Display-》Brightness-》Auto,然后再执行以上操作则100%能够正常关闭背光显示。


Platform:MT6732

Android版本:4.4KK

BuildType:user

系统软件版本:SWA1H+UM

系统RAM:1GB


参考机行为:参考机1正常,参考机2正常


二、MTK平台Android的Sensor流程框架


整个流程框架主要分为6个部分:

1,APPLICATIONS

这里主要是指Dialer/PhoneApp,他们是用户直接操作的接口,他们使用了P-Sensor来进行亮屏和灭屏的操作(通过向PowerManagerService请求PROXIMITY_SCREEN_OFF_WAKE_LOCK实现)。

2, FRAMEWORKS(JAVA)

主要包括两部分:

一、PowerManager/PowerManagerService,其作用是提供PROXIMITY_SCREEN_OFF_WAKE_LOCK,并与SensorManager/SystemSensorManager交互。

二、SensorManager/ SystemSensorManager,其作用是提供JAVA层控制sensor的接口,并透过JNI与Native的SensorManager通信。

3,FRAMEWORKS(JNI)

这里主要是是指SensorManager JNI,其主要作用是提供接口给SensorManager/SystemSensorManager与NatvieLibs的SensorManager通信。

4,FRAMEWORKS(LIBS/NativeService)

主要包括两部分:

一、SensorManager/SensorEventQueue,其属于NativeLibs,主要作用是为SensorManager JNI提供接口,请求SensorService创建SensorEventQueue(基于Binder的IPC),从而完成SensorEvent从SensorService到SensorManager JNI的传输。

二、Sensorservice/sensordevice,其属于NativeService,主要作用是为上层提供接口createSensorEventConnection,与Sensor的HAL层进行交互,控制sensor以及获取sensorEvent。

5,HAL

这里主要是指Nusensors和Hwmsen,其主要功能是为SensorService提供接口,与Sensor的Driver层进行交互,从而达到控制Sensor和获取SensorEvent的目的。

6,Driver

这里主要包括两大部分:

一、hwmsen_dev/StandardInputDevice,这部分是在具体的SensorDriver的上面又抽象出的一层,其主要功能是集中处理不同类型的sensor,包括lightsensor,proximitysensor等。

二、PROXIMITY/LIGHT(stk3x1x-new)等,这部分是指具体的SensorDriver,其主要功能是与具体的Sensor交互,包括控制、获取数据并上报等。这里有一点需要说明的是,Sensor分两种:一种是interrupt sensor,一种是polling sensor,他们的区别在于interrupt sensor是直接挂接在特定的中断上的,一旦sensor有数据就会触发中断处理(我们的PROXIMITYsensor就属于interrupt sensor),polling sensor是被动的提供数据,抽象出的hwmsen_dev会按照一定频率定时的去获取它的数据(我们的LIGHTsensor就属于polling sensor)。


三、问题分析

1、初步分析

根据问题在遮住p-sensor的情况下拨打电话无法灭屏的表面现象,我们首先考虑的是p-sensor硬件有没有产生数据并报给Driver,为了确认这一点我们首先在p-sensor的Driver中添加log:

然后执行操作,打出的log如下:

以上log中value 0x0,代表p-sensor的接近,0x1代表p-sensor的远离,所以说明硬件已经将p-sensor的数据上报到了SensorDriver中,SensorDriver又将数据上报到了driver抽象层hwmsen_dev/StandardInputDevice中,接下我们就要看driver抽象层是否将p-sensor的数据正确上报到了HAL。Nusensor.cpp中的关键代码如下:

以上部分代码是HAL中轮询所有sensor并获取event,其中就包括p-sensor,另外这里有一个很关键的data type,就是SENSOR_TYPE_META_DATA,下面会具体说明它的作用,同时说明一下这里的轮询的实现代码是通过读取StandardInputDevice的节点("/dev/input/event%d", num)来实现的。

在轮询完所有的sensor之后,如果还有空间没有用完就继续poll在sensor的data_fd上去继续获取event以填充完一次获取,然后返回给上层的sensorservice。使用同样的方法再这些代码流中添加log,以获取运行时的数据状态,发现p-sensor的数据同样正确的获取到了,这里就不再赘述。

接下来继续分析sensorservice中的数据流向,看是否正确上报到了SensorManager/SensorEventQueue中,sensorservice的关键代码如下:

首先,从代码中我们看到sensorservice继承于Thread,所以其本身是一个Thread并拥有一个闭合循环的threadloop,不断的从sensor的HAL中读取数据,通过添加log信息,发现在以后代码中p-sensor的数据依然被正确的获取到。

其次,读取完数据之后它会向当前所有连接到sensorservice的client发送sensorEvent,在以上代码中加上发送之前的log打印出p-sensor的数据依然存在。

然后,是具体的发送到client之前的处理代码,我们继续再其中添加log,发现在处理之前p-sensor的数据都是存在的,具体代码如下:

最后,是最终将处理完的数据发送到client的代码,我们在发送之前添加log,最终发现打印出的log中p-sensor的数据已经不存在了,具体代码如下:

2、继续分析

根据以上分析我们发现在被sendEvents处理之前,p-sensor的数据还存在,处理之后在发送之前p-sensor的数据已经被过滤掉,我们可以初步将问题的关键定位在处理过程中。

通过阅读和分析其处理过程的代码,发现了一个关键条件,就是如果sensor的数据想要被最终发送,必须满足mSensorInfo[index].mFirstFlushPending == false的条件,而这个条件满足的前提是当前这个SensorEventConnection必须先接收到SENSOR_TYPE_META_DATA,将mSensorInfo[index].mFirstFlushPending置为false,然后再接收到的具体sensor数据才能被最终发送出去。

根据初步分析的过程中添加的log,我们发现SENSOR_TYPE_META_DATA在sensor的数据流中是存在,但是却是在具体的sensor数据之后,从而导致具体的sensor数据被忽略(这里指是p-sensor的靠近数据)。

通过分析代码我们发现SENSOR_TYPE_META_DATA是sensor被enable之后发出的第一个first flush event,应当在具体的sensor数据之前,enable的关键代码如下:

首先batch,然后setFirstFlushPending为true并flush,在alto4.5TMO中这些操作就会为BatchSensor产生SENSOR_TYPE_META_DATA奠定基础。

最终会走到activate,将sensor真正enable,enable之后sensor会马上产生中断并上报数据,这里p-sensor的数据产生的地方是来自于Hwmsen(在nusensor的sensorlist中,Hwmsen是在第一位的,也就是说在做轮询数据的时候它会被第一个处理)。

这里需要说明的是Soul4NA和Yaris3.5AT&T为什么没有这个问题,原因就在于他们不支持batch,所以在执行batch之后会返回error,不会执行到setFirstFlushPending为true并flush的这个代码分支,而且mFirstFlushPending默认是false,具体代码如下:

从BatchSensor中获取SENSOR_TYPE_META_DATA的具体代码如下:

从log中我们发现在HAL返回数据给sensorservice时,SENSOR_TYPE_META_DATA已经被放在了具体的sensor数据之后,也就是说在sensorservice执行poll获取sensor数据的时候先获取到了具体的sensor数据,后获取到的SENSOR_TYPE_META_DATA。

3、深度分析

带着上面的问题,先获取到了sensor的数据,后获取到的SENSOR_TYPE_META_DATA,这是不正常的。对比关闭AUTO调节背光之后的正常log,我们发现一个关键现象,就是在打开AUTO调节背光的情况下,LIGHT sensor已经在工作,90%的情况下执行enable会阻塞sensorservice被系统调度,也就是执行的poll的thread不会被调度,直观的现象就是看到log中enable执行完才会调度sensorservice的poll的thread去获取事件,在这种情况下问题是必现的,另外10%的情况就是在enable执行的过程中batch刚刚执行完,满足产生SENSOR_TYPE_META_DATA的时候会先发生调度,这样sensorservice的poll的thread就先获取到了SENSOR_TYPE_META_DATA,这种情况下就没有此问题,屏幕可以正常熄灭。

根据这个关键现象我们又深入分析了enable的代码,然后再结合LIGHT sensor开和关的情况下,我们发现Driver中的执行流程存在一个条件差异:

100%可以正常熄灭屏幕的情况:

关闭AUTO调节背光,也就是关闭LIGHT sensor的情况下,在hwmsen_get_interrupt_data函数中obj->dc->polling_running的值为0,所以p-sensor上报数据时不会走hwmsen_work_func,具体代码如下:

在enable的IOCTL还没有执行完,并且没有其他活动的sensor时obj->dc->polling_running的值就会为0,enable的IOCTL执行完之后就会将obj->dc->polling_running的值置为1,同时开启polling的timer,按照一定的频率去polling sensor的数据

90%不能熄灭屏幕的情况以及10%可以熄灭屏幕的情况:

打开AUTO调节背光,也就是LIGHT sensor打开的情况下,在hwmsen_get_interrupt_data函数中obj->dc->polling_running的值为1,p-sensor上报数据时就会走hwmsen_work_func,具体代码如下:

在hwmsen_work_func中就会循环遍历所有sensor的driver,同时会区分interrupt sensor和polling sensor,然后获取它们的数据并上报。

1、90%不能熄灭的情况

由于p-sensor是interrupt sensor,所以这些调用都是在中断服务程序中处理的,由于正常情况下中断服务程序是不会被打断和抢占的,所以CPU会被其hold住直到中断服务器程序处理完毕并返回。如果在执行完enable中的batch和flush之后,系统没有发生调度并调度到sensorservice并先获取到SENSOR_TYPE_META_DATA,那么就会被activate的IOCTL触发p-sensor的数据中断,并将p-sensor的数据先上报,从而导致sensorservice被这个上报过程阻塞,最终影响到sensorservice获取数据的正常流程。

2、10%可以熄灭的情况

在执行完enable中的batch和flush之后,系统发生了调度并调度到sensorservice并先获取到SENSOR_TYPE_META_DATA,然后activate的IOCTL再触发p-sensor的数据中断,再将p-sensor的数据上报,这时就不会影响sensorservice获取数据的正常流程。

4、根本原因

在无法保证系统调度的情况下,我们发现问题的根本原因在于p-sensor的中断服务程序在LIGHT sensor打开时(obj->dc->polling_running的值为1)没有分上下段执行,而是将所有处理都放在了中断服务程序里面,从而影响了sensorservice的正常执行及数据流的正常顺序。


四、解决方案

通过以上分析,我们可以知道造成最终问题的原因是中断服务程序在LIGHT sensor打开时(obj->dc->polling_running1)没有分上执行

通过详细分析当前的代码逻辑、结构以及测试,我们给出以下改动和影响尽可能小的解决方案:

1、在Sensor的抽象Driver中(hwmsen_dev),将interrupt sensor(即p-sensor)的中断服务程序调用的函数:hwmsen_get_interrupt_data中的中断下半部处理的代码移除,只执行中断的上半部分处理,将关键数据和状态保存,即将以下代码移除:

中断的下半部分的操作放在固定频率的timer中执行,因为代码原来的逻辑就是在enable sensor的时候开启timer,去完成interrupt sensor的work,具体代码如下:

 


五、结论及后续动作

Sensor的抽象Driver中(hwmsen_dev)的中断服务程序不分上下段执行的问题在Yaris3.5AT&T以及SOUL4NA中都是存在的,但是由于没有BatchSensor的SENSOR_TYPE_META_DATA的影响,所有并没有出现这个问题。因此在以后的MTK的平台上我们都要检查是否存在此问题,以提前避免,Qualcomm平台也会同时关注。


#analyzed by vincent.song from SWD2 Framework team.

#vincent.song@tcl.com

#201501071718


目录
相关文章
|
16天前
|
Java Android开发 iOS开发
深入探讨移动操作系统的性能优化:安卓与iOS的对比分析
在现代移动设备中,操作系统的性能优化至关重要。本文从系统架构、内存管理、电池续航和应用程序运行效率等多个维度,深入探讨了安卓(Android)和iOS两大主流移动操作系统的优化策略及其实际效果,旨在为开发者和用户提供更清晰的了解和选择依据。
29 0
|
1月前
|
存储 Java Android开发
Android系统 设置第三方应用为默认Launcher实现和原理分析
Android系统 设置第三方应用为默认Launcher实现和原理分析
162 0
|
3天前
|
API 开发工具 Android开发
安卓与iOS开发环境对比分析
本文将探讨安卓与iOS两大移动操作系统在开发环境中的差异,包括编程语言、工具链、API设计哲学、应用商店政策以及开发者社区支持等方面。通过比较分析,旨在帮助开发者更好地选择适合自己项目需求的平台,并理解不同环境下的开发挑战和机遇。
|
13天前
|
安全 Android开发 iOS开发
探索Android与iOS开发的差异:平台特性与用户体验的对比分析
在移动应用开发的广阔天地中,Android和iOS两大阵营各据一方。本文将深入探讨这两个操作系统在开发环境、编程语言、用户界面设计及市场分布等方面的主要区别。通过比较分析,我们将揭示各自平台的特有优势,并讨论如何根据目标受众和业务需求选择适合的开发平台。
|
1天前
|
前端开发 开发工具 Android开发
安卓与iOS开发环境的差异性分析
在移动应用开发的广阔天地中,安卓与iOS两大平台各自占据着半壁江山。开发者在选择开发环境时往往需权衡两者的技术架构、开发工具及市场策略等多方面因素。本文深入探讨了安卓和iOS开发环境的主要差异,包括编程语言、IDE选择、API设计哲学等技术层面,以及用户群体、市场份额和分发渠道等市场层面的差异。通过对比分析,旨在为移动应用开发者提供清晰的决策依据,帮助他们在激烈的市场竞争中找到适合自身项目需求的最佳开发路径。
7 0
|
2天前
|
IDE 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS平台各自扮演着不可或缺的角色。本文将深入探讨两大主流移动操作系统的开发环境,从编程语言、开发工具、用户界面设计以及跨平台框架等多个维度进行细致对比。我们将揭示它们在开发效率、用户体验和技术生态上的差异,旨在为开发者提供一份全面而实用的指南,帮助他们根据项目需求和目标受众作出更明智的技术选择。
6 0
|
7天前
|
Java Linux API
微信API:探究Android平台下Hook技术的比较与应用场景分析
微信API:探究Android平台下Hook技术的比较与应用场景分析
|
7天前
|
安全 Android开发 iOS开发
探索安卓与iOS开发的差异:平台特性与用户体验的对比分析
移动应用开发的两大阵营——安卓与iOS,各自拥有独特的开发环境、用户群体和市场定位。本文将深入探讨这两个操作系统在应用开发过程中的主要差异,包括编程语言、开发工具、用户界面设计、性能优化、安全性考量以及发布流程等方面。通过比较分析,旨在为开发者提供跨平台开发的见解和策略,以优化应用性能和提升用户体验。
11 0
|
7天前
|
缓存 Java Linux
Android 匿名内存深入分析
Android 匿名内存深入分析
10 0
|
16天前
|
搜索推荐 安全 Android开发
安卓与iOS操作系统的对比分析
在移动设备市场上,安卓和iOS操作系统一直是主要竞争对手。本文将从用户界面、应用生态系统、定制化程度和安全性等方面对安卓和iOS进行对比分析,并探讨两者在不同场景下的适用性。