Skip to content

Commit

Permalink
Make volume sensors update instantly by subscribing to a broadcast (#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
marazmarci authored Feb 2, 2024
1 parent 471f7de commit c185b87
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit c185b87

Please sign in to comment.