Notification sensors: make arrays and bundles within main bundle readable (#2482)

* Notification sensors: convert extra bundle arrays to lists

 - If the notification extras contain any arrays, convert them to lists because when stringified, this will create a human readable text like "[Message 1, Message 2]" instead of something like "[Ljava.lang.String;@5d099f62"

* Convert BaseBundle arrays to lists as well

 - Include array types that are in the superclass BaseBundle as well when converting values to a list
 - Moved to another function to limit duplicated code

* Map bundles within a notification's bundle as well

 - Also map any bundles we find inside a bundle, or if there is an array of bundles, to make this information readable as well
This commit is contained in:
Joris Pelgröm 2022-04-30 13:53:30 +02:00 committed by GitHub
parent b418491667
commit 13a747fdb9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -8,6 +8,7 @@ import android.content.res.Configuration
import android.media.MediaMetadata
import android.media.session.MediaSessionManager
import android.media.session.PlaybackState
import android.os.Bundle
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
@ -132,9 +133,7 @@ class NotificationSensorManager : NotificationListenerService(), SensorManager {
return
}
val attr = sbn.notification.extras.keySet()
.map { it to sbn.notification.extras.get(it) }
.toMap()
val attr = mappedBundle(sbn.notification.extras)
.plus("package" to sbn.packageName)
.plus("post_time" to sbn.postTime)
.plus("is_clearable" to sbn.isClearable)
@ -185,9 +184,7 @@ class NotificationSensorManager : NotificationListenerService(), SensorManager {
return
}
val attr = sbn.notification.extras.keySet()
.map { it to sbn.notification.extras.get(it) }
.toMap()
val attr = mappedBundle(sbn.notification.extras)
.plus("package" to sbn.packageName)
.plus("post_time" to sbn.postTime)
.plus("is_clearable" to sbn.isClearable)
@ -215,9 +212,7 @@ class NotificationSensorManager : NotificationListenerService(), SensorManager {
try {
val attr: MutableMap<String, Any?> = mutableMapOf()
for (item in activeNotifications) {
attr += item.notification.extras.keySet()
.map { it + "_" + item.packageName to item.notification.extras.get(it) }
.toMap()
attr += mappedBundle(item.notification.extras, "_${item.packageName}")
.plus(item.packageName + "_" + item.id + "_post_time" to item.postTime)
.plus(item.packageName + "_" + item.id + "_is_ongoing" to item.isOngoing)
.plus(item.packageName + "_" + item.id + "_is_clearable" to item.isClearable)
@ -283,4 +278,31 @@ class NotificationSensorManager : NotificationListenerService(), SensorManager {
else -> "Unknown"
}
}
/**
* Returns the values of a bundle as a key/value map for use as a sensor's attributes.
* Arrays are converted to lists to make them human readable.
* Bundles inside the given bundle will also be mapped as a key/value map.
*/
private fun mappedBundle(bundle: Bundle, keySuffix: String = ""): Map<String, Any?> {
return bundle.keySet().associate { key ->
val keyValue = when (val value = bundle.get(key)) {
is Array<*> -> {
if (value.all { it is Bundle }) value.map { mappedBundle(it as Bundle) }
else value.toList()
}
is BooleanArray -> value.toList()
is Bundle -> mappedBundle(value)
is ByteArray -> value.toList()
is CharArray -> value.toList()
is DoubleArray -> value.toList()
is FloatArray -> value.toList()
is IntArray -> value.toList()
is LongArray -> value.toList()
is ShortArray -> value.toList()
else -> value
}
"${key}$keySuffix" to keyValue
}
}
}