parent
8da216a719
commit
9f868aeddf
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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(...);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue