代码改变世界

android Phone 距离感应器锁的实现

2012-12-30 14:17  Kevin-wang  阅读(746)  评论(0编辑  收藏  举报

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

   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()。这个函数就是我们最终申请锁的地方。

我们看下比较重要的地方

   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()做了什么

   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。
   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。