aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.java
diff options
context:
space:
mode:
Diffstat (limited to 'ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.java')
-rw-r--r--ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.java112
1 files changed, 112 insertions, 0 deletions
diff --git a/ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.java b/ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.java
new file mode 100644
index 00000000..565854b4
--- /dev/null
+++ b/ui/src/main/java/com/wireguard/android/preference/LogExporterPreference.java
@@ -0,0 +1,112 @@
+/*
+ * 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 androidx.annotation.Nullable;
+import com.google.android.material.snackbar.Snackbar;
+import androidx.preference.Preference;
+
+import android.util.AttributeSet;
+import android.util.Log;
+
+import com.wireguard.android.Application;
+import com.wireguard.android.R;
+import com.wireguard.android.util.DownloadsFileSaver;
+import com.wireguard.android.util.DownloadsFileSaver.DownloadsFile;
+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.
+ */
+
+public class LogExporterPreference extends Preference {
+ private static final String TAG = "WireGuard/" + LogExporterPreference.class.getSimpleName();
+
+ @Nullable private String exportedFilePath;
+
+ public LogExporterPreference(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ private void exportLog() {
+ Application.getAsyncWorker().supplyAsync(() -> {
+ DownloadsFile outputFile = DownloadsFileSaver.save(getContext(), "wireguard-log.txt", "text/plain", true);
+ try {
+ final Process process = Runtime.getRuntime().exec(new String[]{
+ "logcat", "-b", "all", "-d", "-v", "threadtime", "*:V"});
+ try (final BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ final BufferedReader stderr = new BufferedReader(new InputStreamReader(process.getErrorStream())))
+ {
+ String line;
+ while ((line = stdout.readLine()) != null) {
+ outputFile.getOutputStream().write(line.getBytes());
+ outputFile.getOutputStream().write('\n');
+ }
+ outputFile.getOutputStream().close();
+ stdout.close();
+ if (process.waitFor() != 0) {
+ final StringBuilder errors = new StringBuilder();
+ errors.append(R.string.logcat_error);
+ while ((line = stderr.readLine()) != null)
+ errors.append(line);
+ throw new Exception(errors.toString());
+ }
+ }
+ } catch (final Exception e) {
+ outputFile.delete();
+ throw e;
+ }
+ return outputFile.getFileName();
+ }).whenComplete(this::exportLogComplete);
+ }
+
+ private void exportLogComplete(final String filePath, @Nullable final Throwable throwable) {
+ if (throwable != null) {
+ final String error = ErrorMessages.get(throwable);
+ final String message = getContext().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();
+ setEnabled(true);
+ } else {
+ exportedFilePath = filePath;
+ notifyChanged();
+ }
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return exportedFilePath == null ?
+ getContext().getString(R.string.log_export_summary) :
+ getContext().getString(R.string.log_export_success, exportedFilePath);
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return getContext().getString(R.string.log_export_title);
+ }
+
+ @Override
+ protected void onClick() {
+ FragmentUtils.getPrefActivity(this).ensurePermissions(
+ new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ (permissions, granted) -> {
+ if (granted.length > 0 && granted[0] == PackageManager.PERMISSION_GRANTED) {
+ setEnabled(false);
+ exportLog();
+ }
+ });
+ }
+
+}