Commit 5bc7c9f8 authored by Mygod's avatar Mygod

Fix bandwidth display in ProfilesFragment when hot swapping profiles

parent 115fbcb2
...@@ -2,5 +2,7 @@ package com.github.shadowsocks.aidl; ...@@ -2,5 +2,7 @@ package com.github.shadowsocks.aidl;
interface IShadowsocksServiceCallback { interface IShadowsocksServiceCallback {
oneway void stateChanged(int state, String profileName, String msg); oneway void stateChanged(int state, String profileName, String msg);
oneway void trafficUpdated(long txRate, long rxRate, long txTotal, long rxTotal); oneway void trafficUpdated(int profileId, long txRate, long rxRate, long txTotal, long rxTotal);
// Traffic data has persisted to database, listener should refetch their data from database
oneway void trafficPersisted(int profileId);
} }
...@@ -97,7 +97,8 @@ trait BaseService extends Service { ...@@ -97,7 +97,8 @@ trait BaseService extends Service {
}, 1000, 1000) }, 1000, 1000)
} }
TrafficMonitor.updateRate() TrafficMonitor.updateRate()
cb.trafficUpdated(TrafficMonitor.txRate, TrafficMonitor.rxRate, TrafficMonitor.txTotal, TrafficMonitor.rxTotal) cb.trafficUpdated(profile.id,
TrafficMonitor.txRate, TrafficMonitor.rxRate, TrafficMonitor.txTotal, TrafficMonitor.rxTotal)
} }
override def stopListeningForBandwidth(cb: IShadowsocksServiceCallback): Unit = override def stopListeningForBandwidth(cb: IShadowsocksServiceCallback): Unit =
...@@ -246,6 +247,20 @@ trait BaseService extends Service { ...@@ -246,6 +247,20 @@ trait BaseService extends Service {
p.tx += tx p.tx += tx
p.rx += rx p.rx += rx
app.profileManager.updateProfile(p) app.profileManager.updateProfile(p)
handler.post(() => {
if (bandwidthListeners.nonEmpty) {
val n = callbacks.beginBroadcast()
for (i <- 0 until n) {
try {
val item = callbacks.getBroadcastItem(i)
if (bandwidthListeners.contains(item.asBinder)) item.trafficPersisted(p.id)
} catch {
case _: Exception => // Ignore
}
}
callbacks.finishBroadcast()
}
})
case None => case None =>
} }
} }
...@@ -266,7 +281,8 @@ trait BaseService extends Service { ...@@ -266,7 +281,8 @@ trait BaseService extends Service {
for (i <- 0 until n) { for (i <- 0 until n) {
try { try {
val item = callbacks.getBroadcastItem(i) val item = callbacks.getBroadcastItem(i)
if (bandwidthListeners.contains(item.asBinder)) item.trafficUpdated(txRate, rxRate, txTotal, rxTotal) if (bandwidthListeners.contains(item.asBinder))
item.trafficUpdated(profile.id, txRate, rxRate, txTotal, rxTotal)
} catch { } catch {
case _: Exception => // Ignore case _: Exception => // Ignore
} }
......
...@@ -97,8 +97,10 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe ...@@ -97,8 +97,10 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe
var state: Int = _ var state: Int = _
private val callback = new IShadowsocksServiceCallback.Stub { private val callback = new IShadowsocksServiceCallback.Stub {
def stateChanged(s: Int, profileName: String, m: String): Unit = handler.post(() => changeState(s, profileName, m)) def stateChanged(s: Int, profileName: String, m: String): Unit = handler.post(() => changeState(s, profileName, m))
def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit = def trafficUpdated(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit =
handler.post(() => updateTraffic(txRate, rxRate, txTotal, rxTotal)) handler.post(() => updateTraffic(profileId, txRate, rxRate, txTotal, rxTotal))
override def trafficPersisted(profileId: Int): Unit = handler.post(() => if (ProfilesFragment.instance != null)
ProfilesFragment.instance.onTrafficPersisted(profileId))
} }
private lazy val greyTint = ContextCompat.getColorStateList(MainActivity.this, R.color.material_primary_500) private lazy val greyTint = ContextCompat.getColorStateList(MainActivity.this, R.color.material_primary_500)
...@@ -136,25 +138,22 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe ...@@ -136,25 +138,22 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe
state = s state = s
if (state == State.CONNECTED) fab.setBackgroundTintList(greenTint) else { if (state == State.CONNECTED) fab.setBackgroundTintList(greenTint) else {
fab.setBackgroundTintList(greyTint) fab.setBackgroundTintList(greyTint)
updateTraffic(0, 0, 0, 0) updateTraffic(-1, 0, 0, 0, 0)
testCount += 1 // suppress previous test messages testCount += 1 // suppress previous test messages
} }
if (ProfilesFragment.instance != null) { if (ProfilesFragment.instance != null)
val adapter = ProfilesFragment.instance.profilesAdapter ProfilesFragment.instance.profilesAdapter.notifyDataSetChanged() // refresh button enabled state
adapter.notifyDataSetChanged() // refresh button enabled state
if (state == State.STOPPED) adapter.refreshId(app.profileId) // refresh bandwidth statistics
}
fab.setEnabled(false) fab.setEnabled(false)
if (state == State.CONNECTED || state == State.STOPPED) if (state == State.CONNECTED || state == State.STOPPED)
handler.postDelayed(() => fab.setEnabled(state == State.CONNECTED || state == State.STOPPED), 1000) handler.postDelayed(() => fab.setEnabled(state == State.CONNECTED || state == State.STOPPED), 1000)
} }
def updateTraffic(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) { def updateTraffic(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) {
txText.setText(TrafficMonitor.formatTraffic(txTotal)) txText.setText(TrafficMonitor.formatTraffic(txTotal))
rxText.setText(TrafficMonitor.formatTraffic(rxTotal)) rxText.setText(TrafficMonitor.formatTraffic(rxTotal))
txRateText.setText(TrafficMonitor.formatTraffic(txRate) + "/s") txRateText.setText(TrafficMonitor.formatTraffic(txRate) + "/s")
rxRateText.setText(TrafficMonitor.formatTraffic(rxRate) + "/s") rxRateText.setText(TrafficMonitor.formatTraffic(rxRate) + "/s")
val child = getFragmentManager.findFragmentById(R.id.fragment_holder).asInstanceOf[ToolbarFragment] val child = getFragmentManager.findFragmentById(R.id.fragment_holder).asInstanceOf[ToolbarFragment]
if (state != State.STOPPING && child != null) child.onTrafficUpdated(txRate, rxRate, txTotal, rxTotal) if (state != State.STOPPING && child != null) child.onTrafficUpdated(profileId, txRate, rxRate, txTotal, rxTotal)
} }
override def onServiceConnected() { override def onServiceConnected() {
......
...@@ -101,7 +101,7 @@ class ProfileConfigFragment extends PreferenceFragment with OnMenuItemClickListe ...@@ -101,7 +101,7 @@ class ProfileConfigFragment extends PreferenceFragment with OnMenuItemClickListe
def saveAndExit() { def saveAndExit() {
profile.deserialize(app.settings) profile.deserialize(app.settings)
app.profileManager.updateProfile(profile) app.profileManager.updateProfile(profile)
if (ProfilesFragment.instance != null) ProfilesFragment.instance.profilesAdapter.refreshId(profile.id) if (ProfilesFragment.instance != null) ProfilesFragment.instance.profilesAdapter.deepRefreshId(profile.id)
getActivity.finish() getActivity.finish()
} }
} }
...@@ -106,7 +106,7 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic ...@@ -106,7 +106,7 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic
edit.setAlpha(if (editable) 1 else 0.5F) edit.setAlpha(if (editable) 1 else 0.5F)
var tx = item.tx var tx = item.tx
var rx = item.rx var rx = item.rx
if (item.id == app.profileId) { if (item.id == bandwidthProfile) {
tx += txTotal tx += txTotal
rx += rxTotal rx += rxTotal
} }
...@@ -222,6 +222,10 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic ...@@ -222,6 +222,10 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic
for ((_, item) <- actions) app.profileManager.delProfile(item.id) for ((_, item) <- actions) app.profileManager.delProfile(item.id)
def refreshId(id: Int) { def refreshId(id: Int) {
val index = profiles.indexWhere(_.id == id)
if (index >= 0) notifyItemChanged(index)
}
def deepRefreshId(id: Int) {
val index = profiles.indexWhere(_.id == id) val index = profiles.indexWhere(_.id == id)
if (index >= 0) { if (index >= 0) {
profiles(index) = app.profileManager.getProfile(id).get profiles(index) = app.profileManager.getProfile(id).get
...@@ -242,6 +246,7 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic ...@@ -242,6 +246,7 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic
lazy val profilesAdapter = new ProfilesAdapter lazy val profilesAdapter = new ProfilesAdapter
private var undoManager: UndoSnackbarManager[Profile] = _ private var undoManager: UndoSnackbarManager[Profile] = _
private var bandwidthProfile: Int = _
private var txTotal: Long = _ private var txTotal: Long = _
private var rxTotal: Long = _ private var rxTotal: Long = _
...@@ -292,10 +297,24 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic ...@@ -292,10 +297,24 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic
}).attachToRecyclerView(profilesList) }).attachToRecyclerView(profilesList)
} }
override def onTrafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit = { override def onTrafficUpdated(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit =
if (profileId != -1) { // ignore resets from MainActivity
if (bandwidthProfile != profileId) {
onTrafficPersisted(bandwidthProfile)
bandwidthProfile = profileId
}
this.txTotal = txTotal this.txTotal = txTotal
this.rxTotal = rxTotal this.rxTotal = rxTotal
profilesAdapter.refreshId(app.profileId) profilesAdapter.refreshId(profileId)
}
def onTrafficPersisted(profileId: Int) {
txTotal = 0
rxTotal = 0
if (bandwidthProfile != profileId) {
onTrafficPersisted(bandwidthProfile)
bandwidthProfile = profileId
}
profilesAdapter.deepRefreshId(profileId)
} }
override def onDetach() { override def onDetach() {
......
...@@ -39,7 +39,7 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str ...@@ -39,7 +39,7 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
private lazy val nm = service.getSystemService(Context.NOTIFICATION_SERVICE).asInstanceOf[NotificationManager] private lazy val nm = service.getSystemService(Context.NOTIFICATION_SERVICE).asInstanceOf[NotificationManager]
private lazy val callback = new Stub { private lazy val callback = new Stub {
override def stateChanged(state: Int, profileName: String, msg: String): Unit = () // ignore override def stateChanged(state: Int, profileName: String, msg: String): Unit = () // ignore
override def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) { override def trafficUpdated(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) {
val txr = TrafficMonitor.formatTraffic(txRate) val txr = TrafficMonitor.formatTraffic(txRate)
val rxr = TrafficMonitor.formatTraffic(rxRate) val rxr = TrafficMonitor.formatTraffic(rxRate)
builder.setContentText(service.getString(R.string.traffic_summary).formatLocal(Locale.ENGLISH, txr, rxr)) builder.setContentText(service.getString(R.string.traffic_summary).formatLocal(Locale.ENGLISH, txr, rxr))
...@@ -47,6 +47,7 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str ...@@ -47,6 +47,7 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
TrafficMonitor.formatTraffic(txTotal), TrafficMonitor.formatTraffic(rxTotal))) TrafficMonitor.formatTraffic(txTotal), TrafficMonitor.formatTraffic(rxTotal)))
show() show()
} }
override def trafficPersisted(profileId: Int): Unit = ()
} }
private var lockReceiver: BroadcastReceiver = _ private var lockReceiver: BroadcastReceiver = _
private var callbackRegistered: Boolean = _ private var callbackRegistered: Boolean = _
......
...@@ -36,7 +36,7 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext ...@@ -36,7 +36,7 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext
private lazy val iconBusy = Icon.createWithResource(this, R.drawable.ic_start_busy) private lazy val iconBusy = Icon.createWithResource(this, R.drawable.ic_start_busy)
private lazy val iconConnected = Icon.createWithResource(this, R.drawable.ic_start_connected) private lazy val iconConnected = Icon.createWithResource(this, R.drawable.ic_start_connected)
private lazy val callback = new IShadowsocksServiceCallback.Stub { private lazy val callback = new IShadowsocksServiceCallback.Stub {
def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit = () def trafficUpdated(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit = ()
def stateChanged(state: Int, profileName: String, msg: String) { def stateChanged(state: Int, profileName: String, msg: String) {
val tile = getQsTile val tile = getQsTile
if (tile != null) { if (tile != null) {
...@@ -57,6 +57,7 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext ...@@ -57,6 +57,7 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext
tile.updateTile() tile.updateTile()
} }
} }
override def trafficPersisted(profileId: Int): Unit = ()
} }
override def onServiceConnected(): Unit = callback.stateChanged(bgService.getState, bgService.getProfileName, null) override def onServiceConnected(): Unit = callback.stateChanged(bgService.getState, bgService.getProfileName, null)
......
...@@ -35,5 +35,5 @@ class ToolbarFragment extends Fragment { ...@@ -35,5 +35,5 @@ class ToolbarFragment extends Fragment {
if (activity.crossfader == null) activity.drawer.setToolbar(activity, toolbar, true) if (activity.crossfader == null) activity.drawer.setToolbar(activity, toolbar, true)
} }
def onTrafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit = () def onTrafficUpdated(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit = ()
} }
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