Make volume sensors update instantly by subscribing to a broadcast (#4162)

* Make volume sensors update instantly by subscribing to a broadcast

* Change skippableActions to a 1-to-many map and the list of all volume sensors to the corresponding Intent action key
This commit is contained in:
Márton Maráz 2024-02-02 21:25:55 +01:00 committed by GitHub
parent 471f7de8da
commit c185b871fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 92 additions and 57 deletions

View file

@ -14,6 +14,7 @@ import android.telephony.TelephonyManager
import dagger.hilt.android.HiltAndroidApp
import io.homeassistant.companion.android.common.data.keychain.KeyChainRepository
import io.homeassistant.companion.android.common.data.prefs.PrefsRepository
import io.homeassistant.companion.android.common.sensors.AudioSensorManager
import io.homeassistant.companion.android.common.sensors.LastUpdateManager
import io.homeassistant.companion.android.database.AppDatabase
import io.homeassistant.companion.android.database.settings.SensorUpdateFrequencySetting
@ -158,6 +159,7 @@ open class HomeAssistantApplication : Application() {
addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
addAction(AudioManager.ACTION_HEADSET_PLUG)
addAction(AudioManager.RINGER_MODE_CHANGED_ACTION)
addAction(AudioSensorManager.VOLUME_CHANGED_ACTION)
}
)

View file

@ -101,24 +101,34 @@ class SensorReceiver : SensorReceiverBase() {
// Suppress Lint because we only register for the receiver if the android version matches the intent
@SuppressLint("InlinedApi")
override val skippableActions = mapOf(
"android.app.action.NEXT_ALARM_CLOCK_CHANGED" to NextAlarmManager.nextAlarm.id,
"android.bluetooth.device.action.ACL_CONNECTED" to BluetoothSensorManager.bluetoothConnection.id,
"android.bluetooth.device.action.ACL_DISCONNECTED" to BluetoothSensorManager.bluetoothConnection.id,
"com.oculus.intent.action.MOUNT_STATE_CHANGED" to QuestSensorManager.headsetMounted.id,
"android.net.wifi.WIFI_AP_STATE_CHANGED" to NetworkSensorManager.hotspotState.id,
BluetoothAdapter.ACTION_STATE_CHANGED to BluetoothSensorManager.bluetoothState.id,
Intent.ACTION_SCREEN_OFF to PowerSensorManager.interactiveDevice.id,
Intent.ACTION_SCREEN_ON to PowerSensorManager.interactiveDevice.id,
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED to PowerSensorManager.powerSave.id,
PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED to PowerSensorManager.doze.id,
NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED to DNDSensorManager.dndSensor.id,
AudioManager.ACTION_MICROPHONE_MUTE_CHANGED to AudioSensorManager.micMuted.id,
AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED to AudioSensorManager.speakerphoneState.id,
AudioManager.RINGER_MODE_CHANGED_ACTION to AudioSensorManager.audioSensor.id,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE to DevicePolicyManager.isWorkProfile.id,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE to DevicePolicyManager.isWorkProfile.id,
WifiManager.WIFI_STATE_CHANGED_ACTION to NetworkSensorManager.wifiState.id,
NfcAdapter.ACTION_ADAPTER_STATE_CHANGED to NfcSensorManager.nfcStateSensor.id
"android.app.action.NEXT_ALARM_CLOCK_CHANGED" to listOf(NextAlarmManager.nextAlarm.id),
"android.bluetooth.device.action.ACL_CONNECTED" to listOf(BluetoothSensorManager.bluetoothConnection.id),
"android.bluetooth.device.action.ACL_DISCONNECTED" to listOf(BluetoothSensorManager.bluetoothConnection.id),
"com.oculus.intent.action.MOUNT_STATE_CHANGED" to listOf(QuestSensorManager.headsetMounted.id),
"android.net.wifi.WIFI_AP_STATE_CHANGED" to listOf(NetworkSensorManager.hotspotState.id),
BluetoothAdapter.ACTION_STATE_CHANGED to listOf(BluetoothSensorManager.bluetoothState.id),
Intent.ACTION_SCREEN_OFF to listOf(PowerSensorManager.interactiveDevice.id),
Intent.ACTION_SCREEN_ON to listOf(PowerSensorManager.interactiveDevice.id),
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED to listOf(PowerSensorManager.powerSave.id),
PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED to listOf(PowerSensorManager.doze.id),
NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED to listOf(DNDSensorManager.dndSensor.id),
AudioManager.ACTION_MICROPHONE_MUTE_CHANGED to listOf(AudioSensorManager.micMuted.id),
AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED to listOf(AudioSensorManager.speakerphoneState.id),
AudioManager.RINGER_MODE_CHANGED_ACTION to listOf(AudioSensorManager.audioSensor.id),
AudioSensorManager.VOLUME_CHANGED_ACTION to listOf(
AudioSensorManager.volAccessibility.id,
AudioSensorManager.volAlarm.id,
AudioSensorManager.volCall.id,
AudioSensorManager.volDTMF.id,
AudioSensorManager.volNotification.id,
AudioSensorManager.volMusic.id,
AudioSensorManager.volRing.id,
AudioSensorManager.volSystem.id
),
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE to listOf(DevicePolicyManager.isWorkProfile.id),
Intent.ACTION_MANAGED_PROFILE_AVAILABLE to listOf(DevicePolicyManager.isWorkProfile.id),
WifiManager.WIFI_STATE_CHANGED_ACTION to listOf(NetworkSensorManager.wifiState.id),
NfcAdapter.ACTION_ADAPTER_STATE_CHANGED to listOf(NfcSensorManager.nfcStateSensor.id)
)
override fun getSensorSettingsIntent(

View file

@ -12,6 +12,7 @@ import io.homeassistant.companion.android.common.R as commonR
class AudioSensorManager : SensorManager {
companion object {
private const val TAG = "AudioSensor"
const val VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION"
val audioSensor = SensorManager.BasicSensor(
"audio_sensor",
@ -69,69 +70,77 @@ class AudioSensorManager : SensorManager {
SensorManager.BasicSensor.UpdateType.WORKER
}
)
private val volAlarm = SensorManager.BasicSensor(
val volAlarm = SensorManager.BasicSensor(
"volume_alarm",
"sensor",
commonR.string.sensor_name_volume_alarm,
commonR.string.sensor_description_volume_alarm,
"mdi:alarm",
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
updateType = SensorManager.BasicSensor.UpdateType.INTENT
)
private val volCall = SensorManager.BasicSensor(
val volCall = SensorManager.BasicSensor(
"volume_call",
"sensor",
commonR.string.sensor_name_volume_call,
commonR.string.sensor_description_volume_call,
"mdi:phone",
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
updateType = SensorManager.BasicSensor.UpdateType.INTENT
)
private val volMusic = SensorManager.BasicSensor(
val volMusic = SensorManager.BasicSensor(
"volume_music",
"sensor",
commonR.string.sensor_name_volume_music,
commonR.string.sensor_description_volume_music,
"mdi:music",
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
updateType = SensorManager.BasicSensor.UpdateType.INTENT
)
private val volRing = SensorManager.BasicSensor(
val volRing = SensorManager.BasicSensor(
"volume_ring",
"sensor",
commonR.string.sensor_name_volume_ring,
commonR.string.sensor_description_volume_ring,
"mdi:phone-ring",
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
updateType = SensorManager.BasicSensor.UpdateType.INTENT
)
private val volNotification = SensorManager.BasicSensor(
val volNotification = SensorManager.BasicSensor(
"volume_notification",
"sensor",
commonR.string.sensor_name_volume_notification,
commonR.string.sensor_description_volume_notification,
"mdi:bell-ring",
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
updateType = SensorManager.BasicSensor.UpdateType.INTENT
)
private val volSystem = SensorManager.BasicSensor(
val volSystem = SensorManager.BasicSensor(
"volume_system",
"sensor",
commonR.string.sensor_name_volume_system,
commonR.string.sensor_description_volume_system,
"mdi:cellphone-sound",
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
updateType = SensorManager.BasicSensor.UpdateType.INTENT
)
private val volAccessibility = SensorManager.BasicSensor(
val volAccessibility = SensorManager.BasicSensor(
"volume_accessibility",
"sensor",
commonR.string.sensor_name_volume_accessibility,
commonR.string.sensor_description_volume_accessibility,
"mdi:human",
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
updateType = SensorManager.BasicSensor.UpdateType.INTENT
)
private val volDTMF = SensorManager.BasicSensor(
val volDTMF = SensorManager.BasicSensor(
"volume_dtmf",
"sensor",
commonR.string.sensor_name_volume_dtmf,
commonR.string.sensor_description_volume_dtmf,
"mdi:volume-high",
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
updateType = SensorManager.BasicSensor.UpdateType.INTENT
)
}

View file

@ -78,7 +78,7 @@ abstract class SensorReceiverBase : BroadcastReceiver() {
Intent.ACTION_POWER_DISCONNECTED
)
protected abstract val skippableActions: Map<String, String>
protected abstract val skippableActions: Map<String, List<String>>
protected abstract fun getSensorSettingsIntent(
context: Context,
@ -89,14 +89,16 @@ abstract class SensorReceiverBase : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(tag, "Received intent: ${intent.action}")
if (skippableActions.containsKey(intent.action)) {
val sensor = skippableActions[intent.action]
if (!isSensorEnabled(sensor!!)) {
skippableActions[intent.action]?.let { sensors ->
val noSensorsEnabled = sensors.none {
isSensorEnabled(it)
}
if (noSensorsEnabled) {
Log.d(
tag,
String.format(
"Sensor %s corresponding to received event %s is disabled, skipping sensors update",
sensor,
"Sensor(s) %s corresponding to received event %s are disabled, skipping sensors update",
sensors.toString(),
intent.action
)
)

View file

@ -26,7 +26,7 @@ class SensorUpdateReceiver : SensorReceiverBase() {
override val managers: List<SensorManager>
get() = listOf(BluetoothSensorManager())
override val skippableActions: Map<String, String>
override val skippableActions: Map<String, List<String>>
get() = emptyMap()
override fun getSensorSettingsIntent(

View file

@ -13,6 +13,7 @@ import android.os.PowerManager
import dagger.hilt.android.HiltAndroidApp
import io.homeassistant.companion.android.common.data.keychain.KeyChainRepository
import io.homeassistant.companion.android.common.data.keychain.KeyStoreRepositoryImpl
import io.homeassistant.companion.android.common.sensors.AudioSensorManager
import io.homeassistant.companion.android.complications.ComplicationReceiver
import io.homeassistant.companion.android.sensors.SensorReceiver
import kotlinx.coroutines.CoroutineScope
@ -73,6 +74,7 @@ open class HomeAssistantApplication : Application() {
addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
addAction(AudioManager.ACTION_HEADSET_PLUG)
addAction(AudioManager.RINGER_MODE_CHANGED_ACTION)
addAction(AudioSensorManager.VOLUME_CHANGED_ACTION)
}
)

View file

@ -105,22 +105,32 @@ class SensorReceiver : SensorReceiverBase() {
// Suppress Lint because we only register for the receiver if the android version matches the intent
@SuppressLint("InlinedApi")
override val skippableActions = mapOf(
WifiManager.WIFI_STATE_CHANGED_ACTION to NetworkSensorManager.wifiState.id,
"android.app.action.NEXT_ALARM_CLOCK_CHANGED" to NextAlarmManager.nextAlarm.id,
Intent.ACTION_SCREEN_OFF to PowerSensorManager.interactiveDevice.id,
Intent.ACTION_SCREEN_ON to PowerSensorManager.interactiveDevice.id,
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED to PowerSensorManager.powerSave.id,
PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED to PowerSensorManager.doze.id,
NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED to DNDSensorManager.dndSensor.id,
AudioManager.ACTION_MICROPHONE_MUTE_CHANGED to AudioSensorManager.micMuted.id,
AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED to AudioSensorManager.speakerphoneState.id,
AudioManager.RINGER_MODE_CHANGED_ACTION to AudioSensorManager.audioSensor.id,
"com.google.android.clockwork.actions.WET_MODE_STARTED" to WetModeSensorManager.wetModeSensor.id,
"com.google.android.clockwork.actions.WET_MODE_ENDED" to WetModeSensorManager.wetModeSensor.id,
"android.bluetooth.device.action.ACL_CONNECTED" to BluetoothSensorManager.bluetoothConnection.id,
"android.bluetooth.device.action.ACL_DISCONNECTED" to BluetoothSensorManager.bluetoothConnection.id,
BluetoothAdapter.ACTION_STATE_CHANGED to BluetoothSensorManager.bluetoothState.id,
NfcAdapter.ACTION_ADAPTER_STATE_CHANGED to NfcSensorManager.nfcStateSensor.id
WifiManager.WIFI_STATE_CHANGED_ACTION to listOf(NetworkSensorManager.wifiState.id),
"android.app.action.NEXT_ALARM_CLOCK_CHANGED" to listOf(NextAlarmManager.nextAlarm.id),
Intent.ACTION_SCREEN_OFF to listOf(PowerSensorManager.interactiveDevice.id),
Intent.ACTION_SCREEN_ON to listOf(PowerSensorManager.interactiveDevice.id),
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED to listOf(PowerSensorManager.powerSave.id),
PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED to listOf(PowerSensorManager.doze.id),
NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED to listOf(DNDSensorManager.dndSensor.id),
AudioManager.ACTION_MICROPHONE_MUTE_CHANGED to listOf(AudioSensorManager.micMuted.id),
AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED to listOf(AudioSensorManager.speakerphoneState.id),
AudioManager.RINGER_MODE_CHANGED_ACTION to listOf(AudioSensorManager.audioSensor.id),
AudioSensorManager.VOLUME_CHANGED_ACTION to listOf(
AudioSensorManager.volAccessibility.id,
AudioSensorManager.volAlarm.id,
AudioSensorManager.volCall.id,
AudioSensorManager.volDTMF.id,
AudioSensorManager.volNotification.id,
AudioSensorManager.volMusic.id,
AudioSensorManager.volRing.id,
AudioSensorManager.volSystem.id
),
"com.google.android.clockwork.actions.WET_MODE_STARTED" to listOf(WetModeSensorManager.wetModeSensor.id),
"com.google.android.clockwork.actions.WET_MODE_ENDED" to listOf(WetModeSensorManager.wetModeSensor.id),
"android.bluetooth.device.action.ACL_CONNECTED" to listOf(BluetoothSensorManager.bluetoothConnection.id),
"android.bluetooth.device.action.ACL_DISCONNECTED" to listOf(BluetoothSensorManager.bluetoothConnection.id),
BluetoothAdapter.ACTION_STATE_CHANGED to listOf(BluetoothSensorManager.bluetoothState.id),
NfcAdapter.ACTION_ADAPTER_STATE_CHANGED to listOf(NfcSensorManager.nfcStateSensor.id)
)
override fun getSensorSettingsIntent(