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.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);

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() {
try {
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.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);

View File

@ -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());

View File

@ -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);
}
}

View File

@ -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<String, ParcelFileDescriptor> getLogs() {
var map = new LinkedHashMap<String, ParcelFileDescriptor>();
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<String, ParcelFileDescriptor>();
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<String, ParcelFileDescriptor> map, Path path) throws IOException {

View File

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

View File

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