aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.kt
diff options
context:
space:
mode:
Diffstat (limited to 'ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.kt')
-rw-r--r--ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.kt94
1 files changed, 94 insertions, 0 deletions
diff --git a/ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.kt b/ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.kt
new file mode 100644
index 00000000..b4671309
--- /dev/null
+++ b/ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package com.wireguard.android.preference
+
+import android.Manifest
+import android.content.Context
+import android.content.pm.PackageManager
+import android.util.AttributeSet
+import android.util.Log
+import androidx.preference.Preference
+import com.google.android.material.snackbar.Snackbar
+import com.wireguard.android.Application
+import com.wireguard.android.R
+import com.wireguard.android.util.DownloadsFileSaver
+import com.wireguard.android.util.ErrorMessages
+import com.wireguard.android.util.FragmentUtils
+import java.io.BufferedReader
+import java.io.InputStreamReader
+
+/**
+ * Preference implementing a button that asynchronously exports logs.
+ */
+class LogExporterPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
+ private var exportedFilePath: String? = null
+ private fun exportLog() {
+ Application.getAsyncWorker().supplyAsync {
+ val outputFile = DownloadsFileSaver.save(context, "wireguard-log.txt", "text/plain", true)
+ try {
+ val process = Runtime.getRuntime().exec(arrayOf(
+ "logcat", "-b", "all", "-d", "-v", "threadtime", "*:V"))
+ BufferedReader(InputStreamReader(process.inputStream)).use { stdout ->
+ BufferedReader(InputStreamReader(process.errorStream)).use { stderr ->
+ while (true) {
+ val line = stdout.readLine() ?: break
+ outputFile.outputStream.write(line.toByteArray())
+ outputFile.outputStream.write('\n'.toInt())
+ }
+ outputFile.outputStream.close()
+ if (process.waitFor() != 0) {
+ val errors = StringBuilder()
+ errors.append(R.string.logcat_error)
+ while (true) {
+ val line = stderr.readLine() ?: break
+ errors.append(line)
+ }
+ throw Exception(errors.toString())
+ }
+ }
+ }
+ } catch (e: Exception) {
+ outputFile.delete()
+ throw e
+ }
+ outputFile.fileName
+ }.whenComplete(this::exportLogComplete)
+ }
+
+ private fun exportLogComplete(filePath: String, throwable: Throwable?) {
+ if (throwable != null) {
+ val error = ErrorMessages.get(throwable)
+ val message = context.getString(R.string.log_export_error, error)
+ Log.e(TAG, message, throwable)
+ Snackbar.make(
+ FragmentUtils.getPrefActivity(this).findViewById(android.R.id.content),
+ message, Snackbar.LENGTH_LONG).show()
+ isEnabled = true
+ } else {
+ exportedFilePath = filePath
+ notifyChanged()
+ }
+ }
+
+ override fun getSummary() = if (exportedFilePath == null)
+ context.getString(R.string.log_export_summary)
+ else
+ context.getString(R.string.log_export_success, exportedFilePath)
+
+ override fun getTitle() = context.getString(R.string.log_export_title)
+
+ override fun onClick() {
+ FragmentUtils.getPrefActivity(this).ensurePermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { _, granted ->
+ if (granted.isNotEmpty() && granted[0] == PackageManager.PERMISSION_GRANTED) {
+ isEnabled = false
+ exportLog()
+ }
+ }
+ }
+
+ companion object {
+ private val TAG = "WireGuard/" + LogExporterPreference::class.java.simpleName
+ }
+}