先说现象,现象就是来电话,接通电话,把手机屏幕靠近脸部,遮挡住P-sensor,屏幕变黑了,不遮挡住P-sensor,屏幕就点亮了。接着我们来看看代码流程。

距离感应器与屏幕休眠可参考

http://blog.csdn.net/wds1181977/article/details/42125699

先来说说靠近P-sensor,不灭屏的正常的现象:

  1. 插入耳机
  2. 打开扬声器
  3. 打开蓝牙耳机
  4. 链接蓝牙键盘

步骤一: 在PhoneGlobals.java文件中onCreate()方法中:

。。。 。。。

[java]  view plain copy print ?
  1. // lock used to keep the processor awake, when we don't care for the display.
  2. mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
  3. | PowerManager.ON_AFTER_RELEASE, LOG_TAG);
  4. // Wake lock used to control proximity sensor behavior.
  5. if (mPowerManager.isWakeLockLevelSupported(
  6. PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
  7. mProximityWakeLock = mPowerManager.newWakeLock(
  8. PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, LOG_TAG);
  9. }

。。。 。。。

注意这个private PowerManager.WakeLock mProximityWakeLock;这个初始化变量,

这个mProximityWakeLock就是所说的P-Sensor锁,它是用来唤醒屏幕和使屏幕睡眠的锁。

步骤二:在PhoneGlobals.java文件中的onCreate()方法中:

[java]  view plain copy print ?
  1. // create mAccelerometerListener only if we are using the proximity sensor
  2. if (proximitySensorModeEnabled()) {
  3. mAccelerometerListener = new AccelerometerListener(this, this);
  4. }

创建加速度感应器。

步骤三:在更新Phone的状态的时候确定这个加速度的P-sensor感应器起作用;

[java]  view plain copy print ?
  1. <span style="font-size:18px;">/**
  2. * Notifies the phone app when the phone state changes.
  3. *
  4. * This method will updates various states inside Phone app (e.g. proximity sensor mode,
  5. * accelerometer listener state, update-lock state, etc.)
  6. */
  7. /* package */ void updatePhoneState(PhoneConstants.State state) {
  8. if (state != mLastPhoneState) {
  9. mLastPhoneState = state;
  10. if (state == PhoneConstants.State.IDLE)
  11. PhoneGlobals.getInstance().pokeUserActivity();
  12. updateProximitySensorMode(state);
  13. // Try to acquire or release UpdateLock.
  14. //
  15. // Watch out: we don't release the lock here when the screen is still in foreground.
  16. // At that time InCallScreen will release it on onPause().
  17. if (state != PhoneConstants.State.IDLE) {
  18. // UpdateLock is a recursive lock, while we may get "acquire" request twice and
  19. // "release" request once for a single call (RINGING + OFFHOOK and IDLE).
  20. // We need to manually ensure the lock is just acquired once for each (and this
  21. // will prevent other possible buggy situations too).
  22. if (!mUpdateLock.isHeld()) {
  23. mUpdateLock.acquire();
  24. }
  25. } else {
  26. if (!isShowingCallScreen()) {
  27. if (!mUpdateLock.isHeld()) {
  28. mUpdateLock.release();
  29. }
  30. } else {
  31. // For this case InCallScreen will take care of the release() call.
  32. }
  33. }
  34. if (mAccelerometerListener != null) {
  35. // use accelerometer to augment proximity sensor when in call
  36. mOrientation = AccelerometerListener.ORIENTATION_UNKNOWN;
  37. </span><span style="color:#ff0000;"><strong><span style="font-size:24px;"> </span><span style="font-size:18px;">mAccelerometerListener.enable(state == PhoneConstants.State.OFFHOOK);</span></strong></span><span style="font-size:18px;">
  38. }
  39. // clear our beginning call flag
  40. mBeginningCall = false;
  41. // While we are in call, the in-call screen should dismiss the keyguard.
  42. // This allows the user to press Home to go directly home without going through
  43. // an insecure lock screen.
  44. // But we do not want to do this if there is no active call so we do not
  45. // bypass the keyguard if the call is not answered or declined.
  46. if (mInCallScreen != null) {
  47. if (VDBG) Log.d(LOG_TAG, "updatePhoneState: state = " + state);
  48. if (!PhoneUtils.isDMLocked())
  49. mInCallScreen.updateKeyguardPolicy(state == PhoneConstants.State.OFFHOOK);
  50. }
  51. }
  52. }</span>

步骤四:用AccelerometerListener.java类中的监听事件来处理一些这个覆盖的改变,一共有2个状态,一个是

horizontal,一个是vertical的状态。在上述步骤三红色的调用部分注册这个监听事件:

[java]  view plain copy print ?
  1. public void enable(boolean enable) {
  2. if (DEBUG) Log.d(TAG, "enable(" + enable + ")");
  3. synchronized (this) {
  4. if (enable) {
  5. mOrientation = ORIENTATION_UNKNOWN;
  6. mPendingOrientation = ORIENTATION_UNKNOWN;
  7. mSensorManager.registerListener(mSensorListener, mSensor,
  8. SensorManager.SENSOR_DELAY_NORMAL);
  9. } else {
  10. mSensorManager.unregisterListener(mSensorListener);
  11. mHandler.removeMessages(ORIENTATION_CHANGED);
  12. }
  13. }
  14. }

步骤五:监听事件的相应的过程如下:

[java]  view plain copy print ?
  1. SensorEventListener mSensorListener = new SensorEventListener() {
  2. public void onSensorChanged(SensorEvent event) {
  3. onSensorEvent(event.values[0], event.values[1], event.values[2]);
  4. }
  5. public void onAccuracyChanged(Sensor sensor, int accuracy) {
  6. // ignore
  7. }
  8. };
[java]  view plain copy print ?
  1. private void onSensorEvent(double x, double y, double z) {
  2. if (VDEBUG) Log.d(TAG, "onSensorEvent(" + x + ", " + y + ", " + z + ")");
  3. // If some values are exactly zero, then likely the sensor is not powered up yet.
  4. // ignore these events to avoid false horizontal positives.
  5. if (x == 0.0 || y == 0.0 || z == 0.0) return;
  6. // magnitude of the acceleration vector projected onto XY plane
  7. double xy = Math.sqrt(x*x + y*y);
  8. // compute the vertical angle
  9. double angle = Math.atan2(xy, z);
  10. // convert to degrees
  11. angle = angle * 180.0 / Math.PI;
  12. int orientation = (angle >  VERTICAL_ANGLE ? ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL);
  13. if (VDEBUG) Log.d(TAG, "angle: " + angle + " orientation: " + orientation);
  14. setOrientation(orientation);
  15. }
  16. private void setOrientation(int orientation) {
  17. synchronized (this) {
  18. if (mPendingOrientation == orientation) {
  19. // Pending orientation has not changed, so do nothing.
  20. return;
  21. }
  22. // Cancel any pending messages.
  23. // We will either start a new timer or cancel alltogether
  24. // if the orientation has not changed.
  25. mHandler.removeMessages(ORIENTATION_CHANGED);
  26. if (mOrientation != orientation) {
  27. // Set timer to send an event if the orientation has changed since its
  28. // previously reported value.
  29. mPendingOrientation = orientation;
  30. Message m = mHandler.obtainMessage(ORIENTATION_CHANGED);
  31. // set delay to our debounce timeout
  32. int delay = (orientation == ORIENTATION_VERTICAL ? VERTICAL_DEBOUNCE
  33. : HORIZONTAL_DEBOUNCE);
  34. mHandler.sendMessageDelayed(m, delay);
  35. } else {
  36. // no message is pending
  37. mPendingOrientation = ORIENTATION_UNKNOWN;
  38. }
  39. }
  40. }

然后发送消息ORIENTATION_CHANGED这个改变的消息;这个消息会调用一个回调函数,然后根据状态判断,调用acquire和release()方法;

[java]  view plain copy print ?
  1. Handler mHandler = new Handler() {
  2. public void handleMessage(Message msg) {
  3. switch (msg.what) {
  4. case ORIENTATION_CHANGED:
  5. synchronized (this) {
  6. mOrientation = mPendingOrientation;
  7. if (DEBUG) {
  8. Log.d(TAG, "orientation: " +
  9. (mOrientation == ORIENTATION_HORIZONTAL ? "horizontal"
  10. : (mOrientation == ORIENTATION_VERTICAL ? "vertical"
  11. : "unknown")));
  12. }
  13. mListener.orientationChanged(mOrientation);
  14. }
  15. break;
  16. }
  17. }
  18. };

步骤五:回调到PhoneGlobals.java这个类的 orientationChanged()

[java]  view plain copy print ?
  1. @Override
  2. public void orientationChanged(int orientation) {
  3. mOrientation = orientation;
  4. updateProximitySensorMode(mCM.getState());
  5. }
[java]  view plain copy print ?
  1. <pre name="code" class="java">/**
  2. * Updates the wake lock used to control proximity sensor behavior,
  3. * based on the current state of the phone.  This method is called
  4. * from the CallNotifier on any phone state change.
  5. *
  6. * On devices that have a proximity sensor, to avoid false touches
  7. * during a call, we hold a PROXIMITY_SCREEN_OFF_WAKE_LOCK wake lock
  8. * whenever the phone is off hook.  (When held, that wake lock causes
  9. * the screen to turn off automatically when the sensor detects an
  10. * object close to the screen.)
  11. *
  12. * This method is a no-op for devices that don't have a proximity
  13. * sensor.
  14. *
  15. * Note this method doesn't care if the InCallScreen is the foreground
  16. * activity or not.  That's because we want the proximity sensor to be
  17. * enabled any time the phone is in use, to avoid false cheek events
  18. * for whatever app you happen to be running.
  19. *
  20. * Proximity wake lock will *not* be held if any one of the
  21. * conditions is true while on a call:
  22. * 1) If the audio is routed via Bluetooth
  23. * 2) If a wired headset is connected
  24. * 3) if the speaker is ON
  25. * 4) If the slider is open(i.e. the hardkeyboard is *not* hidden)
  26. *
  27. * @param state current state of the phone (see {@link Phone#State})
  28. */
  29. /* package */ void updateProximitySensorMode(PhoneConstants.State state) {
  30. boolean isRingingWhenActive = false;//MTK81281 add isRingingWhenActive for Cr:ALPS00117091
  31. if (VDBG) Log.d(LOG_TAG, "updateProximitySensorMode: state = " + state);
  32. if (proximitySensorModeEnabled()) {
  33. synchronized (mProximityWakeLock) {
  34. // turn proximity sensor off and turn screen on immediately if
  35. // we are using a headset, the keyboard is open, or the device
  36. // is being held in a horizontal position.
  37. boolean screenOnImmediately = (isHeadsetPlugged()
  38. || PhoneUtils.isSpeakerOn(this)
  39. || isBluetoothHeadsetAudioOn()
  40. || mIsHardKeyboardOpen);
  41. if (FeatureOption.MTK_VT3G324M_SUPPORT) {
  42. screenOnImmediately = screenOnImmediately ||
  43. ((!VTCallUtils.isVTIdle()) && (!VTCallUtils.isVTRinging()));
  44. }
  45. // We do not keep the screen off when the user is outside in-call screen and we are
  46. // horizontal, but we do not force it on when we become horizontal until the
  47. // proximity sensor goes negative.
  48. // this horizontal is not the same portrait.
  49. boolean horizontal =
  50. (mOrientation == AccelerometerListener.ORIENTATION_HORIZONTAL);
  51. screenOnImmediately |= !isShowingCallScreenForProximity() && horizontal;
  52. if (VDBG) Log.d(LOG_TAG, "updateProximitySensorMode: mBeginningCall = " + mBeginningCall);
  53. if (VDBG) Log.d(LOG_TAG, "updateProximitySensorMode: screenOnImmediately = " + screenOnImmediately);
  54. //MTK81281 add isRingingWhenActive for Cr:ALPS00117091 start
  55. //when a call is activeand p-sensor turn off the screen,
  56. //another call or vtcall in we don't release the lock and acquire again
  57. //(the prowermanagerservice will turn on and off the screen and it's a problem)
  58. //instead ,we don't release the lock(prowermanagerservice will not turn on and off the screen)
  59. isRingingWhenActive = (state == PhoneConstants.State.RINGING)
  60. && (mCM.getActiveFgCallState() == Call.State.ACTIVE)
  61. && (mCM.getFirstActiveRingingCall().getState() == Call.State.WAITING);
  62. if (VDBG) Log.d(LOG_TAG, "updateProximitySensorMode: isRingingWhenActive = " + isRingingWhenActive);
  63. //MTK81281 add  isRingingWhenActive for Cr:ALPS00117091 end
  64. //MTK81281 add isRingingWhenActive for Cr:ALPS00117091
  65. if (((state == PhoneConstants.State.OFFHOOK) || mBeginningCall || isRingingWhenActive)
  66. && !screenOnImmediately) {
  67. // Phone is in use!  Arrange for the screen to turn off
  68. // automatically when the sensor detects a close object.
  69. if (!mProximityWakeLock.isHeld()) {
  70. if (DBG) Log.d(LOG_TAG, "updateProximitySensorMode: acquiring...");
  71. <span style="color:#ff0000;"><strong>mProximityWakeLock.acquire();</strong></span>
  72. } else {
  73. if (VDBG) Log.d(LOG_TAG, "updateProximitySensorMode: lock already held.");
  74. }
  75. } else {
  76. // Phone is either idle, or ringing.  We don't want any
  77. // special proximity sensor behavior in either case.
  78. if (mProximityWakeLock.isHeld()) {
  79. if (DBG) Log.d(LOG_TAG, "updateProximitySensorMode: releasing...");
  80. // Wait until user has moved the phone away from his head if we are
  81. // releasing due to the phone call ending.
  82. // Qtherwise, turn screen on immediately
  83. int flags =
  84. (screenOnImmediately ? 0 : PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
  85. <strong><span style="color:#ff0000;">mProximityWakeLock.release(flags);</span></strong>
  86. } else {
  87. if (VDBG) {
  88. Log.d(LOG_TAG, "updateProximitySensorMode: lock already released.");
  89. }
  90. }
  91. }
  92. }
  93. }
  94. }</pre><br><br>

到这已经把Phone层的P-sensor的亮屏和灭屏说完了,回头再来屡屡这个mProximityWakeLock在framework层怎么具体实现的亮屏和灭屏的;敬请期待。。。 。。。


更正:上述的讲解是不正确的,后来经过打log,发现,这个mProximityWakeLock.acquire();和mProximityWakeLock.release(flags);只是申请这个锁,和释放这个锁,防止其他的调用,

其实,在4.2以前Phone模块的P-Sensor在PowerManagerServer.java中处理的,而Android4.2的时候,谷歌对代码进行了一些调整,所以Phone的模块的P-Sensor的控制的类在DisplayPowerController.java

路径:framework/base/services/java/com/android/server/power/DisplayPowerController.java中的:

[java]  view plain copy print ?
  1. private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
  2. @Override
  3. public void onSensorChanged(SensorEvent event) {
  4. if (mProximitySensorEnabled) {
  5. final long time = SystemClock.uptimeMillis();
  6. final float distance = event.values[0];
  7. boolean positive = distance >= 0.0f && distance < mProximityThreshold;
  8. if (DEBUG) {
  9. Slog.d(TAG, "P-Sensor Changed: " + positive);
  10. }
  11. handleProximitySensorEvent(time, positive);
  12. }
  13. }
[java]  view plain copy print ?
  1. <span style="color: rgb(255, 0, 0);"><strong></strong></span>

这个onSensorChanged()就是距离感应器的;这个log:

P-Sensor Changed:true  表示:靠近手机,P-sensor被遮挡住;

P-Sensor Changed:false 表示:离开手机,P-sensor没有被遮挡住;

通过这个log也能帮我们分析一些问题;这个mProximitySensorListener的注册和反注册,大家可以自己在这个类中搜索就可以了;

补充:在PowserManagerServerice.java这个类中,  private LightsService.Light mButtonLight;这个变量申请的就是按键灯,像:home,返回键,menu键的灯,申请这个灯的代码:

[java]  view plain copy print ?
  1. private LightsService mLightsService;
  2. 。。。 。。。
  3. mButtonLight = mLightsService.getLight(LightsService.LIGHT_ID_BUTTONS);

通过LightService可以获得键盘灯的实例,

打开灯的方法:mButtonLight.setBrightness(120);//120可以是(0~255)任意数字;

关闭灯的方法:mButtonLight.turnOff();


     需求:要想使Phone通话界面的P-Sensor亮灭屏幕和按键灯同步,当屏幕灭的时候,按键灯也灭,屏幕亮的时候,按键灯也亮;其实做法很简单了,在onSensorChanged()的时候处理,扩一些接口,

具体设计的类我列举一下:

  • PowerManager.java
  • PowerManagerService.java
  • BridgetPowerManager.java
  • IPowerManager.adil
  • DisPlayPowerController.java

具体代码就不详细赘述了,还是“觉知此事要躬行”;

注意在

[java]  view plain copy print ?
  1. mLastUserActivityButtonTime = SystemClock.uptimeMillis();
  2. mButtonLight.setBrightness(102);

在设置打开按键灯的时候,设置一下最后一次用户触摸按钮的时间;至于为什么??大家自已到时候打log就明白了。。。 。。。

[java]  view plain copy print ?
  1. mLastUserActivityButtonTime

Android4.2距离感应器相关推荐

  1. PowerManager屏幕休眠断网与距离感应器P-Sensor

    PowerManager.java . 1.  应用程序获取PowerManager服务, 我们可以这样书写: PowerManager pm = (PowerManager) getSystemSe ...

  2. Android 距离感应器和耳机状态监测(控制Audio输出通道切换)

    * 切换扬声器播放声音 or 听筒播放  * 1. 距离感应器:继承SensorEventListener这个监听,重写onSensorChanged方法  * 2. 检测耳机插入和拔出:Headse ...

  3. 距离感应器下的休眠唤醒机制实现

    前言 从事Android framework开发已经两年了,今天起决定把工作上遇到的问题.做过的需求都用博客的形式记录一下,特地新开一个系列---Android framework开发工作记录,有需要 ...

  4. android距离感应器控制黑屏,白屏

    最近在做一个网络通话的apk,功能和手机打sim卡电话一样.虽然只做java部分,但也遇到很多问题,其中一个就是模拟通话时的状态,要控制屏幕锁屏.我知道是通过手机上的距离感应器来实现,但也搞了好久,今 ...

  5. 距离感应器实现锁频教程

    首先说一下android平台下的11种感应器:            1. ACCELEROMETER 加速,描述加速度的.            2.GRAVITY 重力,这个在大家都知道.     ...

  6. android距离感应器控制屏幕灭屏白屏

    最近在做一个网络通话的apk,功能和手机打sim卡电话一样.虽然只做java部分,但也遇到很多问题,其中一个就是模拟通话时的状态,要控制屏幕锁屏.我知道是通过手机上的距离感应器来实现,但也搞了好久,今 ...

  7. 米2距离感应器的设置问题。无法挂断电话等问题的解决

    通话过程中一直黑屏,无法挂断电话 首先打开拨号界面,点击三道杠的菜单键--设置--来电时状态设置--启用距离感应器(打开 ︳),来电防误操作 直接关闭得了.

  8. android Phone 距离感应器锁的实现

    android手机在正常打电话的过程中,靠近面部会灭屏,这个主要是PhoneApp中的mProximityWakeLock的作用.这个锁是在PhoneApp中被初始化的. if ((pm.getSup ...

  9. 手机中的传感器:重力感应器、加速度传感器、陀螺仪、电子罗盘和光线距离感应器

    智能手机之所以受到大家的欢迎,与其具有的娱乐功能分不开,使得它不仅仅是个通话的工具.智能手机支持那么多的娱乐应用,归根结底在于它里面集成的各类传感器,主要有重力感应器.加速度传感器.陀螺仪.电子罗盘和 ...

最新文章

  1. ubuntu 16.04 更新后搜狗输入法无法输入中文的问题
  2. 3分钟解决MySQL 1032 主从错误
  3. Sql2000命名中的’_’好象会引发问题
  4. JAVA黑白圆圈图形_CSS3 黑白交替旋转圆圈
  5. 向量距离计算 java_Milvus 向量搜索引擎开源了!
  6. DL:听着歌曲《成都》三分钟看遍主流的深度学习的神经网络的发展框架(1950~2018)
  7. 搜索引擎的选择—百度还是谷歌?
  8. 5922. 统计出现过一次的公共字符串
  9. ASP.NET操作Excel
  10. Blazor服务器应用程序中使用EF Core的多租户
  11. java安装选择哪个可选功能_java章节习题及期末考试题答案.doc
  12. linux下三三维建模软件,SolidWorks是基于()原创的三维实体建模软件。A.UNIXB.WindowsC.LinuxD.Dos...
  13. Juniper设备管理
  14. JAVA ajax搜索框_JAVAEE AJAX实现搜素框关键字提示语功能
  15. 常见面试问题整理(考研复试面试/计算机408+数据库基础概念)
  16. BZOJ 4198 [Noi2015 D2T1] 荷马史诗
  17. hsql导入mysql_关于HSQLDB访问已有数据库文件的操作说明
  18. 学习打印机,了解打印命令
  19. 判定一个关键词的SEO优化难度等级标准
  20. dnf鹰犬机器人补丁_DNF补丁大全DNF东方Projece界面补丁下载

热门文章

  1. Excel 条件格式的设置方法
  2. 初识 GraphQL 和 Apollo Federation
  3. 用python将十进制数转换成二进制数_python中的数据结构-将十进制数转换为二进制数...
  4. Android 获取下载链接文件大小
  5. uniapp 中使用 sha1 加密
  6. 在游戏中弹出GameCenter登陆界面
  7. 【通达信指标公式】主力博弈分时指标,分时图抓日内弱转强牛股
  8. uniapp使用 Ucharts2.0绘制图形
  9. 2020最新Python入门笔记,建议收藏
  10. log4j日志设置保留天数