(一)前言
P-Sensor、距离传感器,能够感知手机和人体的距离。 具体使用用途是在通话中打开P-Sensor,当手机屏幕接近用户的脸时,它会自动感知手机和人体的距离是多少。 当霸气的皮卡丘成为一个值时,关闭画面,不再接收用户触摸画面的事件,可以有效地防止通话中错误触摸的事件的发生。 通话中有很多人脸部触摸了切断按钮,导致通话中断吗? ^_^ )。
(二)打开P-Sensor
刚才提到了P-Sensor主要用于防止用户在通话中意外操作屏幕,让我们来看看电话程序在通话中为P-Sensor做了什么。
答:电话程序在启动时,在PhoneApp.java中创建了一个新的p-sensor wack lock对象。 如下所示,将内容复制到剪贴板代码: mproximitywakelock=pm.newwakelock (power manager.)其实,wackLock这个东东以前也说过,那是风险具体来说,可以看到这个帖子。 http://BBS.51cto.com/thread-1018050-1.html
b.ok,那我们有这个P-Sensor对象,你怎么用它?
例如,当电话状态改变时,当接通电话时,该方法调用PhoneApp.java的updateproximitysensormode (phone.statestate )方法,以根据当前电话状态
那么,如果在通话中,电话也就是OFF-HOOK状态,例如,打开P-Sensor:将内容复制到剪贴板代码: if (mproximitywakelock.is held )
if(DBG ) log.d ) log_tag,' updateproximitysensormode : acquiring . ';
mProximityWakeLock.acquire (;
}其中mProximityWakeLock.acquire (; 辗转调用到PowerManagerService.java的enableProximityLockLocked () )方法。 顾名思义,这个方法是打开P-Sensor。 是的! 该方法确定当前手机上是否有P-Sensor,如果有,则在SensorManager中注册P-Sensor侦听器。 当P-Sensor检测到手机与人体之间的距离发生变化时,它会调用我们的PowerManagerService.java侦听器。 同样,当电话挂断时
确定.那么,接下来就是分析电源管理器服务中的这个p传感器是如何工作的。
(三)电源管理器服务中的P-Sensor监听器工作原理
监听器的代码。 P-Sensor检测到距离变化时发生。 内容为剪贴板代码: sensoreventlistenermproximitylistener=newsensoreventlistener () {
publicvoidonsensorchanged (sensoreventevent )
long milliseconds=system clock.elapsed real time (;
同步(mlocks ) {
float distance=event.values[0]; 检测手机与人体的距离
longtimesincelastevent=milliseconds-mlastproximityeventtime; //这次检查和上次检查的时间差
mlastproximityeventtime=milliseconds; //更新上次检查的时间
mhandler.remove callbacks (mproximitytask;
booleanproximitytaskqueued=false;
//compareagainstgetmaximumrangetosupportsensorsthatonlyreturn0or 1
boolean active=(distance=0.0 distance proximity _ threshold amp
;distance < mProximitySensor.getMaximumRange()); //如果距离霸气的皮卡丘一个距离阈值,默认是5.0f,说明手机和脸部距离贴近,应该要熄灭屏幕。
if (mDebugProximitySensor) {
Slog.d(TAG, "mProximityListener.onSensorChanged active: " + active);
}
if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
// enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing
mProximityPendingValue = (active ? 1 : 0);
mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);
proximityTaskQueued = true;
} else {
// process the value immediately
mProximityPendingValue = -1;
proximityChangedLocked(active); //熄灭屏幕操作
}
// update mProximityPartialLock state
boolean held = mProximityPartialLock.isHeld();
if (!held && proximityTaskQueued) {
// hold wakelock until mProximityTask runs
mProximityPartialLock.acquire();
} else if (held && !proximityTaskQueued) {
mProximityPartialLock.release();
}
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// ignore
}
}; 代码里面我已经有一些注释,下面来用文字描述下。
a. 首先会拿到这测距离变化的距离,float distance = event.values[0];
b. 检测这次距离变化和上次距离变化时间差,如果小于系统设置的阈值,则不会去熄灭屏幕。过于频繁的操作系统会忽略掉。所以,如果你感觉P-Sensor不够灵敏,就可以修改这个系统默认值 复制内容到剪贴板 代码: private static final int PROXIMITY_SENSOR_DELAY = 1000; 如果你改的很小,就会发现P-Sensor会变得灵敏很多。。。
c. 嗯,如果P-Sensor检测到这次距离变化小于系统默认值,且这次是一次正常的变化,那么就应该去熄灭屏幕: 复制内容到剪贴板 代码: proximityChangedLocked(active); 这里的active是true,同样,在这里它还会判断P-Sensor是否可以用,如果不可用,则返回。。忽略这次距离变化 复制内容到剪贴板 代码: if (!mProximitySensorEnabled) {
Slog.d(TAG, "Ignoring proximity change after sensor is disabled");
return;
} 如果一切都满足,则调用: 复制内容到剪贴板 代码: goToSleepLocked(SystemClock.uptimeMillis(),
WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR); 熄灭屏幕。。
当然了,这里面还有很多,比较复杂,如果大家有兴趣,可以把系统源代码下载下来,慢慢研究啦~