Merge pull request #583 from JLLK/master
Fix binder ipc issue when process died unexpected
This commit is contained in:
@@ -4,16 +4,15 @@ import android.content.{ComponentName, Context, Intent, ServiceConnection}
|
||||
import android.os.{RemoteException, IBinder}
|
||||
import com.github.shadowsocks.aidl.{IShadowsocksServiceCallback, IShadowsocksService}
|
||||
import com.github.shadowsocks.utils.Action
|
||||
import com.github.shadowsocks.utils.Utils
|
||||
|
||||
/**
|
||||
* @author Mygod
|
||||
*/
|
||||
trait ServiceBoundContext extends Context {
|
||||
|
||||
trait ServiceBoundContext extends Context { outer =>
|
||||
class ShadowsocksServiceConnection extends ServiceConnection {
|
||||
override def onServiceConnected(name: ComponentName, service: IBinder) {
|
||||
bgService = IShadowsocksService.Stub.asInterface(service)
|
||||
bgService.asBinder().linkToDeath(new ShadowsocksDeathRecipient(outer), 0)
|
||||
registerCallback
|
||||
ServiceBoundContext.this.onServiceConnected()
|
||||
}
|
||||
@@ -33,11 +32,12 @@ trait ServiceBoundContext extends Context {
|
||||
} catch {
|
||||
case ignored: RemoteException => // Nothing
|
||||
}
|
||||
|
||||
def unregisterCallback = if (bgService != null && callback != null && callbackRegistered) try {
|
||||
bgService.unregisterCallback(callback)
|
||||
callbackRegistered = false
|
||||
} catch {
|
||||
case ignored: RemoteException => // Nothing
|
||||
case ignored: RemoteException => callbackRegistered = false
|
||||
}
|
||||
|
||||
def onServiceConnected() = ()
|
||||
|
||||
@@ -377,7 +377,11 @@ class Shadowsocks
|
||||
})
|
||||
updateTraffic(0, 0, 0, 0)
|
||||
|
||||
// Bind to the service
|
||||
bindToService()
|
||||
}
|
||||
|
||||
// Bind to the service
|
||||
def bindToService() {
|
||||
handler.post(() => attachService)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.github.shadowsocks
|
||||
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import com.github.shadowsocks.utils.ProcessUtils._
|
||||
|
||||
/**
|
||||
* @author chentaov5@gmail.com
|
||||
*/
|
||||
class ShadowsocksDeathRecipient(val mContext: ServiceBoundContext)
|
||||
extends IBinder.DeathRecipient {
|
||||
|
||||
val TAG = "ShadowsocksDeathRecipient"
|
||||
|
||||
override def binderDied(): Unit = {
|
||||
Log.d(TAG, "[ShadowsocksDeathRecipient] binder died.")
|
||||
|
||||
mContext match {
|
||||
case ss: Shadowsocks =>
|
||||
inShadowsocks {
|
||||
ss.unregisterCallback
|
||||
ss.bindToService()
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.github.shadowsocks.utils
|
||||
|
||||
import android.util.Log
|
||||
|
||||
/**
|
||||
* @author chentaov5@gmail.com
|
||||
*/
|
||||
object IOUtils {
|
||||
|
||||
val TAG = "IOUtils"
|
||||
|
||||
def autoClose[R <: {def close() : Unit}, T](in: R)(fun: => T): T = {
|
||||
try {
|
||||
fun
|
||||
} finally if (in ne null)
|
||||
try {
|
||||
in.close()
|
||||
} catch {
|
||||
case e: Exception => Log.d(TAG, e.getMessage, e)
|
||||
}
|
||||
}
|
||||
|
||||
def inSafe[T](fun: => T): Option[T] = {
|
||||
var res: Option[T] = None
|
||||
try {
|
||||
res = Some(fun)
|
||||
} catch {
|
||||
case e: Exception => Log.d(TAG, e.getMessage, e)
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.github.shadowsocks.utils
|
||||
|
||||
import java.io.{BufferedReader, FileInputStream, InputStreamReader}
|
||||
|
||||
import com.github.shadowsocks.utils.IOUtils._
|
||||
|
||||
/**
|
||||
* @author chentaov5@gmail.com
|
||||
*/
|
||||
object ProcessUtils {
|
||||
|
||||
val SHADOWNSOCKS = "com.github.shadowsocks"
|
||||
val SHADOWNSOCKS_VPN = "com.github.shadowsocks:vpn"
|
||||
val SHADOWNSOCKS_NAT = "com.github.shadowsocks:nat"
|
||||
val TUN2SOCKS = "/data/data/com.github.shadowsocks/tun2socks"
|
||||
val SS_LOCAL = "/data/data/com.github.shadowsocks/ss-local"
|
||||
val SS_TUNNEL = "/data/data/com.github.shadowsocks/ss-tunnel"
|
||||
val PDNSD = "/data/data/com.github.shadowsocks/pdnsd"
|
||||
|
||||
def getCurrentProcessName: String = {
|
||||
inSafe {
|
||||
val inputStream = new FileInputStream("/proc/self/cmdline")
|
||||
val reader = new BufferedReader(new InputStreamReader(inputStream))
|
||||
autoClose(reader) {
|
||||
reader.readLine() match {
|
||||
case name: String => name
|
||||
case _ => ""
|
||||
}
|
||||
}
|
||||
} match {
|
||||
case Some(name: String) => name
|
||||
case None => ""
|
||||
}
|
||||
}
|
||||
|
||||
def inShadowsocks[A](fun: => A): Unit =
|
||||
if(getCurrentProcessName startsWith SHADOWNSOCKS) fun
|
||||
|
||||
def inVpn[A](fun: => A): Unit =
|
||||
if (getCurrentProcessName startsWith SHADOWNSOCKS_VPN) fun
|
||||
|
||||
|
||||
def inNat[A](fun: => A): Unit =
|
||||
if (getCurrentProcessName startsWith SHADOWNSOCKS_NAT) fun
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user