Commit 37d05236 authored by Mygod's avatar Mygod

Improve performance when fetching app list

parent faa1e5de
......@@ -39,7 +39,6 @@
package com.github.shadowsocks
import android.content.pm.PackageManager
import android.content.{ClipData, ClipboardManager, Context, SharedPreferences}
import android.graphics.PixelFormat
import android.graphics.drawable.Drawable
......@@ -56,45 +55,16 @@ import android.widget.CompoundButton.OnCheckedChangeListener
import android.widget._
import com.github.shadowsocks.utils.{Key, Utils}
import scala.collection.JavaConversions._
import scala.collection.mutable
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.language.implicitConversions
case class ProxiedApp(uid: Int, name: String, packageName: String, icon: Drawable, var proxied: Boolean)
class ObjectArrayTools[T <: AnyRef](a: Array[T]) {
def binarySearch(key: T) = {
java.util.Arrays.binarySearch(a.asInstanceOf[Array[AnyRef]], key)
}
}
case class ListEntry(switch: Switch, text: TextView, icon: ImageView)
object AppManager {
implicit def anyrefarray_tools[T <: AnyRef](a: Array[T]): ObjectArrayTools[T] = new ObjectArrayTools(a)
def getProxiedApps(context: Context, proxiedAppString: String): Array[ProxiedApp] = {
val proxiedApps = proxiedAppString.split('|').sortWith(_ < _)
import scala.collection.JavaConversions._
val packageManager: PackageManager = context.getPackageManager
val appList = packageManager.getInstalledApplications(0)
appList.filter(_.uid >= 10000).map {
case a =>
val uid = a.uid
val userName = uid.toString
val name = packageManager.getApplicationLabel(a).toString
val packageName = a.packageName
val proxied = proxiedApps.binarySearch(userName) >= 0
new ProxiedApp(uid, name, packageName, null, proxied)
}.toArray
}
}
class AppManager extends AppCompatActivity with OnCheckedChangeListener with OnClickListener
with OnMenuItemClickListener {
......@@ -102,49 +72,32 @@ class AppManager extends AppCompatActivity with OnCheckedChangeListener with OnC
val MSG_LOAD_FINISH = 2
val STUB = android.R.drawable.sym_def_app_icon
implicit def anyrefarray_tools[T <: AnyRef](a: Array[T]): ObjectArrayTools[T] = new ObjectArrayTools(a)
var apps: Array[ProxiedApp] = _
var apps: mutable.Buffer[ProxiedApp] = _
var appListView: ListView = _
var loadingView: View = _
var overlay: TextView = _
var adapter: ListAdapter = _
@volatile var appsLoading: Boolean = _
def loadApps(context: Context): Array[ProxiedApp] = {
val proxiedAppString = ShadowsocksApplication.settings.getString(Key.proxied, "")
val proxiedApps = proxiedAppString.split('|').sortWith(_ < _)
import scala.collection.JavaConversions._
val packageManager: PackageManager = context.getPackageManager
val appList = packageManager.getInstalledApplications(0)
def loadApps() {
appsLoading = true
val proxiedApps = ShadowsocksApplication.settings.getString(Key.proxied, "").split('|').toSet
appList.filter(a => a.uid >= 10000
&& packageManager.getApplicationLabel(a) != null
&& packageManager.getApplicationIcon(a) != null).map {
a =>
val packageManager = getPackageManager
apps = packageManager.getInstalledApplications(0).filter(_.uid >= 10000).map {
case a =>
val uid = a.uid
val userName = uid.toString
val name = packageManager.getApplicationLabel(a).toString
val packageName = a.packageName
val proxied = (proxiedApps binarySearch userName) >= 0
val proxied = proxiedApps.contains(userName)
new ProxiedApp(uid, name, packageName, a.loadIcon(packageManager), proxied)
}.toArray
}
def loadApps() {
appsLoading = true
apps = loadApps(this).sortWith((a, b) => {
}.sortWith((a, b) => {
if (a == null || b == null || a.name == null || b.name == null) {
true
} else if (a.proxied == b.proxied) {
a.name < b.name
} else if (a.proxied) {
true
} else {
false
}
} else a.proxied
})
adapter = new ArrayAdapter[ProxiedApp](this, R.layout.layout_apps_item, R.id.itemtext, apps) {
override def getView(position: Int, view: View, parent: ViewGroup): View = {
......
......@@ -54,7 +54,6 @@ import com.github.shadowsocks.aidl.Config
import com.github.shadowsocks.utils._
import scala.collection.JavaConversions._
import scala.collection._
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
......@@ -68,15 +67,14 @@ class ShadowsocksNatService extends BaseService {
"-j DNAT --to-destination 127.0.0.1:8123"
private var notification: ShadowsocksNotification = _
var closeReceiver: BroadcastReceiver = null
var connReceiver: BroadcastReceiver = null
var apps: Array[ProxiedApp] = null
var closeReceiver: BroadcastReceiver = _
var connReceiver: BroadcastReceiver = _
val myUid = android.os.Process.myUid()
var sslocalProcess: Process = null
var sstunnelProcess: Process = null
var redsocksProcess: Process = null
var pdnsdProcess: Process = null
var sslocalProcess: Process = _
var sstunnelProcess: Process = _
var redsocksProcess: Process = _
var pdnsdProcess: Process = _
private val dnsAddressCache = new SparseArray[String]
......@@ -378,16 +376,7 @@ class ShadowsocksNatService extends BaseService {
http_sb.append(Utils.getIptables + CMD_IPTABLES_DNAT_ADD_SOCKS)
}
if (config.isProxyApps) {
if (apps == null || apps.length <= 0) {
apps = AppManager.getProxiedApps(this, config.proxiedAppString)
}
val uidSet: mutable.HashSet[Int] = new mutable.HashSet[Int]
for (app <- apps) {
if (app.proxied) {
uidSet.add(app.uid)
}
}
for (uid <- uidSet) {
for (uid <- config.proxiedAppString.split('|').distinct) {
if (!config.isBypassApps) {
http_sb.append((Utils.getIptables + CMD_IPTABLES_DNAT_ADD_SOCKS).replace("-t nat", "-t nat -m owner --uid-owner " + uid))
} else {
......
......@@ -54,7 +54,6 @@ import com.github.shadowsocks.utils._
import org.apache.commons.net.util.SubnetUtils
import scala.collection.JavaConversions._
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
......@@ -392,14 +391,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (Utils.isLollipopOrAbove) {
if (config.isProxyApps) {
val apps = AppManager.getProxiedApps(this, config.proxiedAppString)
val pkgSet: mutable.HashSet[String] = new mutable.HashSet[String]
for (app <- apps) {
if (app.proxied) {
pkgSet.add(app.packageName)
}
}
for (pkg <- pkgSet) {
for (pkg <- config.proxiedAppString.split('|').distinct) {
if (!config.isBypassApps) {
builder.addAllowedApplication(pkg)
} else {
......
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