From a8f502ef4f3460b8bb127d01d430f24a08259156 Mon Sep 17 00:00:00 2001 From: kr328 Date: Tue, 25 May 2021 20:28:40 +0800 Subject: [PATCH] Improve: merge ClashManager and ProfileService --- .../github/kr328/clash/AppCrashedActivity.kt | 2 - .../com/github/kr328/clash/LogcatService.kt | 8 +- .../github/kr328/clash/log/SystemLogcat.kt | 3 +- .../com/github/kr328/clash/remote/Remote.kt | 6 +- .../com/github/kr328/clash/remote/Service.kt | 64 ++++++++++++++ .../com/github/kr328/clash/remote/Services.kt | 88 ------------------- .../com/github/kr328/clash/util/Remote.kt | 10 ++- service/src/main/AndroidManifest.xml | 6 +- .../kr328/clash/service/ClashManager.kt | 17 ++-- .../{ProfileService.kt => ProfileManager.kt} | 50 +++++------ .../kr328/clash/service/RemoteService.kt | 46 ++++++++++ .../clash/service/remote/IRemoteService.kt | 9 ++ 12 files changed, 161 insertions(+), 148 deletions(-) create mode 100644 app/src/main/java/com/github/kr328/clash/remote/Service.kt delete mode 100644 app/src/main/java/com/github/kr328/clash/remote/Services.kt rename service/src/main/java/com/github/kr328/clash/service/{ProfileService.kt => ProfileManager.kt} (81%) create mode 100644 service/src/main/java/com/github/kr328/clash/service/RemoteService.kt create mode 100644 service/src/main/java/com/github/kr328/clash/service/remote/IRemoteService.kt diff --git a/app/src/main/java/com/github/kr328/clash/AppCrashedActivity.kt b/app/src/main/java/com/github/kr328/clash/AppCrashedActivity.kt index 374c6fa9..0a0a2044 100644 --- a/app/src/main/java/com/github/kr328/clash/AppCrashedActivity.kt +++ b/app/src/main/java/com/github/kr328/clash/AppCrashedActivity.kt @@ -24,8 +24,6 @@ class AppCrashedActivity : BaseActivity() { SystemLogcat.dumpCrash() } - Tracker.uploadLogcat(logs) - design.setAppLogs(logs) while (isActive) { diff --git a/app/src/main/java/com/github/kr328/clash/LogcatService.kt b/app/src/main/java/com/github/kr328/clash/LogcatService.kt index 11a75757..4484f86a 100644 --- a/app/src/main/java/com/github/kr328/clash/LogcatService.kt +++ b/app/src/main/java/com/github/kr328/clash/LogcatService.kt @@ -20,9 +20,9 @@ import com.github.kr328.clash.common.util.intent import com.github.kr328.clash.core.model.LogMessage import com.github.kr328.clash.log.LogcatCache import com.github.kr328.clash.log.LogcatWriter -import com.github.kr328.clash.service.ClashManager -import com.github.kr328.clash.service.remote.IClashManager +import com.github.kr328.clash.service.RemoteService import com.github.kr328.clash.service.remote.ILogObserver +import com.github.kr328.clash.service.remote.IRemoteService import com.github.kr328.clash.service.remote.unwrap import com.github.kr328.clash.util.logsDir import kotlinx.coroutines.* @@ -52,7 +52,7 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De showNotification() - bindService(ClashManager::class.intent, connection, Context.BIND_AUTO_CREATE) + bindService(RemoteService::class.intent, connection, Context.BIND_AUTO_CREATE) } override fun onDestroy() { @@ -88,7 +88,7 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De return stopSelf() launch(Dispatchers.IO) { - val service = binder.unwrap(IClashManager::class) + val service = binder.unwrap(IRemoteService::class).clash() val channel = Channel(CACHE_CAPACITY) try { diff --git a/app/src/main/java/com/github/kr328/clash/log/SystemLogcat.kt b/app/src/main/java/com/github/kr328/clash/log/SystemLogcat.kt index bbead046..848e0572 100644 --- a/app/src/main/java/com/github/kr328/clash/log/SystemLogcat.kt +++ b/app/src/main/java/com/github/kr328/clash/log/SystemLogcat.kt @@ -8,7 +8,8 @@ object SystemLogcat { "Go", "DEBUG", "AndroidRuntime", - "ClashForAndroid" + "ClashForAndroid", + "LwIP", ) fun dumpCrash(): String { diff --git a/app/src/main/java/com/github/kr328/clash/remote/Remote.kt b/app/src/main/java/com/github/kr328/clash/remote/Remote.kt index 664ecc3a..a80bc2ae 100644 --- a/app/src/main/java/com/github/kr328/clash/remote/Remote.kt +++ b/app/src/main/java/com/github/kr328/clash/remote/Remote.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.launch object Remote { val broadcasts: Broadcasts = Broadcasts(Global.application) - val services: Services = Services(Global.application) { + val service: Service = Service(Global.application) { ApplicationObserver.createdActivities.forEach { it.finish() } val intent = AppCrashedActivity::class.intent @@ -56,10 +56,10 @@ object Remote { while (true) { if (visible.receive()) { - services.bind() + service.bind() broadcasts.register() } else { - services.unbind() + service.unbind() broadcasts.unregister() } } diff --git a/app/src/main/java/com/github/kr328/clash/remote/Service.kt b/app/src/main/java/com/github/kr328/clash/remote/Service.kt new file mode 100644 index 00000000..079c0ae4 --- /dev/null +++ b/app/src/main/java/com/github/kr328/clash/remote/Service.kt @@ -0,0 +1,64 @@ +package com.github.kr328.clash.remote + +import android.app.Application +import android.content.ComponentName +import android.content.Context +import android.content.ServiceConnection +import android.os.IBinder +import com.github.kr328.clash.Tracker +import com.github.kr328.clash.common.log.Log +import com.github.kr328.clash.common.util.intent +import com.github.kr328.clash.log.SystemLogcat +import com.github.kr328.clash.service.RemoteService +import com.github.kr328.clash.service.remote.IRemoteService +import com.github.kr328.clash.service.remote.unwrap +import com.github.kr328.clash.util.unbindServiceSilent +import java.util.concurrent.TimeUnit + +class Service(private val context: Application, val crashed: () -> Unit) { + val remote = Resource() + + private val connection = object : ServiceConnection { + private var lastCrashed: Long = -1 + + override fun onServiceConnected(name: ComponentName?, service: IBinder) { + remote.set(service.unwrap(IRemoteService::class)) + } + + override fun onServiceDisconnected(name: ComponentName?) { + remote.set(null) + + Tracker.uploadLogcat(SystemLogcat.dumpCrash()) + + if (System.currentTimeMillis() - lastCrashed < TOGGLE_CRASHED_INTERVAL) { + unbind() + + crashed() + } + + lastCrashed = System.currentTimeMillis() + + Log.w("RemoteManager crashed") + } + } + + fun bind() { + try { + context.bindService(RemoteService::class.intent, connection, Context.BIND_AUTO_CREATE) + } catch (e: Exception) { + unbind() + + crashed() + } + } + + fun unbind() { + context.unbindServiceSilent(connection) + + remote.set(null) + } + + companion object { + private val TOGGLE_CRASHED_INTERVAL = TimeUnit.SECONDS.toMillis(10) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/kr328/clash/remote/Services.kt b/app/src/main/java/com/github/kr328/clash/remote/Services.kt deleted file mode 100644 index 3d9d7f10..00000000 --- a/app/src/main/java/com/github/kr328/clash/remote/Services.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.github.kr328.clash.remote - -import android.app.Application -import android.content.ComponentName -import android.content.Context -import android.content.ServiceConnection -import android.os.IBinder -import com.github.kr328.clash.common.log.Log -import com.github.kr328.clash.common.util.intent -import com.github.kr328.clash.service.ClashManager -import com.github.kr328.clash.service.ProfileService -import com.github.kr328.clash.service.remote.IClashManager -import com.github.kr328.clash.service.remote.IProfileManager -import com.github.kr328.clash.service.remote.unwrap -import com.github.kr328.clash.util.unbindServiceSilent -import java.util.concurrent.TimeUnit - -class Services(private val context: Application, val crashed: () -> Unit) { - val clash = Resource() - val profile = Resource() - - private val clashConnection = object : ServiceConnection { - private var lastCrashed: Long = -1 - - override fun onServiceConnected(name: ComponentName?, service: IBinder?) { - clash.set(service?.unwrap(IClashManager::class)) - } - - override fun onServiceDisconnected(name: ComponentName?) { - clash.set(null) - - if (System.currentTimeMillis() - lastCrashed < TOGGLE_CRASHED_INTERVAL) { - unbind() - - crashed() - } - - lastCrashed = System.currentTimeMillis() - - Log.w("ClashManager crashed") - } - } - - private val profileConnection = object : ServiceConnection { - private var lastCrashed: Long = -1 - - override fun onServiceConnected(name: ComponentName?, service: IBinder?) { - profile.set(service?.unwrap(IProfileManager::class)) - } - - override fun onServiceDisconnected(name: ComponentName?) { - profile.set(null) - - if (System.currentTimeMillis() - lastCrashed < TOGGLE_CRASHED_INTERVAL) { - unbind() - - crashed() - } - - lastCrashed = System.currentTimeMillis() - - Log.w("ProfileService crashed") - } - } - - fun bind() { - try { - context.bindService(ClashManager::class.intent, clashConnection, Context.BIND_AUTO_CREATE) - context.bindService(ProfileService::class.intent, profileConnection, Context.BIND_AUTO_CREATE) - } catch (e: Exception) { - unbind() - - crashed() - } - } - - fun unbind() { - context.unbindServiceSilent(clashConnection) - context.unbindServiceSilent(profileConnection) - - clash.set(null) - profile.set(null) - } - - companion object { - private val TOGGLE_CRASHED_INTERVAL = TimeUnit.SECONDS.toMillis(10) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/kr328/clash/util/Remote.kt b/app/src/main/java/com/github/kr328/clash/util/Remote.kt index ffc9c8bc..20120c41 100644 --- a/app/src/main/java/com/github/kr328/clash/util/Remote.kt +++ b/app/src/main/java/com/github/kr328/clash/util/Remote.kt @@ -14,14 +14,15 @@ suspend fun withClash( block: suspend IClashManager.() -> T ): T { while (true) { - val client = Remote.services.clash.get() + val remote = Remote.service.remote.get() + val client = remote.clash() try { return withContext(context) { client.block() } } catch (e: DeadObjectException) { Log.w("Remote services panic") - Remote.services.clash.reset(client) + Remote.service.remote.reset(remote) } } } @@ -31,14 +32,15 @@ suspend fun withProfile( block: suspend IProfileManager.() -> T ): T { while (true) { - val client = Remote.services.profile.get() + val remote = Remote.service.remote.get() + val client = remote.profile() try { return withContext(context) { client.block() } } catch (e: DeadObjectException) { Log.w("Remote services panic") - Remote.services.profile.reset(client) + Remote.service.remote.reset(remote) } } } diff --git a/service/src/main/AndroidManifest.xml b/service/src/main/AndroidManifest.xml index 60d3dbfd..d869fb38 100644 --- a/service/src/main/AndroidManifest.xml +++ b/service/src/main/AndroidManifest.xml @@ -25,11 +25,7 @@ - ? = null - override fun onBind(intent: Intent?): IBinder { - return binder - } - override fun queryTunnelState(): TunnelState { return Clash.queryTunnelState() } @@ -68,7 +61,7 @@ class ClashManager : BaseService(), IClashManager { override fun patchOverride(slot: Clash.OverrideSlot, configuration: ConfigurationOverride) { Clash.patchOverride(slot, configuration) - sendOverrideChanged() + context.sendOverrideChanged() } override fun clearOverride(slot: Clash.OverrideSlot) { diff --git a/service/src/main/java/com/github/kr328/clash/service/ProfileService.kt b/service/src/main/java/com/github/kr328/clash/service/ProfileManager.kt similarity index 81% rename from service/src/main/java/com/github/kr328/clash/service/ProfileService.kt rename to service/src/main/java/com/github/kr328/clash/service/ProfileManager.kt index 699bec8c..47d66b04 100644 --- a/service/src/main/java/com/github/kr328/clash/service/ProfileService.kt +++ b/service/src/main/java/com/github/kr328/clash/service/ProfileManager.kt @@ -1,7 +1,6 @@ package com.github.kr328.clash.service -import android.content.Intent -import android.os.IBinder +import android.content.Context import com.github.kr328.clash.service.data.Database import com.github.kr328.clash.service.data.ImportedDao import com.github.kr328.clash.service.data.Pending @@ -9,34 +8,27 @@ import com.github.kr328.clash.service.data.PendingDao import com.github.kr328.clash.service.model.Profile import com.github.kr328.clash.service.remote.IFetchObserver import com.github.kr328.clash.service.remote.IProfileManager -import com.github.kr328.clash.service.remote.wrap import com.github.kr328.clash.service.store.ServiceStore import com.github.kr328.clash.service.util.directoryLastModified import com.github.kr328.clash.service.util.generateProfileUUID import com.github.kr328.clash.service.util.importedDir import com.github.kr328.clash.service.util.pendingDir +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.FileNotFoundException import java.util.* -class ProfileService : BaseService(), IProfileManager { - private val service = this - private val store by lazy { ServiceStore(this) } - private val binder = this.wrap() - - override fun onBind(intent: Intent?): IBinder { - return binder - } - - override fun onCreate() { - super.onCreate() - - Database.database //.init +class ProfileManager(private val context: Context) : IProfileManager, + CoroutineScope by CoroutineScope(Dispatchers.IO) { + private val store = ServiceStore(context) + init { launch { - ProfileReceiver.rescheduleAll(service) + Database.database //.init + + ProfileReceiver.rescheduleAll(context) } } @@ -52,7 +44,7 @@ class ProfileService : BaseService(), IProfileManager { PendingDao().insert(pending) - pendingDir.resolve(uuid.toString()).apply { + context.pendingDir.resolve(uuid.toString()).apply { deleteRecursively() mkdirs() @@ -119,21 +111,21 @@ class ProfileService : BaseService(), IProfileManager { } override suspend fun commit(uuid: UUID, callback: IFetchObserver?) { - ProfileProcessor.apply(service, uuid, callback) + ProfileProcessor.apply(context, uuid, callback) scheduleUpdate(uuid, false) } override suspend fun release(uuid: UUID) { - ProfileProcessor.release(this, uuid) + ProfileProcessor.release(context, uuid) } override suspend fun delete(uuid: UUID) { ImportedDao().queryByUUID(uuid)?.also { - ProfileReceiver.cancelNext(service, it) + ProfileReceiver.cancelNext(context, it) } - ProfileProcessor.delete(service, uuid) + ProfileProcessor.delete(context, uuid) } override suspend fun queryByUUID(uuid: UUID): Profile? { @@ -159,7 +151,7 @@ class ProfileService : BaseService(), IProfileManager { } override suspend fun setActive(profile: Profile) { - ProfileProcessor.active(this, profile.uuid) + ProfileProcessor.active(context, profile.uuid) } private suspend fun resolveProfile(uuid: UUID): Profile? { @@ -186,14 +178,14 @@ class ProfileService : BaseService(), IProfileManager { } private fun resolveUpdatedAt(uuid: UUID): Long { - return pendingDir.resolve(uuid.toString()).directoryLastModified - ?: importedDir.resolve(uuid.toString()).directoryLastModified + return context.pendingDir.resolve(uuid.toString()).directoryLastModified + ?: context.importedDir.resolve(uuid.toString()).directoryLastModified ?: -1 } private fun cloneImportedFiles(source: UUID, target: UUID = source) { - val s = importedDir.resolve(source.toString()) - val t = pendingDir.resolve(target.toString()) + val s = context.importedDir.resolve(source.toString()) + val t = context.pendingDir.resolve(target.toString()) if (!s.exists()) throw FileNotFoundException("profile $source not found") @@ -207,9 +199,9 @@ class ProfileService : BaseService(), IProfileManager { val imported = ImportedDao().queryByUUID(uuid) ?: return if (startImmediately) { - ProfileReceiver.schedule(service, imported) + ProfileReceiver.schedule(context, imported) } else { - ProfileReceiver.scheduleNext(service, imported) + ProfileReceiver.scheduleNext(context, imported) } } } \ No newline at end of file diff --git a/service/src/main/java/com/github/kr328/clash/service/RemoteService.kt b/service/src/main/java/com/github/kr328/clash/service/RemoteService.kt new file mode 100644 index 00000000..802110f3 --- /dev/null +++ b/service/src/main/java/com/github/kr328/clash/service/RemoteService.kt @@ -0,0 +1,46 @@ +package com.github.kr328.clash.service + +import android.content.Intent +import android.os.IBinder +import com.github.kr328.clash.service.remote.IClashManager +import com.github.kr328.clash.service.remote.IRemoteService +import com.github.kr328.clash.service.remote.IProfileManager +import com.github.kr328.clash.service.remote.wrap +import com.github.kr328.clash.service.util.cancelAndJoinBlocking + +class RemoteService : BaseService(), IRemoteService { + private val binder = this.wrap() + + private var clash: ClashManager? = null + private var profile: ProfileManager? = null + private var clashBinder: IClashManager? = null + private var profileBinder: IProfileManager? = null + + override fun onCreate() { + super.onCreate() + + clash = ClashManager(this) + profile = ProfileManager(this) + clashBinder = clash?.wrap() as IClashManager? + profileBinder = profile?.wrap() as IProfileManager? + } + + override fun onDestroy() { + super.onDestroy() + + clash?.cancelAndJoinBlocking() + profile?.cancelAndJoinBlocking() + } + + override fun onBind(intent: Intent?): IBinder { + return binder + } + + override fun clash(): IClashManager { + return clashBinder!! + } + + override fun profile(): IProfileManager { + return profileBinder!! + } +} \ No newline at end of file diff --git a/service/src/main/java/com/github/kr328/clash/service/remote/IRemoteService.kt b/service/src/main/java/com/github/kr328/clash/service/remote/IRemoteService.kt new file mode 100644 index 00000000..b8c92456 --- /dev/null +++ b/service/src/main/java/com/github/kr328/clash/service/remote/IRemoteService.kt @@ -0,0 +1,9 @@ +package com.github.kr328.clash.service.remote + +import com.github.kr328.kaidl.BinderInterface + +@BinderInterface +interface IRemoteService { + fun clash(): IClashManager + fun profile(): IProfileManager +} \ No newline at end of file