mirror of
https://github.com/wgtunnel/android.git
synced 2026-07-03 14:07:49 +02:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0008573b4d | |||
| 47b2deaf3d | |||
| 99f6b438ab | |||
| f047a1e1b8 |
@@ -8,7 +8,6 @@ import com.zaneschepke.wireguardautotunnel.data.repository.AppStateRepository
|
||||
import com.zaneschepke.wireguardautotunnel.data.repository.SettingsRepository
|
||||
import com.zaneschepke.wireguardautotunnel.module.ApplicationScope
|
||||
import com.zaneschepke.wireguardautotunnel.module.IoDispatcher
|
||||
import com.zaneschepke.wireguardautotunnel.module.MainDispatcher
|
||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.BackendState
|
||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelService
|
||||
import com.zaneschepke.wireguardautotunnel.util.LocaleUtil
|
||||
@@ -18,7 +17,6 @@ import dagger.hilt.android.HiltAndroidApp
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -45,10 +43,6 @@ class WireGuardAutoTunnel : Application() {
|
||||
@IoDispatcher
|
||||
lateinit var ioDispatcher: CoroutineDispatcher
|
||||
|
||||
@Inject
|
||||
@MainDispatcher
|
||||
lateinit var mainDispatcher: CoroutineDispatcher
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
instance = this
|
||||
@@ -65,19 +59,22 @@ class WireGuardAutoTunnel : Application() {
|
||||
} else {
|
||||
Timber.plant(ReleaseTree())
|
||||
}
|
||||
|
||||
applicationScope.launch {
|
||||
withContext(mainDispatcher) {
|
||||
if (appStateRepository.isLocalLogsEnabled() && !isRunningOnTv()) logReader.initialize()
|
||||
}
|
||||
if (!settingsRepository.getSettings().isKernelEnabled) {
|
||||
tunnelService.setBackendState(BackendState.SERVICE_ACTIVE, emptyList())
|
||||
}
|
||||
|
||||
appStateRepository.getLocale()?.let {
|
||||
LocaleUtil.changeLocale(it)
|
||||
}
|
||||
}
|
||||
if (!isRunningOnTv()) {
|
||||
applicationScope.launch(ioDispatcher) {
|
||||
if (appStateRepository.isLocalLogsEnabled()) {
|
||||
Timber.d("Starting logger")
|
||||
logReader.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTerminate() {
|
||||
|
||||
@@ -2,9 +2,9 @@ package com.zaneschepke.wireguardautotunnel.module
|
||||
|
||||
import android.content.Context
|
||||
import com.zaneschepke.logcatter.LogReader
|
||||
import com.zaneschepke.logcatter.LogcatCollector
|
||||
import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
|
||||
import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification
|
||||
import com.zaneschepke.logcatter.LogcatReader
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
@@ -27,7 +27,7 @@ class AppModule {
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideLogCollect(@ApplicationContext context: Context): LogReader {
|
||||
return LogcatReader.init(storageDir = context.filesDir.absolutePath)
|
||||
return LogcatCollector.init(context = context)
|
||||
}
|
||||
|
||||
@Singleton
|
||||
|
||||
@@ -141,6 +141,7 @@ constructor(
|
||||
}
|
||||
|
||||
private suspend fun onLoggerStop() {
|
||||
logReader.stop()
|
||||
logReader.deleteAndClearLogs()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
object Constants {
|
||||
const val VERSION_NAME = "3.6.3"
|
||||
const val VERSION_NAME = "3.6.1"
|
||||
const val JVM_TARGET = "17"
|
||||
const val VERSION_CODE = 36300
|
||||
const val VERSION_CODE = 36100
|
||||
const val TARGET_SDK = 35
|
||||
const val MIN_SDK = 26
|
||||
const val APP_ID = "com.zaneschepke.wireguardautotunnel"
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
What's new:
|
||||
- Added VPN kill switch w/LAN bypass
|
||||
- Improved auto tunnel speed and reliability
|
||||
- Improved tile sync
|
||||
- Various bug fixes and improvements
|
||||
@@ -49,7 +49,6 @@ dependencies {
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
|
||||
implementation(libs.androidx.lifecycle.process)
|
||||
// logging
|
||||
implementation(libs.timber)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ import com.zaneschepke.logcatter.model.LogMessage
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface LogReader {
|
||||
fun initialize(onLogMessage: ((message: LogMessage) -> Unit)? = null)
|
||||
suspend fun start(onLogMessage: ((message: LogMessage) -> Unit)? = null)
|
||||
fun stop()
|
||||
fun zipLogFiles(path: String)
|
||||
suspend fun deleteAndClearLogs()
|
||||
val bufferedLogs: Flow<LogMessage>
|
||||
|
||||
+85
-62
@@ -1,30 +1,26 @@
|
||||
package com.zaneschepke.logcatter
|
||||
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import android.content.Context
|
||||
import com.zaneschepke.logcatter.model.LogMessage
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.BufferedReader
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
object LogcatReader {
|
||||
object LogcatCollector {
|
||||
|
||||
private const val MAX_FILE_SIZE = 2097152L // 2MB
|
||||
private const val MAX_FOLDER_SIZE = 10485760L // 10MB
|
||||
@@ -44,7 +40,7 @@ object LogcatReader {
|
||||
var logcatPath = ""
|
||||
}
|
||||
|
||||
fun init(maxFileSize: Long = MAX_FILE_SIZE, maxFolderSize: Long = MAX_FOLDER_SIZE, storageDir: String): LogReader {
|
||||
fun init(maxFileSize: Long = MAX_FILE_SIZE, maxFolderSize: Long = MAX_FOLDER_SIZE, context: Context): LogReader {
|
||||
if (maxFileSize > maxFolderSize) {
|
||||
throw IllegalStateException("maxFileSize must be less than maxFolderSize")
|
||||
}
|
||||
@@ -52,11 +48,13 @@ object LogcatReader {
|
||||
LogcatHelperInit.maxFileSize = maxFileSize
|
||||
LogcatHelperInit.maxFolderSize = maxFolderSize
|
||||
LogcatHelperInit.pID = android.os.Process.myPid()
|
||||
LogcatHelperInit.publicAppDirectory = storageDir
|
||||
LogcatHelperInit.logcatPath = LogcatHelperInit.publicAppDirectory + File.separator + "logs"
|
||||
val logDirectory = File(LogcatHelperInit.logcatPath)
|
||||
if (!logDirectory.exists()) {
|
||||
logDirectory.mkdir()
|
||||
context.getExternalFilesDir(null)?.let {
|
||||
LogcatHelperInit.publicAppDirectory = it.absolutePath
|
||||
LogcatHelperInit.logcatPath = LogcatHelperInit.publicAppDirectory + File.separator + "logs"
|
||||
val logDirectory = File(LogcatHelperInit.logcatPath)
|
||||
if (!logDirectory.exists()) {
|
||||
logDirectory.mkdir()
|
||||
}
|
||||
}
|
||||
return Logcat
|
||||
}
|
||||
@@ -64,12 +62,7 @@ object LogcatReader {
|
||||
|
||||
internal object Logcat : LogReader {
|
||||
|
||||
private lateinit var logcatReader: LogcatReader
|
||||
|
||||
override fun initialize(onLogMessage: ((message: LogMessage) -> Unit)?) {
|
||||
logcatReader = LogcatReader(LogcatHelperInit.pID.toString(), LogcatHelperInit.logcatPath, onLogMessage)
|
||||
ProcessLifecycleOwner.get().lifecycle.addObserver(logcatReader)
|
||||
}
|
||||
private var logcatReader: LogcatReader? = null
|
||||
|
||||
private fun obfuscator(log: String): String {
|
||||
return findKeyRegex.replace(log, "<crypto-key>").let { first ->
|
||||
@@ -79,10 +72,22 @@ object LogcatReader {
|
||||
}.let { last -> findIpv4AddressRegex.replace(last, "<ipv4-address>") }
|
||||
}
|
||||
|
||||
override suspend fun start(onLogMessage: ((message: LogMessage) -> Unit)?) {
|
||||
logcatReader ?: run {
|
||||
logcatReader = LogcatReader(LogcatHelperInit.pID.toString(), LogcatHelperInit.logcatPath, onLogMessage)
|
||||
}
|
||||
logcatReader?.run()
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
logcatReader?.stop()
|
||||
logcatReader = null
|
||||
}
|
||||
|
||||
override fun zipLogFiles(path: String) {
|
||||
logcatReader.cancel()
|
||||
logcatReader?.pause()
|
||||
zipAll(path)
|
||||
logcatReader.onCreate(ProcessLifecycleOwner.get())
|
||||
logcatReader?.resume()
|
||||
}
|
||||
|
||||
private fun zipAll(zipFilePath: String) {
|
||||
@@ -105,10 +110,10 @@ object LogcatReader {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override suspend fun deleteAndClearLogs() {
|
||||
withContext(ioDispatcher) {
|
||||
logcatReader.cancel()
|
||||
logcatReader?.pause()
|
||||
_bufferedLogs.resetReplayCache()
|
||||
logcatReader.deleteAllFiles()
|
||||
logcatReader.onCreate(ProcessLifecycleOwner.get())
|
||||
logcatReader?.deleteAllFiles()
|
||||
logcatReader?.resume()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,25 +134,57 @@ object LogcatReader {
|
||||
pID: String,
|
||||
private val logcatPath: String,
|
||||
private val callback: ((input: LogMessage) -> Unit)?,
|
||||
) : DefaultLifecycleObserver {
|
||||
) {
|
||||
private var logcatProc: Process? = null
|
||||
private var reader: BufferedReader? = null
|
||||
|
||||
private val command = "logcat -v epoch | grep \"($pID)\""
|
||||
private val clearLogCommand = "logcat -c"
|
||||
private var logJob: Job? = null
|
||||
@get:Synchronized @set:Synchronized
|
||||
private var paused = false
|
||||
|
||||
@get:Synchronized @set:Synchronized
|
||||
private var stopped = false
|
||||
private var command = ""
|
||||
private var clearLogCommand = ""
|
||||
private var outputStream: FileOutputStream? = null
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
super.onCreate(owner)
|
||||
logJob = owner.lifecycleScope.launch(ioDispatcher) {
|
||||
init {
|
||||
try {
|
||||
outputStream = FileOutputStream(createLogFile(logcatPath))
|
||||
} catch (e: FileNotFoundException) {
|
||||
Timber.e(e)
|
||||
}
|
||||
|
||||
command = "logcat -v epoch | grep \"($pID)\""
|
||||
clearLogCommand = "logcat -c"
|
||||
}
|
||||
|
||||
fun pause() {
|
||||
paused = true
|
||||
}
|
||||
fun stop() {
|
||||
stopped = true
|
||||
}
|
||||
|
||||
fun resume() {
|
||||
paused = false
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
Runtime.getRuntime().exec(clearLogCommand)
|
||||
}
|
||||
|
||||
suspend fun run() {
|
||||
withContext(ioDispatcher) {
|
||||
paused = false
|
||||
stopped = false
|
||||
if (outputStream == null) return@withContext
|
||||
try {
|
||||
if (outputStream == null) outputStream = createNewLogFileStream()
|
||||
clear()
|
||||
logcatProc = Runtime.getRuntime().exec(command)
|
||||
reader = BufferedReader(InputStreamReader(logcatProc!!.inputStream), 1024)
|
||||
var line: String? = null
|
||||
while (true) {
|
||||
var line: String?
|
||||
while (!stopped) {
|
||||
if (paused) continue
|
||||
line = reader?.readLine()
|
||||
if (line.isNullOrEmpty()) continue
|
||||
outputStream?.let {
|
||||
@@ -159,8 +196,8 @@ object LogcatReader {
|
||||
deleteOldestFile()
|
||||
}
|
||||
line.let { text ->
|
||||
val sanitized = obfuscator(text)
|
||||
it.write((sanitized + System.lineSeparator()).toByteArray())
|
||||
val obfuscated = obfuscator(text)
|
||||
it.write((obfuscated + System.lineSeparator()).toByteArray())
|
||||
try {
|
||||
val logMessage = LogMessage.from(text)
|
||||
_bufferedLogs.tryEmit(logMessage)
|
||||
@@ -177,34 +214,19 @@ object LogcatReader {
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
} finally {
|
||||
reset()
|
||||
logcatProc?.destroy()
|
||||
logcatProc = null
|
||||
|
||||
try {
|
||||
reader?.close()
|
||||
outputStream?.close()
|
||||
reader = null
|
||||
outputStream = null
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
logJob?.invokeOnCompletion {
|
||||
reset()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
super.onDestroy(owner)
|
||||
logJob?.cancel()
|
||||
}
|
||||
|
||||
fun cancel() {
|
||||
logJob?.cancel()
|
||||
}
|
||||
|
||||
private fun reset() {
|
||||
logcatProc?.destroy()
|
||||
logcatProc = null
|
||||
reader?.close()
|
||||
outputStream?.close()
|
||||
reader = null
|
||||
outputStream = null
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
Runtime.getRuntime().exec(clearLogCommand)
|
||||
}
|
||||
|
||||
private fun getFolderSize(path: String): Long {
|
||||
@@ -244,6 +266,7 @@ object LogcatReader {
|
||||
directory.listFiles()?.toMutableList()?.run {
|
||||
this.forEach { it.delete() }
|
||||
}
|
||||
outputStream = createNewLogFileStream()
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1 +1 @@
|
||||
13
|
||||
12
|
||||
Reference in New Issue
Block a user