From 6749afd26340c2937384798f6ec3f06123b1b699 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Thu, 12 Nov 2015 12:10:38 +0800 Subject: [PATCH 1/3] add TrafficMonitor --- .../shadowsocks/database/DBHelper.scala | 7 +- .../github/shadowsocks/database/Profile.scala | 9 ++ .../shadowsocks/utils/TrafficMonitor.scala | 83 +++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala diff --git a/src/main/scala/com/github/shadowsocks/database/DBHelper.scala b/src/main/scala/com/github/shadowsocks/database/DBHelper.scala index d2ed5a4c..627d6b48 100644 --- a/src/main/scala/com/github/shadowsocks/database/DBHelper.scala +++ b/src/main/scala/com/github/shadowsocks/database/DBHelper.scala @@ -51,7 +51,7 @@ object DBHelper { } class DBHelper(val context: Context) - extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 12) { + extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 13) { lazy val profileDao: Dao[Profile, Int] = getDao(classOf[Profile]) @@ -89,6 +89,11 @@ class DBHelper(val context: Context) " ipv6, individual FROM `tmp`;") profileDao.executeRawNoArgs("DROP TABLE `tmp`;") } + if (oldVersion < 13) { + profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN tx LONG;") + profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN rx LONG;") + profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN date DATE;") + } } } } diff --git a/src/main/scala/com/github/shadowsocks/database/Profile.scala b/src/main/scala/com/github/shadowsocks/database/Profile.scala index 8be48264..66744357 100644 --- a/src/main/scala/com/github/shadowsocks/database/Profile.scala +++ b/src/main/scala/com/github/shadowsocks/database/Profile.scala @@ -83,4 +83,13 @@ class Profile { @DatabaseField(dataType = DataType.LONG_STRING) var individual: String = "" + + @DatabaseField + var tx: Long = 0 + + @DatabaseField + var rx: Long = 0 + + @DatabaseField + val date: java.util.Date = new java.util.Date() } diff --git a/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala b/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala new file mode 100644 index 00000000..eb715113 --- /dev/null +++ b/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala @@ -0,0 +1,83 @@ +package com.github.shadowsocks.utils + +import android.net.TrafficStats +import android.os.Process +import java.lang.{String, System} +import java.util.Locale + +case class Traffic(tx: Long, rx: Long, timestamp: Long) + +object TrafficMonitor { + val uid = Process.myUid + var last: Traffic = getTraffic + + // Kilo bytes per second + var txRate: Long = 0 + var rxRate: Long = 0 + + // Kilo bytes for the current session + var txTotal: Long = 0 + var rxTotal: Long = 0 + + def getTraffic(): Traffic = { + new Traffic(TrafficStats.getUidTxBytes(uid), + TrafficStats.getUidRxBytes(uid), System.currentTimeMillis()) + } + + def formatTraffic(n: Long): String { + if (n <= 1024) { + "%d KB".formatLocal(Locale.ENGLISH, n) + } else if (n > 1024) { + "%d MB".formatLocal(Locale.ENGLISH, n / 1024) + } else if (n > 1024 * 1024) { + "%d GB".formatLocal(Locale.ENGLISH, n / 1024 / 1024) + } else if (n > 1024 * 1024 * 1024) { + "%d TB".formatLocal(Locale.ENGLISH, n / 1024 / 1024 / 1024) + } else { + ">1024 TB" + } + } + + def updateTraffic() { + val now = getTraffic + txRate = ((now.tx - last.tx) / 1024 / (now.timestamp - last.timestamp)) + rxRate = ((now.rx - last.rx) / 1024 / (now.timestamp - last.timestamp)) + txTotal += (now.tx - last.tx) / 1024 + rxTotal += (now.rx - last.rx) / 1024 + last = now + } + + def resetTraffic() { + txRate = 0 + rxRate = 0 + txTotal = 0 + rxTotal = 0 + last = getTraffic + } + + def getTxTotal(): String = { + formatTraffic(txTotal) + } + + def getRxTotal(): String = { + formatTraffic(rxTotal) + } + + def getTotal(): String = { + formatTraffic(txTotal + rxTotal) + } + + def getTxRate(): String = { + formatTraffic(txRate) + "/s" + } + + def getTxRate(): String = { + formatTraffic(rxRate) + "/s" + } + + def getRate(): String = { + formatTraffic(txRate + rxRate) + "/s" + } +} + +class TrafficMonitor () From 6fb8db771a676055ab50b19a14ffb65d1240496a Mon Sep 17 00:00:00 2001 From: Max Lv Date: Thu, 12 Nov 2015 13:03:04 +0800 Subject: [PATCH 2/3] fix typo --- .../scala/com/github/shadowsocks/utils/TrafficMonitor.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala b/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala index eb715113..d26c236d 100644 --- a/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala +++ b/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala @@ -24,7 +24,7 @@ object TrafficMonitor { TrafficStats.getUidRxBytes(uid), System.currentTimeMillis()) } - def formatTraffic(n: Long): String { + def formatTraffic(n: Long): String = { if (n <= 1024) { "%d KB".formatLocal(Locale.ENGLISH, n) } else if (n > 1024) { @@ -71,7 +71,7 @@ object TrafficMonitor { formatTraffic(txRate) + "/s" } - def getTxRate(): String = { + def getRxRate(): String = { formatTraffic(rxRate) + "/s" } From f0abbb73048357759e6fde3351802241da477ee5 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Wed, 18 Nov 2015 14:02:29 +0800 Subject: [PATCH 3/3] add TrafficMonitor to the main activity --- src/main/res/values-zh/strings.xml | 3 ++ src/main/res/values/strings.xml | 2 ++ src/main/res/xml/pref_all.xml | 2 ++ .../com/github/shadowsocks/Shadowsocks.scala | 30 +++++++++++++++++-- .../shadowsocks/ShadowsocksNatService.scala | 4 +++ .../shadowsocks/ShadowsocksVpnService.scala | 4 +++ .../github/shadowsocks/utils/Constants.scala | 1 + .../shadowsocks/utils/TrafficMonitor.scala | 8 ++--- 8 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/main/res/values-zh/strings.xml b/src/main/res/values-zh/strings.xml index da320a87..02d6f29d 100755 --- a/src/main/res/values-zh/strings.xml +++ b/src/main/res/values-zh/strings.xml @@ -72,6 +72,9 @@ IPv6 路由 向远程服务器转发 IPv6 流量 + 网络流量 + 发送:\t%1$s\t|\t接收:\t%2$s\n上传:\t%3$s\t|\t下载:\t%4$s + 为影梭添加此配置文件? 扫描二维码 diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 597957e6..ba72d186 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -12,6 +12,8 @@ NAT mode (deprecated) Use NAT mode instead of VPN mode NAT mode is disabled without root + Network Traffic + Send:\t%1$s\t|\tReceive:\t%2$s\nUpload:\t%3$s\t|\tDownload:\t%4$s Server Settings diff --git a/src/main/res/xml/pref_all.xml b/src/main/res/xml/pref_all.xml index 637eebaa..82412e04 100644 --- a/src/main/res/xml/pref_all.xml +++ b/src/main/res/xml/pref_all.xml @@ -8,6 +8,8 @@ + + { + preferences.findPreference(Key.stat).setSummary(trafficStat) + }) + } + } + } + timer = new Timer(true) + timer.schedule(task, TIMER_INTERVAL * 1000, TIMER_INTERVAL * 1000) } private def setPreferenceEnabled(enabled: Boolean) { @@ -510,6 +530,12 @@ class Shadowsocks override def onStop() { super.onStop() clearDialog() + + // reset timer + if (timer != null) { + timer.cancel() + timer = null + } } override def onDestroy() { diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala index 52e11c9d..72bf9d7b 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala @@ -420,6 +420,8 @@ class ShadowsocksNatService extends Service with BaseService { override def startRunner(c: Config) { + TrafficMonitor.reset() + config = c // register close receiver @@ -509,6 +511,8 @@ class ShadowsocksNatService extends Service with BaseService { override def stopRunner() { + TrafficMonitor.reset() + // channge the state changeState(State.STOPPING) diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala index 8b78ba7c..082cec64 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala @@ -144,6 +144,8 @@ class ShadowsocksVpnService extends VpnService with BaseService { override def stopRunner() { + TrafficMonitor.reset() + if (vpnThread != null) { vpnThread.stopThread() vpnThread = null @@ -217,6 +219,8 @@ class ShadowsocksVpnService extends VpnService with BaseService { override def startRunner(c: Config) { + TrafficMonitor.reset() + vpnThread = new ShadowsocksVpnThread(this) vpnThread.start() diff --git a/src/main/scala/com/github/shadowsocks/utils/Constants.scala b/src/main/scala/com/github/shadowsocks/utils/Constants.scala index 07b645fd..c207e08d 100644 --- a/src/main/scala/com/github/shadowsocks/utils/Constants.scala +++ b/src/main/scala/com/github/shadowsocks/utils/Constants.scala @@ -68,6 +68,7 @@ object Key { val profiles = "profiles" val isNAT = "isNAT" val route = "route" + val stat = "stat" val isRunning = "isRunning" val isAutoConnect = "isAutoConnect" diff --git a/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala b/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala index d26c236d..d3b7c478 100644 --- a/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala +++ b/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala @@ -38,16 +38,16 @@ object TrafficMonitor { } } - def updateTraffic() { + def update() { val now = getTraffic - txRate = ((now.tx - last.tx) / 1024 / (now.timestamp - last.timestamp)) - rxRate = ((now.rx - last.rx) / 1024 / (now.timestamp - last.timestamp)) + txRate = (now.tx - last.tx) / (now.timestamp - last.timestamp) + rxRate = (now.rx - last.rx) / (now.timestamp - last.timestamp) txTotal += (now.tx - last.tx) / 1024 rxTotal += (now.rx - last.rx) / 1024 last = now } - def resetTraffic() { + def reset() { txRate = 0 rxRate = 0 txTotal = 0