diff --git a/app/src/gplay/java/eu/darken/capod/common/upgrade/core/billing/GplayServiceUnavailableException.kt b/app/src/gplay/java/eu/darken/capod/common/upgrade/core/billing/GplayServiceUnavailableException.kt index 84d2b841..0edf3521 100644 --- a/app/src/gplay/java/eu/darken/capod/common/upgrade/core/billing/GplayServiceUnavailableException.kt +++ b/app/src/gplay/java/eu/darken/capod/common/upgrade/core/billing/GplayServiceUnavailableException.kt @@ -10,6 +10,7 @@ import eu.darken.capod.common.debug.logging.Logging.Priority.ERROR import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.error.HasLocalizedError import eu.darken.capod.common.error.LocalizedError +import eu.darken.capod.common.debug.logging.logTag class GplayServiceUnavailableException(cause: Throwable) : BillingException("Google Play services are unavailable.", cause), HasLocalizedError { @@ -48,10 +49,11 @@ class GplayServiceUnavailableException(cause: Throwable) : ) private fun onLaunchFailed(e: Exception) { - log(ERROR) { "Can't launch settings intent for Google Play: $e" } + log(TAG, ERROR) { "Can't launch settings intent for Google Play: $e" } } companion object { private const val GPLAY_PKG = "com.android.vending" + private val TAG = logTag("Upgrade", "Gplay", "ServiceUnavailable") } } diff --git a/app/src/main/java/eu/darken/capod/common/BroadcastReceiverExtensions.kt b/app/src/main/java/eu/darken/capod/common/BroadcastReceiverExtensions.kt index 59eac05e..41a9e6b1 100644 --- a/app/src/main/java/eu/darken/capod/common/BroadcastReceiverExtensions.kt +++ b/app/src/main/java/eu/darken/capod/common/BroadcastReceiverExtensions.kt @@ -1,10 +1,13 @@ import android.content.BroadcastReceiver import eu.darken.capod.common.debug.logging.log +import eu.darken.capod.common.debug.logging.logTag fun BroadcastReceiver.PendingResult.finish2(): Boolean = try { finish() true } catch (e: IllegalStateException) { - log { "BroadcastReceiver.PendingResult.finish() failed: $e" } + log(TAG) { "BroadcastReceiver.PendingResult.finish() failed: $e" } false -} \ No newline at end of file +} + +private val TAG = logTag("Common", "BroadcastReceiver") diff --git a/app/src/main/java/eu/darken/capod/common/WebpageTool.kt b/app/src/main/java/eu/darken/capod/common/WebpageTool.kt index 3e993ef6..9620c311 100644 --- a/app/src/main/java/eu/darken/capod/common/WebpageTool.kt +++ b/app/src/main/java/eu/darken/capod/common/WebpageTool.kt @@ -9,6 +9,7 @@ import eu.darken.capod.common.debug.logging.Logging.Priority.ERROR import eu.darken.capod.common.debug.logging.asLog import eu.darken.capod.common.debug.logging.log import javax.inject.Inject +import eu.darken.capod.common.debug.logging.logTag @Reusable class WebpageTool @Inject constructor( @@ -25,9 +26,12 @@ class WebpageTool @Inject constructor( context.startActivity(intent) true } catch (e: Exception) { - log(ERROR) { "Failed to launch: ${e.asLog()}" } + log(TAG, ERROR) { "Failed to launch: ${e.asLog()}" } false } } + companion object { + private val TAG = logTag("WebpageTool") + } } \ No newline at end of file diff --git a/app/src/main/java/eu/darken/capod/common/bluetooth/BleScannerExtensions.kt b/app/src/main/java/eu/darken/capod/common/bluetooth/BleScannerExtensions.kt index 2665a83b..d3157232 100644 --- a/app/src/main/java/eu/darken/capod/common/bluetooth/BleScannerExtensions.kt +++ b/app/src/main/java/eu/darken/capod/common/bluetooth/BleScannerExtensions.kt @@ -2,6 +2,7 @@ package eu.darken.capod.common.bluetooth import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE import eu.darken.capod.common.debug.logging.log +import eu.darken.capod.common.debug.logging.logTag suspend fun Collection.onlyNewAndUnique(): List = this .groupBy { it.address } @@ -10,7 +11,9 @@ suspend fun Collection.onlyNewAndUnique(): List = // For each address we only want the newest result, upstream may batch data val newest = sameAdrDevs.maxByOrNull { it.generatedAtNanos }!! sameAdrDevs.minus(newest).let { - if (it.isNotEmpty()) log(VERBOSE) { "Discarding stale results: ${it.logSummary()}" } + if (it.isNotEmpty()) log(TAG, VERBOSE) { "Discarding stale results: ${it.logSummary()}" } } newest } + +private val TAG = logTag("Bluetooth", "Scanner") diff --git a/app/src/main/java/eu/darken/capod/common/bluetooth/BluetoothExtensions.kt b/app/src/main/java/eu/darken/capod/common/bluetooth/BluetoothExtensions.kt index 07cdf103..2365441f 100644 --- a/app/src/main/java/eu/darken/capod/common/bluetooth/BluetoothExtensions.kt +++ b/app/src/main/java/eu/darken/capod/common/bluetooth/BluetoothExtensions.kt @@ -6,6 +6,7 @@ import android.bluetooth.le.ScanResult import android.os.ParcelUuid import eu.darken.capod.common.debug.logging.asLog import eu.darken.capod.common.debug.logging.log +import eu.darken.capod.common.debug.logging.logTag fun BluetoothDevice.hasFeature(uuid: ParcelUuid): Boolean { return uuids?.contains(uuid) ?: false @@ -21,6 +22,8 @@ fun BluetoothDevice.hasFeature(uuid: ParcelUuid): Boolean { fun ScanFilter.matchesSafe(scanResult: ScanResult): Boolean = try { matches(scanResult) } catch (e: NullPointerException) { - log { "AOSP error: ${e.asLog()}" } + log(TAG) { "AOSP error: ${e.asLog()}" } false -} \ No newline at end of file +} + +private val TAG = logTag("Bluetooth", "Extensions") diff --git a/app/src/main/java/eu/darken/capod/common/datastore/DataStoreValue.kt b/app/src/main/java/eu/darken/capod/common/datastore/DataStoreValue.kt index f5b9b040..6b74bc4f 100644 --- a/app/src/main/java/eu/darken/capod/common/datastore/DataStoreValue.kt +++ b/app/src/main/java/eu/darken/capod/common/datastore/DataStoreValue.kt @@ -15,6 +15,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking +import eu.darken.capod.common.debug.logging.logTag class DataStoreValue( private val dataStore: DataStore, @@ -45,10 +46,14 @@ class DataStoreValue( prefs[key as Preferences.Key] = raw } } - log(VERBOSE) { "DataStoreValue($keyName) updated from $old to $new" } + log(TAG, VERBOSE) { "DataStoreValue($keyName) updated from $old to $new" } @Suppress("UNCHECKED_CAST") return Updated(old as T, new as T) } + + companion object { + private val TAG = logTag("DataStore", "Value") + } } suspend fun DataStoreValue.value(): T = flow.first() diff --git a/app/src/main/java/eu/darken/capod/common/debug/logging/Logging.kt b/app/src/main/java/eu/darken/capod/common/debug/logging/Logging.kt index 9ebedd7f..64b99bb7 100644 --- a/app/src/main/java/eu/darken/capod/common/debug/logging/Logging.kt +++ b/app/src/main/java/eu/darken/capod/common/debug/logging/Logging.kt @@ -34,6 +34,8 @@ object Logging { ) } + private val TAG = logTag("Logging") + private val internalLoggers = mutableListOf() val loggers: List @@ -46,11 +48,11 @@ object Logging { fun install(logger: Logger) { synchronized(internalLoggers) { internalLoggers.add(logger) } - log { "Was installed $logger" } + log(TAG) { "Was installed $logger" } } fun remove(logger: Logger) { - log { "Removing: $logger" } + log(TAG) { "Removing: $logger" } synchronized(internalLoggers) { internalLoggers.remove(logger) } } @@ -77,26 +79,11 @@ object Logging { } fun clearAll() { - log { "Clearing all loggers" } + log(TAG) { "Clearing all loggers" } synchronized(internalLoggers) { internalLoggers.clear() } } } -inline fun Any.log( - priority: Logging.Priority = Logging.Priority.DEBUG, - metaData: Map? = null, - message: () -> String, -) { - if (Logging.hasReceivers) { - Logging.logInternal( - tag = "CAP:${logTagViaCallSite()}", - priority = priority, - metaData = metaData, - message = message(), - ) - } -} - inline fun log( tag: String, priority: Logging.Priority = Logging.Priority.DEBUG, @@ -135,15 +122,3 @@ fun Throwable.asLogSummary(): String { private fun Throwable.safeMessage(): String? = runCatching { message }.getOrNull() -@PublishedApi -internal fun Any.logTagViaCallSite(): String { - val javaClass = this::class.java - val fullClassName = javaClass.name - val outerClassName = fullClassName.substringBefore('$') - val simplerOuterClassName = outerClassName.substringAfterLast('.') - return if (simplerOuterClassName.isEmpty()) { - fullClassName - } else { - simplerOuterClassName.removeSuffix("Kt") - } -} diff --git a/app/src/main/java/eu/darken/capod/common/livedata/SingleLiveEvent.kt b/app/src/main/java/eu/darken/capod/common/livedata/SingleLiveEvent.kt index 5d837703..329008d5 100644 --- a/app/src/main/java/eu/darken/capod/common/livedata/SingleLiveEvent.kt +++ b/app/src/main/java/eu/darken/capod/common/livedata/SingleLiveEvent.kt @@ -25,6 +25,7 @@ import androidx.lifecycle.Observer import eu.darken.capod.common.debug.logging.Logging.Priority.WARN import eu.darken.capod.common.debug.logging.log import java.util.concurrent.atomic.AtomicBoolean +import eu.darken.capod.common.debug.logging.logTag /** * A lifecycle-aware observable that sends only new updates after subscription, used for events like @@ -46,7 +47,7 @@ class SingleLiveEvent : MutableLiveData() { @MainThread override fun observe(owner: LifecycleOwner, observer: Observer) { if (hasActiveObservers()) { - log(WARN) { "Multiple observers registered but only one will be notified of changes." } + log(TAG, WARN) { "Multiple observers registered but only one will be notified of changes." } } // Observe the internal MutableLiveData @@ -73,4 +74,8 @@ class SingleLiveEvent : MutableLiveData() { fun call() { value = null } + + companion object { + private val TAG = logTag("SingleLiveEvent") + } } diff --git a/app/src/main/java/eu/darken/capod/common/uix/ViewModel2.kt b/app/src/main/java/eu/darken/capod/common/uix/ViewModel2.kt index 42ccdcfe..f959ca9b 100644 --- a/app/src/main/java/eu/darken/capod/common/uix/ViewModel2.kt +++ b/app/src/main/java/eu/darken/capod/common/uix/ViewModel2.kt @@ -42,7 +42,7 @@ abstract class ViewModel2( if (this is ErrorEventSource) { return CoroutineExceptionHandler { _, ex -> - log(WARN) { "Error during launch: ${ex.asLog()}" } + log(TAG, WARN) { "Error during launch: ${ex.asLog()}" } errorEvents.postValue(ex) } } diff --git a/app/src/main/java/eu/darken/capod/monitor/core/receiver/BluetoothEventReceiver.kt b/app/src/main/java/eu/darken/capod/monitor/core/receiver/BluetoothEventReceiver.kt index 0c908797..c2b33908 100644 --- a/app/src/main/java/eu/darken/capod/monitor/core/receiver/BluetoothEventReceiver.kt +++ b/app/src/main/java/eu/darken/capod/monitor/core/receiver/BluetoothEventReceiver.kt @@ -34,7 +34,7 @@ class BluetoothEventReceiver : BroadcastReceiver() { log(TAG, WARN) { "Event without Bluetooth device association." } return } else { - log { "Event related to $bluetoothDevice" } + log(TAG) { "Event related to $bluetoothDevice" } } val supportedFeatures = try { ContinuityProtocol.BLE_FEATURE_UUIDS.filter { bluetoothDevice.hasFeature(it) } @@ -47,7 +47,7 @@ class BluetoothEventReceiver : BroadcastReceiver() { log(TAG) { "Device has no features we support." } return } else { - log { "Device has the following we features we support $supportedFeatures" } + log(TAG) { "Device has the following we features we support $supportedFeatures" } } when (intent.action) { diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/DualApplePods.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/DualApplePods.kt index 4a982bfa..c4007c20 100644 --- a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/DualApplePods.kt +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/DualApplePods.kt @@ -8,6 +8,7 @@ import eu.darken.capod.pods.core.apple.ble.BATTERY_RESOLUTION_DECILE import eu.darken.capod.pods.core.apple.ble.BATTERY_RESOLUTION_PERCENT import eu.darken.capod.pods.core.apple.ble.DualBlePodSnapshot import eu.darken.capod.pods.core.apple.ble.DualBlePodSnapshot.Pod +import eu.darken.capod.common.debug.logging.logTag interface DualApplePods : ApplePods, HasChargeDetectionDual, DualBlePodSnapshot, HasEarDetectionDual, HasCase, HasDualMicrophone, HasAppleColor { @@ -38,7 +39,7 @@ interface DualApplePods : ApplePods, HasChargeDetectionDual, DualBlePodSnapshot, return when (value) { 15 -> null else -> if (value > 10) { - log { "Left pod: Above 100% battery: $value" } + log(TAG) { "Left pod: Above 100% battery: $value" } 1.0f } else { (value / 10f) @@ -59,7 +60,7 @@ interface DualApplePods : ApplePods, HasChargeDetectionDual, DualBlePodSnapshot, return when (value) { 15 -> null else -> if (value > 10) { - log { "Right pod: Above 100% battery: $value" } + log(TAG) { "Right pod: Above 100% battery: $value" } 1.0f } else { value / 10f @@ -131,7 +132,7 @@ interface DualApplePods : ApplePods, HasChargeDetectionDual, DualBlePodSnapshot, return when (val value = pubCaseBattery.toInt()) { 15 -> null else -> if (value > 10) { - log { "Case: Above 100% battery: $value" } + log(TAG) { "Case: Above 100% battery: $value" } 1.0f } else { value / 10f @@ -206,3 +207,5 @@ interface DualApplePods : ApplePods, HasChargeDetectionDual, DualBlePodSnapshot, } } + +private val TAG = logTag("Pod", "Apple", "DualApplePods") diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/SingleApplePods.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/SingleApplePods.kt index 1ae0fc3a..581bb994 100644 --- a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/SingleApplePods.kt +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/SingleApplePods.kt @@ -3,6 +3,7 @@ package eu.darken.capod.pods.core.apple.ble.devices import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.lowerNibble import eu.darken.capod.pods.core.apple.ble.SingleBlePodSnapshot +import eu.darken.capod.common.debug.logging.logTag /** * Devices that only present a single charge level, e.g. most Beats devices @@ -17,11 +18,13 @@ interface SingleApplePods : ApplePods, SingleBlePodSnapshot, HasAppleColor { return when (val value = pubPodsBattery.lowerNibble.toInt()) { 15 -> null else -> if (value > 10) { - log { "Headset above 100% battery: $value" } + log(TAG) { "Headset above 100% battery: $value" } 1.0f } else { (value / 10f) } } } -} \ No newline at end of file +} + +private val TAG = logTag("Pod", "Apple", "SingleApplePods") diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/protocol/ProximityPairing.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/protocol/ProximityPairing.kt index 8f9ecf82..4c421d40 100644 --- a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/protocol/ProximityPairing.kt +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/protocol/ProximityPairing.kt @@ -14,7 +14,7 @@ object ProximityPairing { class Decoder @Inject constructor() { fun decode(message: ContinuityProtocol.Message): ProximityMessage? { if (message.type != CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING) { - log { "Not a proximity pairing message: $this" } + log(TAG) { "Not a proximity pairing message: $message" } return null } diff --git a/app/src/main/java/eu/darken/capod/profiles/core/DeviceProfilesRepo.kt b/app/src/main/java/eu/darken/capod/profiles/core/DeviceProfilesRepo.kt index 79777df1..16d580a0 100644 --- a/app/src/main/java/eu/darken/capod/profiles/core/DeviceProfilesRepo.kt +++ b/app/src/main/java/eu/darken/capod/profiles/core/DeviceProfilesRepo.kt @@ -141,7 +141,7 @@ class DeviceProfilesRepo @Inject constructor( if (addFirst) add(0, profile) else add(profile) }.toList() settings.profiles.valueBlocking = DeviceProfilesContainer(updatedProfiles) - log(VERBOSE) { "Added device profile: ${profile.label}" } + log(TAG, VERBOSE) { "Added device profile: ${profile.label}" } } suspend fun updateProfile(profile: DeviceProfile) = mutex.withLock { @@ -152,7 +152,7 @@ class DeviceProfilesRepo @Inject constructor( if (it.id == profile.id) profile else it } settings.profiles.valueBlocking = DeviceProfilesContainer(updatedProfiles) - log(VERBOSE) { "Updated device profile: ${profile.label}" } + log(TAG, VERBOSE) { "Updated device profile: ${profile.label}" } } /** @@ -176,14 +176,14 @@ class DeviceProfilesRepo @Inject constructor( checkAddressUniqueness(updated, otherProfiles) val updatedProfiles = currentContainer.profiles.map { if (it.id == id) updated else it } settings.profiles.valueBlocking = DeviceProfilesContainer(updatedProfiles) - log(VERBOSE) { "Updated apple device profile: ${updated.label}" } + log(TAG, VERBOSE) { "Updated apple device profile: ${updated.label}" } } suspend fun removeProfile(profileId: ProfileId) = mutex.withLock { val currentContainer = settings.profiles.valueBlocking val updatedProfiles = currentContainer.profiles.filter { it.id != profileId } settings.profiles.valueBlocking = DeviceProfilesContainer(updatedProfiles) - log(VERBOSE) { "Removed device profile with ID: $profileId" } + log(TAG, VERBOSE) { "Removed device profile with ID: $profileId" } deviceStateCache.delete(profileId) batteryDrainStore.delete(profileId) } @@ -196,7 +196,7 @@ class DeviceProfilesRepo @Inject constructor( val byId = current.associateBy { it.id } val reordered = orderedIds.map { byId.getValue(it) } settings.profiles.valueBlocking = DeviceProfilesContainer(reordered) - log(VERBOSE) { "Reordered ${reordered.size} device profiles by ID" } + log(TAG, VERBOSE) { "Reordered ${reordered.size} device profiles by ID" } } suspend fun clear() = mutex.withLock {