diff options
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.kt | 94 |
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 + } +} |