Commit 1970a565 authored by Max Lv's avatar Max Lv

try to fix ANR on some modified ROMs #19

parent 849b7f18
...@@ -66,16 +66,19 @@ import android.content.pm.{PackageInfo, PackageManager} ...@@ -66,16 +66,19 @@ import android.content.pm.{PackageInfo, PackageManager}
import android.net.{Uri, VpnService} import android.net.{Uri, VpnService}
import android.webkit.{WebViewClient, WebView} import android.webkit.{WebViewClient, WebView}
import android.app.backup.BackupManager import android.app.backup.BackupManager
import scala.concurrent.ops._
object Shadowsocks { object Shadowsocks {
val PREFS_NAME = "Shadowsocks" val PREFS_NAME = "Shadowsocks"
val PROXY_PREFS = Array("proxy", "remotePort", "port", "sitekey", "encMethod") val PROXY_PREFS = Array("proxy", "remotePort", "port", "sitekey", "encMethod")
val FEATRUE_PREFS = Array("isDNSProxy", "isGFWList", "isGlobalProxy", val FEATRUE_PREFS = Array("isGFWList", "isGlobalProxy", "isBypassApps", "proxyedApps",
"isBypassApps", "proxyedApps", "isAutoConnect") "isAutoConnect")
val TAG = "Shadowsocks" val TAG = "Shadowsocks"
val REQUEST_CONNECT = 1 val REQUEST_CONNECT = 1
private var vpnEnabled = -1
def isServiceStarted(context: Context): Boolean = { def isServiceStarted(context: Context): Boolean = {
ShadowsocksService.isServiceStarted(context) || ShadowVpnService.isServiceStarted(context) ShadowsocksService.isServiceStarted(context) || ShadowVpnService.isServiceStarted(context)
} }
...@@ -133,11 +136,11 @@ object Shadowsocks { ...@@ -133,11 +136,11 @@ object Shadowsocks {
val pref: Preference = findPreference(name) val pref: Preference = findPreference(name)
if (pref != null) { if (pref != null) {
val settings = PreferenceManager.getDefaultSharedPreferences(getActivity) val settings = PreferenceManager.getDefaultSharedPreferences(getActivity)
if ((name == "isBypassApps") || (name == "proxyedApps")) { if ((name == Key.isBypassApps) || (name == Key.proxyedApps)) {
val isGlobalProxy: Boolean = settings.getBoolean("isGlobalProxy", false) val isGlobalProxy: Boolean = settings.getBoolean(Key.isGlobalProxy, false)
pref.setEnabled(enabled && !isGlobalProxy) pref.setEnabled(enabled && !isGlobalProxy)
} else if (name == "isAutoConnect") { } else if (name == Key.isAutoConnect) {
pref.setEnabled(Utils.getRoot) pref.setEnabled(if (Shadowsocks.vpnEnabled == 1) false else true)
} else { } else {
pref.setEnabled(enabled) pref.setEnabled(enabled)
} }
...@@ -217,10 +220,7 @@ class Shadowsocks ...@@ -217,10 +220,7 @@ class Shadowsocks
Crouton.makeText(Shadowsocks.this, R.string.crash_alert, Style.ALERT).show() Crouton.makeText(Shadowsocks.this, R.string.crash_alert, Style.ALERT).show()
settings.edit().putBoolean(Key.isRunning, false).apply() settings.edit().putBoolean(Key.isRunning, false).apply()
case MSG_INITIAL_FINISH => case MSG_INITIAL_FINISH =>
if (progressDialog != null) { clearDialog()
progressDialog.dismiss()
progressDialog = null
}
} }
super.handleMessage(msg) super.handleMessage(msg)
} }
...@@ -314,22 +314,31 @@ class Shadowsocks ...@@ -314,22 +314,31 @@ class Shadowsocks
false false
} }
def prepareStartService() {
clearDialog()
progressDialog = ProgressDialog
.show(Shadowsocks.this, "", getString(R.string.connecting), true, true)
spawn {
if (isVpnEnabled) {
val intent = VpnService.prepare(this)
if (intent != null) {
startActivityForResult(intent, Shadowsocks.REQUEST_CONNECT)
} else {
onActivityResult(Shadowsocks.REQUEST_CONNECT, Activity.RESULT_OK, null)
}
} else {
if (!serviceStart) {
switchButton.setChecked(false)
}
}
}
}
def onCheckedChanged(compoundButton: CompoundButton, checked: Boolean) { def onCheckedChanged(compoundButton: CompoundButton, checked: Boolean) {
if (compoundButton eq switchButton) { if (compoundButton eq switchButton) {
checked match { checked match {
case true => { case true => {
if (isVpnEnabled) { prepareStartService()
val intent = VpnService.prepare(this)
if (intent != null) {
startActivityForResult(intent, Shadowsocks.REQUEST_CONNECT)
} else {
onActivityResult(Shadowsocks.REQUEST_CONNECT, Activity.RESULT_OK, null)
}
} else {
if (!serviceStart) {
switchButton.setChecked(false)
}
}
} }
case false => { case false => {
serviceStop() serviceStop()
...@@ -366,24 +375,15 @@ class Shadowsocks ...@@ -366,24 +375,15 @@ class Shadowsocks
if (progressDialog == null) { if (progressDialog == null) {
progressDialog = ProgressDialog.show(this, "", getString(R.string.initializing), true, true) progressDialog = ProgressDialog.show(this, "", getString(R.string.initializing), true, true)
} }
new Thread { spawn {
override def run() { Utils.getRoot
Utils.getRoot val update = getSharedPreferences(Key.update, Context.MODE_WORLD_WRITEABLE)
var versionName: String = null if (!update.getBoolean(getVersionName, false)) {
try { update.edit.putBoolean(getVersionName, true).apply()
versionName = getPackageManager.getPackageInfo(getPackageName, 0).versionName reset()
} catch {
case e: PackageManager.NameNotFoundException => {
versionName = "NONE"
}
}
if (!settings.getBoolean(versionName, false)) {
settings.edit.putBoolean(versionName, true).apply()
reset()
}
handler.sendEmptyMessage(MSG_INITIAL_FINISH)
} }
}.start() handler.sendEmptyMessage(MSG_INITIAL_FINISH)
}
} }
} }
...@@ -460,12 +460,10 @@ class Shadowsocks ...@@ -460,12 +460,10 @@ class Shadowsocks
Crouton.cancelAllCroutons() Crouton.cancelAllCroutons()
setPreferenceEnabled(true) setPreferenceEnabled(true)
if (settings.getBoolean(Key.isRunning, false)) { if (settings.getBoolean(Key.isRunning, false)) {
new Thread { spawn {
override def run() { crash_recovery()
crash_recovery() handler.sendEmptyMessage(MSG_CRASH_RECOVER)
handler.sendEmptyMessage(MSG_CRASH_RECOVER) }
}
}.start()
} }
onStateChanged(State.STOPPED, null) onStateChanged(State.STOPPED, null)
} }
...@@ -484,11 +482,11 @@ class Shadowsocks ...@@ -484,11 +482,11 @@ class Shadowsocks
for (name <- Shadowsocks.FEATRUE_PREFS) { for (name <- Shadowsocks.FEATRUE_PREFS) {
val pref: Preference = findPreference(name) val pref: Preference = findPreference(name)
if (pref != null) { if (pref != null) {
if ((name == "isBypassApps") || (name == "proxyedApps")) { if ((name == Key.isBypassApps) || (name == Key.proxyedApps)) {
val isGlobalProxy: Boolean = settings.getBoolean("isGlobalProxy", false) val isGlobalProxy: Boolean = settings.getBoolean("isGlobalProxy", false)
pref.setEnabled(enabled && !isGlobalProxy) pref.setEnabled(enabled && !isGlobalProxy)
} else if (name == "isAutoConnect") { } else if (name == Key.isAutoConnect) {
pref.setEnabled(Utils.getRoot) pref.setEnabled(if (Shadowsocks.vpnEnabled == 1) false else true)
} else { } else {
pref.setEnabled(enabled) pref.setEnabled(enabled)
} }
...@@ -504,10 +502,7 @@ class Shadowsocks ...@@ -504,10 +502,7 @@ class Shadowsocks
override def onStop() { override def onStop() {
super.onStop() super.onStop()
EasyTracker.getInstance.activityStop(this) EasyTracker.getInstance.activityStop(this)
if (progressDialog != null) { clearDialog()
progressDialog.dismiss()
progressDialog = null
}
} }
override def onDestroy() { override def onDestroy() {
...@@ -530,24 +525,18 @@ class Shadowsocks ...@@ -530,24 +525,18 @@ class Shadowsocks
} }
private def recovery() { private def recovery() {
if (progressDialog == null) { clearDialog()
progressDialog = ProgressDialog.show(this, "", getString(R.string.recovering), true, true) progressDialog = ProgressDialog.show(this, "", getString(R.string.recovering), true, true)
}
val h: Handler = new Handler { val h: Handler = new Handler {
override def handleMessage(msg: Message) { override def handleMessage(msg: Message) {
if (progressDialog != null) { clearDialog()
progressDialog.dismiss()
progressDialog = null
}
} }
} }
serviceStop() serviceStop()
new Thread { spawn {
override def run() { reset()
reset() h.sendEmptyMessage(0)
h.sendEmptyMessage(0) }
}
}.start()
} }
override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
...@@ -565,7 +554,15 @@ class Shadowsocks ...@@ -565,7 +554,15 @@ class Shadowsocks
} }
def isVpnEnabled: Boolean = { def isVpnEnabled: Boolean = {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && !Utils.getRoot if (Shadowsocks.vpnEnabled < 0) {
Shadowsocks.vpnEnabled = if (Build.VERSION.SDK_INT
>= Build.VERSION_CODES.ICE_CREAM_SANDWICH && !Utils.getRoot) {
1
} else {
0
}
}
if (Shadowsocks.vpnEnabled == 1) true else false
} }
def serviceStop() { def serviceStop() {
...@@ -580,9 +577,9 @@ class Shadowsocks ...@@ -580,9 +577,9 @@ class Shadowsocks
/** Called when connect button is clicked. */ /** Called when connect button is clicked. */
def serviceStart: Boolean = { def serviceStart: Boolean = {
val proxy = settings.getString("proxy", "") val proxy = settings.getString(Key.proxy, "")
if (isTextEmpty(proxy, getString(R.string.proxy_empty))) return false if (isTextEmpty(proxy, getString(R.string.proxy_empty))) return false
val portText = settings.getString("port", "") val portText = settings.getString(Key.localPort, "")
if (isTextEmpty(portText, getString(R.string.port_empty))) return false if (isTextEmpty(portText, getString(R.string.port_empty))) return false
try { try {
val port: Int = Integer.valueOf(portText) val port: Int = Integer.valueOf(portText)
...@@ -677,7 +674,8 @@ class Shadowsocks ...@@ -677,7 +674,8 @@ class Shadowsocks
state match { state match {
case State.CONNECTING => { case State.CONNECTING => {
if (progressDialog == null) { if (progressDialog == null) {
progressDialog = ProgressDialog.show(Shadowsocks.this, "", getString(R.string.connecting), true, true) progressDialog = ProgressDialog
.show(Shadowsocks.this, "", getString(R.string.connecting), true, true)
} }
setPreferenceEnabled(false) setPreferenceEnabled(false)
} }
...@@ -699,7 +697,9 @@ class Shadowsocks ...@@ -699,7 +697,9 @@ class Shadowsocks
.setBackgroundColorValue(Style.holoRedLight) .setBackgroundColorValue(Style.holoRedLight)
.setDuration(Style.DURATION_INFINITE) .setDuration(Style.DURATION_INFINITE)
.build() .build()
Crouton.makeText(Shadowsocks.this, getString(R.string.vpn_error).format(m), style).show() Crouton
.makeText(Shadowsocks.this, getString(R.string.vpn_error).format(m), style)
.show()
} }
setPreferenceEnabled(true) setPreferenceEnabled(true)
} }
......
...@@ -50,6 +50,7 @@ class ShadowsocksReceiver extends BroadcastReceiver { ...@@ -50,6 +50,7 @@ class ShadowsocksReceiver extends BroadcastReceiver {
def onReceive(context: Context, intent: Intent) { def onReceive(context: Context, intent: Intent) {
val settings: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) val settings: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
val update = context.getSharedPreferences(Key.update, Context.MODE_WORLD_READABLE)
if (intent.getAction == Action.UPDATE_STATE) { if (intent.getAction == Action.UPDATE_STATE) {
val state = intent.getIntExtra(Extra.STATE, State.INIT) val state = intent.getIntExtra(Extra.STATE, State.INIT)
...@@ -58,7 +59,7 @@ class ShadowsocksReceiver extends BroadcastReceiver { ...@@ -58,7 +59,7 @@ class ShadowsocksReceiver extends BroadcastReceiver {
case State.CONNECTED => true case State.CONNECTED => true
case _ => false case _ => false
} }
settings.edit.putBoolean(Key.isRunning, running).apply() settings.edit.putBoolean(Key.isRunning, running).commit()
return return
} }
...@@ -70,8 +71,8 @@ class ShadowsocksReceiver extends BroadcastReceiver { ...@@ -70,8 +71,8 @@ class ShadowsocksReceiver extends BroadcastReceiver {
versionName = "NONE" versionName = "NONE"
} }
} }
val isAutoConnect: Boolean = settings.getBoolean("isAutoConnect", false) val isAutoConnect: Boolean = settings.getBoolean(Key.isAutoConnect, false)
val isInstalled: Boolean = settings.getBoolean(versionName, false) val isInstalled: Boolean = update.getBoolean(versionName, false)
if (isAutoConnect && isInstalled) { if (isAutoConnect && isInstalled) {
if (Utils.getRoot) { if (Utils.getRoot) {
if (ShadowsocksService.isServiceStarted(context)) return if (ShadowsocksService.isServiceStarted(context)) return
......
...@@ -53,7 +53,11 @@ import android.graphics.{Canvas, Bitmap} ...@@ -53,7 +53,11 @@ import android.graphics.{Canvas, Bitmap}
import android.app.ActivityManager import android.app.ActivityManager
object Key { object Key {
val update = "update"
val proxyedApps = "proxyedApps"
val isRunning = "isRunning" val isRunning = "isRunning"
val isAutoConnect = "isAutoConnect"
val isGlobalProxy = "isGlobalProxy" val isGlobalProxy = "isGlobalProxy"
val isGFWList = "isGFWList" val isGFWList = "isGFWList"
...@@ -490,16 +494,16 @@ object Utils { ...@@ -490,16 +494,16 @@ object Utils {
root_shell = "su" root_shell = "su"
} }
val sb = new StringBuilder val sb = new StringBuilder
val command: String = "ls /\n exit\n" val command: String = "id\n"
val exitcode: Int = runScript(command, sb, 10 * 1000, asroot = true) val exitcode: Int = runScript(command, sb, 10 * 1000, asroot = true)
if (exitcode == TIME_OUT) { if (exitcode == TIME_OUT) {
return false return false
} }
val lines = sb.toString() val lines = sb.toString()
if (lines.contains("system")) { if (lines.contains("uid=0")) {
isRoot = 1 isRoot = 1
} else { } else {
if (rootTries > 3) isRoot = 0 if (rootTries >= 1) isRoot = 0
rootTries += 1 rootTries += 1
} }
isRoot == 1 isRoot == 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment