From 74c55e99472dfe3a4105e7ec12bb7528d53fd848 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Wed, 2 Feb 2022 16:01:59 +0800 Subject: [PATCH] Fix log save (#1605) --- .../main/java/org/lsposed/manager/App.java | 6 +- .../org/lsposed/manager/ConfigManager.java | 9 --- .../manager/ui/fragment/LogsFragment.java | 37 ++--------- .../org/lsposed/manager/util/BackupUtils.java | 10 +-- daemon/src/main/cpp/logcat.cpp | 9 +-- .../lspd/service/ConfigFileManager.java | 61 ++++++++++++++++--- .../lspd/service/LSPManagerService.java | 4 +- .../org/lsposed/lspd/ILSPManagerService.aidl | 2 +- 8 files changed, 71 insertions(+), 67 deletions(-) diff --git a/app/src/main/java/org/lsposed/manager/App.java b/app/src/main/java/org/lsposed/manager/App.java index 0f89ee75..f4d7d2fb 100644 --- a/app/src/main/java/org/lsposed/manager/App.java +++ b/app/src/main/java/org/lsposed/manager/App.java @@ -63,6 +63,7 @@ import java.util.concurrent.FutureTask; import okhttp3.Cache; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; +import rikka.core.os.FileUtils; import rikka.material.app.DayNightDelegate; import rikka.material.app.LocaleDelegate; @@ -74,10 +75,7 @@ public class App extends Application { try { var input = App.getInstance().getAssets().open("webview/" + name); var result = new ByteArrayOutputStream(1024); - var buffer = new byte[1024]; - for (int length; (length = input.read(buffer)) != -1; ) { - result.write(buffer, 0, length); - } + FileUtils.copy(input, result); return result.toString(StandardCharsets.UTF_8.name()); } catch (IOException e) { Log.e(App.TAG, "read webview HTML", e); diff --git a/app/src/main/java/org/lsposed/manager/ConfigManager.java b/app/src/main/java/org/lsposed/manager/ConfigManager.java index 48f2b21b..0a3621c3 100644 --- a/app/src/main/java/org/lsposed/manager/ConfigManager.java +++ b/app/src/main/java/org/lsposed/manager/ConfigManager.java @@ -314,15 +314,6 @@ public class ConfigManager { } } - public static Map getLogs() { - try { - return LSPManagerServiceHolder.getService().getLogs(); - } catch (RemoteException e) { - Log.e(App.TAG, Log.getStackTraceString(e)); - return new HashMap<>(); - } - } - public static String getApi() { try { return LSPManagerServiceHolder.getService().getApi(); diff --git a/app/src/main/java/org/lsposed/manager/ui/fragment/LogsFragment.java b/app/src/main/java/org/lsposed/manager/ui/fragment/LogsFragment.java index 4a7b3592..843e43cc 100644 --- a/app/src/main/java/org/lsposed/manager/ui/fragment/LogsFragment.java +++ b/app/src/main/java/org/lsposed/manager/ui/fragment/LogsFragment.java @@ -50,11 +50,11 @@ import org.lsposed.manager.R; import org.lsposed.manager.databinding.FragmentPagerBinding; import org.lsposed.manager.databinding.ItemLogTextviewBinding; import org.lsposed.manager.databinding.SwiperefreshRecyclerviewBinding; +import org.lsposed.manager.receivers.LSPManagerServiceHolder; import org.lsposed.manager.ui.widget.EmptyStateRecyclerView; import java.io.BufferedReader; import java.io.FileInputStream; -import java.io.IOException; import java.io.InputStreamReader; import java.time.LocalDateTime; import java.util.Arrays; @@ -62,11 +62,7 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; -import java.util.zip.Deflater; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; -import rikka.core.os.FileUtils; import rikka.material.app.LocaleDelegate; import rikka.recyclerview.RecyclerViewKt; @@ -89,11 +85,9 @@ public class LogsFragment extends BaseFragment { runAsync(() -> { var context = requireContext(); var contentResolver = context.getContentResolver(); - try (var os = new ZipOutputStream(contentResolver.openOutputStream(uri))) { - os.setLevel(Deflater.BEST_COMPRESSION); - zipLogs(os); - os.finish(); - } catch (IOException e) { + try (var zipFd = contentResolver.openFileDescriptor(uri, "wt")) { + LSPManagerServiceHolder.getService().getLogs(zipFd); + } catch (Throwable e) { var text = context.getString(R.string.logs_save_failed2, e.getMessage()); showHint(text, false); Log.w(App.TAG, "save log", e); @@ -171,29 +165,6 @@ public class LogsFragment extends BaseFragment { saveLogsLauncher.launch(filename); } - private static void zipLogs(ZipOutputStream os) { - var logs = ConfigManager.getLogs(); - logs.forEach((name, fd) -> { - try (var is = new FileInputStream(fd.getFileDescriptor())) { - os.putNextEntry(new ZipEntry(name)); - FileUtils.copy(is, os); - os.closeEntry(); - } catch (IOException e) { - Log.w(App.TAG, name, e); - } - }); - - var now = LocalDateTime.now(); - var name = "app_" + now.toString() + ".log"; - try (var is = new ProcessBuilder("logcat", "-d").start().getInputStream()) { - os.putNextEntry(new ZipEntry(name)); - FileUtils.copy(is, os); - os.closeEntry(); - } catch (IOException e) { - Log.w(App.TAG, name, e); - } - } - @Override public void onDestroy() { handler.removeCallbacksAndMessages(null); diff --git a/app/src/main/java/org/lsposed/manager/util/BackupUtils.java b/app/src/main/java/org/lsposed/manager/util/BackupUtils.java index 5b8734b2..0ce966ae 100644 --- a/app/src/main/java/org/lsposed/manager/util/BackupUtils.java +++ b/app/src/main/java/org/lsposed/manager/util/BackupUtils.java @@ -29,12 +29,15 @@ import org.lsposed.manager.App; import org.lsposed.manager.ConfigManager; import org.lsposed.manager.adapters.ScopeAdapter; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; +import rikka.core.os.FileUtils; + public class BackupUtils { private static final int VERSION = 2; @@ -79,10 +82,9 @@ public class BackupUtils { public static void restore(Uri uri, String packageName) throws IOException, JSONException { try (GZIPInputStream gzipInputStream = new GZIPInputStream(App.getInstance().getContentResolver().openInputStream(uri), 32)) { StringBuilder string = new StringBuilder(); - byte[] data = new byte[32]; - int bytesRead; - while ((bytesRead = gzipInputStream.read(data)) != -1) { - string.append(new String(data, 0, bytesRead)); + try (var os = new ByteArrayOutputStream()) { + FileUtils.copy(gzipInputStream, os); + string.append(os); } gzipInputStream.close(); JSONObject rootObject = new JSONObject(string.toString()); diff --git a/daemon/src/main/cpp/logcat.cpp b/daemon/src/main/cpp/logcat.cpp index fe90a511..1343e99d 100644 --- a/daemon/src/main/cpp/logcat.cpp +++ b/daemon/src/main/cpp/logcat.cpp @@ -105,7 +105,7 @@ private: inline void Log(std::string_view str); - void OnCrash(); + void OnCrash(int err); void ProcessBuffer(struct log_msg *buf); @@ -191,7 +191,8 @@ inline void Logcat::Log(std::string_view str) { fflush(modules_file_.get()); } -void Logcat::OnCrash() { +void Logcat::OnCrash(int err) { + using namespace std::string_literals; constexpr size_t max_restart_logd_wait = 1U << 10; static size_t kLogdCrashCount = 0; static size_t kLogdRestartWait = 1 << 3; @@ -204,7 +205,7 @@ void Logcat::OnCrash() { kLogdCrashCount = 0; } } else { - Log("\nLogd maybe crashed, retrying in 1s...\n"); + Log("\nLogd maybe crashed (err="s + strerror(err) + "), retrying in 1s...\n"); } std::this_thread::sleep_for(1s); @@ -317,7 +318,7 @@ void Logcat::Run() { if (modules_print_count_ >= kMaxLogSize) [[unlikely]] RefreshFd(false); } - OnCrash(); + OnCrash(errno); } } diff --git a/daemon/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java b/daemon/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java index ebaeead0..252e62d1 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/ConfigFileManager.java @@ -7,6 +7,7 @@ import android.content.res.AssetManager; import android.content.res.Resources; import android.os.ParcelFileDescriptor; import android.os.Process; +import android.os.RemoteException; import android.os.SELinux; import android.os.SharedMemory; import android.system.ErrnoException; @@ -22,8 +23,12 @@ import org.lsposed.lspd.util.Utils; import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.lang.reflect.Method; import java.nio.channels.Channels; import java.nio.channels.FileChannel; @@ -45,7 +50,9 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; import hidden.HiddenApiBridge; @@ -77,6 +84,15 @@ public class ConfigFileManager { } } + public static void transfer(InputStream in, OutputStream out) throws IOException { + int size = 8192; + var buffer = new byte[size]; + int read; + while ((read = in.read(buffer, 0, size)) >= 0) { + out.write(buffer, 0, read); + } + } + private static void createLogDirPath() throws IOException { if (!Files.isDirectory(logDirPath, LinkOption.NOFOLLOW_LINKS)) { Files.deleteIfExists(logDirPath); @@ -194,17 +210,42 @@ public class ConfigFileManager { return logDirPath.resolve("props.txt").toFile(); } - static Map getLogs() { - var map = new LinkedHashMap(); - try { - putFds(map, logDirPath); - putFds(map, oldLogDirPath); - putFds(map, Paths.get("/data/tombstones")); - putFds(map, Paths.get("/data/anr")); - } catch (IOException e) { - Log.e(TAG, "getLogs", e); + static void getLogs(ParcelFileDescriptor zipFd) throws RemoteException { + var logs = new LinkedHashMap(); + try (var os = new ZipOutputStream(new FileOutputStream(zipFd.getFileDescriptor()))) { + putFds(logs, logDirPath); + putFds(logs, oldLogDirPath); + putFds(logs, Paths.get("/data/tombstones")); + putFds(logs, Paths.get("/data/anr")); + logs.forEach((name, fd) -> { + try (var is = new FileInputStream(fd.getFileDescriptor())) { + os.putNextEntry(new ZipEntry(name)); + transfer(is, os); + os.closeEntry(); + } catch (IOException e) { + Log.w(TAG, name, e); + } + }); + var name = "full.log"; + try (var is = new ProcessBuilder("logcat", "-d").start().getInputStream()) { + os.putNextEntry(new ZipEntry(name)); + transfer(is, os); + os.closeEntry(); + } catch (IOException e) { + Log.w(TAG, name, e); + } + name = "dmesg.log"; + try (var is = new ProcessBuilder("dmesg").start().getInputStream()) { + os.putNextEntry(new ZipEntry(name)); + transfer(is, os); + os.closeEntry(); + } catch (IOException e) { + Log.w(TAG, name, e); + } + } catch (Throwable e) { + Log.w(TAG, "get log", e); + throw new RemoteException(Log.getStackTraceString(e)); } - return map; } private static void putFds(Map map, Path path) throws IOException { diff --git a/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java b/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java index 28fa690b..393a5259 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java @@ -711,8 +711,8 @@ public class LSPManagerService extends ILSPManagerService.Stub { } @Override - public Map getLogs() { - return ConfigFileManager.getLogs(); + public void getLogs(ParcelFileDescriptor zipFd) throws RemoteException { + ConfigFileManager.getLogs(zipFd); } @Override diff --git a/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl b/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl index c9db96c2..d434db83 100644 --- a/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl +++ b/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl @@ -60,7 +60,7 @@ interface ILSPManagerService { void setHiddenIcon(boolean hide) = 33; - Map getLogs() = 34; + void getLogs(in ParcelFileDescriptor zipFd) = 34; void restartFor(in Intent intent) = 35;