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

一、问题现象

先遮盖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_running的值为1)没有分上下段执行。

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

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.

#[email protected]

#201501071718

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-01 22:47:32

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

Android4.4 无Proximity Sensor的设备拨号中实现自动灭屏

现在的电子产品越来越人性化,用户友好化,在给用户带来全新体验的同时,也在改变着人们的日常生活,所以说科技是伟大的,创新是伟大的. 随着移动设备的多元化发展,各种微型芯片的嵌入,使得它的功能越来越强大.比如各种各样的Sensor,最常见的一种是Proximity Sensor,现在的品牌机几乎都具备,也就是在打电话的时候,为了避免误操作,在电话接近耳朵的时候让手机处于灭屏状态,要实现这一功能使用Proximity Sensor是再好不过的了. 但是也有一些设备不具备Proximity Sensor

程序员也需要下点成本啊!!IOS input渲染 和android不同,以及自动添加拨打电话功能导致的问题

前几天公众号做完了给领导审查,因为这个公众号是在之前的1.0基础上开发的,所以没有在意兼容性问题[其实是忽略了IOS=.=原谅我的无知] 结果出问题了,有几个问题: 1. input渲染效果和andriod下不同 2. 长串数字会被渲染成电话号码 3.四位小数被渲染成超链接 1.input Android下设置没有圆角.无渐变,文字居中显示,完全没问题啊 到了IOS就变成这个鸟样子了!!这是什么鬼啊?? 原来iPhone上的safari解析input[type="submit"]和in

安卓笔记1——入门介绍及拨打电话和发送短信案例

现在开始接触安卓开发.以后后同步发出对应笔记.老规矩,用一张图来介绍今天的内容. 图片看不清的话可以右键新窗口打开. 一.开发工具 · Eclipse + ADT(Android Developer Tools) · Android Studio · SDK (软件开发环境, Android调试工具, 模拟等) 二.SDK目录介绍 · add-ons :(额外开发资料, google地图资源) · build-tools : 编译工具目录 · docs : 离线版开发文档 · extras : 

如何让HTML在手机上实现直接拨打电话以及发送短信?

拨打电话的HTML实现方式: <a href="tel:134289210xx″>拨打电话</a> 上面是比较常用的方式,但是有可能在某些场景下是支持不太好,可以试用以下的方式哦: <a href="wtai://wp/mc;134289210xx″>拨打电话</a> 接下来看发送短信的方法 <a href="sms:134289210xx?body=你好,我要预定!">短信下单</a>

使用Android拨打电话功能

1.要使用Android系统中的电话拨号功能,首先必须在AndroidManifest.xml功能清单中加入允许拨打电话的权限: <uses-permission android:name="android.permission.CALL_PHONE" /> // 允许拨打电话权限 2.进行拨打电话的代码: a.调用Android系统的拨号界面,但不发起呼叫,用户按下拨号键才会进行呼叫 1 @Override 2 public void onCreate(Bundle sa

Android拨打电话不弹出系统拨号界面总结

我在网上搜了一下,解决这个问题,有两种方式: 1.反射调用系统底层方法,并获取系统权限 反射调用的代码如下: Class phoneFactoryClass = Class.forName("com.android.internal.telephony.PhoneFactory"); Method makeDefaultPhones=phoneFactoryClass.getMethod("makeDefaultPhones",Context.class); mak

仿IOS通讯录效果,实现获取手机通讯录、字母排序显示、搜索联系人、拨打电话

1.使用UITableView,实现联系人字母排序.点击字母跳转显示联系人组目录: 2.使用UISearchController,实现联系搜索,动态显示符合查询的联系人: 3.点击通讯录列表项,显示联系人信息(使用自定义模式化窗口类似与UIAlertView,使用UIwindow实现),点击拨号,可以直接拨打电话: 4.实现获取手机通讯录里面的联系人信息: 详情见资源:http://download.csdn.net/detail/u011622479/9505751 效果图如下: 获取联系人:

怎么在Ubuntu手机上发送短信及拨打电话

由于一些平台安全性的原因,Ubuntu手机目前暂时没有提供供第三方开发者发送短信及拨打电话的接口,但是在实际的应用中,我们也许会需要用到发送短信息或拨打电话.这个时候我们怎么办呢?我们在前面的文章"使用URL dispatcher的范例"中已经介绍了如何使用url dispatcher来调用第三方应用的方法.这里我们用该方法来展示如何在我们的应用中发送短信息及拨打电话. 首先,我们创建一个最简单的"App with Simple UI"模版应用,并修改我们的&quo

Android手机拨打电话的开发实例

一部手机最常用的功能就是打电话和发短信了,在Android开发中我们如何通过程序拨打电话呢?本文就给出一个用Android手机拨打电话的简单的实例. 下面是开发此实例的具体步骤: 一.新建一个Android工程,命名为phoneCallDemo. 二.设计程序的界面,打开main.xml把内容修改如下: XML/HTML代码 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:and