通話中自動關閉螢幕proximit ysensor功能分析

來源:互聯網
上載者:User

通話中自動關閉螢幕proximit ysensor功能應用

在android中, 接近感應器(proximity sensor)在系統中唯一有用處的地方, 應該就是通話過程中, 為防止臉部觸碰通話中介面按鍵, 而自動關閉螢幕.

下面jwisp從架構層來給大家分析一下, 這個功能是如何?的

涉及類: PowerManagerService.java(frameworks\base\services\java\com\android\server\)

 分析時應首先想到, ProximityListener*********中的onSensorChanged是決定是否關閉或開啟螢幕的入口, 我們來看看代碼

    SensorEventListener mProximityListener = new SensorEventListener() {        public void onSensorChanged(SensorEvent event) {            long milliseconds = SystemClock.elapsedRealtime();            synchronized (mLocks) {                float distance = event.values[0];                long timeSinceLastEvent = milliseconds - mLastProximityEventTime;                mLastProximityEventTime = milliseconds;                mHandler.removeCallbacks(mProximityTask);                boolean proximityTaskQueued = false;                boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&                        distance < mProximitySensor.getMaximumRange());                    if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {                    mProximityPendingValue = (active ? 1 : 0);                    mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);                    proximityTaskQueued = true;                } else {                    mProximityPendingValue = -1;                    proximityChangedLocked(active);                }                boolean held = mProximityPartialLock.isHeld();                if (!held && proximityTaskQueued) {                    mProximityPartialLock.acquire();                } else if (held && !proximityTaskQueued) {                    mProximityPartialLock.release();                }            }        }    };

我們來逐行分析一下

            long milliseconds = SystemClock.elapsedRealtime();            long timeSinceLastEvent = milliseconds - mLastProximityEventTime;            mLastProximityEventTime = milliseconds;

           
milliseconds得到系統從啟動到當前的時間(不論休眠與否)
mLastProximityEventTime為上次獲得的milliseconds
timeSinceLastEvent 從上次事件發生到現在所間隔的時間, 也就是上面兩個變數的相對時間.

 float distance = event.values[0]; boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD && distance < mProximitySensor.getMaximumRange());

由distance獲得psensor事件中感應到的距離值是多少

PROXIMITY_THRESHOLD為距離值達到多少才經行相應動作的閥值(門檻)

所以在下面的代碼中, 將由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);        }

PROXIMITY_SENSOR_DELAY為PowerMangerService設定的psensor感應延遲時間, 這裡解決bug時會用的. 比如當你覺得通話中, psensor感應太慢, 如果能排除是驅動的問題, 那基本上就是這裡設定的問題了.

jwisp這裡的問題就是這樣, 於是將預設的1000ms改成了100ms, 明顯會感覺到psensor靈敏多了.

if判斷兩次事件發生的間距時間若小於延遲時間, 則由handler執行mProximityTask任務

若大於等於延遲時間, 則執行proximityChangedLocked()方法

我們來看一下mProximityTask是一個什麼樣的任務

    private Runnable mProximityTask = new Runnable() {        public void run() {            synchronized (mLocks) {                if (mProximityPendingValue != -1) {                    proximityChangedLocked(mProximityPendingValue == 1);                    mProximityPendingValue = -1;                }                if (mProximityPartialLock.isHeld()) {                    mProximityPartialLock.release();                }            }        }    };

看出來主要也是執行了proximityChangedLocked()方法

所以上面的if-else判斷,只是判斷是否需要順延強制任務, 而不管延遲或不延遲, 都是需要執行proximityChangedLocked()方法的.

其實proximityChangedLocked()方法也是真正關閉開啟螢幕的執行者

我們來看看它:

    private void proximityChangedLocked(boolean active) {        if (!mProximitySensorEnabled) {            return;        }        if (active) {            if (!mProxIgnoredBecauseScreenTurnedOff) {                goToSleepLocked(SystemClock.uptimeMillis(),                        WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);            }            mProximitySensorActive = true;        } else {            mProximitySensorActive = false;            if (!mProxIgnoredBecauseScreenTurnedOff) {                forceUserActivityLocked();            }            if (mProximityWakeLockCount == 0) {                disableProximityLockLocked();            }        }    }

意思很明顯了, 如果active為true則執行goToSleepLocked()方法, 並設定ProximitySensorActive = true

如果為false則執行forceUserActivityLocked方法

在下一篇中, jwisp將深入分析這兩個方法是怎麼如何?的.

移植總結:

若proximity sensor在接電話中反映太慢, 感覺不靈敏, 可以通過設定PROXIMITY_SENSOR_DELAY的值來調試, 若降低該值, 靈敏度提高, 基本上就可用確定不是驅動的問題了.

若距離太遠, 螢幕就已經關閉, 則可通過設定距離感應器的閥值, 來調節在多遠的距離可以關閉螢幕. 常量值為PROXIMITY_THRESHOLD 預設 = 5.0f

著作權,轉載請註明出處:http://www.jwisp.com/?p=102

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.