ManagerIPC.kt (2202B) - raw


      1 package me.rhunk.snapenhance.scripting.impl
      2 
      3 import android.os.DeadObjectException
      4 import me.rhunk.snapenhance.bridge.scripting.IPCListener
      5 import me.rhunk.snapenhance.common.scripting.impl.IPCInterface
      6 import me.rhunk.snapenhance.common.scripting.impl.Listener
      7 import java.util.concurrent.ConcurrentHashMap
      8 
      9 typealias IPCListeners = ConcurrentHashMap<String, MutableMap<String, MutableSet<IPCListener>>>  // channel, eventName -> listeners
     10 
     11 class ManagerIPC(
     12     private val ipcListeners: IPCListeners = ConcurrentHashMap(),
     13 ) : IPCInterface() {
     14     companion object {
     15         private const val TAG = "RemoteManagerIPC"
     16     }
     17 
     18     override fun on(eventName: String, listener: Listener) {
     19         onBroadcast(context.moduleInfo.name, eventName, listener)
     20     }
     21 
     22     override fun emit(eventName: String, vararg args: String?): Int {
     23         return broadcast(context.moduleInfo.name, eventName, *args)
     24     }
     25 
     26     override fun onBroadcast(channel: String, eventName: String, listener: Listener) {
     27         ipcListeners.getOrPut(channel) { mutableMapOf() }.getOrPut(eventName) { mutableSetOf() }.add(object: IPCListener.Stub() {
     28             override fun onMessage(args: Array<out String?>) {
     29                 try {
     30                     listener(args.toList())
     31                 } catch (doe: DeadObjectException) {
     32                     ipcListeners[channel]?.get(eventName)?.remove(this)
     33                 } catch (t: Throwable) {
     34                     context.runtime.logger.error("Failed to receive message for channel: $channel, event: $eventName", t, TAG)
     35                 }
     36             }
     37         })
     38     }
     39 
     40     override fun broadcast(channel: String, eventName: String, vararg args: String?): Int {
     41         var dispatchCount = 0
     42         ipcListeners[channel]?.get(eventName)?.toList()?.forEach {
     43             try {
     44                 it.onMessage(args)
     45                 dispatchCount++
     46             } catch (doe: DeadObjectException) {
     47                 ipcListeners[channel]?.get(eventName)?.remove(it)
     48             } catch (t: Throwable) {
     49                 context.runtime.logger.error("Failed to send message for channel: $channel, event: $eventName", t, TAG)
     50             }
     51         }
     52         return dispatchCount
     53     }
     54 }