Fix log save (#1605)

This commit is contained in:
LoveSy 2022-02-02 16:01:59 +08:00 committed by GitHub
parent a885818a4d
commit 74c55e9947
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 71 additions and 67 deletions

View File

@ -63,6 +63,7 @@ import java.util.concurrent.FutureTask;
import okhttp3.Cache; import okhttp3.Cache;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import rikka.core.os.FileUtils;
import rikka.material.app.DayNightDelegate; import rikka.material.app.DayNightDelegate;
import rikka.material.app.LocaleDelegate; import rikka.material.app.LocaleDelegate;
@ -74,10 +75,7 @@ public class App extends Application {
try { try {
var input = App.getInstance().getAssets().open("webview/" + name); var input = App.getInstance().getAssets().open("webview/" + name);
var result = new ByteArrayOutputStream(1024); var result = new ByteArrayOutputStream(1024);
var buffer = new byte[1024]; FileUtils.copy(input, result);
for (int length; (length = input.read(buffer)) != -1; ) {
result.write(buffer, 0, length);
}
return result.toString(StandardCharsets.UTF_8.name()); return result.toString(StandardCharsets.UTF_8.name());
} catch (IOException e) { } catch (IOException e) {
Log.e(App.TAG, "read webview HTML", e); Log.e(App.TAG, "read webview HTML", e);

View File

@ -314,15 +314,6 @@ public class ConfigManager {
} }
} }
public static Map<String, ParcelFileDescriptor> getLogs() {
try {
return LSPManagerServiceHolder.getService().getLogs();
} catch (RemoteException e) {
Log.e(App.TAG, Log.getStackTraceString(e));
return new HashMap<>();
}
}
public static String getApi() { public static String getApi() {
try { try {
return LSPManagerServiceHolder.getService().getApi(); return LSPManagerServiceHolder.getService().getApi();

View File

@ -50,11 +50,11 @@ import org.lsposed.manager.R;
import org.lsposed.manager.databinding.FragmentPagerBinding; import org.lsposed.manager.databinding.FragmentPagerBinding;
import org.lsposed.manager.databinding.ItemLogTextviewBinding; import org.lsposed.manager.databinding.ItemLogTextviewBinding;
import org.lsposed.manager.databinding.SwiperefreshRecyclerviewBinding; import org.lsposed.manager.databinding.SwiperefreshRecyclerviewBinding;
import org.lsposed.manager.receivers.LSPManagerServiceHolder;
import org.lsposed.manager.ui.widget.EmptyStateRecyclerView; import org.lsposed.manager.ui.widget.EmptyStateRecyclerView;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Arrays; import java.util.Arrays;
@ -62,11 +62,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream; 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.material.app.LocaleDelegate;
import rikka.recyclerview.RecyclerViewKt; import rikka.recyclerview.RecyclerViewKt;
@ -89,11 +85,9 @@ public class LogsFragment extends BaseFragment {
runAsync(() -> { runAsync(() -> {
var context = requireContext(); var context = requireContext();
var contentResolver = context.getContentResolver(); var contentResolver = context.getContentResolver();
try (var os = new ZipOutputStream(contentResolver.openOutputStream(uri))) { try (var zipFd = contentResolver.openFileDescriptor(uri, "wt")) {
os.setLevel(Deflater.BEST_COMPRESSION); LSPManagerServiceHolder.getService().getLogs(zipFd);
zipLogs(os); } catch (Throwable e) {
os.finish();
} catch (IOException e) {
var text = context.getString(R.string.logs_save_failed2, e.getMessage()); var text = context.getString(R.string.logs_save_failed2, e.getMessage());
showHint(text, false); showHint(text, false);
Log.w(App.TAG, "save log", e); Log.w(App.TAG, "save log", e);
@ -171,29 +165,6 @@ public class LogsFragment extends BaseFragment {
saveLogsLauncher.launch(filename); 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 @Override
public void onDestroy() { public void onDestroy() {
handler.removeCallbacksAndMessages(null); handler.removeCallbacksAndMessages(null);

View File

@ -29,12 +29,15 @@ import org.lsposed.manager.App;
import org.lsposed.manager.ConfigManager; import org.lsposed.manager.ConfigManager;
import org.lsposed.manager.adapters.ScopeAdapter; import org.lsposed.manager.adapters.ScopeAdapter;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
import rikka.core.os.FileUtils;
public class BackupUtils { public class BackupUtils {
private static final int VERSION = 2; private static final int VERSION = 2;
@ -79,10 +82,9 @@ public class BackupUtils {
public static void restore(Uri uri, String packageName) throws IOException, JSONException { public static void restore(Uri uri, String packageName) throws IOException, JSONException {
try (GZIPInputStream gzipInputStream = new GZIPInputStream(App.getInstance().getContentResolver().openInputStream(uri), 32)) { try (GZIPInputStream gzipInputStream = new GZIPInputStream(App.getInstance().getContentResolver().openInputStream(uri), 32)) {
StringBuilder string = new StringBuilder(); StringBuilder string = new StringBuilder();
byte[] data = new byte[32]; try (var os = new ByteArrayOutputStream()) {
int bytesRead; FileUtils.copy(gzipInputStream, os);
while ((bytesRead = gzipInputStream.read(data)) != -1) { string.append(os);
string.append(new String(data, 0, bytesRead));
} }
gzipInputStream.close(); gzipInputStream.close();
JSONObject rootObject = new JSONObject(string.toString()); JSONObject rootObject = new JSONObject(string.toString());

View File

@ -105,7 +105,7 @@ private:
inline void Log(std::string_view str); inline void Log(std::string_view str);
void OnCrash(); void OnCrash(int err);
void ProcessBuffer(struct log_msg *buf); void ProcessBuffer(struct log_msg *buf);
@ -191,7 +191,8 @@ inline void Logcat::Log(std::string_view str) {
fflush(modules_file_.get()); 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; constexpr size_t max_restart_logd_wait = 1U << 10;
static size_t kLogdCrashCount = 0; static size_t kLogdCrashCount = 0;
static size_t kLogdRestartWait = 1 << 3; static size_t kLogdRestartWait = 1 << 3;
@ -204,7 +205,7 @@ void Logcat::OnCrash() {
kLogdCrashCount = 0; kLogdCrashCount = 0;
} }
} else { } 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); std::this_thread::sleep_for(1s);
@ -317,7 +318,7 @@ void Logcat::Run() {
if (modules_print_count_ >= kMaxLogSize) [[unlikely]] RefreshFd(false); if (modules_print_count_ >= kMaxLogSize) [[unlikely]] RefreshFd(false);
} }
OnCrash(); OnCrash(errno);
} }
} }

View File

@ -7,6 +7,7 @@ import android.content.res.AssetManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.Process; import android.os.Process;
import android.os.RemoteException;
import android.os.SELinux; import android.os.SELinux;
import android.os.SharedMemory; import android.os.SharedMemory;
import android.system.ErrnoException; import android.system.ErrnoException;
@ -22,8 +23,12 @@ import org.lsposed.lspd.util.Utils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
@ -45,7 +50,9 @@ import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import hidden.HiddenApiBridge; 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 { private static void createLogDirPath() throws IOException {
if (!Files.isDirectory(logDirPath, LinkOption.NOFOLLOW_LINKS)) { if (!Files.isDirectory(logDirPath, LinkOption.NOFOLLOW_LINKS)) {
Files.deleteIfExists(logDirPath); Files.deleteIfExists(logDirPath);
@ -194,17 +210,42 @@ public class ConfigFileManager {
return logDirPath.resolve("props.txt").toFile(); return logDirPath.resolve("props.txt").toFile();
} }
static Map<String, ParcelFileDescriptor> getLogs() { static void getLogs(ParcelFileDescriptor zipFd) throws RemoteException {
var map = new LinkedHashMap<String, ParcelFileDescriptor>(); var logs = new LinkedHashMap<String, ParcelFileDescriptor>();
try { try (var os = new ZipOutputStream(new FileOutputStream(zipFd.getFileDescriptor()))) {
putFds(map, logDirPath); putFds(logs, logDirPath);
putFds(map, oldLogDirPath); putFds(logs, oldLogDirPath);
putFds(map, Paths.get("/data/tombstones")); putFds(logs, Paths.get("/data/tombstones"));
putFds(map, Paths.get("/data/anr")); putFds(logs, Paths.get("/data/anr"));
} catch (IOException e) { logs.forEach((name, fd) -> {
Log.e(TAG, "getLogs", e); 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<String, ParcelFileDescriptor> map, Path path) throws IOException { private static void putFds(Map<String, ParcelFileDescriptor> map, Path path) throws IOException {

View File

@ -711,8 +711,8 @@ public class LSPManagerService extends ILSPManagerService.Stub {
} }
@Override @Override
public Map<String, ParcelFileDescriptor> getLogs() { public void getLogs(ParcelFileDescriptor zipFd) throws RemoteException {
return ConfigFileManager.getLogs(); ConfigFileManager.getLogs(zipFd);
} }
@Override @Override

View File

@ -60,7 +60,7 @@ interface ILSPManagerService {
void setHiddenIcon(boolean hide) = 33; void setHiddenIcon(boolean hide) = 33;
Map<String,ParcelFileDescriptor> getLogs() = 34; void getLogs(in ParcelFileDescriptor zipFd) = 34;
void restartFor(in Intent intent) = 35; void restartFor(in Intent intent) = 35;