5

I'm trying to create a custom phone app, and one of the features i'm trying to implement is to turn the screen off when the phone is brought close to face to avoid accidental touches.

I have read about the proximity sensor in the android documentation, and saw that this exact feature is implemented via a PROXIMITY_SCREEN_OFF_WAKE_LOCK WakeLock.

I have created a test app to test this feature in isolation, which includes two buttons: one to require the wake lock and one to release it.

class MainActivity: AppCompatActivity() {

    private lateinit var mPowerManager:PowerManager
    private lateinit var mWakeLock:PowerManager.WakeLock

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mPowerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
        mWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "TEST_PROXIMITY_SENSOR_TAG:wake_lock_tag")

        button_activate.setOnClickListener {
            if (!mWakeLock.isHeld)
                mWakeLock.acquire()
        }

        button_deactivate.setOnClickListener {
            if (mWakeLock.isHeld)
                mWakeLock.release()
        }
    }
}

And added the following WakeLock permission to my AndroidManifest.xml

<uses-permission android:name="android.permission.WAKE_LOCK" />

For the most part, this code works fine. However, sometimes when I unblock the proximity sensor the screen doesn't turn on for 10-30 seconds instead of immediately.

At first I though this was a hardware problem with the physical device I was testing with (Nexus 5, android Pie), but I have added additional logging of the proximity sensor values to the activity.

override fun onCreate(savedInstanceState: Bundle?) {

    ...

    mSensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)

    mSensorManager.registerListener(
        this as SensorEventListener,
        mSensor,
        SensorManager.SENSOR_DELAY_NORMAL
    )
}

override fun onSensorChanged(event: SensorEvent?) {
    Log.d(TAG,"${event?.values?.get(0)}")
}

The sensor reported correct measurements. And when the screen was turned off wrongly by the WakeLock, the sensor reported "far".

I have tested the same scenario with the default dialer app, but it works fine. What's the problem with my implementation? I have looked at the AOSP dialer code and Signal's android app, but I couldn't find a noticeable difference.

David Barishev
  • 534
  • 7
  • 30
  • 1
    [Signal's app](https://github.com/signalapp/Signal-Android/blob/master/src/org/thoughtcrime/securesms/webrtc/locks/ProximityLock.java) uses [RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY](https://developer.android.com/reference/android/os/PowerManager#RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) – user70 Nov 26 '19 at 20:11

0 Answers0