android Phone 距离感应器锁的实现

来源:互联网 发布:淘宝称呼买家的昵称 编辑:程序博客网 时间:2024/04/29 17:51

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

[java] view plaincopy
  1. if ((pm.getSupportedWakeLockFlags()  
  2.                  & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) != 0x0) {  
  3.                 mProximityWakeLock =  
  4.                         pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, LOG_TAG);  
  5.             }  

初始化这个锁之后,就有acquire与release这把锁来亮灭屏了,主要是函数updateProximitySensorMode(Phone.State state) 发挥的作用,这个函数在电话状态发生改变的时候会调用(还有类似手机插拔,手机方向改变等等)。那我们来看下这个函数主要做了什么。

此函数在源码中的解释已经很清楚了,在此不做赘述,这个函数主要是acquire与release mProximityWakeLock这把锁。那么,我们来看下,申请这把锁的时候,究竟干了什么事情。PhoneApp里的mProximityWakeLock.acquire() 调用PowerManager里的acquire(),然后调用PowerManagerService里的acquireWakeLock(),接着调用acquireWakeLockLocked()。这个函数就是我们最终申请锁的地方。

我们看下比较重要的地方

[java] view plaincopy
  1. if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {  
  2.     mProximityWakeLockCount++;  
  3.     if (mProximityWakeLockCount == 1) {  
  4.         enableProximityLockLocked();  
  5.     }  
  6. }  


 

这个地方就是判断,如果我们申请的是PROXIMITY_SCREEN_OFF_WAKE_LOCK,那么就enableProximityLockLocked();mProximityWakeLockCount说明的是PROXIMITY_SCREEN_OFF_WAKE_LOCK是采用计数方式的锁。

继续看enableProximityLockLocked()做了什么

[java] view plaincopy
  1. private void enableProximityLockLocked() {  
  2.     if (mDebugProximitySensor) {  
  3.         Slog.d(TAG, "enableProximityLockLocked");  
  4.     }  
  5.     if (!mProximitySensorEnabled) {  
  6.         // clear calling identity so sensor manager battery stats are accurate  
  7.         long identity = Binder.clearCallingIdentity();  
  8.         try {  
  9.             mSensorManager.registerListener(mProximityListener, mProximitySensor,  
  10.                     SensorManager.SENSOR_DELAY_NORMAL);  
  11.             mProximitySensorEnabled = true;  
  12.         } finally {  
  13.             Binder.restoreCallingIdentity(identity);  
  14.         }  
  15.     }  
  16. }  

原来,这个函数主要是注册了mProximityListener,也就是说,我们监听距离感应器的操作是在加锁之后发生的。灭屏是在距离感应器监听到数值才激发的,那么我们看下mProximityListener。

[java] view plaincopy
  1. SensorEventListener mProximityListener = new SensorEventListener() {  
  2.         public void onSensorChanged(SensorEvent event) {  
  3.             long milliseconds = SystemClock.elapsedRealtime();  
  4.             synchronized (mLocks) {  
  5.                 float distance = event.values[0];  
  6.                 long timeSinceLastEvent = milliseconds - mLastProximityEventTime;  
  7.                 mLastProximityEventTime = milliseconds;  
  8.                 mHandler.removeCallbacks(mProximityTask);  
  9.                 boolean proximityTaskQueued = false;  
  10.   
  11.                 // compare against getMaximumRange to support sensors that only return 0 or 1  
  12.                 boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&  
  13.                         distance < mProximitySensor.getMaximumRange());  
  14.   
  15.                 if (mDebugProximitySensor) {  
  16.                     Slog.d(TAG, "mProximityListener.onSensorChanged active: " + active);  
  17.                 }  
  18.                 if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {  
  19.                     // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing  
  20.                     mProximityPendingValue = (active ? 1 : 0);  
  21.                     mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);  
  22.                     proximityTaskQueued = true;  
  23.                 } else {  
  24.                     // process the value immediately  
  25.                     mProximityPendingValue = -1;  
  26.                     proximityChangedLocked(active);  
  27.                 }  
  28.   
  29.                 // update mProximityPartialLock state  
  30.                 boolean held = mProximityPartialLock.isHeld();  
  31.                 if (!held && proximityTaskQueued) {  
  32.                     // hold wakelock until mProximityTask runs  
  33.                     mProximityPartialLock.acquire();  
  34.                 } else if (held && !proximityTaskQueued) {  
  35.                     mProximityPartialLock.release();  
  36.                 }  
  37.             }  
  38.         }  

复写了onSensorChanged()函数,当检测到actiove的时候,执行了proximityChangedLocked并申请了一个mProximityPartialLock。(if else里的代码都会执行proximityChangedLocked)。proximityChangedLocked()函数会在active的时候执行goToSleepLocked。

至此,加锁过程分析完毕,解锁过程与加锁过程分析方法一样,不再赘述。