|
| 1 | +/* |
| 2 | + * SPDX-FileCopyrightText: 2015 The CyanogenMod Project |
| 3 | + * SPDX-FileCopyrightText: The LineageOS Project |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +package org.lineageos.settings.device.actions |
| 8 | + |
| 9 | +import android.content.Context |
| 10 | +import android.content.Intent |
| 11 | +import android.content.SharedPreferences |
| 12 | +import android.hardware.Sensor |
| 13 | +import android.hardware.SensorEvent |
| 14 | +import android.hardware.SensorEventListener |
| 15 | +import android.os.PowerManager |
| 16 | +import android.os.PowerManager.WakeLock |
| 17 | +import android.os.UserHandle |
| 18 | +import android.util.Log |
| 19 | +import org.lineageos.settings.device.MotoActionsSettings |
| 20 | +import org.lineageos.settings.device.MotoActionsSettings.GESTURE_IR_WAKEUP_KEY |
| 21 | +import org.lineageos.settings.device.MotoActionsSettings.GESTURE_PICK_UP_KEY |
| 22 | +import org.lineageos.settings.device.MotoActionsSettings.GESTURE_POCKET_KEY |
| 23 | +import org.lineageos.settings.device.SensorHelper |
| 24 | +import org.lineageos.settings.device.SensorHelper.Companion.SENSOR_TYPE_MMI_FLAT_UP |
| 25 | +import org.lineageos.settings.device.SensorHelper.Companion.SENSOR_TYPE_MMI_STOW |
| 26 | + |
| 27 | +class DozePulse( |
| 28 | + private val context: Context, |
| 29 | + private val sharedPreferences: SharedPreferences, |
| 30 | + private val sensorHelper: SensorHelper, |
| 31 | +) : UpdatedStateNotifier { |
| 32 | + |
| 33 | + private val powerManager: PowerManager = context.getSystemService(PowerManager::class.java) |
| 34 | + private val wakeLock: WakeLock = |
| 35 | + powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "$TAG:WakeLock") |
| 36 | + private val flatUpSensor: Sensor = sensorHelper.getSensor(SENSOR_TYPE_MMI_FLAT_UP)!! |
| 37 | + private val stowSensor: Sensor = sensorHelper.getSensor(SENSOR_TYPE_MMI_STOW)!! |
| 38 | + |
| 39 | + private var isStowed = false |
| 40 | + private var lastStowed = false |
| 41 | + private var lastStowedTime = 0L |
| 42 | + |
| 43 | + private var lastFlatUp = false |
| 44 | + |
| 45 | + private var lastDozeTime: Long = 0L |
| 46 | + |
| 47 | + fun onScreenStateChanged(screenOn: Boolean) { |
| 48 | + if (!wakeLock.isHeld) { |
| 49 | + if (screenOn) { |
| 50 | + wakeLock.acquire() |
| 51 | + } else { |
| 52 | + wakeLock.release() |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + if (screenOn) { |
| 57 | + Log.d(TAG, "Disabling") |
| 58 | + sensorHelper.unregisterListener(flatUpListener) |
| 59 | + sensorHelper.unregisterListener(stowListener) |
| 60 | + } else { |
| 61 | + Log.d(TAG, "Enabling") |
| 62 | + sensorHelper.registerListener(flatUpSensor, flatUpListener) |
| 63 | + sensorHelper.registerListener(stowSensor, stowListener) |
| 64 | + lastDozeTime = System.currentTimeMillis() |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + @Synchronized |
| 69 | + override fun updateState() { |
| 70 | + onScreenStateChanged(powerManager.isInteractive) |
| 71 | + } |
| 72 | + |
| 73 | + private val flatUpListener = |
| 74 | + object : SensorEventListener { |
| 75 | + @Synchronized |
| 76 | + override fun onSensorChanged(event: SensorEvent) { |
| 77 | + val thisFlatUp = event.values[0] != 0f |
| 78 | + val pickUpGestureEnabled = sharedPreferences.getBoolean(GESTURE_PICK_UP_KEY, true) |
| 79 | + if (pickUpGestureEnabled && lastFlatUp && !thisFlatUp && !isStowed) { |
| 80 | + onStartPulse() |
| 81 | + } |
| 82 | + lastFlatUp = thisFlatUp |
| 83 | + Log.d(TAG, "event: $thisFlatUp") |
| 84 | + } |
| 85 | + |
| 86 | + override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {} |
| 87 | + } |
| 88 | + |
| 89 | + private val stowListener = |
| 90 | + object : SensorEventListener { |
| 91 | + @Synchronized |
| 92 | + override fun onSensorChanged(event: SensorEvent) { |
| 93 | + isStowed = event.values[0] != 0f |
| 94 | + if (isStowed) { |
| 95 | + lastStowedTime = event.timestamp |
| 96 | + } else if (lastStowed && shouldPulse(event.timestamp)) { |
| 97 | + onStartPulse() |
| 98 | + } |
| 99 | + lastStowed = isStowed |
| 100 | + Log.d(TAG, "event: $isStowed") |
| 101 | + } |
| 102 | + |
| 103 | + private fun shouldPulse(timestamp: Long): Boolean { |
| 104 | + val delta = timestamp - lastStowedTime |
| 105 | + |
| 106 | + val irWakeupEnabled = sharedPreferences.getBoolean(GESTURE_IR_WAKEUP_KEY, true) |
| 107 | + val pocketGestureEnabled = sharedPreferences.getBoolean(GESTURE_POCKET_KEY, true) |
| 108 | + |
| 109 | + return when { |
| 110 | + irWakeupEnabled && pocketGestureEnabled -> true |
| 111 | + irWakeupEnabled -> delta < HANDWAVE_MAX_DELTA_NS |
| 112 | + pocketGestureEnabled -> delta >= POCKET_MIN_DELTA_NS |
| 113 | + else -> false |
| 114 | + } |
| 115 | + } |
| 116 | + |
| 117 | + override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {} |
| 118 | + } |
| 119 | + |
| 120 | + private fun onStartPulse() { |
| 121 | + if ( |
| 122 | + !MotoActionsSettings.isDozeEnabled(context) || |
| 123 | + MotoActionsSettings.isAlwaysOnEnabled(context) |
| 124 | + ) { |
| 125 | + return |
| 126 | + } |
| 127 | + val now = System.currentTimeMillis() |
| 128 | + if (now - lastDozeTime > DELAY_BETWEEN_DOZES_IN_MS) { |
| 129 | + lastDozeTime = now |
| 130 | + context.sendBroadcastAsUser( |
| 131 | + Intent("com.android.systemui.doze.pulse"), |
| 132 | + UserHandle.CURRENT, |
| 133 | + ) |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + companion object { |
| 138 | + private const val TAG = "MotoActions-DozePulse" |
| 139 | + private const val DELAY_BETWEEN_DOZES_IN_MS = 1500 |
| 140 | + private const val HANDWAVE_MAX_DELTA_NS = 1000L * 1000 * 1000 |
| 141 | + private const val POCKET_MIN_DELTA_NS = 5000L * 1000 * 1000 |
| 142 | + } |
| 143 | +} |
0 commit comments