From b98d5a5ce0ba6dfb40eb107f846dd17fa6ceae57 Mon Sep 17 00:00:00 2001 From: Kr328 <39107975+Kr328@users.noreply.github.com> Date: Wed, 20 Nov 2019 12:10:33 +0800 Subject: [PATCH] clash service --- app/src/main/AndroidManifest.xml | 77 ++++++++--------- .../github/kr328/clash/IClashObserver.aidl | 4 +- .../com/github/kr328/clash/IClashService.aidl | 2 +- .../kr328/clash/core/ClashProcessStatus.aidl | 3 + .../github/kr328/clash/model/ClashStatus.aidl | 3 - .../com/github/kr328/clash/ClashService.kt | 22 ++--- .../com/github/kr328/clash/DataProvider.kt | 44 ++++++++++ .../com/github/kr328/clash/MainActivity.kt | 83 ++++++------------- .../java/com/github/kr328/clash/TunService.kt | 3 +- .../github/kr328/clash/model/ClashStatus.kt | 38 --------- .../java/com/github/kr328/clash/core/Clash.kt | 12 +-- .../github/kr328/clash/core/ClashProcess.kt | 10 +-- .../kr328/clash/core/ClashProcessStatus.kt | 32 +++++++ .../github/kr328/clash/core/ClashStatus.kt | 35 ++++++++ 14 files changed, 201 insertions(+), 167 deletions(-) create mode 100644 app/src/main/aidl/com/github/kr328/clash/core/ClashProcessStatus.aidl delete mode 100644 app/src/main/aidl/com/github/kr328/clash/model/ClashStatus.aidl create mode 100644 app/src/main/java/com/github/kr328/clash/DataProvider.kt delete mode 100644 app/src/main/java/com/github/kr328/clash/model/ClashStatus.kt create mode 100644 core/src/main/java/com/github/kr328/clash/core/ClashProcessStatus.kt create mode 100644 core/src/main/java/com/github/kr328/clash/core/ClashStatus.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ce5c234..b69d08b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,38 +1,41 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/aidl/com/github/kr328/clash/IClashObserver.aidl b/app/src/main/aidl/com/github/kr328/clash/IClashObserver.aidl index 77ce192..a18efbf 100644 --- a/app/src/main/aidl/com/github/kr328/clash/IClashObserver.aidl +++ b/app/src/main/aidl/com/github/kr328/clash/IClashObserver.aidl @@ -1,7 +1,7 @@ package com.github.kr328.clash; -import com.github.kr328.clash.model.ClashStatus; +import com.github.kr328.clash.core.ClashProcessStatus; interface IClashObserver { - void onStatusChanged(in ClashStatus status); + void onStatusChanged(in ClashProcessStatus status); } diff --git a/app/src/main/aidl/com/github/kr328/clash/IClashService.aidl b/app/src/main/aidl/com/github/kr328/clash/IClashService.aidl index 7158770..23c6de3 100644 --- a/app/src/main/aidl/com/github/kr328/clash/IClashService.aidl +++ b/app/src/main/aidl/com/github/kr328/clash/IClashService.aidl @@ -8,6 +8,6 @@ interface IClashService { void stop(); void registerObserver(String id, in IClashObserver observer); void unregisterObserver(String id); - void loadProfile(in Uri path); void startTunDevice(in ParcelFileDescriptor fd, int mtu); + void stopTunDevice(); } diff --git a/app/src/main/aidl/com/github/kr328/clash/core/ClashProcessStatus.aidl b/app/src/main/aidl/com/github/kr328/clash/core/ClashProcessStatus.aidl new file mode 100644 index 0000000..4d17b7c --- /dev/null +++ b/app/src/main/aidl/com/github/kr328/clash/core/ClashProcessStatus.aidl @@ -0,0 +1,3 @@ +package com.github.kr328.clash.core; + +parcelable ClashProcessStatus; \ No newline at end of file diff --git a/app/src/main/aidl/com/github/kr328/clash/model/ClashStatus.aidl b/app/src/main/aidl/com/github/kr328/clash/model/ClashStatus.aidl deleted file mode 100644 index f4fffc6..0000000 --- a/app/src/main/aidl/com/github/kr328/clash/model/ClashStatus.aidl +++ /dev/null @@ -1,3 +0,0 @@ -package com.github.kr328.clash.model; - -parcelable ClashStatus; \ No newline at end of file diff --git a/app/src/main/java/com/github/kr328/clash/ClashService.kt b/app/src/main/java/com/github/kr328/clash/ClashService.kt index ed029a7..51088f7 100644 --- a/app/src/main/java/com/github/kr328/clash/ClashService.kt +++ b/app/src/main/java/com/github/kr328/clash/ClashService.kt @@ -2,13 +2,11 @@ package com.github.kr328.clash import android.app.Service import android.content.Intent -import android.net.Uri import android.os.IBinder import android.os.ParcelFileDescriptor import android.os.RemoteException import com.github.kr328.clash.core.Clash -import com.github.kr328.clash.core.ClashProcess -import com.github.kr328.clash.model.ClashStatus +import com.github.kr328.clash.core.ClashProcessStatus import java.io.IOException class ClashService : Service() { @@ -18,13 +16,13 @@ class ClashService : Service() { private lateinit var clash: Clash - private var status = ClashProcess.Status.STOPPED + private var status = ClashProcessStatus(ClashProcessStatus.STATUS_STOPPED) set(value) { field = value for (kv in observers) { runCatching { - kv.value.onStatusChanged(ClashStatus(status)) + kv.value.onStatusChanged(status) } } } @@ -37,7 +35,7 @@ class ClashService : Service() { observers[id] = observer - observer.onStatusChanged(ClashStatus(status)) + observer.onStatusChanged(status) observer.asBinder().linkToDeath({ observers.remove(id) @@ -51,6 +49,10 @@ class ClashService : Service() { observers.remove(id) } + override fun stopTunDevice() { + clash.stop() + } + override fun start() { try { clash.start() @@ -63,14 +65,6 @@ class ClashService : Service() { clash.stop() } - override fun loadProfile(url: Uri?) { - try { - clash.loadProfile(url ?: throw RemoteException()) - } catch (e: IOException) { - throw RemoteException(e.message) - } - } - override fun startTunDevice(fd: ParcelFileDescriptor, mtu: Int) { try { clash.startTunDevice(fd.fileDescriptor, mtu) diff --git a/app/src/main/java/com/github/kr328/clash/DataProvider.kt b/app/src/main/java/com/github/kr328/clash/DataProvider.kt new file mode 100644 index 0000000..a1c0be1 --- /dev/null +++ b/app/src/main/java/com/github/kr328/clash/DataProvider.kt @@ -0,0 +1,44 @@ +package com.github.kr328.clash + +import android.content.ContentProvider +import android.content.ContentValues +import android.database.Cursor +import android.net.Uri + +class DataProvider : ContentProvider() { + override fun insert(uri: Uri, values: ContentValues?): Uri? { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun query( + uri: Uri, + projection: Array?, + selection: String?, + selectionArgs: Array?, + sortOrder: String? + ): Cursor? { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun onCreate(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array? + ): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun getType(uri: Uri): String? { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/github/kr328/clash/MainActivity.kt b/app/src/main/java/com/github/kr328/clash/MainActivity.kt index 1b27a98..b4d5b8d 100644 --- a/app/src/main/java/com/github/kr328/clash/MainActivity.kt +++ b/app/src/main/java/com/github/kr328/clash/MainActivity.kt @@ -1,57 +1,26 @@ -package com.github.kr328.clash - -import android.app.Activity -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.content.ServiceConnection -import android.net.VpnService -import android.os.Bundle -import android.os.IBinder -import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity -import kotlinx.android.synthetic.main.activity_main.* -import kotlin.concurrent.thread - -class MainActivity : AppCompatActivity() { - companion object { - private const val REQUEST_CODE = 233 - private const val VPN_REQUEST = 234 - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - - button.setOnClickListener { - startActivityForResult(Intent(Intent.ACTION_GET_CONTENT).setType("*/*"), REQUEST_CODE) - } - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { - Toast.makeText(this, intent?.dataString, Toast.LENGTH_LONG).show() - - thread { - bindService(Intent(this, ClashService::class.java), object : ServiceConnection { - override fun onServiceDisconnected(name: ComponentName?) { - Toast.makeText(this@MainActivity, "Disconnected", Toast.LENGTH_LONG).show() - } - - override fun onServiceConnected(name: ComponentName?, service: IBinder?) { - IClashService.Stub.asInterface(service)?.loadProfile(data?.data) - - VpnService.prepare(this@MainActivity)?.apply { - startActivityForResult(this, VPN_REQUEST) - } ?: startService(Intent(this@MainActivity, TunService::class.java)) - } - - }, Context.BIND_AUTO_CREATE) - } - } else if (requestCode == VPN_REQUEST && resultCode == Activity.RESULT_OK) { - startService(Intent(this, TunService::class.java)) - } else { - super.onActivityResult(requestCode, resultCode, data) - } - } -} +package com.github.kr328.clash + +import android.app.Activity +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.net.VpnService +import android.os.Bundle +import android.os.IBinder +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import kotlinx.android.synthetic.main.activity_main.* +import kotlin.concurrent.thread + +class MainActivity : AppCompatActivity() { + companion object { + private const val REQUEST_CODE = 233 + private const val VPN_REQUEST = 234 + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + } +} diff --git a/app/src/main/java/com/github/kr328/clash/TunService.kt b/app/src/main/java/com/github/kr328/clash/TunService.kt index b4b018f..e19de33 100644 --- a/app/src/main/java/com/github/kr328/clash/TunService.kt +++ b/app/src/main/java/com/github/kr328/clash/TunService.kt @@ -9,9 +9,8 @@ import android.net.VpnService import android.os.IBinder import android.os.ParcelFileDescriptor import com.github.kr328.clash.core.ClashProcess -import com.github.kr328.clash.model.ClashStatus +import com.github.kr328.clash.core.ClashStatus import java.lang.NullPointerException -import java.lang.RuntimeException class TunService : VpnService() { companion object { diff --git a/app/src/main/java/com/github/kr328/clash/model/ClashStatus.kt b/app/src/main/java/com/github/kr328/clash/model/ClashStatus.kt deleted file mode 100644 index 26cbc76..0000000 --- a/app/src/main/java/com/github/kr328/clash/model/ClashStatus.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.github.kr328.clash.model - -import android.os.Parcel -import android.os.Parcelable -import com.github.kr328.clash.core.ClashProcess - -data class ClashStatus(val status: ClashProcess.Status) : Parcelable { - override fun writeToParcel(parcel: Parcel, flags: Int) { - when ( status ) { - ClashProcess.Status.STOPPED -> parcel.writeInt(0) - ClashProcess.Status.STARTED -> parcel.writeInt(1) - } - } - - override fun describeContents(): Int { - return 0 - } - - companion object CREATOR : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): ClashStatus { - return ClashStatus(readFromParcel(parcel)) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - - private fun readFromParcel(parcel: Parcel): ClashProcess.Status { - return when ( parcel.readInt() ) { - 0 -> ClashProcess.Status.STOPPED - 1 -> ClashProcess.Status.STARTED - else -> throw IllegalArgumentException() - } - } - } - - -} \ No newline at end of file diff --git a/core/src/main/java/com/github/kr328/clash/core/Clash.kt b/core/src/main/java/com/github/kr328/clash/core/Clash.kt index 35fc20b..94fe2d7 100644 --- a/core/src/main/java/com/github/kr328/clash/core/Clash.kt +++ b/core/src/main/java/com/github/kr328/clash/core/Clash.kt @@ -4,16 +4,16 @@ import android.content.Context import android.net.LocalSocket import android.net.LocalSocketAddress import android.net.Uri -import android.os.ParcelFileDescriptor import android.util.Log import org.json.JSONObject import java.io.* -class Clash(private val context: Context, - clashDir: File, - private val controllerPath: File, - listener: (Status) -> Unit) : - ClashProcess(context, clashDir, controllerPath, listener) { +class Clash( + private val context: Context, + clashDir: File, + private val controllerPath: File, + listener: (ClashProcessStatus) -> Unit +) : ClashProcess(context, clashDir, controllerPath, listener) { companion object { const val COMMAND_PING = 0 const val COMMAND_TUN_START = 1 diff --git a/core/src/main/java/com/github/kr328/clash/core/ClashProcess.kt b/core/src/main/java/com/github/kr328/clash/core/ClashProcess.kt index 88f1544..5970db2 100644 --- a/core/src/main/java/com/github/kr328/clash/core/ClashProcess.kt +++ b/core/src/main/java/com/github/kr328/clash/core/ClashProcess.kt @@ -11,7 +11,7 @@ import kotlin.concurrent.thread abstract class ClashProcess(private val context: Context, private val clashDir: File, private val controllerPath: File, - private val listener: (Status) -> Unit) { + private val listener: (ClashProcessStatus) -> Unit) { companion object { const val TAG = "ClashForAndroid" @@ -23,10 +23,6 @@ abstract class ClashProcess(private val context: Context, private val CONTROLLER_ERROR_PATTERN = Regex("\\[CONTROLLER] ERROR=\\{(.+)\\}") } - enum class Status { - STARTED, STOPPED - } - private var pid: Int = 0 private var process: Process? = null @@ -83,7 +79,7 @@ abstract class ClashProcess(private val context: Context, process = p pid = currentPid - listener(Status.STARTED) + listener(ClashProcessStatus(ClashProcessStatus.STATUS_STARTED)) Log.i(TAG, "Clash started pid = $pid") @@ -99,7 +95,7 @@ abstract class ClashProcess(private val context: Context, pid = -1 } - listener(Status.STOPPED) + listener(ClashProcessStatus(ClashProcessStatus.STATUS_STOPPED)) } } diff --git a/core/src/main/java/com/github/kr328/clash/core/ClashProcessStatus.kt b/core/src/main/java/com/github/kr328/clash/core/ClashProcessStatus.kt new file mode 100644 index 0000000..563c0d2 --- /dev/null +++ b/core/src/main/java/com/github/kr328/clash/core/ClashProcessStatus.kt @@ -0,0 +1,32 @@ +package com.github.kr328.clash.core + +import android.os.Parcel +import android.os.Parcelable + +data class ClashProcessStatus(val status: Int) : Parcelable { + companion object { + const val STATUS_STOPPED = 0 + const val STATUS_STARTED = 1 + + @JvmField + val CREATOR = object: Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): ClashProcessStatus { + return ClashProcessStatus(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + } + + constructor(parcel: Parcel) : this(parcel.readInt()) + + override fun writeToParcel(parcel: Parcel, flags: Int) { + parcel.writeInt(status) + } + + override fun describeContents(): Int { + return 0 + } +} \ No newline at end of file diff --git a/core/src/main/java/com/github/kr328/clash/core/ClashStatus.kt b/core/src/main/java/com/github/kr328/clash/core/ClashStatus.kt new file mode 100644 index 0000000..ddd805c --- /dev/null +++ b/core/src/main/java/com/github/kr328/clash/core/ClashStatus.kt @@ -0,0 +1,35 @@ +package com.github.kr328.clash.core + +import android.os.Parcel +import android.os.Parcelable + +data class ClashStatus(val status: Int) : Parcelable { + companion object { + const val STOPPED = 0 + const val IDLE = 1 + const val LOADING_PROFILE = 2 + + @JvmField + val CREATOR = object: Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): ClashStatus { + return ClashStatus(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + } + + constructor(parcel: Parcel) : this(parcel.readInt()) + + override fun writeToParcel(dest: Parcel?, flags: Int) { + dest?.writeInt(status) + } + + override fun describeContents(): Int { + return 0 + } + + +} \ No newline at end of file