diff --git a/android/app/build.gradle b/android/app/build.gradle index 92159109..d1d735d0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -105,6 +105,8 @@ dependencies { implementation 'com.google.android.material:material:1.9.0' + implementation 'com.github.tony19:logback-android:3.0.0' + // testing dependencies testImplementation "junit:junit:$project.junitVersion" testImplementation "org.mockito:mockito-core:$project.mockitoVersion" diff --git a/android/app/src/main/assets/logback.xml b/android/app/src/main/assets/logback.xml new file mode 100644 index 00000000..2d8d6982 --- /dev/null +++ b/android/app/src/main/assets/logback.xml @@ -0,0 +1,31 @@ + + + + + + + %msg + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/AppContext.kt b/android/app/src/main/kotlin/com/yubico/authenticator/AppContext.kt index 71a9a413..2106df02 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/AppContext.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/AppContext.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2023 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,18 @@ package com.yubico.authenticator -import com.yubico.authenticator.logging.Log import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodChannel + import kotlinx.coroutines.CoroutineScope +import org.slf4j.LoggerFactory + class AppContext(messenger: BinaryMessenger, coroutineScope: CoroutineScope, private val appViewModel: MainViewModel) { private val channel = MethodChannel(messenger, "android.state.appContext") + private val logger = LoggerFactory.getLogger(AppContext::class.java) + init { channel.setHandler(coroutineScope) { method, args -> when (method) { @@ -36,11 +40,7 @@ class AppContext(messenger: BinaryMessenger, coroutineScope: CoroutineScope, pri private suspend fun setContext(subPageIndex: Int): String { val appContext = OperationContext.getByValue(subPageIndex) appViewModel.setAppContext(appContext) - Log.d(TAG, "App context is now $appContext") + logger.debug("App context is now {}", appContext) return NULL } - - companion object { - const val TAG = "appContext" - } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/AppPreferences.kt b/android/app/src/main/kotlin/com/yubico/authenticator/AppPreferences.kt index e5afc9c7..fd063b14 100755 --- a/android/app/src/main/kotlin/com/yubico/authenticator/AppPreferences.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/AppPreferences.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2023 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,8 @@ package com.yubico.authenticator import android.content.Context import android.content.SharedPreferences import android.content.SharedPreferences.OnSharedPreferenceChangeListener -import com.yubico.authenticator.logging.Log + +import org.slf4j.LoggerFactory class AppPreferences(context: Context) { companion object { @@ -32,15 +33,15 @@ class AppPreferences(context: Context) { const val PREF_CLIP_KBD_LAYOUT = "flutter.prefClipKbdLayout" const val DEFAULT_CLIP_KBD_LAYOUT = "US" - - const val TAG = "AppPreferences" } + private val logger = LoggerFactory.getLogger(AppPreferences::class.java) + private val prefs: SharedPreferences = context.getSharedPreferences(PREFS_FILE, Context.MODE_PRIVATE).also { - Log.d(TAG, "Current app preferences:") + logger.debug("Current app preferences:") it.all.map { preference -> - Log.d(TAG, "${preference.key}: ${preference.value}") + logger.debug("{}: {}", preference.key, preference.value) } } @@ -66,12 +67,12 @@ class AppPreferences(context: Context) { get() = prefs.getBoolean(PREF_USB_OPEN_APP, false) fun registerListener(listener: OnSharedPreferenceChangeListener) { - Log.d(TAG, "registering change listener") + logger.debug("registering change listener") prefs.registerOnSharedPreferenceChangeListener(listener) } fun unregisterListener(listener: OnSharedPreferenceChangeListener) { prefs.unregisterOnSharedPreferenceChangeListener(listener) - Log.d(TAG, "unregistered change listener") + logger.debug("unregistered change listener") } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/ClipboardUtil.kt b/android/app/src/main/kotlin/com/yubico/authenticator/ClipboardUtil.kt index 1121b0f5..3feff47e 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/ClipboardUtil.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/ClipboardUtil.kt @@ -23,11 +23,12 @@ import android.content.ClipboardManager import android.content.Context import android.os.Build import android.os.PersistableBundle -import com.yubico.authenticator.logging.Log + +import org.slf4j.LoggerFactory object ClipboardUtil { - private const val TAG = "ClipboardUtil" + private val logger = LoggerFactory.getLogger(ClipboardUtil::class.java) fun setPrimaryClip(context: Context, toClipboard: String, isSensitive: Boolean) { try { @@ -41,7 +42,7 @@ object ClipboardUtil { clipboardManager.setPrimaryClip(clipData) } catch (e: Exception) { - Log.e(TAG, "Failed to set string to clipboard", e.stackTraceToString()) + logger.error( "Failed to set string to clipboard", e) throw UnsupportedOperationException() } } diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/DialogManager.kt b/android/app/src/main/kotlin/com/yubico/authenticator/DialogManager.kt index 0e001c5b..49e8214f 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/DialogManager.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/DialogManager.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2023 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -91,8 +91,4 @@ class DialogManager(messenger: BinaryMessenger, private val coroutineScope: Coro } return NULL } - - companion object { - const val TAG = "dialogManager" - } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt b/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt index 78a7d6c4..173eb214 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt @@ -39,7 +39,6 @@ import androidx.core.content.ContextCompat import androidx.core.view.WindowCompat import androidx.lifecycle.lifecycleScope import com.yubico.authenticator.logging.FlutterLog -import com.yubico.authenticator.logging.Log import com.yubico.authenticator.oath.AppLinkMethodChannel import com.yubico.authenticator.oath.OathManager import com.yubico.authenticator.oath.OathViewModel @@ -48,7 +47,6 @@ import com.yubico.yubikit.android.transport.nfc.NfcConfiguration import com.yubico.yubikit.android.transport.nfc.NfcNotAvailable import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyDevice import com.yubico.yubikit.android.transport.usb.UsbConfiguration -import com.yubico.yubikit.core.Logger import com.yubico.yubikit.core.YubiKeyDevice import io.flutter.embedding.android.FlutterFragmentActivity import io.flutter.embedding.engine.FlutterEngine @@ -56,6 +54,7 @@ import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodChannel import kotlinx.coroutines.launch import org.json.JSONObject +import org.slf4j.LoggerFactory import java.io.Closeable import java.util.concurrent.Executors @@ -73,6 +72,8 @@ class MainActivity : FlutterFragmentActivity() { private val qrScannerCameraClosedBR = QRScannerCameraClosedBR() private val nfcAdapterStateChangeBR = NfcAdapterStateChangedBR() + private val logger = LoggerFactory.getLogger(MainActivity::class.java) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -85,8 +86,6 @@ class MainActivity : FlutterFragmentActivity() { allowScreenshots(false) yubikit = YubiKitManager(this) - - setupYubiKitLogger() } /** @@ -117,7 +116,7 @@ class MainActivity : FlutterFragmentActivity() { private fun startNfcDiscovery() = try { - Log.d(TAG, "Starting nfc discovery") + logger.debug("Starting nfc discovery") yubikit.startNfcDiscovery( nfcConfiguration.disableNfcDiscoverySound(appPreferences.silenceNfcSounds), this, @@ -131,16 +130,16 @@ class MainActivity : FlutterFragmentActivity() { private fun stopNfcDiscovery() { if (hasNfc) { yubikit.stopNfcDiscovery(this) - Log.d(TAG, "Stopped nfc discovery") + logger.debug("Stopped nfc discovery") } } private fun startUsbDiscovery() { - Log.d(TAG, "Starting usb discovery") + logger.debug("Starting usb discovery") val usbConfiguration = UsbConfiguration().handlePermissions(true) yubikit.startUsbDiscovery(usbConfiguration) { device -> viewModel.setConnectedYubiKey(device) { - Log.d(TAG, "YubiKey was disconnected, stopping usb discovery") + logger.debug("YubiKey was disconnected, stopping usb discovery") stopUsbDiscovery() } processYubiKey(device) @@ -149,22 +148,7 @@ class MainActivity : FlutterFragmentActivity() { private fun stopUsbDiscovery() { yubikit.stopUsbDiscovery() - Log.d(TAG, "Stopped usb discovery") - } - - private fun setupYubiKitLogger() { - Logger.setLogger(object : Logger() { - private val TAG = "yubikit" - - override fun logDebug(message: String) { - // redirect yubikit debug logs to traffic - Log.t(TAG, message) - } - - override fun logError(message: String, throwable: Throwable) { - Log.e(TAG, message, throwable.message ?: throwable.toString()) - } - }) + logger.debug("Stopped usb discovery") } @SuppressLint("WrongConstant") @@ -230,7 +214,7 @@ class MainActivity : FlutterFragmentActivity() { startNfcDiscovery() } } catch (e: Throwable) { - Log.e(TAG, "Error processing YubiKey in AppContextManager", e.toString()) + logger.error("Error processing YubiKey in AppContextManager", e) } } } else { @@ -280,7 +264,7 @@ class MainActivity : FlutterFragmentActivity() { try { it.processYubiKey(device) } catch (e: Throwable) { - Log.e(TAG, "Error processing YubiKey in AppContextManager", e.toString()) + logger.error("Error processing YubiKey in AppContextManager", e) } } } @@ -336,7 +320,6 @@ class MainActivity : FlutterFragmentActivity() { } companion object { - const val TAG = "MainActivity" const val YUBICO_VENDOR_ID = 4176 const val FLAG_SECURE = WindowManager.LayoutParams.FLAG_SECURE } @@ -363,6 +346,9 @@ class MainActivity : FlutterFragmentActivity() { } class NfcAdapterStateChangedBR : BroadcastReceiver() { + + private val logger = LoggerFactory.getLogger(NfcAdapterStateChangedBR::class.java) + companion object { val intentFilter = IntentFilter("android.nfc.action.ADAPTER_STATE_CHANGED") } @@ -370,7 +356,7 @@ class MainActivity : FlutterFragmentActivity() { override fun onReceive(context: Context?, intent: Intent?) { intent?.let { val state = it.getIntExtra("android.nfc.extra.ADAPTER_STATE", 0) - Log.d(TAG, "NfcAdapter state changed to $state") + logger.debug("NfcAdapter state changed to {}", state) if (state == STATE_ON || state == STATE_TURNING_OFF) { (context as? MainActivity)?.appMethodChannel?.nfcAdapterStateChanged(state == STATE_ON) } @@ -430,7 +416,7 @@ class MainActivity : FlutterFragmentActivity() { startActivity(Intent(ACTION_NFC_SETTINGS)) result.success(true) } - else -> Log.w(TAG, "Unknown app method: ${methodCall.method}") + else -> logger.warn("Unknown app method: {}", methodCall.method) } } } @@ -446,10 +432,10 @@ class MainActivity : FlutterFragmentActivity() { private fun allowScreenshots(value: Boolean): Boolean { // Note that FLAG_SECURE is the inverse of allowScreenshots if (value) { - Log.d(TAG, "Clearing FLAG_SECURE (allow screenshots)") + logger.debug("Clearing FLAG_SECURE (allow screenshots)") window.clearFlags(FLAG_SECURE) } else { - Log.d(TAG, "Setting FLAG_SECURE (disallow screenshots)") + logger.debug("Setting FLAG_SECURE (disallow screenshots)") window.setFlags(FLAG_SECURE, FLAG_SECURE) } diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/NdefActivity.kt b/android/app/src/main/kotlin/com/yubico/authenticator/NdefActivity.kt index 47c5ece5..662150f6 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/NdefActivity.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/NdefActivity.kt @@ -24,9 +24,12 @@ import android.nfc.Tag import android.os.Build import android.os.Bundle import android.widget.Toast -import com.yubico.authenticator.logging.Log + import com.yubico.authenticator.ndef.KeyboardLayout import com.yubico.yubikit.core.util.NdefUtils + +import org.slf4j.LoggerFactory + import java.nio.charset.StandardCharsets typealias ResourceId = Int @@ -34,6 +37,8 @@ typealias ResourceId = Int class NdefActivity : Activity() { private lateinit var appPreferences: AppPreferences + private val logger = LoggerFactory.getLogger(NdefActivity::class.java) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) appPreferences = AppPreferences(this) @@ -68,10 +73,9 @@ class NdefActivity : Activity() { } } catch (illegalArgumentException: IllegalArgumentException) { - Log.e( - TAG, + logger.error( illegalArgumentException.message ?: "Failure when handling YubiKey OTP", - illegalArgumentException.stackTraceToString() + illegalArgumentException ) showToast(R.string.otp_parse_failure, Toast.LENGTH_LONG) } catch (_: UnsupportedOperationException) { @@ -111,10 +115,6 @@ class NdefActivity : Activity() { } } - companion object { - const val TAG = "YubicoAuthenticatorOTPActivity" - } - enum class OtpType { Otp, Password } diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/logging/Log.kt b/android/app/src/main/kotlin/com/yubico/authenticator/logging/Log.kt index 5d33e0e9..ce11c8a4 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/logging/Log.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/logging/Log.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2023 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,16 @@ package com.yubico.authenticator.logging -import android.util.Log +import ch.qos.logback.classic.Level import com.yubico.authenticator.BuildConfig +import org.slf4j.Logger +import org.slf4j.LoggerFactory + object Log { + private val logger = LoggerFactory.getLogger("com.yubico.authenticator") + enum class LogLevel { TRAFFIC, DEBUG, @@ -42,34 +47,10 @@ object Log { LogLevel.INFO } - private const val TAG = "yubico-authenticator" - - @Suppress("unused") - fun t(tag: String, message: String, error: String? = null) { - log(LogLevel.TRAFFIC, tag, message, error) + init { + setLevel(level) } - @Suppress("unused") - fun d(tag: String, message: String, error: String? = null) { - log(LogLevel.DEBUG, tag, message, error) - } - - @Suppress("unused") - fun i(tag: String, message: String, error: String? = null) { - log(LogLevel.INFO, tag, message, error) - } - - @Suppress("unused") - fun w(tag: String, message: String, error: String? = null) { - log(LogLevel.WARNING, tag, message, error) - } - - @Suppress("unused") - fun e(tag: String, message: String, error: String? = null) { - log(LogLevel.ERROR, tag, message, error) - } - - @Suppress("unused") fun log(level: LogLevel, loggerName: String, message: String, error: String?) { if (level < this.level) { return @@ -79,27 +60,33 @@ object Log { buffer.removeAt(0) } - val logMessage = "[$loggerName] ${level.name}: $message".also { - buffer.add(it) - } + val logMessage = (if (error == null) + "[$loggerName] ${level.name}: $message" + else + "[$loggerName] ${level.name}: $message (err: $error)" + ).also { + buffer.add(it) + } when (level) { - LogLevel.TRAFFIC -> Log.v(TAG, logMessage) - LogLevel.DEBUG -> Log.d(TAG, logMessage) - LogLevel.INFO -> Log.i(TAG, logMessage) - LogLevel.WARNING -> Log.w(TAG, logMessage) - LogLevel.ERROR -> Log.e(TAG, logMessage) - } - - error?.let { - Log.e(TAG, "[$loggerName] ${level.name}(details): $error".also { - buffer.add(it) - }) + LogLevel.TRAFFIC -> logger.trace(logMessage) + LogLevel.DEBUG -> logger.debug(logMessage) + LogLevel.INFO -> logger.info(logMessage) + LogLevel.WARNING -> logger.warn(logMessage) + LogLevel.ERROR -> logger.error(logMessage) } } - @Suppress("unused") fun setLevel(newLevel: LogLevel) { level = newLevel + + val root = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as ch.qos.logback.classic.Logger + root.level = when (newLevel) { + LogLevel.TRAFFIC -> Level.TRACE + LogLevel.DEBUG -> Level.DEBUG + LogLevel.INFO -> Level.INFO + LogLevel.WARNING -> Level.WARN + LogLevel.ERROR -> Level.ERROR + } } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/oath/AppLinkMethodChannel.kt b/android/app/src/main/kotlin/com/yubico/authenticator/oath/AppLinkMethodChannel.kt index 7cb9cd4b..3012601a 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/oath/AppLinkMethodChannel.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/oath/AppLinkMethodChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2023 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,25 +17,26 @@ package com.yubico.authenticator.oath import android.net.Uri + import androidx.annotation.UiThread -import com.yubico.authenticator.logging.Log + import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodChannel + import org.json.JSONObject +import org.slf4j.LoggerFactory + class AppLinkMethodChannel(messenger: BinaryMessenger) { private val methodChannel = MethodChannel(messenger, "app.link.methods") + private val logger = LoggerFactory.getLogger(AppLinkMethodChannel::class.java) @UiThread fun handleUri(uri: Uri) { - Log.t(TAG, "Handling URI: $uri") + logger.trace("Handling URI: {}", uri) methodChannel.invokeMethod( "handleOtpAuthLink", JSONObject(mapOf("link" to uri.toString())).toString() ) } - - companion object { - const val TAG = "AppLinkMethodChannel" - } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/oath/OathManager.kt b/android/app/src/main/kotlin/com/yubico/authenticator/oath/OathManager.kt index c550ea1e..ab88b531 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/oath/OathManager.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/oath/OathManager.kt @@ -61,6 +61,7 @@ import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodChannel import kotlinx.coroutines.* import kotlinx.serialization.encodeToString +import org.slf4j.LoggerFactory import java.net.URI import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicBoolean @@ -77,7 +78,6 @@ class OathManager( private val appPreferences: AppPreferences, ) : AppContextManager { companion object { - const val TAG = "OathManager" const val NFC_DATA_CLEANUP_DELAY = 30L * 1000 // 30s val OTP_AID = byteArrayOf(0xa0.toByte(), 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01) } @@ -98,6 +98,8 @@ class OathManager( ) } + private val logger = LoggerFactory.getLogger(OathManager::class.java) + @TargetApi(Build.VERSION_CODES.M) private fun createKeyStoreProviderM(): KeyProvider = KeyStoreProvider() @@ -117,7 +119,7 @@ class OathManager( // cancel any pending actions, except for addToAny if (!addToAny) { pendingAction?.let { - Log.d(TAG, "Cancelling pending action/closing nfc dialog.") + logger.debug("Cancelling pending action/closing nfc dialog.") it.invoke(Result.failure(CancellationException())) coroutineScope.launch { dialogManager.closeDialog() @@ -134,7 +136,7 @@ class OathManager( if (canInvoke) { if (appViewModel.connectedYubiKey.value == null) { // no USB YubiKey is connected, reset known data on resume - Log.d(TAG, "Removing NFC data after resume.") + logger.debug("Removing NFC data after resume.") appViewModel.setDeviceInfo(null) oathViewModel.setSessionState(null) } @@ -169,7 +171,7 @@ class OathManager( refreshJob = coroutineScope.launch { val delayMs = earliest - now - Log.d(TAG, "Will execute refresh in ${delayMs}ms") + logger.debug("Will execute refresh in {}ms", delayMs) if (delayMs > 0) { delay(delayMs) } @@ -177,9 +179,9 @@ class OathManager( if (currentState.isAtLeast(Lifecycle.State.RESUMED)) { requestRefresh() } else { - Log.d( - TAG, - "Cannot run credential refresh in current lifecycle state: $currentState" + logger.debug( + "Cannot run credential refresh in current lifecycle state: {}", + currentState ) } } @@ -257,7 +259,7 @@ class OathManager( try { oathViewModel.updateCredentials(calculateOathCodes(session)) } catch (error: Exception) { - Log.e(TAG, "Failed to refresh codes", error.toString()) + logger.error("Failed to refresh codes", error) } } } else { @@ -296,7 +298,7 @@ class OathManager( try { SmartCardProtocol(connection).select(OTP_AID) } catch (e: Exception) { - Log.e(TAG, "Failed to recognize this OATH device.") + logger.error("Failed to recognize this OATH device.") // we know this is NFC device and it supports OATH val oathCapabilities = Capabilities(nfc = 0x20) appViewModel.setDeviceInfo( @@ -325,25 +327,24 @@ class OathManager( } } - Log.d( - TAG, + logger.debug( "Successfully read Oath session info (and credentials if unlocked) from connected key" ) } catch (e: Exception) { // OATH not enabled/supported, try to get DeviceInfo over other USB interfaces - Log.e(TAG, "Failed to connect to CCID", e.toString()) + logger.error("Failed to connect to CCID", e) if (device.transport == Transport.USB || e is ApplicationNotAvailableException) { val deviceInfo = try { getDeviceInfo(device) } catch (e: IllegalArgumentException) { - Log.d(TAG, "Device was not recognized") + logger.debug("Device was not recognized") UnknownDevice.copy(isNfc = device.transport == Transport.NFC) } catch (e: Exception) { - Log.d(TAG, "Failure getting device info: ${e.message}") + logger.error("Failure getting device info", e) null } - Log.d(TAG, "Setting device info: $deviceInfo") + logger.debug("Setting device info: {}", deviceInfo) appViewModel.setDeviceInfo(deviceInfo) } @@ -377,7 +378,7 @@ class OathManager( Code.from(code) ) - Log.d(TAG, "Added cred $credential") + logger.debug("Added cred {}", credential) jsonSerializer.encodeToString(addedCred) } } @@ -431,7 +432,7 @@ class OathManager( session.setAccessKey(accessKey) keyManager.addKey(session.deviceId, accessKey, false) oathViewModel.setSessionState(Session(session, false)) - Log.d(TAG, "Successfully set password") + logger.debug("Successfully set password") NULL } @@ -443,7 +444,7 @@ class OathManager( session.deleteAccessKey() keyManager.removeKey(session.deviceId) oathViewModel.setSessionState(Session(session, false)) - Log.d(TAG, "Successfully unset password") + logger.debug("Successfully unset password") return@useOathSession NULL } } @@ -452,7 +453,7 @@ class OathManager( private suspend fun forgetPassword(): String { keyManager.clearAll() - Log.d(TAG, "Cleared all keys.") + logger.debug("Cleared all keys.") oathViewModel.sessionState.value?.let { oathViewModel.setSessionState( it.copy( @@ -516,7 +517,7 @@ class OathManager( oathViewModel.updateCredentials(calculateOathCodes(session)) } catch (apduException: ApduException) { if (apduException.sw == SW.SECURITY_CONDITION_NOT_SATISFIED) { - Log.d(TAG, "Handled oath credential refresh on locked session.") + logger.debug("Handled oath credential refresh on locked session.") oathViewModel.setSessionState( Session( session, @@ -524,10 +525,9 @@ class OathManager( ) ) } else { - Log.e( - TAG, + logger.error( "Unexpected sw when refreshing oath credentials", - apduException.message + apduException ) } } @@ -543,7 +543,7 @@ class OathManager( Credential(credential, session.deviceId), code ) - Log.d(TAG, "Code calculated $code") + logger.debug("Code calculated {}", code) jsonSerializer.encodeToString(code) } @@ -679,7 +679,7 @@ class OathManager( }) } dialogManager.showDialog(Icon.NFC, "Tap your key", title) { - Log.d(TAG, "Cancelled Dialog $title") + logger.debug("Cancelled Dialog {}", title) pendingAction?.invoke(Result.failure(CancellationException())) pendingAction = null } diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/yubikit/DeviceInfoHelper.kt b/android/app/src/main/kotlin/com/yubico/authenticator/yubikit/DeviceInfoHelper.kt index 433f7b5e..9a985c92 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/yubikit/DeviceInfoHelper.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/yubikit/DeviceInfoHelper.kt @@ -17,8 +17,6 @@ package com.yubico.authenticator.yubikit import com.yubico.authenticator.device.Info -import com.yubico.authenticator.logging.Log -import com.yubico.authenticator.oath.OathManager import com.yubico.authenticator.compatUtil import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyDevice import com.yubico.yubikit.android.transport.usb.UsbYubiKeyDevice @@ -29,22 +27,25 @@ import com.yubico.yubikit.core.smartcard.SmartCardConnection import com.yubico.yubikit.management.DeviceInfo import com.yubico.yubikit.support.DeviceUtil +import org.slf4j.LoggerFactory + suspend fun getDeviceInfo(device: YubiKeyDevice): Info { val pid = (device as? UsbYubiKeyDevice)?.pid + val logger = LoggerFactory.getLogger("getDeviceInfo") val deviceInfo = runCatching { device.withConnection { DeviceUtil.readInfo(it, pid) } }.recoverCatching { t -> - Log.d(OathManager.TAG, "Smart card connection not available: ${t.message}") + logger.debug("Smart card connection not available: {}", t.message) device.withConnection { DeviceUtil.readInfo(it, pid) } }.recoverCatching { t -> - Log.d(OathManager.TAG, "OTP connection not available: ${t.message}") + logger.debug("OTP connection not available: {}", t.message) device.withConnection { DeviceUtil.readInfo(it, pid) } }.recoverCatching { t -> - Log.d(OathManager.TAG, "FIDO connection not available: ${t.message}") + logger.debug("FIDO connection not available: {}", t.message) return SkyHelper(compatUtil).getDeviceInfo(device) }.getOrElse { - Log.e(OathManager.TAG, "Failed to recognize device: ${it.message}") + logger.debug("Failed to recognize device: {}", it.message) throw it } diff --git a/android/build.gradle b/android/build.gradle index abc6dde0..c91fe98b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -24,7 +24,7 @@ allprojects { targetSdkVersion = 33 compileSdkVersion = 33 - yubiKitVersion = "2.2.0" + yubiKitVersion = "2.3.0" junitVersion = "4.13.2" mockitoVersion = "5.3.1" }