1. 程式人生 > >Android4.2中Phone的P-sensor的應用的分析。

Android4.2中Phone的P-sensor的應用的分析。

先說現象,現象就是來電話,接通電話,把手機螢幕靠近臉部,遮擋住P-sensor,螢幕變黑了,不遮擋住P-sensor,螢幕就點亮了。接著我們來看看程式碼流程。

     先來說說靠近P-sensor,不滅屏的正常的現象:

  1. 插入耳機
  2. 開啟揚聲器
  3. 開啟藍芽耳機
  4. 連結藍芽鍵盤

   步驟一: 在PhoneGlobals.java檔案中onCreate()方法中:

。。。 。。。

[java] view plaincopyprint?
  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 plaincopyprint?
  1. // create mAccelerometerListener only if we are using the proximity sensor
  2.             if (proximitySensorModeEnabled()) {  
  3.                 mAccelerometerListener = new AccelerometerListener(thisthis);  
  4.             }  
建立加速度感應器。

步驟三:在更新Phone的狀態的時候確定這個加速度的P-sensor感應器起作用;

[java] view plaincopyprint?
  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 plaincopyprint?
  1. publicvoid 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 plaincopyprint?
  1. SensorEventListener mSensorListener = new SensorEventListener() {  
  2.         publicvoid onSensorChanged(SensorEvent event) {  
  3.             onSensorEvent(event.values[0], event.values[1], event.values[2]);  
  4.         }  
  5.         publicvoid onAccuracyChanged(Sensor sensor, int accuracy) {  
  6.             // ignore
  7.         }  
  8.     };  

[java] view plaincopyprint?
  1. privatevoid onSensorEvent(double x, double y, double z) {  
  2.         if