event framework

This commit is contained in:
Kr328 committed 2019-11-25 00:35:06 +08:00
1 parent da532df009
commit 0e6cb05796
11 files changed
+258 -22

No files matched your search

@@ -0,0 +1,31 @@
package com.github.kr328.clash.core.event
import android.os.Parcel
import android.os.Parcelable
import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
@Serializable
data class ErrorEvent(val type: Type, val message: String): Event, Parcelable {
enum class Type {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
Parcels.dump(serializer(), this, parcel)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<ErrorEvent> {
override fun createFromParcel(parcel: Parcel): ErrorEvent {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<ErrorEvent?> {
return arrayOfNulls(size)
}
}
}
@@ -1,5 +1,8 @@
package com.github.kr328.clash.core.event
import android.os.Parcel
import android.os.Parcelable
import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Decoder
import kotlinx.serialization.Encoder
import kotlinx.serialization.KSerializer
@@ -10,12 +13,23 @@ import java.lang.IllegalArgumentException
@Serializable
data class LogEvent(val level: Level, val message: String):
Event {
Event, Parcelable {
companion object {
const val DEBUG_VALUE = 1
const val INFO_VALUE = 2
const val WARN_VALUE = 3
const val ERROR_VALUE = 4
@JvmField
val CREATOR = object: Parcelable.Creator<LogEvent> {
override fun createFromParcel(parcel: Parcel): LogEvent {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<LogEvent?> {
return arrayOfNulls(size)
}
}
}
@Serializable(LevelSerializer::class)
@@ -45,4 +59,12 @@ data class LogEvent(val level: Level, val message: String):
encoder.encodeInt(obj.value)
}
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
Parcels.dump(serializer(), this, parcel)
}
override fun describeContents(): Int {
return 0
}
}
@@ -1,5 +1,28 @@
package com.github.kr328.clash.core.event
import android.os.Parcel
import android.os.Parcelable
import com.github.kr328.clash.core.event.Event
import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
class ProxyChangedEvent : Event
@Serializable
data class ProxyChangedEvent(val name: String, val selected: String) : Event,Parcelable {
override fun writeToParcel(parcel: Parcel, flags: Int) {
Parcels.dump(serializer(), this, parcel)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<ProxyChangedEvent> {
override fun createFromParcel(parcel: Parcel): ProxyChangedEvent {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<ProxyChangedEvent?> {
return arrayOfNulls(size)
}
}
}
@@ -1,6 +1,27 @@
package com.github.kr328.clash.core.event
import android.os.Parcel
import android.os.Parcelable
import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
@Serializable
data class TrafficEvent(val down: Long, val up: Long, val total: Long): Event
data class TrafficEvent(val down: Long, val up: Long, val total: Long): Event, Parcelable {
override fun writeToParcel(parcel: Parcel, flags: Int) {
Parcels.dump(serializer(), this, parcel)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<TrafficEvent> {
override fun createFromParcel(parcel: Parcel): TrafficEvent {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<TrafficEvent?> {
return arrayOfNulls(size)
}
}
}
@@ -1,3 +0,0 @@
package com.github.kr328.clash.core;
parcelable ClashProcessStatus;
@@ -0,0 +1,7 @@
package com.github.kr328.clash.core.event;
parcelable ProcessEvent;
parcelable LogEvent;
parcelable ProxyChangedEvent;
parcelable TrafficEvent;
parcelable ErrorEvent;
@@ -0,0 +1,11 @@
package com.github.kr328.clash.service;
import com.github.kr328.clash.core.event.Event;
interface IClashEventObserver {
void onProcessEvent(in ProcessEvent event);
void onProxyChangedEvent(in ProxyChangedEvent event);
void onLogEvent(in LogEvent event);
void onErrorEvent(in ErrorEvent event);
void onTrafficEvent(in TrafficEvent event);
}
@@ -0,0 +1,11 @@
package com.github.kr328.clash.service;
import com.github.kr328.clash.service.IClashEventObserver;
interface IClashEventService {
void registerEventObserver(String id, in IClashEventObserver observer);
void unregisterEventObserver(String id);
void acquireEvent(String id, int event);
void releaseEvent(String id, int event);
}
@@ -1,9 +0,0 @@
package com.github.kr328.clash.service;
import com.github.kr328.clash.core.model.ClashProcessStatus;
interface IClashObserver {
void onProxyChanged();
void onNewLogItem();
void onProcessStatusChanged(in ClashProcessStatus status);
}
@@ -1,14 +1,13 @@
package com.github.kr328.clash.service;
import com.github.kr328.clash.service.IClashObserver;
import com.github.kr328.clash.core.model.ClashProcessStatus;
import com.github.kr328.clash.service.IClashEventObserver;
import com.github.kr328.clash.service.IClashEventService;
import com.github.kr328.clash.core.event.Event;
interface IClashService {
void start();
void stop();
ClashProcessStatus getClashProcessStatus();
void registerObserver(String id, boolean notifyCurrent, in IClashObserver observer);
void unregisterObserver(String id);
IClashEventService getEventService();
void startTunDevice(in ParcelFileDescriptor fd, int mtu);
void stopTunDevice();
void start();
void stop();
}
@@ -0,0 +1,123 @@
package com.github.kr328.clash.service
import android.os.Handler
import android.os.Looper
import com.github.kr328.clash.core.event.*
import java.util.*
import kotlin.concurrent.thread
class ClashEventService(private val master: Master) : IClashEventService.Stub() {
interface Master {
fun requireEvent(event: Int)
fun releaseEvent(event: Int)
}
companion object {
private val EVENT_SET = setOf(Event.EVENT_LOG, Event.EVENT_TRAFFIC, Event.EVENT_PROXY_CHANGED)
}
private data class EventObserverRecord(val observer: IClashEventObserver, val acquiredEvent: MutableSet<Int>)
private val observers = mutableMapOf<String, EventObserverRecord>()
private lateinit var handler: Handler
init {
thread {
Looper.prepare()
handler = Handler()
Looper.loop()
}
}
fun preformProcessEvent(event: ProcessEvent) {
handler.post {
observers.values.forEach {
it.observer.onProcessEvent(event)
}
}
}
fun preformLogEvent(event: LogEvent) {
handler.post {
observers.values.forEach {
it.observer.onLogEvent(event)
}
}
}
fun preformProxyChangedEvent(event: ProxyChangedEvent) {
handler.post {
observers.values.forEach {
it.observer.onProxyChangedEvent(event)
}
}
}
fun preformTrafficEvent(event: TrafficEvent) {
handler.post {
observers.values.forEach {
it.observer.onTrafficEvent(event)
}
}
}
fun preformErrorEvent(event: ErrorEvent) {
handler.post {
observers.values.forEach {
it.observer.onErrorEvent(event)
}
}
}
override fun acquireEvent(id: String?, event: Int) {
handler.post {
require(id != null)
observers[id]?.acquiredEvent?.add(event)
recastEventRequirement()
}
}
override fun releaseEvent(id: String?, event: Int) {
handler.post {
require(id != null)
observers[id]?.acquiredEvent?.remove(event)
recastEventRequirement()
}
}
override fun unregisterEventObserver(id: String?) {
handler.post {
require(id != null)
observers.remove(id)
recastEventRequirement()
}
}
override fun registerEventObserver(id: String?, observer: IClashEventObserver?) {
handler.post {
require(id != null && observer != null)
observers[id] = EventObserverRecord(observer, mutableSetOf())
}
}
fun recastEventRequirement() {
handler.post {
val req = observers.values.flatMap {
it.acquiredEvent
}.toSet()
val rel = EVENT_SET - req
req.forEach(master::requireEvent)
rel.forEach(master::releaseEvent)
}
}
}