diff options
44 files changed, 247 insertions, 196 deletions
diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0ca522f7..8638af34 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -107,12 +107,11 @@ dependencies { exclude(group = "org.apache.httpcomponents", module = "httpclient") } implementation(libs.thirdparty.kotlinResult) + implementation(libs.thirdparty.logcat) implementation(libs.thirdparty.modernAndroidPrefs) implementation(libs.thirdparty.plumber) implementation(libs.thirdparty.sshauth) implementation(libs.thirdparty.sshj) - implementation(libs.thirdparty.timber) - implementation(libs.thirdparty.timberkt) if (isSnapshot()) { implementation(libs.thirdparty.whatthestack) diff --git a/app/src/main/java/dev/msfjarvis/aps/Application.kt b/app/src/main/java/dev/msfjarvis/aps/Application.kt index 508bdbf9..bcbc699c 100644 --- a/app/src/main/java/dev/msfjarvis/aps/Application.kt +++ b/app/src/main/java/dev/msfjarvis/aps/Application.kt @@ -13,8 +13,6 @@ import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES -import com.github.ajalt.timberkt.Timber.DebugTree -import com.github.ajalt.timberkt.Timber.plant import dagger.hilt.android.HiltAndroidApp import dev.msfjarvis.aps.injection.context.FilesDirPath import dev.msfjarvis.aps.injection.prefs.SettingsPreferences @@ -25,6 +23,7 @@ import dev.msfjarvis.aps.util.settings.GitSettings import dev.msfjarvis.aps.util.settings.PreferenceKeys import dev.msfjarvis.aps.util.settings.runMigrations import javax.inject.Inject +import logcat.AndroidLogcatLogger @Suppress("Unused") @HiltAndroidApp @@ -41,7 +40,7 @@ class Application : android.app.Application(), SharedPreferences.OnSharedPrefere if (BuildConfig.ENABLE_DEBUG_FEATURES || prefs.getBoolean(PreferenceKeys.ENABLE_DEBUG_LOGGING, false) ) { - plant(DebugTree()) + AndroidLogcatLogger.installOnDebuggableApp(this) StrictMode.setVmPolicy(VmPolicy.Builder().detectAll().penaltyLog().build()) StrictMode.setThreadPolicy(ThreadPolicy.Builder().detectAll().penaltyLog().build()) } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivity.kt index 07ae4c42..67273110 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivity.kt @@ -17,8 +17,6 @@ import androidx.activity.result.contract.ActivityResultContracts.StartIntentSend import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.d -import com.github.ajalt.timberkt.e import com.github.androidpasswordstore.autofillparser.AutofillAction import com.github.androidpasswordstore.autofillparser.Credentials import com.github.michaelbull.result.getOrElse @@ -31,6 +29,7 @@ import dev.msfjarvis.aps.util.autofill.AutofillPreferences import dev.msfjarvis.aps.util.autofill.AutofillResponseBuilder import dev.msfjarvis.aps.util.autofill.DirectoryStructure import dev.msfjarvis.aps.util.extensions.OPENPGP_PROVIDER +import dev.msfjarvis.aps.util.extensions.asLog import java.io.ByteArrayOutputStream import java.io.File import java.io.InputStream @@ -43,6 +42,9 @@ import kotlin.coroutines.suspendCoroutine import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat import me.msfjarvis.openpgpktx.util.OpenPgpApi import me.msfjarvis.openpgpktx.util.OpenPgpServiceConnection import org.openintents.openpgp.IOpenPgpService2 @@ -108,21 +110,21 @@ class AutofillDecryptActivity : AppCompatActivity() { val filePath = intent?.getStringExtra(EXTRA_FILE_PATH) ?: run { - e { "AutofillDecryptActivity started without EXTRA_FILE_PATH" } + logcat(ERROR) { "AutofillDecryptActivity started without EXTRA_FILE_PATH" } finish() return } val clientState = intent?.getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE) ?: run { - e { "AutofillDecryptActivity started without EXTRA_CLIENT_STATE" } + logcat(ERROR) { "AutofillDecryptActivity started without EXTRA_CLIENT_STATE" } finish() return } val isSearchAction = intent?.getBooleanExtra(EXTRA_SEARCH_ACTION, true)!! val action = if (isSearchAction) AutofillAction.Search else AutofillAction.Match directoryStructure = AutofillPreferences.directoryStructure(this) - d { action.toString() } + logcat { action.toString() } lifecycleScope.launch { val credentials = decryptCredential(File(filePath)) if (credentials == null) { @@ -183,14 +185,14 @@ class AutofillDecryptActivity : AppCompatActivity() { val command = resumeIntent ?: Intent().apply { action = OpenPgpApi.ACTION_DECRYPT_VERIFY } runCatching { file.inputStream() } .onFailure { e -> - e(e) { "File to decrypt not found" } + logcat(ERROR) { e.asLog("File to decrypt not found") } return null } .onSuccess { encryptedInput -> val decryptedOutput = ByteArrayOutputStream() runCatching { executeOpenPgpApi(command, encryptedInput, decryptedOutput) } .onFailure { e -> - e(e) { "OpenPgpApi ACTION_DECRYPT_VERIFY failed" } + logcat(ERROR) { e.asLog("OpenPgpApi ACTION_DECRYPT_VERIFY failed") } return null } .onSuccess { result -> @@ -212,7 +214,7 @@ class AutofillDecryptActivity : AppCompatActivity() { ) } .getOrElse { e -> - e(e) { "Failed to parse password entry" } + logcat(ERROR) { e.asLog("Failed to parse password entry") } return null } } @@ -232,7 +234,9 @@ class AutofillDecryptActivity : AppCompatActivity() { decryptCredential(file, intentToResume) } .getOrElse { e -> - e(e) { "OpenPgpApi ACTION_DECRYPT_VERIFY failed with user interaction" } + logcat(ERROR) { + e.asLog("OpenPgpApi ACTION_DECRYPT_VERIFY failed with user interaction") + } return null } } @@ -247,14 +251,14 @@ class AutofillDecryptActivity : AppCompatActivity() { ) .show() } - e { + logcat(ERROR) { "OpenPgpApi ACTION_DECRYPT_VERIFY failed (${error.errorId}): ${error.message}" } } null } else -> { - e { "Unrecognized OpenPgpApi result: $resultCode" } + logcat(ERROR) { "Unrecognized OpenPgpApi result: $resultCode" } null } } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivityV2.kt b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivityV2.kt index 27a12867..bb2e6492 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivityV2.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivityV2.kt @@ -14,8 +14,6 @@ import android.view.autofill.AutofillManager import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.d -import com.github.ajalt.timberkt.e import com.github.androidpasswordstore.autofillparser.AutofillAction import com.github.androidpasswordstore.autofillparser.Credentials import com.github.michaelbull.result.getOrElse @@ -29,11 +27,15 @@ import dev.msfjarvis.aps.ui.crypto.DecryptActivityV2 import dev.msfjarvis.aps.util.autofill.AutofillPreferences import dev.msfjarvis.aps.util.autofill.AutofillResponseBuilder import dev.msfjarvis.aps.util.autofill.DirectoryStructure +import dev.msfjarvis.aps.util.extensions.asLog import java.io.File import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat @RequiresApi(Build.VERSION_CODES.O) @AndroidEntryPoint @@ -80,21 +82,21 @@ class AutofillDecryptActivityV2 : AppCompatActivity() { val filePath = intent?.getStringExtra(EXTRA_FILE_PATH) ?: run { - e { "AutofillDecryptActivityV2 started without EXTRA_FILE_PATH" } + logcat(ERROR) { "AutofillDecryptActivityV2 started without EXTRA_FILE_PATH" } finish() return } val clientState = intent?.getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE) ?: run { - e { "AutofillDecryptActivityV2 started without EXTRA_CLIENT_STATE" } + logcat(ERROR) { "AutofillDecryptActivityV2 started without EXTRA_CLIENT_STATE" } finish() return } val isSearchAction = intent?.getBooleanExtra(EXTRA_SEARCH_ACTION, true)!! val action = if (isSearchAction) AutofillAction.Search else AutofillAction.Match directoryStructure = AutofillPreferences.directoryStructure(this) - d { action.toString() } + logcat { action.toString() } lifecycleScope.launch { val credentials = decryptCredential(File(filePath)) if (credentials == null) { @@ -121,7 +123,7 @@ class AutofillDecryptActivityV2 : AppCompatActivity() { private suspend fun decryptCredential(file: File): Credentials? { runCatching { file.inputStream() } .onFailure { e -> - e(e) { "File to decrypt not found" } + logcat(ERROR) { e.asLog("File to decrypt not found") } return null } .onSuccess { encryptedInput -> @@ -136,7 +138,7 @@ class AutofillDecryptActivityV2 : AppCompatActivity() { } } .onFailure { e -> - e(e) { "Decryption failed" } + logcat(ERROR) { e.asLog("Decryption failed") } return null } .onSuccess { result -> @@ -145,7 +147,7 @@ class AutofillDecryptActivityV2 : AppCompatActivity() { AutofillPreferences.credentialsFromStoreEntry(this, file, entry, directoryStructure) } .getOrElse { e -> - e(e) { "Failed to parse password entry" } + logcat(ERROR) { e.asLog("Failed to parse password entry") } return null } } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillFilterActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillFilterActivity.kt index 04fb83d5..bb6d1056 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillFilterActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillFilterActivity.kt @@ -24,7 +24,6 @@ import androidx.core.widget.addTextChangedListener import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager -import com.github.ajalt.timberkt.e import com.github.androidpasswordstore.autofillparser.FormOrigin import dev.msfjarvis.aps.R import dev.msfjarvis.aps.data.password.PasswordItem @@ -39,6 +38,8 @@ import dev.msfjarvis.aps.util.viewmodel.ListMode import dev.msfjarvis.aps.util.viewmodel.SearchMode import dev.msfjarvis.aps.util.viewmodel.SearchableRepositoryAdapter import dev.msfjarvis.aps.util.viewmodel.SearchableRepositoryViewModel +import logcat.LogPriority.ERROR +import logcat.logcat @TargetApi(Build.VERSION_CODES.O) class AutofillFilterView : AppCompatActivity() { @@ -102,7 +103,7 @@ class AutofillFilterView : AppCompatActivity() { window.attributes = params if (intent?.hasExtra(AutofillManager.EXTRA_CLIENT_STATE) != true) { - e { "AutofillFilterActivity started without EXTRA_CLIENT_STATE" } + logcat(ERROR) { "AutofillFilterActivity started without EXTRA_CLIENT_STATE" } finish() return } @@ -115,7 +116,7 @@ class AutofillFilterView : AppCompatActivity() { FormOrigin.App(intent!!.getStringExtra(EXTRA_FORM_ORIGIN_APP)!!) } else -> { - e { + logcat(ERROR) { "AutofillFilterActivity started without EXTRA_FORM_ORIGIN_WEB or EXTRA_FORM_ORIGIN_APP" } finish() diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt index 6ea47ea1..e37ebf5e 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt @@ -17,7 +17,6 @@ import android.text.format.DateUtils import android.view.View import android.view.autofill.AutofillManager import androidx.appcompat.app.AppCompatActivity -import com.github.ajalt.timberkt.e import com.github.androidpasswordstore.autofillparser.FormOrigin import com.github.androidpasswordstore.autofillparser.computeCertificatesHash import com.github.michaelbull.result.onFailure @@ -26,7 +25,10 @@ import dev.msfjarvis.aps.R import dev.msfjarvis.aps.databinding.ActivityOreoAutofillPublisherChangedBinding import dev.msfjarvis.aps.util.autofill.AutofillMatcher import dev.msfjarvis.aps.util.autofill.AutofillPublisherChangedException +import dev.msfjarvis.aps.util.extensions.asLog import dev.msfjarvis.aps.util.extensions.viewBinding +import logcat.LogPriority.ERROR +import logcat.logcat @TargetApi(Build.VERSION_CODES.O) class AutofillPublisherChangedActivity : AppCompatActivity() { @@ -69,7 +71,7 @@ class AutofillPublisherChangedActivity : AppCompatActivity() { appPackage = intent.getStringExtra(EXTRA_APP_PACKAGE) ?: run { - e { "AutofillPublisherChangedActivity started without EXTRA_PACKAGE_NAME" } + logcat(ERROR) { "AutofillPublisherChangedActivity started without EXTRA_PACKAGE_NAME" } finish() return } @@ -117,7 +119,7 @@ class AutofillPublisherChangedActivity : AppCompatActivity() { } } .onFailure { e -> - e(e) { "Failed to retrieve package info for $appPackage" } + logcat(ERROR) { e.asLog("Failed to retrieve package info for $appPackage") } finish() } } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillSaveActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillSaveActivity.kt index a2ed02fd..c6feec1e 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillSaveActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillSaveActivity.kt @@ -15,7 +15,6 @@ import androidx.activity.result.contract.ActivityResultContracts.StartActivityFo import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.core.os.bundleOf -import com.github.ajalt.timberkt.e import com.github.androidpasswordstore.autofillparser.AutofillAction import com.github.androidpasswordstore.autofillparser.Credentials import com.github.androidpasswordstore.autofillparser.FormOrigin @@ -26,6 +25,8 @@ import dev.msfjarvis.aps.util.autofill.AutofillPreferences import dev.msfjarvis.aps.util.autofill.AutofillResponseBuilder import dev.msfjarvis.aps.util.extensions.unsafeLazy import java.io.File +import logcat.LogPriority.ERROR +import logcat.logcat @RequiresApi(Build.VERSION_CODES.O) class AutofillSaveActivity : AppCompatActivity() { @@ -131,7 +132,7 @@ class AutofillSaveActivity : AppCompatActivity() { val clientState = intent?.getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE) ?: run { - e { "AutofillDecryptActivity started without EXTRA_CLIENT_STATE" } + logcat(ERROR) { "AutofillDecryptActivity started without EXTRA_CLIENT_STATE" } finish() return@registerForActivityResult } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/BasePgpActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/BasePgpActivity.kt index 0a114827..6920bba2 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/BasePgpActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/BasePgpActivity.kt @@ -17,9 +17,6 @@ import android.view.WindowManager import androidx.annotation.CallSuper import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity -import com.github.ajalt.timberkt.Timber.tag -import com.github.ajalt.timberkt.e -import com.github.ajalt.timberkt.i import com.github.michaelbull.result.getOr import com.github.michaelbull.result.runCatching import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -29,6 +26,7 @@ import dev.msfjarvis.aps.R import dev.msfjarvis.aps.injection.prefs.SettingsPreferences import dev.msfjarvis.aps.util.FeatureFlags import dev.msfjarvis.aps.util.extensions.OPENPGP_PROVIDER +import dev.msfjarvis.aps.util.extensions.asLog import dev.msfjarvis.aps.util.extensions.clipboard import dev.msfjarvis.aps.util.extensions.getString import dev.msfjarvis.aps.util.extensions.snackbar @@ -37,6 +35,9 @@ import dev.msfjarvis.aps.util.services.ClipboardService import dev.msfjarvis.aps.util.settings.PreferenceKeys import java.io.File import javax.inject.Inject +import logcat.LogPriority.ERROR +import logcat.LogPriority.INFO +import logcat.logcat import me.msfjarvis.openpgpktx.util.OpenPgpApi import me.msfjarvis.openpgpktx.util.OpenPgpServiceConnection import org.openintents.openpgp.IOpenPgpService2 @@ -82,7 +83,6 @@ open class BasePgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBou override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE) - tag(TAG) } /** @@ -121,7 +121,7 @@ open class BasePgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBou * super. */ override fun onError(e: Exception) { - e(e) { "Callers must handle their own exceptions" } + logcat(ERROR) { e.asLog("Callers must handle their own exceptions") } throw e } @@ -176,7 +176,7 @@ open class BasePgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBou * @param result The intent returned by OpenKeychain */ fun getUserInteractionRequestIntent(result: Intent): IntentSender { - i { "RESULT_CODE_USER_INTERACTION_REQUIRED" } + logcat(INFO) { "RESULT_CODE_USER_INTERACTION_REQUIRED" } return result.getParcelableExtra<PendingIntent>(OpenPgpApi.RESULT_INTENT)!!.intentSender } @@ -196,8 +196,8 @@ open class BasePgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBou } else -> { snackbar(message = getString(R.string.openpgp_error_unknown, error.message)) - e { "onError getErrorId: ${error.errorId}" } - e { "onError getMessage: ${error.message}" } + logcat(ERROR) { "onError getErrorId: ${error.errorId}" } + logcat(ERROR) { "onError getMessage: ${error.message}" } } } } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt index 10298dca..e1ee2195 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt @@ -12,7 +12,6 @@ import android.view.MenuItem import androidx.activity.result.IntentSenderRequest import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.runCatching import dagger.hilt.android.AndroidEntryPoint @@ -35,6 +34,9 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat import me.msfjarvis.openpgpktx.util.OpenPgpApi import me.msfjarvis.openpgpktx.util.OpenPgpServiceConnection import org.openintents.openpgp.IOpenPgpService2 @@ -110,7 +112,7 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound { } override fun onError(e: Exception) { - e(e) + logcat(ERROR) { e.asLog() } } /** @@ -212,7 +214,7 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound { binding.recyclerView.adapter = adapter adapter.updateItems(items) } - .onFailure { e -> e(e) } + .onFailure { e -> logcat(ERROR) { e.asLog() } } } OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED -> { val sender = getUserInteractionRequestIntent(result) diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/GetKeyIdsActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/GetKeyIdsActivity.kt index c98ea877..b24868c9 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/GetKeyIdsActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/GetKeyIdsActivity.kt @@ -10,12 +10,14 @@ import android.os.Bundle import androidx.activity.result.IntentSenderRequest import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.runCatching import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat import me.msfjarvis.openpgpktx.util.OpenPgpApi import me.msfjarvis.openpgpktx.util.OpenPgpUtils import org.openintents.openpgp.IOpenPgpService2 @@ -43,7 +45,7 @@ class GetKeyIdsActivity : BasePgpActivity() { } override fun onError(e: Exception) { - e(e) + logcat(ERROR) { e.asLog() } } /** Get the Key ids from OpenKeychain */ @@ -63,7 +65,7 @@ class GetKeyIdsActivity : BasePgpActivity() { setResult(RESULT_OK, keyResult) finish() } - .onFailure { e -> e(e) } + .onFailure { e -> logcat(ERROR) { e.asLog() } } } OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED -> { val sender = getUserInteractionRequestIntent(result) diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt index cf34ac36..947ee1ea 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt @@ -20,7 +20,6 @@ import androidx.core.content.edit import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.onSuccess import com.github.michaelbull.result.runCatching @@ -39,6 +38,7 @@ import dev.msfjarvis.aps.ui.dialogs.XkPasswordGeneratorDialogFragment import dev.msfjarvis.aps.util.autofill.AutofillPreferences import dev.msfjarvis.aps.util.autofill.DirectoryStructure import dev.msfjarvis.aps.util.crypto.GpgIdentifier +import dev.msfjarvis.aps.util.extensions.asLog import dev.msfjarvis.aps.util.extensions.base64 import dev.msfjarvis.aps.util.extensions.commitChange import dev.msfjarvis.aps.util.extensions.getString @@ -55,6 +55,9 @@ import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat import me.msfjarvis.openpgpktx.util.OpenPgpApi import me.msfjarvis.openpgpktx.util.OpenPgpServiceConnection @@ -520,7 +523,7 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB } .onFailure { e -> if (e is IOException) { - e(e) { "Failed to write password file" } + logcat(ERROR) { e.asLog("Failed to write password file") } setResult(RESULT_CANCELED) MaterialAlertDialogBuilder(this@PasswordCreationActivity) .setTitle(getString(R.string.password_creation_file_fail_title)) @@ -529,7 +532,7 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB .setPositiveButton(android.R.string.ok) { _, _ -> finish() } .show() } else { - e(e) + logcat(ERROR) { e.asLog() } } } } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt index 645d6c47..c2cc5b10 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt @@ -18,7 +18,6 @@ import androidx.core.content.edit import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.onSuccess import com.github.michaelbull.result.runCatching @@ -35,6 +34,7 @@ import dev.msfjarvis.aps.ui.dialogs.PasswordGeneratorDialogFragment import dev.msfjarvis.aps.ui.dialogs.XkPasswordGeneratorDialogFragment import dev.msfjarvis.aps.util.autofill.AutofillPreferences import dev.msfjarvis.aps.util.autofill.DirectoryStructure +import dev.msfjarvis.aps.util.extensions.asLog import dev.msfjarvis.aps.util.extensions.base64 import dev.msfjarvis.aps.util.extensions.commitChange import dev.msfjarvis.aps.util.extensions.getString @@ -49,6 +49,9 @@ import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat @AndroidEntryPoint class PasswordCreationActivityV2 : BasePgpActivity() { @@ -393,7 +396,7 @@ class PasswordCreationActivityV2 : BasePgpActivity() { } .onFailure { e -> if (e is IOException) { - e(e) { "Failed to write password file" } + logcat(ERROR) { e.asLog("Failed to write password file") } setResult(RESULT_CANCELED) MaterialAlertDialogBuilder(this@PasswordCreationActivityV2) .setTitle(getString(R.string.password_creation_file_fail_title)) @@ -402,7 +405,7 @@ class PasswordCreationActivityV2 : BasePgpActivity() { .setPositiveButton(android.R.string.ok) { _, _ -> finish() } .show() } else { - e(e) + logcat(ERROR) { e.asLog() } } } } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/XkPasswordGeneratorDialogFragment.kt b/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/XkPasswordGeneratorDialogFragment.kt index 645ab9ba..7b2297ff 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/XkPasswordGeneratorDialogFragment.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/XkPasswordGeneratorDialogFragment.kt @@ -16,7 +16,6 @@ import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import androidx.fragment.app.setFragmentResult import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.Timber.tag import com.github.michaelbull.result.fold import com.github.michaelbull.result.getOr import com.github.michaelbull.result.runCatching @@ -24,6 +23,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import dev.msfjarvis.aps.R import dev.msfjarvis.aps.databinding.FragmentXkpwgenBinding import dev.msfjarvis.aps.ui.crypto.PasswordCreationActivity +import dev.msfjarvis.aps.util.extensions.asLog import dev.msfjarvis.aps.util.extensions.getString import dev.msfjarvis.aps.util.pwgenxkpwd.CapsType import dev.msfjarvis.aps.util.pwgenxkpwd.PasswordBuilder @@ -31,6 +31,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onEach +import logcat.LogPriority.ERROR +import logcat.logcat import reactivecircus.flowbinding.android.widget.afterTextChanges import reactivecircus.flowbinding.android.widget.selectionEvents @@ -119,7 +121,7 @@ class XkPasswordGeneratorDialogFragment : DialogFragment() { success = { binding.xkPasswordText.text = it }, failure = { e -> Toast.makeText(requireActivity(), e.message, Toast.LENGTH_SHORT).show() - tag("xkpw").e(e, "failure generating xkpasswd") + logcat("xkpw", ERROR) { e.asLog("failure generating xkpasswd") } binding.xkPasswordText.text = FALLBACK_ERROR_PASS }, ) diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/git/base/BaseGitActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/git/base/BaseGitActivity.kt index b3155264..a008f6c7 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/git/base/BaseGitActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/git/base/BaseGitActivity.kt @@ -7,7 +7,6 @@ package dev.msfjarvis.aps.ui.git.base import android.content.SharedPreferences import androidx.appcompat.app.AppCompatActivity import androidx.core.content.edit -import com.github.ajalt.timberkt.d import com.github.michaelbull.result.Err import com.github.michaelbull.result.Result import com.github.michaelbull.result.andThen @@ -30,6 +29,8 @@ import dev.msfjarvis.aps.util.settings.PreferenceKeys import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import logcat.asLog +import logcat.logcat import net.schmizz.sshj.common.DisconnectReason import net.schmizz.sshj.common.SSHException import net.schmizz.sshj.transport.TransportException @@ -89,7 +90,7 @@ abstract class BaseGitActivity : ContinuationContainerActivity() { if (!isExplicitlyUserInitiatedError(error)) { gitPrefs.edit { remove(PreferenceKeys.HTTPS_PASSWORD) } sharedPrefs.edit { remove(PreferenceKeys.SSH_OPENKEYSTORE_KEYID) } - d(error) + logcat { error.asLog() } withContext(Dispatchers.Main) { MaterialAlertDialogBuilder(this@BaseGitActivity).run { setTitle(resources.getString(R.string.jgit_error_dialog_title)) diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitConfigActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitConfigActivity.kt index 8ca719eb..04014e17 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitConfigActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitConfigActivity.kt @@ -12,7 +12,6 @@ import android.util.Patterns import android.view.MenuItem import androidx.core.os.postDelayed import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.fold import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.onFailure @@ -26,6 +25,8 @@ import dev.msfjarvis.aps.ui.git.base.BaseGitActivity import dev.msfjarvis.aps.ui.git.log.GitLogActivity import dev.msfjarvis.aps.util.extensions.viewBinding import kotlinx.coroutines.launch +import logcat.LogPriority.ERROR +import logcat.logcat import org.eclipse.jgit.lib.Constants import org.eclipse.jgit.lib.Repository import org.eclipse.jgit.lib.RepositoryState @@ -88,7 +89,7 @@ class GitConfigActivity : BaseGitActivity() { } binding.gitLog.setOnClickListener { runCatching { startActivity(Intent(this, GitLogActivity::class.java)) }.onFailure { ex -> - e(ex) { "Failed to start GitLogActivity" } + logcat(ERROR) { "Failed to start GitLogActivity\n${ex}" } } } binding.gitAbortRebase.setOnClickListener { @@ -143,7 +144,7 @@ class GitConfigActivity : BaseGitActivity() { } } .getOrElse { ex -> - e(ex) { "Error getting HEAD reference" } + logcat(ERROR) { "Error getting HEAD reference\n${ex}" } getString(R.string.git_head_missing) } } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitServerConfigActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitServerConfigActivity.kt index 5265131b..d1e84374 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitServerConfigActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitServerConfigActivity.kt @@ -15,7 +15,6 @@ import androidx.core.os.postDelayed import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.fold import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.runCatching @@ -34,6 +33,9 @@ import dev.msfjarvis.aps.util.settings.Protocol import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat /** * Activity that encompasses both the initial clone as well as editing the server config for future @@ -269,7 +271,7 @@ class GitServerConfigActivity : BaseGitActivity() { } } .onFailure { e -> - e(e) + logcat(ERROR) { e.asLog() } MaterialAlertDialogBuilder(this).setMessage(e.message).show() } lifecycleScope.launch { diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/git/log/GitLogAdapter.kt b/app/src/main/java/dev/msfjarvis/aps/ui/git/log/GitLogAdapter.kt index 1470d642..a3080fef 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/git/log/GitLogAdapter.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/git/log/GitLogAdapter.kt @@ -8,12 +8,13 @@ package dev.msfjarvis.aps.ui.git.log import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView -import com.github.ajalt.timberkt.e import dev.msfjarvis.aps.databinding.GitLogRowLayoutBinding import dev.msfjarvis.aps.util.git.GitCommit import dev.msfjarvis.aps.util.git.GitLogModel import java.text.DateFormat import java.util.Date +import logcat.LogPriority.ERROR +import logcat.logcat private fun shortHash(hash: String): String { return hash.substring(0 until 8) @@ -37,7 +38,7 @@ class GitLogAdapter : RecyclerView.Adapter<GitLogAdapter.ViewHolder>() { override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { val commit = model.get(position) if (commit == null) { - e { "There is no git commit for view holder at position $position." } + logcat(ERROR) { "There is no git commit for view holder at position $position." } return } viewHolder.bind(commit) diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/onboarding/fragments/RepoLocationFragment.kt b/app/src/main/java/dev/msfjarvis/aps/ui/onboarding/fragments/RepoLocationFragment.kt index 8503cfbd..befe44f1 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/onboarding/fragments/RepoLocationFragment.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/onboarding/fragments/RepoLocationFragment.kt @@ -13,8 +13,6 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.content.edit import androidx.fragment.app.Fragment -import com.github.ajalt.timberkt.d -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.runCatching import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -33,6 +31,9 @@ import dev.msfjarvis.aps.util.extensions.viewBinding import dev.msfjarvis.aps.util.settings.PasswordSortOrder import dev.msfjarvis.aps.util.settings.PreferenceKeys import java.io.File +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat class RepoLocationFragment : Fragment(R.layout.fragment_repo_location) { @@ -160,9 +161,9 @@ class RepoLocationFragment : Fragment(R.layout.fragment_repo_location) { parentFragmentManager.performTransactionWithBackStack(KeySelectionFragment.newInstance()) } .onFailure { e -> - e(e) + logcat(ERROR) { e.asLog() } if (!localDir.delete()) { - d { "Failed to delete local repository: $localDir" } + logcat { "Failed to delete local repository: $localDir" } } finish() } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordStore.kt b/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordStore.kt index a44d4ed0..ba1e4ac6 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordStore.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordStore.kt @@ -25,9 +25,6 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.commit import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.d -import com.github.ajalt.timberkt.e -import com.github.ajalt.timberkt.i import com.github.michaelbull.result.fold import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.runCatching @@ -68,6 +65,9 @@ import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.LogPriority.ERROR +import logcat.LogPriority.INFO +import logcat.logcat const val PASSWORD_FRAGMENT_TAG = "PasswordsList" @@ -108,18 +108,18 @@ class PasswordStore : BaseGitActivity() { val target = File(requireNotNull(intentData.getStringExtra("SELECTED_FOLDER_PATH"))) val repositoryPath = PasswordRepository.getRepositoryDirectory().absolutePath if (!target.isDirectory) { - e { "Tried moving passwords to a non-existing folder." } + logcat(ERROR) { "Tried moving passwords to a non-existing folder." } return@registerForActivityResult } - d { "Moving passwords to ${intentData.getStringExtra("SELECTED_FOLDER_PATH")}" } - d { filesToMove.joinToString(", ") } + logcat { "Moving passwords to ${intentData.getStringExtra("SELECTED_FOLDER_PATH")}" } + logcat { filesToMove.joinToString(", ") } lifecycleScope.launch(Dispatchers.IO) { for (file in filesToMove) { val source = File(file) if (!source.exists()) { - e { "Tried moving something that appears non-existent." } + logcat(ERROR) { "Tried moving something that appears non-existent." } continue } val destinationFile = File(target.absolutePath + "/" + source.name) @@ -127,7 +127,7 @@ class PasswordStore : BaseGitActivity() { val sourceLongName = getLongName(requireNotNull(source.parent), repositoryPath, basename) val destinationLongName = getLongName(target.absolutePath, repositoryPath, basename) if (destinationFile.exists()) { - e { "Trying to move a file that already exists." } + logcat(ERROR) { "Trying to move a file that already exists." } withContext(Dispatchers.Main) { MaterialAlertDialogBuilder(this@PasswordStore) .setTitle(resources.getString(R.string.password_exists_title)) @@ -389,7 +389,7 @@ class PasswordStore : BaseGitActivity() { private fun checkLocalRepository(localDir: File?) { if (localDir != null && settings.getBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false)) { - d { "Check, dir: ${localDir.absolutePath}" } + logcat { "Check, dir: ${localDir.absolutePath}" } // do not push the fragment if we already have it if (getPasswordFragment() == null || settings.getBoolean(PreferenceKeys.REPO_CHANGED, false) ) { @@ -454,7 +454,7 @@ class PasswordStore : BaseGitActivity() { fun createPassword() { if (!validateState()) return val currentDir = currentDir - i { "Adding file to : ${currentDir.absolutePath}" } + logcat(INFO) { "Adding file to : ${currentDir.absolutePath}" } val intent = Intent(this, PasswordCreationActivity::class.java) intent.putExtra("FILE_PATH", currentDir.absolutePath) intent.putExtra("REPO_PATH", PasswordRepository.getRepositoryDirectory().absolutePath) @@ -632,7 +632,7 @@ class PasswordStore : BaseGitActivity() { mapOf(source to destinationFile) } if (!source.renameTo(destinationFile)) { - e { "Something went wrong while moving $source to $destinationFile." } + logcat(ERROR) { "Something went wrong while moving $source to $destinationFile." } withContext(Dispatchers.Main) { MaterialAlertDialogBuilder(this@PasswordStore) .setTitle(R.string.password_move_error_title) diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/settings/DirectorySelectionActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/settings/DirectorySelectionActivity.kt index 039b7a59..1f8873c0 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/settings/DirectorySelectionActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/settings/DirectorySelectionActivity.kt @@ -12,11 +12,11 @@ import android.provider.DocumentsContract import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.content.edit -import com.github.ajalt.timberkt.d import com.google.android.material.dialog.MaterialAlertDialogBuilder import dev.msfjarvis.aps.R import dev.msfjarvis.aps.util.extensions.sharedPrefs import dev.msfjarvis.aps.util.settings.PreferenceKeys +import logcat.logcat class DirectorySelectionActivity : AppCompatActivity() { @@ -25,7 +25,7 @@ class DirectorySelectionActivity : AppCompatActivity() { registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri: Uri? -> if (uri == null) return@registerForActivityResult - d { "Selected repository URI is $uri" } + logcat { "Selected repository URI is $uri" } // TODO: This is fragile. Workaround until PasswordItem is backed by DocumentFile val docId = DocumentsContract.getTreeDocumentId(uri) val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() @@ -33,7 +33,7 @@ class DirectorySelectionActivity : AppCompatActivity() { val repoPath = "${Environment.getExternalStorageDirectory()}/$path" val prefs = sharedPrefs - d { "Selected repository path is $repoPath" } + logcat { "Selected repository path is $repoPath" } if (Environment.getExternalStorageDirectory().path == repoPath) { MaterialAlertDialogBuilder(this) diff --git a/app/src/main/java/dev/msfjarvis/aps/util/auth/BiometricAuthenticator.kt b/app/src/main/java/dev/msfjarvis/aps/util/auth/BiometricAuthenticator.kt index 7236ac7c..a582337b 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/auth/BiometricAuthenticator.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/auth/BiometricAuthenticator.kt @@ -12,9 +12,8 @@ import androidx.biometric.BiometricPrompt import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import androidx.fragment.app.FragmentActivity -import com.github.ajalt.timberkt.Timber.tag -import com.github.ajalt.timberkt.d import dev.msfjarvis.aps.R +import logcat.logcat object BiometricAuthenticator { @@ -43,7 +42,7 @@ object BiometricAuthenticator { object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) - tag(TAG).d { "BiometricAuthentication error: errorCode=$errorCode, msg=$errString" } + logcat(TAG) { "BiometricAuthentication error: errorCode=$errorCode, msg=$errString" } callback( when (errorCode) { BiometricPrompt.ERROR_CANCELED, diff --git a/app/src/main/java/dev/msfjarvis/aps/util/autofill/Api30AutofillResponseBuilder.kt b/app/src/main/java/dev/msfjarvis/aps/util/autofill/Api30AutofillResponseBuilder.kt index 14cc634c..fd8faa7f 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/autofill/Api30AutofillResponseBuilder.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/autofill/Api30AutofillResponseBuilder.kt @@ -15,7 +15,6 @@ import android.service.autofill.SaveInfo import android.view.inputmethod.InlineSuggestionsRequest import android.widget.inline.InlinePresentationSpec import androidx.annotation.RequiresApi -import com.github.ajalt.timberkt.e import com.github.androidpasswordstore.autofillparser.AutofillAction import com.github.androidpasswordstore.autofillparser.FillableForm import com.github.androidpasswordstore.autofillparser.fillWith @@ -28,6 +27,9 @@ import dev.msfjarvis.aps.ui.autofill.AutofillPublisherChangedActivity import dev.msfjarvis.aps.ui.autofill.AutofillSaveActivity import dev.msfjarvis.aps.util.FeatureFlags import java.io.File +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat /** Implements [AutofillResponseBuilder]'s methods for API 30 and above */ @RequiresApi(Build.VERSION_CODES.R) @@ -213,7 +215,7 @@ class Api30AutofillResponseBuilder(form: FillableForm) { callback.onSuccess(makeFillResponse(context, inlineSuggestionsRequest, matchedFiles)) }, failure = { e -> - e(e) + logcat(ERROR) { e.asLog() } callback.onSuccess(makePublisherChangedResponse(context, inlineSuggestionsRequest, e)) } ) diff --git a/app/src/main/java/dev/msfjarvis/aps/util/autofill/AutofillMatcher.kt b/app/src/main/java/dev/msfjarvis/aps/util/autofill/AutofillMatcher.kt index ea10c1ac..206074fa 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/autofill/AutofillMatcher.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/autofill/AutofillMatcher.kt @@ -8,9 +8,6 @@ import android.content.Context import android.content.SharedPreferences import android.widget.Toast import androidx.core.content.edit -import com.github.ajalt.timberkt.Timber.e -import com.github.ajalt.timberkt.d -import com.github.ajalt.timberkt.w import com.github.androidpasswordstore.autofillparser.FormOrigin import com.github.androidpasswordstore.autofillparser.computeCertificatesHash import com.github.michaelbull.result.Err @@ -18,6 +15,9 @@ import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Result import dev.msfjarvis.aps.R import java.io.File +import logcat.LogPriority.ERROR +import logcat.LogPriority.WARN +import logcat.logcat private const val PREFERENCES_AUTOFILL_APP_MATCHES = "oreo_autofill_app_matches" private val Context.autofillAppMatches @@ -69,7 +69,7 @@ class AutofillMatcher { context.autofillAppMatches.getString(tokenKey(formOrigin), null) ?: return false val hashHasChanged = certificatesHash != storedCertificatesHash if (hashHasChanged) { - e { "$packageName: stored=$storedCertificatesHash, new=$certificatesHash" } + logcat(ERROR) { "$packageName: stored=$storedCertificatesHash, new=$certificatesHash" } true } else { false @@ -134,7 +134,7 @@ class AutofillMatcher { if (hasFormOriginHashChanged(context, formOrigin)) { // This should never happen since we already verified the publisher in // getMatchesFor. - e { "App publisher changed between getMatchesFor and addMatchFor" } + logcat(ERROR) { "App publisher changed between getMatchesFor and addMatchFor" } throw AutofillPublisherChangedException(formOrigin) } val matchPreferences = context.matchPreferences(formOrigin) @@ -154,7 +154,7 @@ class AutofillMatcher { putStringSet(matchesKey(formOrigin), newFiles.map { it.absolutePath }.toSet()) } storeFormOriginHash(context, formOrigin) - d { "Stored match for $formOrigin" } + logcat { "Stored match for $formOrigin" } } /** @@ -176,7 +176,7 @@ class AutofillMatcher { // created with `putStringSet`. @Suppress("UNCHECKED_CAST") val oldMatches = value as? Set<String> if (oldMatches == null) { - w { "Failed to read matches for $key" } + logcat(WARN) { "Failed to read matches for $key" } continue } // Delete all matches for file locations that are going to be overwritten, then @@ -188,7 +188,7 @@ class AutofillMatcher { .minus(oldNewPathMap.values) .map { match -> val newPath = oldNewPathMap[match] ?: return@map match - d { "Updating match for $key: $match --> $newPath" } + logcat { "Updating match for $key: $match --> $newPath" } newPath } .toSet() diff --git a/app/src/main/java/dev/msfjarvis/aps/util/autofill/AutofillResponseBuilder.kt b/app/src/main/java/dev/msfjarvis/aps/util/autofill/AutofillResponseBuilder.kt index 1a825de8..723347f2 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/autofill/AutofillResponseBuilder.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/autofill/AutofillResponseBuilder.kt @@ -13,7 +13,6 @@ import android.service.autofill.FillCallback import android.service.autofill.FillResponse import android.service.autofill.SaveInfo import androidx.annotation.RequiresApi -import com.github.ajalt.timberkt.e import com.github.androidpasswordstore.autofillparser.AutofillAction import com.github.androidpasswordstore.autofillparser.AutofillScenario import com.github.androidpasswordstore.autofillparser.Credentials @@ -28,6 +27,9 @@ import dev.msfjarvis.aps.ui.autofill.AutofillPublisherChangedActivity import dev.msfjarvis.aps.ui.autofill.AutofillSaveActivity import dev.msfjarvis.aps.util.FeatureFlags import java.io.File +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat @RequiresApi(Build.VERSION_CODES.O) class AutofillResponseBuilder(form: FillableForm) { @@ -180,7 +182,7 @@ class AutofillResponseBuilder(form: FillableForm) { .fold( success = { matchedFiles -> callback.onSuccess(makeFillResponse(context, matchedFiles)) }, failure = { e -> - e(e) + logcat(ERROR) { e.asLog() } callback.onSuccess(makePublisherChangedResponse(context, e)) } ) @@ -209,7 +211,7 @@ class AutofillResponseBuilder(form: FillableForm) { } return builder.run { if (scenario != null) fillWith(scenario, action, credentials) - else e { "Failed to recover scenario from client state" } + else logcat(ERROR) { "Failed to recover scenario from client state" } build() } } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/extensions/AndroidExtensions.kt b/app/src/main/java/dev/msfjarvis/aps/util/extensions/AndroidExtensions.kt index 0ad122e6..7671adb4 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/extensions/AndroidExtensions.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/extensions/AndroidExtensions.kt @@ -21,7 +21,6 @@ import androidx.core.content.getSystemService import androidx.fragment.app.FragmentActivity import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKey -import com.github.ajalt.timberkt.d import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Result import com.google.android.material.snackbar.Snackbar @@ -29,6 +28,7 @@ import dev.msfjarvis.aps.BuildConfig import dev.msfjarvis.aps.R import dev.msfjarvis.aps.data.repo.PasswordRepository import dev.msfjarvis.aps.util.git.operation.GitOperation +import logcat.logcat /** Get an instance of [AutofillManager]. Only available on Android Oreo and above */ val Context.autofillManager: AutofillManager? @@ -91,7 +91,7 @@ suspend fun FragmentActivity.commitChange( ) override fun preExecute(): Boolean { - d { "Committing with message: '$message'" } + logcat { "Committing with message: '$message'" } return true } } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/extensions/Extensions.kt b/app/src/main/java/dev/msfjarvis/aps/util/extensions/Extensions.kt index f04dba33..6c779af6 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/extensions/Extensions.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/extensions/Extensions.kt @@ -9,6 +9,7 @@ import com.github.michaelbull.result.runCatching import dev.msfjarvis.aps.data.repo.PasswordRepository import java.io.File import java.util.Date +import logcat.asLog import org.eclipse.jgit.lib.ObjectId import org.eclipse.jgit.revwalk.RevCommit @@ -78,3 +79,6 @@ fun String.splitLines(): Array<String> { /** Alias to [lazy] with thread safety mode always set to [LazyThreadSafetyMode.NONE]. */ fun <T> unsafeLazy(initializer: () -> T) = lazy(LazyThreadSafetyMode.NONE) { initializer.invoke() } + +/** A convenience extension to turn a [Throwable] with a message into a loggable string. */ +fun Throwable.asLog(message: String): String = "$message\n${asLog()}" diff --git a/app/src/main/java/dev/msfjarvis/aps/util/git/GitLogModel.kt b/app/src/main/java/dev/msfjarvis/aps/util/git/GitLogModel.kt index 0fa21271..4753bcd6 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/git/GitLogModel.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/git/GitLogModel.kt @@ -5,24 +5,28 @@ package dev.msfjarvis.aps.util.git -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.runCatching import dev.msfjarvis.aps.data.repo.PasswordRepository +import dev.msfjarvis.aps.util.extensions.asLog import dev.msfjarvis.aps.util.extensions.hash import dev.msfjarvis.aps.util.extensions.time import dev.msfjarvis.aps.util.extensions.unsafeLazy +import logcat.LogPriority.ERROR +import logcat.logcat import org.eclipse.jgit.api.Git import org.eclipse.jgit.revwalk.RevCommit +private val TAG = GitLogModel::class.java.simpleName + private fun commits(): Iterable<RevCommit> { val repo = PasswordRepository.getRepository(null) if (repo == null) { - e { "Could not access git repository" } + logcat(TAG, ERROR) { "Could not access git repository" } return listOf() } return runCatching { Git(repo).log().call() }.getOrElse { e -> - e(e) { "Failed to obtain git commits" } + logcat(TAG, ERROR) { e.asLog("Failed to obtain git commits") } listOf() } } @@ -48,7 +52,8 @@ class GitLogModel { val size = cache.size fun get(index: Int): GitCommit? { - if (index >= size) e { "Cannot get git commit with index $index. There are only $size." } + if (index >= size) + logcat(ERROR) { "Cannot get git commit with index $index. There are only $size." } return cache.getOrNull(index) } } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/git/operation/GitOperation.kt b/app/src/main/java/dev/msfjarvis/aps/util/git/operation/GitOperation.kt index 9d296353..736b69c2 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/git/operation/GitOperation.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/git/operation/GitOperation.kt @@ -7,7 +7,6 @@ package dev.msfjarvis.aps.util.git.operation import android.content.Intent import android.widget.Toast import androidx.fragment.app.FragmentActivity -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.Err import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Result @@ -34,6 +33,9 @@ import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat import net.schmizz.sshj.common.DisconnectReason import net.schmizz.sshj.common.SSHException import net.schmizz.sshj.userauth.password.PasswordFinder @@ -110,7 +112,7 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) { } callingActivity.startActivity(intent) } - .onFailure { e -> e(e) } + .onFailure { e -> logcat(ERROR) { e.asLog() } } } private fun registerAuthProviders( diff --git a/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/OpenKeychainKeyProvider.kt b/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/OpenKeychainKeyProvider.kt index d726c353..3a40b8a2 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/OpenKeychainKeyProvider.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/OpenKeychainKeyProvider.kt @@ -9,7 +9,6 @@ import android.content.Intent import androidx.activity.result.IntentSenderRequest import androidx.core.content.edit import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.d import dev.msfjarvis.aps.util.extensions.OPENPGP_PROVIDER import dev.msfjarvis.aps.util.extensions.sharedPrefs import dev.msfjarvis.aps.util.settings.PreferenceKeys @@ -21,6 +20,7 @@ import kotlin.coroutines.suspendCoroutine import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.logcat import net.schmizz.sshj.common.DisconnectReason import net.schmizz.sshj.common.KeyType import net.schmizz.sshj.userauth.UserAuthException @@ -81,7 +81,7 @@ class OpenKeychainKeyProvider private constructor(val activity: ContinuationCont sshServiceConnection.connect( object : SshAuthenticationConnection.OnBound { override fun onBound(sshAgent: ISshAuthenticationService) { - d { "Bound to SshAuthenticationApi: $OPENPGP_PROVIDER" } + logcat { "Bound to SshAuthenticationApi: $OPENPGP_PROVIDER" } cont.resume(SshAuthenticationApi(context, sshAgent)) } @@ -134,7 +134,7 @@ class OpenKeychainKeyProvider private constructor(val activity: ContinuationCont request: Request, resultOfUserInteraction: Intent? = null ): ApiResponse { - d { "executeRequest($request) called" } + logcat { "executeRequest($request) called" } val result = withContext(Dispatchers.Main) { // If the request required user interaction, the data returned from the @@ -142,7 +142,7 @@ class OpenKeychainKeyProvider private constructor(val activity: ContinuationCont // is used as the real request. sshServiceApi.executeApi(resultOfUserInteraction ?: request.toIntent())!! } - return parseResult(request, result).also { d { "executeRequest($request): $it" } } + return parseResult(request, result).also { logcat { "executeRequest($request): $it" } } } private suspend fun parseResult(request: Request, result: Intent): ApiResponse { diff --git a/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshKey.kt b/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshKey.kt index 66617a18..f2db6067 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshKey.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshKey.kt @@ -16,8 +16,6 @@ import android.util.Base64 import androidx.core.content.edit import androidx.security.crypto.EncryptedFile import androidx.security.crypto.MasterKey -import com.github.ajalt.timberkt.d -import com.github.ajalt.timberkt.e import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.runCatching import dev.msfjarvis.aps.Application @@ -39,6 +37,8 @@ import javax.crypto.SecretKeyFactory import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext +import logcat.asLog +import logcat.logcat import net.i2p.crypto.eddsa.EdDSAPrivateKey import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec @@ -101,7 +101,7 @@ object SshKey { // It is fine to swallow the exception here since it will reappear when the key // is // used for SSH authentication and can then be shown in the UI. - d(error) + logcat { error.asLog() } false } } @@ -317,13 +317,13 @@ object SshKey { override fun getPublic(): PublicKey = runCatching { androidKeystore.sshPublicKey!! }.getOrElse { error -> - e(error) + logcat { error.asLog() } throw IOException("Failed to get public key '$KEYSTORE_ALIAS' from Android Keystore", error) } override fun getPrivate(): PrivateKey = runCatching { androidKeystore.sshPrivateKey!! }.getOrElse { error -> - e(error) + logcat { error.asLog() } throw IOException( "Failed to access private key '$KEYSTORE_ALIAS' from Android Keystore", error @@ -337,7 +337,7 @@ object SshKey { override fun getPublic(): PublicKey = runCatching { parseSshPublicKey(sshPublicKey!!)!! }.getOrElse { error -> - e(error) + logcat { error.asLog() } throw IOException("Failed to get the public key for wrapped ed25519 key", error) } @@ -353,7 +353,7 @@ object SshKey { ) } .getOrElse { error -> - e(error) + logcat { error.asLog() } throw IOException("Failed to unwrap wrapped ed25519 key", error) } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshjConfig.kt b/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshjConfig.kt index f8053ef3..f0405e04 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshjConfig.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshjConfig.kt @@ -4,8 +4,6 @@ */ package dev.msfjarvis.aps.util.git.sshj -import com.github.ajalt.timberkt.Timber -import com.github.ajalt.timberkt.d import com.github.michaelbull.result.runCatching import com.hierynomus.sshj.key.KeyAlgorithms import com.hierynomus.sshj.transport.cipher.BlockCiphers @@ -14,6 +12,12 @@ import com.hierynomus.sshj.transport.kex.ExtInfoClientFactory import com.hierynomus.sshj.transport.mac.Macs import com.hierynomus.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile import java.security.Security +import logcat.LogPriority.ERROR +import logcat.LogPriority.INFO +import logcat.LogPriority.VERBOSE +import logcat.LogPriority.WARN +import logcat.asLog +import logcat.logcat import net.schmizz.keepalive.KeepAliveProvider import net.schmizz.sshj.ConfigImpl import net.schmizz.sshj.common.LoggerFactory @@ -49,7 +53,9 @@ fun setUpBouncyCastleForSshj() { runCatching { Class.forName("sun.security.jca.Providers") } Security.insertProviderAt(BouncyCastleProvider(), bcIndex + 1) } - d { "JCE providers: ${Security.getProviders().joinToString { "${it.name} (${it.version})" }}" } + logcat("setUpBouncyCastleForSshj") { + "JCE providers: ${Security.getProviders().joinToString { "${it.name} (${it.version})" }}" + } // Prevent sshj from forwarding all cryptographic operations to BC. SecurityUtils.setRegisterBouncyCastle(false) SecurityUtils.setSecurityProvider(null) @@ -147,10 +153,9 @@ private abstract class AbstractLogger(private val name: String) : Logger { override fun error(marker: Marker?, msg: String, t: Throwable?) = error(msg, t) } -object TimberLoggerFactory : LoggerFactory { - private class TimberLogger(name: String) : AbstractLogger(name) { +object LogcatLoggerFactory : LoggerFactory { + private class LogcatLogger(name: String) : AbstractLogger(name) { - // We defer the log level checks to Timber. override fun isTraceEnabled() = true override fun isDebugEnabled() = true override fun isInfoEnabled() = true @@ -163,39 +168,39 @@ object TimberLoggerFactory : LoggerFactory { private fun String.fix() = replace("""(?!<\\)\{\}""".toRegex(), "%s") override fun t(message: String, t: Throwable?, vararg args: Any?) { - Timber.tag(name).v(t, message.fix(), *args) + logcat(name, VERBOSE) { message.fix().format(*args) + (t?.asLog() ?: "") } } override fun d(message: String, t: Throwable?, vararg args: Any?) { - Timber.tag(name).d(t, message.fix(), *args) + logcat(name) { message.fix().format(*args) + (t?.asLog() ?: "") } } override fun i(message: String, t: Throwable?, vararg args: Any?) { - Timber.tag(name).i(t, message.fix(), *args) + logcat(name, INFO) { message.fix().format(*args) + (t?.asLog() ?: "") } } override fun w(message: String, t: Throwable?, vararg args: Any?) { - Timber.tag(name).w(t, message.fix(), *args) + logcat(name, WARN) { message.fix().format(*args) + (t?.asLog() ?: "") } } override fun e(message: String, t: Throwable?, vararg args: Any?) { - Timber.tag(name).e(t, message.fix(), *args) + logcat(name, ERROR) { message.fix().format(*args) + (t?.asLog() ?: "") } } } override fun getLogger(name: String): Logger { - return TimberLogger(name) + return LogcatLogger(name) } override fun getLogger(clazz: Class<*>): Logger { - return TimberLogger(clazz.name) + return LogcatLogger(clazz.name) } } class SshjConfig : ConfigImpl() { init { - loggerFactory = TimberLoggerFactory + loggerFactory = LogcatLoggerFactory keepAliveProvider = KeepAliveProvider.HEARTBEAT version = "OpenSSH_8.2p1 Ubuntu-4ubuntu0.1" diff --git a/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshjSessionFactory.kt b/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshjSessionFactory.kt index bc068f52..79438bcc 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshjSessionFactory.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/git/sshj/SshjSessionFactory.kt @@ -5,8 +5,6 @@ package dev.msfjarvis.aps.util.git.sshj import android.util.Base64 -import com.github.ajalt.timberkt.d -import com.github.ajalt.timberkt.w import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.runCatching import dev.msfjarvis.aps.util.git.operation.CredentialFinder @@ -20,6 +18,8 @@ import kotlin.coroutines.Continuation import kotlin.coroutines.suspendCoroutine import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking +import logcat.LogPriority.WARN +import logcat.logcat import net.schmizz.sshj.SSHClient import net.schmizz.sshj.common.Buffer.PlainBuffer import net.schmizz.sshj.common.DisconnectReason @@ -76,7 +76,7 @@ class SshjSessionFactory(private val authMethod: SshAuthMethod, private val host ): RemoteSession { return currentSession ?: SshjSession(uri, uri.user, authMethod, hostKeyFile).connect().also { - d { "New SSH connection created" } + logcat { "New SSH connection created" } currentSession = it } } @@ -96,13 +96,15 @@ private fun makeTofuHostKeyVerifier(hostKeyFile: File): HostKeyVerifier { digest.update(PlainBuffer().putPublicKey(key).compactData) val digestData = digest.digest() val hostKeyEntry = "SHA256:${Base64.encodeToString(digestData, Base64.NO_WRAP)}" - d { "Trusting host key on first use: $hostKeyEntry" } + logcat(SshjSessionFactory::class.java.simpleName) { + "Trusting host key on first use: $hostKeyEntry" + } hostKeyFile.writeText(hostKeyEntry) true } } else { val hostKeyEntry = hostKeyFile.readText() - d { "Pinned host key: $hostKeyEntry" } + logcat(SshjSessionFactory::class.java.simpleName) { "Pinned host key: $hostKeyEntry" } return FingerprintVerifier.getInstance(hostKeyEntry) } } @@ -122,12 +124,12 @@ private class SshjSession( // URIish's String constructor cannot handle '@' in the user part of the URI and the URL // constructor can't be used since Java's URL does not recognize the ssh scheme. We thus // need to patch everything up ourselves. - d { "Before fixup: user=${uri.user}, host=${uri.host}" } + logcat { "Before fixup: user=${uri.user}, host=${uri.host}" } val userPlusHost = "${uri.user}@${uri.host}" val realUser = userPlusHost.substringBeforeLast('@') val realHost = userPlusHost.substringAfterLast('@') uri.setUser(realUser).setHost(realHost).also { - d { "After fixup: user=${it.user}, host=${it.host}" } + logcat { "After fixup: user=${it.user}, host=${it.host}" } } } else { uri @@ -162,7 +164,7 @@ private class SshjSession( override fun exec(commandName: String?, timeout: Int): Process { if (currentCommand != null) { - w { "Killing old command" } + logcat(WARN) { "Killing old command" } disconnect() } val session = ssh.startSession() diff --git a/app/src/main/java/dev/msfjarvis/aps/util/services/ClipboardService.kt b/app/src/main/java/dev/msfjarvis/aps/util/services/ClipboardService.kt index de7d727c..84de5c91 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/services/ClipboardService.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/services/ClipboardService.kt @@ -16,7 +16,6 @@ import android.os.IBinder import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat import androidx.core.content.getSystemService -import com.github.ajalt.timberkt.d import dev.msfjarvis.aps.R import dev.msfjarvis.aps.util.extensions.clipboard import dev.msfjarvis.aps.util.extensions.sharedPrefs @@ -29,6 +28,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.logcat class ClipboardService : Service() { @@ -82,7 +82,7 @@ class ClipboardService : Service() { if (clipboard != null) { scope.launch { - d { "Clearing the clipboard" } + logcat { "Clearing the clipboard" } val clip = ClipData.newPlainText("pgp_handler_result_pm", "") clipboard.setPrimaryClip(clip) if (deepClear) { @@ -95,7 +95,7 @@ class ClipboardService : Service() { } } } else { - d { "Cannot get clipboard manager service" } + logcat { "Cannot get clipboard manager service" } } } @@ -169,7 +169,7 @@ class ClipboardService : Service() { if (manager != null) { manager.createNotificationChannel(serviceChannel) } else { - d { "Failed to create notification channel" } + logcat { "Failed to create notification channel" } } } } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/services/OreoAutofillService.kt b/app/src/main/java/dev/msfjarvis/aps/util/services/OreoAutofillService.kt index 4c75a619..a52caff0 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/services/OreoAutofillService.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/services/OreoAutofillService.kt @@ -14,8 +14,6 @@ import android.service.autofill.FillResponse import android.service.autofill.SaveCallback import android.service.autofill.SaveRequest import androidx.annotation.RequiresApi -import com.github.ajalt.timberkt.d -import com.github.ajalt.timberkt.e import com.github.androidpasswordstore.autofillparser.AutofillScenario import com.github.androidpasswordstore.autofillparser.Credentials import com.github.androidpasswordstore.autofillparser.FillableForm @@ -34,6 +32,8 @@ import dev.msfjarvis.aps.util.extensions.getString import dev.msfjarvis.aps.util.extensions.hasFlag import dev.msfjarvis.aps.util.extensions.sharedPrefs import dev.msfjarvis.aps.util.settings.PreferenceKeys +import logcat.LogPriority.ERROR +import logcat.logcat @RequiresApi(Build.VERSION_CODES.O) class OreoAutofillService : AutofillService() { @@ -92,7 +92,7 @@ class OreoAutofillService : AutofillService() { getCustomSuffixes(), ) ?: run { - d { "Form cannot be filled" } + logcat { "Form cannot be filled" } callback.onSuccess(null) return } @@ -117,21 +117,21 @@ class OreoAutofillService : AutofillService() { val clientState = request.clientState ?: run { - e { "Received save request without client state" } + logcat(ERROR) { "Received save request without client state" } callback.onFailure(getString(R.string.oreo_autofill_save_internal_error)) return } val scenario = AutofillScenario.fromClientState(clientState)?.recoverNodes(structure) ?: run { - e { "Failed to recover client state or nodes from client state" } + logcat(ERROR) { "Failed to recover client state or nodes from client state" } callback.onFailure(getString(R.string.oreo_autofill_save_internal_error)) return } val formOrigin = FormOrigin.fromBundle(clientState) ?: run { - e { "Failed to recover form origin from client state" } + logcat(ERROR) { "Failed to recover form origin from client state" } callback.onFailure(getString(R.string.oreo_autofill_save_internal_error)) return } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/services/PasswordExportService.kt b/app/src/main/java/dev/msfjarvis/aps/util/services/PasswordExportService.kt index 72f14144..6740fc04 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/services/PasswordExportService.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/services/PasswordExportService.kt @@ -15,13 +15,13 @@ import android.os.IBinder import androidx.core.app.NotificationCompat import androidx.core.content.getSystemService import androidx.documentfile.provider.DocumentFile -import com.github.ajalt.timberkt.d import dev.msfjarvis.aps.R import dev.msfjarvis.aps.data.repo.PasswordRepository import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.Calendar import java.util.TimeZone +import logcat.logcat class PasswordExportService : Service() { @@ -62,7 +62,7 @@ class PasswordExportService : Service() { val repositoryDirectory = requireNotNull(PasswordRepository.getRepositoryDirectory()) val sourcePassDir = DocumentFile.fromFile(repositoryDirectory) - d { "Copying ${repositoryDirectory.path} to $targetDirectory" } + logcat { "Copying ${repositoryDirectory.path} to $targetDirectory" } val dateString = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -146,7 +146,7 @@ class PasswordExportService : Service() { if (manager != null) { manager.createNotificationChannel(serviceChannel) } else { - d { "Failed to create notification channel" } + logcat { "Failed to create notification channel" } } } } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/settings/Migrations.kt b/app/src/main/java/dev/msfjarvis/aps/util/settings/Migrations.kt index b24914d0..c001091d 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/settings/Migrations.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/settings/Migrations.kt @@ -8,14 +8,17 @@ package dev.msfjarvis.aps.util.settings import android.content.SharedPreferences import androidx.core.content.edit -import com.github.ajalt.timberkt.e -import com.github.ajalt.timberkt.i import com.github.michaelbull.result.get import com.github.michaelbull.result.runCatching import dev.msfjarvis.aps.util.extensions.getString import dev.msfjarvis.aps.util.git.sshj.SshKey import java.io.File import java.net.URI +import logcat.LogPriority.ERROR +import logcat.LogPriority.INFO +import logcat.logcat + +private const val TAG = "Migrations" fun runMigrations(filesDirPath: String, sharedPrefs: SharedPreferences, gitSettings: GitSettings) { migrateToGitUrlBasedConfig(sharedPrefs, gitSettings) @@ -26,7 +29,7 @@ fun runMigrations(filesDirPath: String, sharedPrefs: SharedPreferences, gitSetti private fun migrateToGitUrlBasedConfig(sharedPrefs: SharedPreferences, gitSettings: GitSettings) { val serverHostname = sharedPrefs.getString(PreferenceKeys.GIT_REMOTE_SERVER) ?: return - i { "Migrating to URL-based Git config" } + logcat(TAG, INFO) { "Migrating to URL-based Git config" } val serverPort = sharedPrefs.getString(PreferenceKeys.GIT_REMOTE_PORT) ?: "" val serverUser = sharedPrefs.getString(PreferenceKeys.GIT_REMOTE_USERNAME) ?: "" val serverPath = sharedPrefs.getString(PreferenceKeys.GIT_REMOTE_LOCATION) ?: "" @@ -79,7 +82,7 @@ private fun migrateToGitUrlBasedConfig(sharedPrefs: SharedPreferences, gitSettin newBranch = gitSettings.branch ) != GitSettings.UpdateConnectionSettingsResult.Valid ) { - e { "Failed to migrate to URL-based Git config, generated URL is invalid" } + logcat(TAG, ERROR) { "Failed to migrate to URL-based Git config, generated URL is invalid" } } } diff --git a/app/src/main/java/dev/msfjarvis/aps/util/shortcuts/ShortcutHandler.kt b/app/src/main/java/dev/msfjarvis/aps/util/shortcuts/ShortcutHandler.kt index 8e36c9af..59eda23e 100644 --- a/app/src/main/java/dev/msfjarvis/aps/util/shortcuts/ShortcutHandler.kt +++ b/app/src/main/java/dev/msfjarvis/aps/util/shortcuts/ShortcutHandler.kt @@ -13,12 +13,12 @@ import android.graphics.drawable.Icon import android.os.Build import androidx.annotation.RequiresApi import androidx.core.content.getSystemService -import com.github.ajalt.timberkt.d import dagger.Reusable import dagger.hilt.android.qualifiers.ApplicationContext import dev.msfjarvis.aps.R import dev.msfjarvis.aps.data.password.PasswordItem import javax.inject.Inject +import logcat.logcat @Reusable class ShortcutHandler @@ -70,7 +70,7 @@ constructor( if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return val shortcutManager: ShortcutManager = context.getSystemService() ?: return if (!shortcutManager.isRequestPinShortcutSupported) { - d { "addPinnedShortcut: pin shortcuts unsupported" } + logcat { "addPinnedShortcut: pin shortcuts unsupported" } return } val shortcut = buildShortcut(item, intent) diff --git a/app/src/nonFree/java/dev/msfjarvis/aps/autofill/oreo/ui/AutofillSmsActivity.kt b/app/src/nonFree/java/dev/msfjarvis/aps/autofill/oreo/ui/AutofillSmsActivity.kt index 5e53bf3e..094c6c33 100644 --- a/app/src/nonFree/java/dev/msfjarvis/aps/autofill/oreo/ui/AutofillSmsActivity.kt +++ b/app/src/nonFree/java/dev/msfjarvis/aps/autofill/oreo/ui/AutofillSmsActivity.kt @@ -17,8 +17,6 @@ import android.view.autofill.AutofillManager import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.e -import com.github.ajalt.timberkt.w import com.github.androidpasswordstore.autofillparser.AutofillAction import com.github.androidpasswordstore.autofillparser.Credentials import com.github.michaelbull.result.onFailure @@ -39,6 +37,8 @@ import kotlin.coroutines.suspendCoroutine import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import logcat.LogPriority.WARN +import logcat.logcat suspend fun <T> Task<T>.suspendableAwait() = suspendCoroutine<T> { cont -> @@ -62,14 +62,14 @@ class AutofillSmsActivity : AppCompatActivity() { val googleApiAvailabilityInstance = GoogleApiAvailability.getInstance() val googleApiStatus = googleApiAvailabilityInstance.isGooglePlayServicesAvailable(context) if (googleApiStatus != ConnectionResult.SUCCESS) { - w { + logcat(WARN) { "Google Play Services unavailable or not updated: ${googleApiAvailabilityInstance.getErrorString(googleApiStatus)}" } return false } // https://developer.android.com/guide/topics/text/autofill-services#sms-autofill if (googleApiAvailabilityInstance.getApkVersion(context) < 190056000) { - w { "Google Play Service 19.0.56 or higher required for SMS OTP Autofill" } + logcat(WARN) { "Google Play Service 19.0.56 or higher required for SMS OTP Autofill" } return false } return true @@ -103,7 +103,7 @@ class AutofillSmsActivity : AppCompatActivity() { clientState = intent?.getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE) ?: run { - e { "AutofillSmsActivity started without EXTRA_CLIENT_STATE" } + logcat(WARN) { "AutofillSmsActivity started without EXTRA_CLIENT_STATE" } finish() return } diff --git a/autofill-parser/build.gradle.kts b/autofill-parser/build.gradle.kts index be71acf0..ed5b5b35 100644 --- a/autofill-parser/build.gradle.kts +++ b/autofill-parser/build.gradle.kts @@ -21,6 +21,6 @@ dependencies { implementation(libs.androidx.autofill) implementation(libs.kotlin.coroutines.android) implementation(libs.kotlin.coroutines.core) - implementation(libs.thirdparty.timberkt) + implementation(libs.thirdparty.logcat) testImplementation(libs.bundles.testDependencies) } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt index 85381254..66205bbc 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt @@ -12,7 +12,7 @@ import android.os.Build import android.os.Bundle import android.view.autofill.AutofillId import androidx.annotation.RequiresApi -import com.github.ajalt.timberkt.d +import logcat.logcat /** * A unique identifier for either an Android app (package name) or a website (origin minus port). @@ -84,7 +84,7 @@ private class AutofillFormParser( private val webOrigins = mutableSetOf<String>() init { - d { "Request from $appPackage (${computeCertificatesHash(context, appPackage)})" } + logcat { "Request from $appPackage (${computeCertificatesHash(context, appPackage)})" } parseStructure(structure) } @@ -92,7 +92,7 @@ private class AutofillFormParser( val formOrigin = determineFormOrigin(context) init { - d { "Origin: $formOrigin" } + logcat { "Origin: $formOrigin" } } private fun parseStructure(structure: AssistStructure) { @@ -111,11 +111,11 @@ private class AutofillFormParser( FormField(node, fieldIndex, false) } if (field.relevantField) { - d { "Relevant: $field" } + logcat { "Relevant: $field" } relevantFields.add(field) fieldIndex++ } else { - d { "Ignored : $field" } + logcat { "Ignored : $field" } ignoredIds.add(field.autofillId) } for (i in 0 until node.childCount) { @@ -134,7 +134,7 @@ private class AutofillFormParser( if (trustedBrowserInfo == null) return node.webOrigin?.let { if (it !in webOrigins) { - d { "Origin encountered: $it" } + logcat { "Origin encountered: $it" } webOrigins.add(it) } } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt index 2de929b9..e8f661ef 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt @@ -15,9 +15,9 @@ import android.util.Base64 import android.view.autofill.AutofillId import android.widget.Toast import androidx.annotation.RequiresApi -import com.github.ajalt.timberkt.Timber.tag -import com.github.ajalt.timberkt.e import java.security.MessageDigest +import logcat.LogPriority.ERROR +import logcat.logcat private fun ByteArray.sha256(): ByteArray { return MessageDigest.getInstance("SHA-256").run { @@ -59,7 +59,7 @@ public fun computeCertificatesHash(context: Context, appPackage: String): String info.signingInfo.signingCertificateHistory ?: info.signingInfo.apkContentsSigners val stableHashNew = stableHash(signaturesNew.map { it.toByteArray() }) if (stableHashNew != stableHashOld) - tag("CertificatesHash").e { + logcat("CertificatesHash", ERROR) { "Mismatch between old and new hash: $stableHashNew != $stableHashOld" } } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt index 11b85b66..fec33285 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt @@ -11,7 +11,9 @@ import android.service.autofill.Dataset import android.view.autofill.AutofillId import android.view.autofill.AutofillValue import androidx.annotation.RequiresApi -import com.github.ajalt.timberkt.e +import logcat.LogPriority.ERROR +import logcat.asLog +import logcat.logcat public enum class AutofillAction { Match, @@ -68,7 +70,7 @@ public sealed class AutofillScenario<out T : Any> { } .build() } catch (e: Throwable) { - e(e) + logcat(ERROR) { e.asLog() } null } } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategyDsl.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategyDsl.kt index 3d7f9849..6d2414d2 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategyDsl.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategyDsl.kt @@ -6,8 +6,8 @@ package com.github.androidpasswordstore.autofillparser import android.os.Build import androidx.annotation.RequiresApi -import com.github.ajalt.timberkt.d -import com.github.ajalt.timberkt.w +import logcat.LogPriority.WARN +import logcat.logcat @DslMarker internal annotation class AutofillDsl @@ -116,16 +116,16 @@ internal class SingleFieldMatcher( val new = current.filter { tieBreaker(it, alreadyMatched) } // skipping those tie breakers that are not satisfied for any remaining field... if (new.isEmpty()) { - d { "Tie breaker #${i + 1}: Didn't match any field; skipping" } + logcat { "Tie breaker #${i + 1}: Didn't match any field; skipping" } continue } // and return if the available options have been narrowed to a single field. if (new.size == 1) { - d { "Tie breaker #${i + 1}: Success" } + logcat { "Tie breaker #${i + 1}: Success" } current = new break } - d { "Tie breaker #${i + 1}: Matched ${new.size} fields; continuing" } + logcat { "Tie breaker #${i + 1}: Matched ${new.size} fields; continuing" } current = new } listOf(current.singleOrNull() ?: return null) @@ -154,16 +154,16 @@ private class PairOfFieldsMatcher( for ((i, tieBreaker) in tieBreakers.withIndex()) { val new = current.filter { tieBreaker(it, alreadyMatched) } if (new.isEmpty()) { - d { "Tie breaker #${i + 1}: Didn't match any pair of fields; skipping" } + logcat { "Tie breaker #${i + 1}: Didn't match any pair of fields; skipping" } continue } // and return if the available options have been narrowed to a single field. if (new.size == 1) { - d { "Tie breaker #${i + 1}: Success" } + logcat { "Tie breaker #${i + 1}: Success" } current = new break } - d { "Tie breaker #${i + 1}: Matched ${new.size} pairs of fields; continuing" } + logcat { "Tie breaker #${i + 1}: Matched ${new.size} pairs of fields; continuing" } current = new } current.singleOrNull()?.toList() @@ -323,14 +323,14 @@ private constructor( isManualRequest: Boolean ): AutofillScenario<FormField>? { if (singleOriginMode && !applyInSingleOriginMode) { - d { "$name: Skipped in single origin mode" } + logcat { "$name: Skipped in single origin mode" } return null } if (!isManualRequest && applyOnManualRequestOnly) { - d { "$name: Skipped since not a manual request" } + logcat { "$name: Skipped since not a manual request" } return null } - d { "$name: Applying..." } + logcat { "$name: Applying..." } val scenarioBuilder = AutofillScenario.Builder<FormField>() val alreadyMatched = mutableListOf<FormField>() for ((type, matcher, optional, matchHidden) in matchers) { @@ -343,13 +343,13 @@ private constructor( val matchResult = matcher.match(fieldsToMatchOn, alreadyMatched) ?: if (optional) { - d { "$name: Skipping optional $type matcher" } + logcat { "$name: Skipping optional $type matcher" } continue } else { - d { "$name: Required $type matcher didn't match; passing to next rule" } + logcat { "$name: Required $type matcher didn't match; passing to next rule" } return null } - d { "$name: Matched $type" } + logcat { "$name: Matched $type" } when (type) { FillableFieldType.Username -> { check(matchResult.size == 1 && scenarioBuilder.username == null) @@ -370,9 +370,9 @@ private constructor( return scenarioBuilder.build().takeIf { scenario -> scenario.passesOriginCheck(singleOriginMode = singleOriginMode).also { passed -> if (passed) { - d { "$name: Detected scenario:\n$scenario" } + logcat { "$name: Detected scenario:\n$scenario" } } else { - w { "$name: Scenario failed origin check:\n$scenario" } + logcat(WARN) { "$name: Scenario failed origin check:\n$scenario" } } } } @@ -411,13 +411,13 @@ internal class AutofillStrategy private constructor(private val rules: List<Auto isManualRequest: Boolean ): AutofillScenario<FormField>? { val possiblePasswordFields = fields.filter { it.passwordCertainty >= CertaintyLevel.Possible } - d { "Possible password fields: ${possiblePasswordFields.size}" } + logcat { "Possible password fields: ${possiblePasswordFields.size}" } val possibleUsernameFields = fields.filter { it.usernameCertainty >= CertaintyLevel.Possible } - d { "Possible username fields: ${possibleUsernameFields.size}" } + logcat { "Possible username fields: ${possibleUsernameFields.size}" } val possibleOtpFields = fields.filter { it.otpCertainty >= CertaintyLevel.Possible } - d { "Possible otp fields: ${possibleOtpFields.size}" } + logcat { "Possible otp fields: ${possibleOtpFields.size}" } // Return the result of the first rule that matches - d { "Rules: ${rules.size}" } + logcat { "Rules: ${rules.size}" } for (rule in rules) { return rule.match( possiblePasswordFields, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3aec93dc..e577433e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -74,12 +74,11 @@ thirdparty-flowbinding-android = { module = "io.github.reactivecircus.flowbindin thirdparty-jgit = "org.eclipse.jgit:org.eclipse.jgit:3.7.1.201504261725-r" thirdparty-kotlinResult = "com.michael-bull.kotlin-result:kotlin-result:1.1.12" thirdparty-leakcanary = "com.squareup.leakcanary:leakcanary-android:2.7" +thirdparty-logcat = "com.squareup.logcat:logcat:0.1" thirdparty-modernAndroidPrefs = "de.maxr1998:modernandroidpreferences:2.1.0" thirdparty-plumber = "com.squareup.leakcanary:plumber-android:2.7" thirdparty-sshj = "com.hierynomus:sshj:0.31.0" thirdparty-sshauth = "com.github.open-keychain.open-keychain:sshauthentication-api:5.7.5" -thirdparty-timber = "com.jakewharton.timber:timber:5.0.1" -thirdparty-timberkt = "com.github.ajalt:timberkt:1.5.1" thirdparty-whatthestack = "com.github.haroldadmin:WhatTheStack:0.3.1" thirdparty-nonfree-googlePlayAuthApiPhone = "com.google.android.gms:play-services-auth-api-phone:17.5.1" |