[core] Native logcat (#960)

Co-authored-by: LoveSy <shana@zju.edu.cn>
This commit is contained in:
vvb2060 2021-08-21 03:15:13 +08:00 committed by GitHub
parent 8da216a719
commit 9f868aeddf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 372 additions and 152 deletions

View File

@ -144,22 +144,10 @@ public class SettingsFragment extends BaseFragment {
boolean installed = ConfigManager.isBinderAlive();
SwitchPreference prefVerboseLogs = findPreference("disable_verbose_log");
if (prefVerboseLogs != null) {
if (requireActivity().getApplicationInfo().uid / 100000 != 0) {
prefVerboseLogs.setVisible(false);
} else {
prefVerboseLogs.setEnabled(installed);
prefVerboseLogs.setChecked(!installed || !ConfigManager.isVerboseLogEnabled());
prefVerboseLogs.setOnPreferenceChangeListener((preference, newValue) -> {
boolean result = ConfigManager.setVerboseLogEnabled(!(boolean) newValue);
SettingsFragment fragment = (SettingsFragment) getParentFragment();
if (result && fragment != null) {
Snackbar.make(fragment.binding.snackbar, R.string.reboot_required, Snackbar.LENGTH_SHORT)
.setAction(R.string.reboot, v -> ConfigManager.reboot(false))
.show();
}
return result;
});
}
prefVerboseLogs.setEnabled(installed);
prefVerboseLogs.setChecked(!installed || !ConfigManager.isVerboseLogEnabled());
prefVerboseLogs.setOnPreferenceChangeListener((preference, newValue) ->
ConfigManager.setVerboseLogEnabled(!(boolean) newValue));
}
SwitchPreference prefEnableResources = findPreference("enable_resources");

View File

@ -252,8 +252,14 @@ val pushLspd = task("pushLspd", Exec::class) {
workingDir("$buildDir/intermediates/dex/debug/mergeDexDebug")
commandLine(adb, "push", "classes.dex", "/data/local/tmp/lspd.dex")
}
val pushLspdNative = task("pushLspdNative", Exec::class) {
dependsOn("mergeDebugNativeLibs")
workingDir("$buildDir/intermediates/merged_native_libs/debug/out/lib/arm64-v8a")
commandLine(adb, "push", "libdaemon.so", "/data/local/tmp/libdaemon.so")
}
task("reRunLspd", Exec::class) {
dependsOn(pushLspd)
dependsOn(pushLspdNative)
dependsOn(killLspd)
commandLine(adb, "shell", "su", "-c", "sh /data/adb/modules/riru_lsposed/service.sh&")
isIgnoreExitValue = true

View File

@ -83,6 +83,9 @@ if [ "$ARCH" = "arm" ] || [ "$ARCH" = "arm64" ]; then
if [ "$IS64BIT" = true ]; then
ui_print "- Extracting arm64 libraries"
extract "$ZIPFILE" "lib/arm64-v8a/lib$RIRU_MODULE_LIB_NAME.so" "$MODPATH/riru/lib64" true
extract "$ZIPFILE" 'lib/arm64-v8a/libdaemon.so' "$MODPATH" true
else
extract "$ZIPFILE" 'lib/armeabi-v7a/libdaemon.so' "$MODPATH" true
fi
fi
@ -93,21 +96,24 @@ if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then
if [ "$IS64BIT" = true ]; then
ui_print "- Extracting x64 libraries"
extract "$ZIPFILE" "lib/x86_64/lib$RIRU_MODULE_LIB_NAME.so" "$MODPATH/riru/lib64" true
extract "$ZIPFILE" 'lib/x86_64/libdaemon.so' "$MODPATH" true
else
extract "$ZIPFILE" 'lib/x86/libdaemon.so' "$MODPATH" true
fi
fi
if [ "$RIRU_MODULE_DEBUG" = true ]; then
mv "$MODPATH/riru" "$MODPATH/system"
mv "$MODPATH/system/lib/liblspd.so" "$MODPATH/system/lib/libriru_lspd.so"
mv "$MODPATH/system/lib64/liblspd.so" "$MODPATH/system/lib64/libriru_lspd.so"
mv "$MODPATH/system/lib/lib$RIRU_MODULE_LIB_NAME.so" "$MODPATH/system/lib/libriru_$RIRU_MODULE_LIB_NAME.so"
mv "$MODPATH/system/lib64/lib$RIRU_MODULE_LIB_NAME.so" "$MODPATH/system/lib64/libriru_$RIRU_MODULE_LIB_NAME.so"
mv "$MODPATH/framework" "$MODPATH/system/framework"
if [ "$RIRU_API" -ge 26 ]; then
mkdir -p "$MODPATH/riru/lib"
mkdir -p "$MODPATH/riru/lib64"
touch "$MODPATH/riru/lib/libriru_lspd"
touch "$MODPATH/riru/lib64/libriru_lspd"
touch "$MODPATH/riru/lib/libriru_$RIRU_MODULE_LIB_NAME"
touch "$MODPATH/riru/lib64/libriru_$RIRU_MODULE_LIB_NAME"
else
mkdir -p "/data/adb/riru/modules/lspd"
mkdir -p "/data/adb/riru/modules/$RIRU_MODULE_LIB_NAME"
fi
fi

View File

@ -6,12 +6,15 @@ debug="false"
if [ -r $tmpLspdDex ]; then
java_options="-Djava.class.path=$tmpLspdDex"
java_options="$java_options -Djava.library.path=/data/local/tmp"
debug="true"
elif [ -d "$dir/system" ]; then
java_options="-Djava.class.path=$dir/system/framework/lspd.dex"
java_options="$java_options -Djava.library.path=$dir"
debug="true"
else
java_options="-Djava.class.path=$dir/framework/lspd.dex"
java_options="$java_options -Djava.library.path=$dir"
fi
if [ $debug = "true" ]; then

View File

@ -20,105 +20,12 @@
# Copyright (C) 2021 LSPosed Contributors
#
grep_prop() {
local REGEX="s/^$1=//p"
shift
local FILES="$@"
[ -z "$FILES" ] && FILES='/system/build.prop'
sed -n "$REGEX" ${FILES} 2>/dev/null | head -n 1
}
MODDIR=${0%/*}
MAGISK_VERSION=$(magisk -v)
MAGISK_VER_CODE=$(magisk -V)
[ ! -f $(magisk --path)/.magisk/modules/riru-core/util_functions.sh ] && exit 1
. $(magisk --path)/.magisk/modules/riru-core/util_functions.sh
LSPD_VERSION=$(grep_prop version "${MODDIR}/module.prop")
ANDROID_SDK=$(getprop ro.build.version.sdk)
BUILD_DESC=$(getprop ro.build.description)
PRODUCT=$(getprop ro.build.product)
MODEL=$(getprop ro.product.model)
MANUFACTURER=$(getprop ro.product.manufacturer)
BRAND=$(getprop ro.product.brand)
FINGERPRINT=$(getprop ro.build.fingerprint)
ARCH=$(getprop ro.product.cpu.abi)
DEVICE=$(getprop ro.product.device)
ANDROID=$(getprop ro.build.version.release)
BUILD=$(getprop ro.build.id)
MISC_PATH=$(cat /data/adb/lspd/misc_path)
BASE_PATH="/data/misc/$MISC_PATH"
LOG_PATH="/data/adb/lspd/log"
ENABLE_VERBOSE_LOG_FILE="/data/adb/lspd/config/verbose_log"
LOG_VERBOSE=false
if [ "$(cat "${ENABLE_VERBOSE_LOG_FILE}")" = "1" ]; then
LOG_VERBOSE=true
fi
# If logcat client is kicked out by klogd server, we'll restart it.
# However, if it is killed manually or by LSPosed Manager, we'll exit.
loop_logcat() {
while true; do
logcat $*
if [ $? -ne 1 ]; then
break
fi
done
}
print_log_head() {
LOG_FILE=$1
touch "${LOG_FILE}"
chmod 666 "${LOG_FILE}"
{
echo "LSPosed Log"
echo "--------- beginning of information"
echo "Manufacturer: ${MANUFACTURER}"
echo "Brand: ${BRAND}"
echo "Device: ${DEVICE}"
echo "Product: ${PRODUCT}"
echo "Model: ${MODEL}"
echo "Fingerprint: ${FINGERPRINT}"
echo "ROM description: ${BUILD_DESC}"
echo "Architecture: ${ARCH}"
echo "Android build: ${BUILD}"
echo "Android version: ${ANDROID}"
echo "Android sdk: ${ANDROID_SDK}"
echo "LSPosed version: ${LSPD_VERSION}"
echo "Riru version: ${RIRU_VERSION_NAME} (${RIRU_VERSION_CODE})"
echo "Riru api: ${RIRU_API}"
echo "Magisk: ${MAGISK_VERSION%:*} (${MAGISK_VER_CODE})"
} >>"${LOG_FILE}"
}
start_log_catcher() {
LOG_FILE_NAME=$1
LOG_TAG_FILTERS=$2
CLEAN_OLD=$3
START_NEW=$4
LOG_FILE="${LOG_PATH}/${LOG_FILE_NAME}.log"
PID_FILE="${LOG_PATH}/${LOG_FILE_NAME}.pid"
mkdir -p ${LOG_PATH}
if [ ${CLEAN_OLD} == true ]; then
rm "${LOG_FILE}.old"
mv "${LOG_FILE}" "${LOG_FILE}.old"
fi
rm "${LOG_PATH}/${LOG_FILE_NAME}.pid"
if [ ${START_NEW} == false ]; then
return
fi
touch "${PID_FILE}"
print_log_head "${LOG_FILE}"
loop_logcat -f "${LOG_FILE}" *:S "${LOG_TAG_FILTERS}" &
LOG_PID=$!
echo "${LOG_PID}" >"${LOG_PATH}/${LOG_FILE_NAME}.pid"
}
chcon -R u:object_r:system_file:s0 "${MODDIR}"
chcon -R u:object_r:system_file:s0 "/data/adb/lspd"
@ -130,9 +37,6 @@ chcon -R u:object_r:magisk_file:s0 ${LOG_PATH}
if [ ! -z "${MISC_PATH}" ]; then
chcon -R u:object_r:magisk_file:s0 "${BASE_PATH}"
chmod 771 "${BASE_PATH}"
print_log_head "${LOG_PATH}/modules.log"
# start_verbose_log_catcher
start_log_catcher all "LSPosed:V XSharedPreferences:V LSPosed-Bridge:V LSPosedManager:V LSPosedService:V *:F" true ${LOG_VERBOSE}
fi
rm -f "/data/local/tmp/lspd.dex"

View File

@ -15,6 +15,9 @@
public static boolean execTransact(int, long, long, int);
public static android.os.IBinder getApplicationServiceForSystemServer(android.os.IBinder, android.os.IBinder);
}
-keepclasseswithmembers class org.lsposed.lspd.service.LogcatService {
private int refreshFd();
}
-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** d(...);

View File

@ -1,6 +1,7 @@
include src/main/cpp/external/DexBuilder/Android.mk
include src/main/cpp/external/yahfa/Android.mk
include src/main/cpp/main/Android.mk
include src/main/cpp/daemon/Android.mk
$(call import-module,prefab/cxx)
$(call import-module,prefab/riru)

View File

@ -0,0 +1,9 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := daemon
LOCAL_SRC_FILES := logcat.cpp
LOCAL_STATIC_LIBRARIES := cxx
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,155 @@
#include <jni.h>
#include <unistd.h>
#include <string>
#include <android/log.h>
#include <array>
#include "logcat.h"
class UniqueFile : public std::unique_ptr<FILE, std::function<void(FILE *)>> {
inline static deleter_type deleter = [](auto f) { f && f != stdout && fclose(f); };
public:
explicit UniqueFile(FILE *f) : std::unique_ptr<FILE, std::function<void(FILE *)>>(f, deleter) {}
UniqueFile(int fd, const char *mode) : UniqueFile(fd > 0 ? fdopen(fd, mode) : stdout) {};
UniqueFile() : UniqueFile(nullptr) {};
};
class Logcat {
public:
explicit Logcat(JNIEnv *env, jobject thiz, jmethodID method, jlong tid) :
env_(env), thiz_(thiz), refresh_fd_method_(method), tid_(tid) { RefreshFd(); };
void Run();
private:
void RefreshFd();
bool ProcessBuffer(struct log_msg *buf);
static char FilterPriToChar(android_LogPriority pri);
static void PrintLogLine(FILE *out, const AndroidLogEntry *entry);
JNIEnv *env_;
jobject thiz_;
jmethodID refresh_fd_method_;
jlong tid_;
UniqueFile out_file_{};
size_t print_count_ = 0;
constexpr static size_t kMaxCount = 500;
constexpr static uint32_t kSetLogSize = 32 * 1024 * 1024;
};
char Logcat::FilterPriToChar(android_LogPriority pri) {
switch (pri) {
case ANDROID_LOG_VERBOSE:
return 'V';
case ANDROID_LOG_DEBUG:
return 'D';
case ANDROID_LOG_INFO:
return 'I';
case ANDROID_LOG_WARN:
return 'W';
case ANDROID_LOG_ERROR:
return 'E';
case ANDROID_LOG_FATAL:
return 'F';
case ANDROID_LOG_SILENT:
return 'S';
case ANDROID_LOG_DEFAULT:
case ANDROID_LOG_UNKNOWN:
default:
return '?';
}
}
void Logcat::PrintLogLine(FILE *out, const AndroidLogEntry *entry) {
if (!out) return;
constexpr static size_t kMaxTimeBuff = 64;
struct tm tm{};
std::array<char, kMaxTimeBuff> time_buff;
auto now = entry->tv_sec;
auto nsec = entry->tv_nsec;
if (now < 0) {
nsec = NS_PER_SEC - nsec;
}
localtime_r(&now, &tm);
strftime(time_buff.data(), time_buff.size(), "%Y-%m-%dT%H:%M:%S", &tm);
fprintf(out, "[ %s.%03ld %8d:%6d:%6d %c/%-15.*s ] %.*s\n", time_buff.data(), nsec / MS_PER_NSEC,
entry->uid, entry->pid, entry->tid,
FilterPriToChar(entry->priority), static_cast<int>(entry->tagLen), entry->tag,
static_cast<int>(entry->messageLen), entry->message);
}
void Logcat::RefreshFd() {
out_file_ = UniqueFile(env_->CallIntMethod(thiz_, refresh_fd_method_), "w");
}
bool Logcat::ProcessBuffer(struct log_msg *buf) {
int err;
AndroidLogEntry entry;
err = android_log_processLogBuffer(&buf->entry, &entry);
if (err < 0) return false;
std::string_view tag(entry.tag);
if (buf->id() == log_id::LOG_ID_CRASH ||
tag == "Magisk" ||
tag.starts_with("Riru") ||
tag.starts_with("LSPosed") ||
tag == "XSharedPreferences") {
++print_count_;
PrintLogLine(out_file_.get(), &entry);
}
return entry.pid == getpid() &&
tag == "LSPosedLogcat" &&
std::string_view(entry.message) == "!!stop!!" + std::to_string(tid_);
}
void Logcat::Run() {
std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
nullptr, &android_logger_list_free};
logger_list.reset(android_logger_list_alloc(0, 0, 0));
for (log_id id:{LOG_ID_MAIN, LOG_ID_CRASH}) {
auto *logger = android_logger_open(logger_list.get(), id);
if (logger == nullptr) {
continue;
}
android_logger_set_log_size(logger, kSetLogSize);
}
while (true) {
struct log_msg msg{};
int ret = android_logger_list_read(logger_list.get(), &msg);
if (ret <= 0) {
continue;
}
if (ProcessBuffer(&msg)) {
break;
}
fflush(out_file_.get());
if (print_count_ > kMaxCount) {
RefreshFd();
print_count_ = 0;
}
}
}
extern "C"
JNIEXPORT void JNICALL
Java_org_lsposed_lspd_service_LogcatService_runLogcat(JNIEnv *env, jobject thiz, jlong tid) {
jclass clazz = env->GetObjectClass(thiz);
jmethodID method = env->GetMethodID(clazz, "refreshFd", "()I");
Logcat logcat(env, thiz, method, tid);
logcat.Run();
}

View File

@ -0,0 +1,62 @@
#pragma once
#include <stdint.h>
#include <sys/types.h>
#include <android/log.h>
#define NS_PER_SEC 1000000000ULL
#define MS_PER_NSEC 1000000
#define LOGGER_ENTRY_MAX_LEN (5 * 1024)
#ifdef __cplusplus
extern "C" {
#endif
typedef struct AndroidLogEntry_t {
time_t tv_sec;
long tv_nsec;
android_LogPriority priority;
int32_t uid;
int32_t pid;
int32_t tid;
const char *tag;
size_t tagLen;
size_t messageLen;
const char *message;
} AndroidLogEntry;
struct logger_entry {
uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry) */
int32_t pid; /* generating process's pid */
uint32_t tid; /* generating process's tid */
uint32_t sec; /* seconds since Epoch */
uint32_t nsec; /* nanoseconds */
uint32_t lid; /* log id of the payload, bottom 4 bits currently */
uint32_t uid; /* generating process's uid */
};
struct log_msg {
union alignas(4) {
unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
struct logger_entry entry;
};
#ifdef __cplusplus
log_id_t id() {
return static_cast<log_id_t>(entry.lid);
}
#endif
};
struct logger;
struct logger_list;
int android_logger_set_log_size(struct logger *logger, unsigned long size);
struct logger_list *android_logger_list_alloc(int mode, unsigned int tail, pid_t pid);
void android_logger_list_free(struct logger_list *logger_list);
int android_logger_list_read(struct logger_list *logger_list, struct log_msg *log_msg);
struct logger *android_logger_open(struct logger_list *logger_list, log_id_t id);
int android_log_processLogBuffer(struct logger_entry *buf, AndroidLogEntry *entry);
#ifdef __cplusplus
}
#endif

View File

@ -22,7 +22,6 @@ package org.lsposed.lspd.core;
import static org.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
import android.annotation.SuppressLint;
import android.app.ActivityThread;
import android.app.LoadedApk;
import android.content.pm.ApplicationInfo;
@ -48,7 +47,6 @@ import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.XposedInit;
@SuppressLint("DefaultLocale")
public class Main {
public static void startBootstrapHook(boolean isSystem, String appDataDir) {
Utils.logD("startBootstrapHook starts: isSystem = " + isSystem);

View File

@ -96,8 +96,7 @@ public class ConfigManager {
private static final File resourceHookSwitch = new File(configPath, "enable_resources");
private boolean resourceHook = false;
private static final File verboseLogSwitch = new File(configPath, "verbose_log");
private boolean verboseLog = false;
private boolean logcat = true;
private static final File managerPath = new File(configPath, "manager");
private String manager = null;
@ -107,9 +106,8 @@ public class ConfigManager {
private String miscPath = null;
private static final File logPath = new File(basePath, "log");
private static final File modulesLog = new File(logPath, "modules.log");
private static final File oldModulesLog = new File(logPath, "modules.old.log");
private static final File verboseLogPath = new File(logPath, "all.log");
private static final File modulesLog = new File(logPath, "modules.txt");
private static final File oldModulesLog = new File(logPath, "modules.old.txt");
static class FileLocker {
private final FileChannel lockChannel;
@ -136,7 +134,7 @@ public class ConfigManager {
static {
try {
Files.createDirectories(basePath.toPath());
Files.createDirectories(logPath.toPath());
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
@ -310,7 +308,6 @@ public class ConfigManager {
private synchronized void updateConfig() {
resourceHook = readInt(resourceHookSwitch, 0) == 1;
verboseLog = readInt(verboseLogSwitch, 0) == 1;
miscPath = "/data/misc/" + readText(miscFile, "lspd");
updateManager();
}
@ -870,9 +867,14 @@ public class ConfigManager {
this.resourceHook = resourceHook;
}
public void setVerboseLog(boolean verboseLog) {
writeInt(verboseLogSwitch, verboseLog ? 1 : 0);
this.verboseLog = verboseLog;
public void setVerboseLog(boolean on) {
var logcatService = ServiceManager.getLogcatService();
if (on) {
logcatService.start();
} else {
logcatService.stop();
}
logcat = on;
}
public boolean resourceHook() {
@ -880,7 +882,11 @@ public class ConfigManager {
}
public boolean verboseLog() {
return verboseLog;
return logcat;
}
public static File getLogPath() {
return logPath;
}
public ParcelFileDescriptor getModulesLog(int mode) {
@ -898,7 +904,8 @@ public class ConfigManager {
public ParcelFileDescriptor getVerboseLog() {
try {
return ParcelFileDescriptor.open(verboseLogPath, ParcelFileDescriptor.MODE_READ_ONLY);
var logcat = ServiceManager.getLogcatService().getLog();
return ParcelFileDescriptor.open(logcat, ParcelFileDescriptor.MODE_READ_ONLY);
} catch (FileNotFoundException e) {
Log.e(TAG, Log.getStackTraceString(e));
return null;
@ -907,7 +914,8 @@ public class ConfigManager {
public boolean clearLogs(boolean verbose) {
try {
OutputStream os = new FileOutputStream(verbose ? verboseLogPath : modulesLog);
var logcat = ServiceManager.getLogcatService().getLog();
OutputStream os = new FileOutputStream(verbose ? logcat : modulesLog);
os.close();
return true;
} catch (IOException e) {

View File

@ -0,0 +1,75 @@
package org.lsposed.lspd.service;
import android.os.ParcelFileDescriptor;
import android.os.SystemProperties;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class LogcatService implements Runnable {
private static final String TAG = "LSPosedLogcat";
private Thread thread;
private final File logPath;
private File log = null;
private static DateTimeFormatter logTimeFormat;
public LogcatService(File logPath) {
System.loadLibrary("daemon");
this.logPath = logPath;
var zone = ZoneId.of(SystemProperties.get("persist.sys.timezone", "GMT"));
logTimeFormat = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(zone);
}
@Override
public void run() {
Log.i(TAG, "start running");
runLogcat(thread.getId());
Log.i(TAG, "stoped");
}
private native void runLogcat(long tid);
@SuppressWarnings("unused")
private int refreshFd() {
if (log == null || log.length() > 32 * 1024 * 1024) {
log = new File(logPath, logTimeFormat.format(Instant.now()) + ".log");
}
var mode = ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE | ParcelFileDescriptor.MODE_APPEND;
try {
return ParcelFileDescriptor.open(log, mode).detachFd();
} catch (FileNotFoundException e) {
Log.w(TAG, "someone chattr +i ?", e);
return -1;
}
}
public void start() {
if (isRunning()) return;
thread = new Thread(this);
thread.setName("logcat");
thread.setUncaughtExceptionHandler((t, e) -> {
Log.e(TAG, "Crash unexpectedly: ", e);
thread = null;
});
thread.start();
}
public void stop() {
// logcat thread is listening for this keyword
Log.i(TAG, "!!stop!!" + thread.getId());
}
public boolean isRunning() {
return thread != null && thread.isAlive();
}
public File getLog() {
return log;
}
}

View File

@ -37,13 +37,14 @@ import java.util.concurrent.ConcurrentHashMap;
import hidden.HiddenApiBridge;
public class ServiceManager {
public static final String TAG = "LSPosedService";
private static final ConcurrentHashMap<String, LSPModuleService> moduleServices = new ConcurrentHashMap<>();
private static final File globalNamespace = new File("/proc/1/root");
private static LSPosedService mainService = null;
final private static ConcurrentHashMap<String, LSPModuleService> moduleServices = new ConcurrentHashMap<>();
private static LSPApplicationService applicationService = null;
private static LSPManagerService managerService = null;
private static LSPSystemServerService systemServerService = null;
public static final String TAG = "LSPosedService";
private static final File globalNamespace = new File("/proc/1/root");
private static LogcatService logcatService = null;
private static void waitSystemService(String name) {
while (android.os.ServiceManager.getService(name) == null) {
@ -77,6 +78,9 @@ public class ServiceManager {
System.exit(1);
});
logcatService = new LogcatService(ConfigManager.getLogPath());
logcatService.start();
Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
Looper.prepareMainLooper();
mainService = new LSPosedService();
@ -137,6 +141,10 @@ public class ServiceManager {
return managerService;
}
public static LogcatService getLogcatService() {
return logcatService;
}
public static boolean systemServerRequested() {
return systemServerService.systemServerRequested();
}

View File

@ -30,6 +30,7 @@ import java.io.IOException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class ModuleLogger {
private static DateTimeFormatter logDateFormat;
@ -39,7 +40,8 @@ public class ModuleLogger {
if (fd == null && fileDescriptor != null) {
fd = fileDescriptor;
var zone = ZoneId.of(SystemProperties.get("persist.sys.timezone", "GMT"));
logDateFormat = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(zone);
var pattern = "uuuu-MM-dd'T'HH:mm:ss.SSS"; // DateTimeFormatter.ISO_LOCAL_DATE_TIME
logDateFormat = DateTimeFormatter.ofPattern(pattern, Locale.ROOT).withZone(zone);
}
}
@ -48,24 +50,16 @@ public class ModuleLogger {
Utils.logE("Logger is not initialized");
return;
}
StringBuilder sb = new StringBuilder();
String processName = ActivityThread.currentProcessName();
sb.append(logDateFormat.format(Instant.now()));
sb.append(' ');
sb.append(isThrowable ? "E" : "I");
sb.append('/');
sb.append(processName == null ? "android" : processName);
sb.append('(');
sb.append(Process.myPid());
sb.append('-');
sb.append(Process.myTid());
sb.append(')');
sb.append(": ");
sb.append(str);
sb.append('\n');
var log = String.format(Locale.ROOT, "[ %s %5d:%5d:%5d %c/%s ] %s\n",
logDateFormat.format(Instant.now()),
Process.myUid(),
Process.myPid(),
Process.myTid(),
isThrowable ? 'E' : 'I',
processName == null ? "android" : processName,
str);
try {
var log = sb.toString();
var writer = new FileWriter(fd.getFileDescriptor());
writer.write(log, 0, log.length());
writer.flush();