Add commands to control screen brightness and a sensor to get its value (#2894)

* Add commands to control screen brightness and a sensor to get the value

* Minor file clean up

* Review comments

* Rename Device Settings to Display Sensors
This commit is contained in:
Daniel Shokouhi 2022-10-01 13:09:01 -07:00 committed by GitHub
parent 070a839b74
commit 1a5776371e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 145 additions and 1 deletions

View file

@ -40,6 +40,8 @@
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions"/>
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
<uses-feature android:name="android.hardware.telephony" android:required="false"/>

View file

@ -167,6 +167,8 @@ class MessagingManager @Inject constructor(
const val COMMAND_LAUNCH_APP = "command_launch_app"
const val COMMAND_PERSISTENT_CONNECTION = "command_persistent_connection"
const val COMMAND_STOP_TTS = "command_stop_tts"
const val COMMAND_AUTO_SCREEN_BRIGHTNESS = "command_auto_screen_brightness"
const val COMMAND_SCREEN_BRIGHTNESS_LEVEL = "command_screen_brightness_level"
// DND commands
const val DND_PRIORITY_ONLY = "priority_only"
@ -243,7 +245,9 @@ class MessagingManager @Inject constructor(
COMMAND_UPDATE_SENSORS,
COMMAND_LAUNCH_APP,
COMMAND_PERSISTENT_CONNECTION,
COMMAND_STOP_TTS
COMMAND_STOP_TTS,
COMMAND_AUTO_SCREEN_BRIGHTNESS,
COMMAND_SCREEN_BRIGHTNESS_LEVEL
)
val DND_COMMANDS = listOf(DND_ALARMS_ONLY, DND_ALL, DND_NONE, DND_PRIORITY_ONLY)
val RM_COMMANDS = listOf(RM_NORMAL, RM_SILENT, RM_VIBRATE)
@ -529,6 +533,22 @@ class MessagingManager @Inject constructor(
}
}
COMMAND_STOP_TTS -> handleDeviceCommands(jsonData)
COMMAND_AUTO_SCREEN_BRIGHTNESS -> {
if (!jsonData[COMMAND].isNullOrEmpty() && jsonData[COMMAND] in ENABLE_COMMANDS)
handleDeviceCommands(jsonData)
else
mainScope.launch {
sendNotification(jsonData)
}
}
COMMAND_SCREEN_BRIGHTNESS_LEVEL -> {
if (!jsonData[COMMAND].isNullOrEmpty() && jsonData[COMMAND]?.toIntOrNull() != null)
handleDeviceCommands(jsonData)
else
mainScope.launch {
sendNotification(jsonData)
}
}
else -> Log.d(TAG, "No command received")
}
}
@ -894,6 +914,16 @@ class MessagingManager @Inject constructor(
COMMAND_STOP_TTS -> {
stopTTS()
}
COMMAND_AUTO_SCREEN_BRIGHTNESS, COMMAND_SCREEN_BRIGHTNESS_LEVEL -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.System.canWrite(context)) {
if (!processScreenBrightness(data))
mainScope.launch { sendNotification(data) }
} else
notifyMissingPermission(data[MESSAGE].toString())
} else if (!processScreenBrightness(data))
mainScope.launch { sendNotification(data) }
}
else -> Log.d(TAG, "No command received")
}
}
@ -1790,6 +1820,14 @@ class MessagingManager @Inject constructor(
context.startActivity(intent)
}
@RequiresApi(Build.VERSION_CODES.M)
private fun requestWriteSystemPermission() {
val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
intent.data = Uri.parse("package:" + context.packageName)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
}
private fun getKeyEvent(key: String): Int {
return when (key) {
MEDIA_FAST_FORWARD -> KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
@ -1996,6 +2034,27 @@ class MessagingManager @Inject constructor(
WebsocketManager.start(context)
}
private fun processScreenBrightness(data: Map<String, String>): Boolean {
val command = data[COMMAND]
val contentResolver = context.contentResolver
val success = Settings.System.putInt(
contentResolver,
if (data[MESSAGE].toString() == COMMAND_SCREEN_BRIGHTNESS_LEVEL)
Settings.System.SCREEN_BRIGHTNESS
else
Settings.System.SCREEN_BRIGHTNESS_MODE,
if (data[MESSAGE].toString() == COMMAND_SCREEN_BRIGHTNESS_LEVEL)
command!!.toInt().coerceIn(0, 255)
else {
if (command == TURN_ON)
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC
else
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL
}
)
return success
}
private fun notifyMissingPermission(type: String) {
val appManager =
context.getSystemService<ActivityManager>()
@ -2030,6 +2089,11 @@ class MessagingManager @Inject constructor(
}
navigateAppDetails()
}
COMMAND_SCREEN_BRIGHTNESS_LEVEL, COMMAND_AUTO_SCREEN_BRIGHTNESS -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestWriteSystemPermission()
}
}
}
}
}

View file

@ -0,0 +1,74 @@
package io.homeassistant.companion.android.sensors
import android.content.Context
import android.provider.Settings
import android.util.Log
import io.homeassistant.companion.android.common.sensors.SensorManager
import io.homeassistant.companion.android.common.R as commonR
class DisplaySensorManager : SensorManager {
companion object {
private const val TAG = "ScreenBrightness"
val screenBrightness = SensorManager.BasicSensor(
"screen_brightness",
"sensor",
commonR.string.basic_sensor_name_screen_brightness,
commonR.string.sensor_description_screen_brightness,
statelessIcon = "mdi:brightness-6"
)
}
override fun docsLink(): String {
return "https://companion.home-assistant.io/docs/core/sensors#screen-brightness-sensor"
}
override val enabledByDefault: Boolean
get() = false
override val name: Int
get() = commonR.string.sensor_name_display_sensors
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
return listOf(screenBrightness)
}
override fun requiredPermissions(sensorId: String): Array<String> {
return emptyArray()
}
override fun requestSensorUpdate(
context: Context
) {
updateScreenBrightness(context)
}
private fun updateScreenBrightness(context: Context) {
if (!isEnabled(context, screenBrightness.id))
return
var brightness = 0
var auto = false
try {
brightness =
Settings.System.getInt(context.contentResolver, Settings.System.SCREEN_BRIGHTNESS)
auto = Settings.System.getInt(
context.contentResolver,
Settings.System.SCREEN_BRIGHTNESS_MODE
) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC
} catch (e: Exception) {
Log.e(TAG, "Unable to get screen brightness settings", e)
}
val icon = if (auto) "mdi:brightness-auto" else screenBrightness.statelessIcon
onSensorUpdated(
context,
screenBrightness,
brightness,
icon,
mapOf(
"automatic" to auto
)
)
}
}

View file

@ -37,6 +37,7 @@ class SensorReceiver : SensorReceiverBase() {
AudioSensorManager(),
BatterySensorManager(),
BluetoothSensorManager(),
DisplaySensorManager(),
DNDSensorManager(),
DynamicColorSensorManager(),
DevicePolicyManager(),

View file

@ -919,4 +919,7 @@
<string name="sensor_name_accent_color_sensor">Accent Color</string>
<string name="sensor_description_accent_color_sensor">A hexadecimal color value for the dynamic accent color used in the device theme</string>
<string name="sensor_name_dynamic_color">Dynamic Color</string>
<string name="basic_sensor_name_screen_brightness">Screen Brightness</string>
<string name="sensor_description_screen_brightness">The current screen brightness on the device, an attribute also indicates if auto-brightness is enabled</string>
<string name="sensor_name_display_sensors">Display Sensors</string>
</resources>