diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ae30f332c..bbf50fb14 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -15,6 +15,7 @@
+
diff --git a/app/src/main/java/io/homeassistant/companion/android/sensors/PhoneStateSensorManager.kt b/app/src/main/java/io/homeassistant/companion/android/sensors/PhoneStateSensorManager.kt
index 19095c3d4..8e65c0b24 100644
--- a/app/src/main/java/io/homeassistant/companion/android/sensors/PhoneStateSensorManager.kt
+++ b/app/src/main/java/io/homeassistant/companion/android/sensors/PhoneStateSensorManager.kt
@@ -2,6 +2,7 @@ package io.homeassistant.companion.android.sensors
import android.Manifest
import android.content.Context
+import android.content.Intent
import android.os.Build
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
@@ -19,6 +20,13 @@ class PhoneStateSensorManager : SensorManager {
R.string.sensor_description_phone_state
)
+ val callNumber = SensorManager.BasicSensor(
+ "call_number",
+ "sensor",
+ R.string.basic_sensor_name_call_number,
+ R.string.sensor_description_call_number
+ )
+
val sim_1 = SensorManager.BasicSensor(
"sim_1",
"sensor",
@@ -41,49 +49,77 @@ class PhoneStateSensorManager : SensorManager {
override val availableSensors: List
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1)
- listOf(phoneState, sim_1, sim_2)
- else listOf(phoneState)
+ listOf(phoneState, callNumber, sim_1, sim_2)
+ else listOf(phoneState, callNumber)
override fun requiredPermissions(sensorId: String): Array {
- return arrayOf(Manifest.permission.READ_PHONE_STATE)
+ return if (sensorId == callNumber.id) {
+ arrayOf(Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_CALL_LOG)
+ } else arrayOf(Manifest.permission.READ_PHONE_STATE)
}
override fun requestSensorUpdate(
context: Context
) {
- updatePhoneStateSensor(context)
+ checkPhoneState(context)
updateSimSensor(context, 0)
updateSimSensor(context, 1)
}
- private fun updatePhoneStateSensor(context: Context) {
- if (!isEnabled(context, phoneState.id))
- return
- var currentPhoneState = "unavailable"
- if (checkPermission(context, phoneState.id)) {
- val telephonyManager =
- (context.applicationContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager)
+ private fun checkPhoneState(context: Context) {
+ if (isEnabled(context, phoneState.id) || isEnabled(context, callNumber.id)) {
+ var currentPhoneState = "unknown"
- currentPhoneState = when (telephonyManager.callState) {
- 0 -> "idle"
- 1 -> "ringing"
- 2 -> "offhook"
- else -> "unknown"
+ if (checkPermission(context, phoneState.id)) {
+ val telephonyManager =
+ (context.applicationContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager)
+
+ currentPhoneState = when (telephonyManager.callState) {
+ 0 -> "idle"
+ 1 -> "ringing"
+ 2 -> "offhook"
+ else -> "unknown"
+ }
}
- }
+ if (isEnabled(context, phoneState.id))
+ updatePhoneStateSensor(context, currentPhoneState)
+ if (isEnabled(context, callNumber.id) && currentPhoneState in arrayOf("idle", "unknown"))
+ updateCallNumberSensor(context, "none")
+ }
+ }
+
+ private fun updatePhoneStateSensor(context: Context, state: String) {
var phoneIcon = "mdi:phone"
- if (currentPhoneState == "ringing" || currentPhoneState == "offhook")
+ if (state == "ringing" || state == "offhook")
phoneIcon += "-in-talk"
onSensorUpdated(context,
phoneState,
- currentPhoneState,
+ state,
phoneIcon,
mapOf()
)
}
+ fun updateCallNumber(context: Context, intent: Intent) {
+ if (checkPermission(context, callNumber.id)) {
+ if (intent.hasExtra(TelephonyManager.EXTRA_INCOMING_NUMBER)) {
+ val number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER)
+ updateCallNumberSensor(context, number)
+ }
+ }
+ }
+
+ private fun updateCallNumberSensor(context: Context, number: String) {
+ onSensorUpdated(context,
+ callNumber,
+ number,
+ "mdi:numeric",
+ mapOf()
+ )
+ }
+
private fun updateSimSensor(context: Context, slotIndex: Int) {
val basicSimSensor = when (slotIndex) {
0 -> sim_1
@@ -110,7 +146,7 @@ class PhoneStateSensorManager : SensorManager {
attrs["mcc"] = info.mccString.toString()
attrs["mnc"] = info.mncString.toString()
attrs["is opportunistic"] = info.isOpportunistic
- if (info.dataRoaming == SubscriptionManager.DATA_ROAMING_ENABLE) attrs["data roaming"] = "enable"
+ if (info.dataRoaming == SubscriptionManager.DATA_ROAMING_ENABLE) attrs["data roaming"] = "enable"
else attrs["data roaming"] = "disable"
}
}
diff --git a/app/src/main/java/io/homeassistant/companion/android/sensors/SensorReceiver.kt b/app/src/main/java/io/homeassistant/companion/android/sensors/SensorReceiver.kt
index 9fcea0f6d..902dfc72d 100644
--- a/app/src/main/java/io/homeassistant/companion/android/sensors/SensorReceiver.kt
+++ b/app/src/main/java/io/homeassistant/companion/android/sensors/SensorReceiver.kt
@@ -4,6 +4,7 @@ import android.bluetooth.BluetoothAdapter
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
+import android.telephony.TelephonyManager
import android.util.Log
import io.homeassistant.companion.android.common.dagger.GraphComponentAccessor
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
@@ -57,6 +58,13 @@ class SensorReceiver : BroadcastReceiver() {
Intent.ACTION_POWER_DISCONNECTED
)
+ private 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,
+ BluetoothAdapter.ACTION_STATE_CHANGED to BluetoothSensorManager.bluetoothState.id
+ )
+
override fun onReceive(context: Context, intent: Intent) {
DaggerSensorComponent.builder()
@@ -64,34 +72,20 @@ class SensorReceiver : BroadcastReceiver() {
.build()
.inject(this)
- when (intent.action) {
- "android.app.action.NEXT_ALARM_CLOCK_CHANGED" -> {
- val sensorDao = AppDatabase.getInstance(context).sensorDao()
- val sensor = sensorDao.get(NextAlarmManager.nextAlarm.id)
- if (sensor?.enabled != true) {
- Log.d(TAG, "Alarm Sensor disabled, skipping sensors update")
- return
- }
- }
- "android.bluetooth.device.action.ACL_CONNECTED",
- "android.bluetooth.device.action.ACL_DISCONNECTED" -> {
- val sensorDao = AppDatabase.getInstance(context).sensorDao()
- val sensorBtConn = sensorDao.get(BluetoothSensorManager.bluetoothConnection.id)
- if (sensorBtConn?.enabled != true) {
- Log.d(TAG, "Bluetooth Connection Sensor disabled, skipping sensors update")
- return
- }
- }
- BluetoothAdapter.ACTION_STATE_CHANGED -> {
- val sensorDao = AppDatabase.getInstance(context).sensorDao()
- val sensorBtState = sensorDao.get(BluetoothSensorManager.bluetoothState.id)
- if (sensorBtState?.enabled != true) {
- Log.d(TAG, "Bluetooth State Sensor disabled, skipping sensors update")
- return
- }
+ if (skippableActions.containsKey(intent.action)) {
+ val sensor = skippableActions[intent.action]
+ if (!isSensorEnabled(context, sensor!!)) {
+ Log.d(TAG, String.format
+ ("Sensor %s corresponding to received event %s is disabled, skipping sensors update", sensor, intent.action))
+ return
}
}
+ if (intent.action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED) &&
+ isSensorEnabled(context, PhoneStateSensorManager.callNumber.id)) {
+ PhoneStateSensorManager().updateCallNumber(context, intent)
+ }
+
ioScope.launch {
updateSensors(context, integrationUseCase)
if (chargingActions.contains(intent.action)) {
@@ -103,6 +97,10 @@ class SensorReceiver : BroadcastReceiver() {
}
}
+ private fun isSensorEnabled(context: Context, id: String): Boolean {
+ return AppDatabase.getInstance(context).sensorDao().get(id)?.enabled == true
+ }
+
suspend fun updateSensors(
context: Context,
integrationUseCase: IntegrationRepository
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f8efa9be1..fa8c049b9 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -28,6 +28,7 @@
Battery State
Bluetooth Connection
Bluetooth State
+ Call Number
Charger Type
Is Charging
Doze Mode
@@ -185,6 +186,7 @@ like to connect to:
The current charging state of the battery
Information about currently connected bluetooth devices
Whether or not bluetooth is enabled on the device
+ The cell number of the incoming or outgoing call
The type of charger plugged into the device currently
Whether or not the device is actively charging
The current activity type as computed by Googles Activity Recognition API