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;
interface IShadowsocksServiceCallback {
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 {
}, 1000, 1000)
}
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 =
......@@ -246,6 +247,20 @@ trait BaseService extends Service {
p.tx += tx
p.rx += rx
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 =>
}
}
......@@ -266,7 +281,8 @@ trait BaseService extends Service {
for (i <- 0 until n) {
try {
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 {
case _: Exception => // Ignore
}
......
......@@ -97,8 +97,10 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe
var state: Int = _
private val callback = new IShadowsocksServiceCallback.Stub {
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 =
handler.post(() => updateTraffic(txRate, rxRate, txTotal, rxTotal))
def trafficUpdated(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit =
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)
......@@ -136,25 +138,22 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe
state = s
if (state == State.CONNECTED) fab.setBackgroundTintList(greenTint) else {
fab.setBackgroundTintList(greyTint)
updateTraffic(0, 0, 0, 0)
updateTraffic(-1, 0, 0, 0, 0)
testCount += 1 // suppress previous test messages
}
if (ProfilesFragment.instance != null) {
val adapter = ProfilesFragment.instance.profilesAdapter
adapter.notifyDataSetChanged() // refresh button enabled state
if (state == State.STOPPED) adapter.refreshId(app.profileId) // refresh bandwidth statistics
}
if (ProfilesFragment.instance != null)
ProfilesFragment.instance.profilesAdapter.notifyDataSetChanged() // refresh button enabled state
fab.setEnabled(false)
if (state == State.CONNECTED || state == State.STOPPED)
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))
rxText.setText(TrafficMonitor.formatTraffic(rxTotal))
txRateText.setText(TrafficMonitor.formatTraffic(txRate) + "/s")
rxRateText.setText(TrafficMonitor.formatTraffic(rxRate) + "/s")
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() {
......
......@@ -101,7 +101,7 @@ class ProfileConfigFragment extends PreferenceFragment with OnMenuItemClickListe
def saveAndExit() {
profile.deserialize(app.settings)
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()
}
}
......@@ -106,7 +106,7 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic
edit.setAlpha(if (editable) 1 else 0.5F)
var tx = item.tx
var rx = item.rx
if (item.id == app.profileId) {
if (item.id == bandwidthProfile) {
tx += txTotal
rx += rxTotal
}
......@@ -222,6 +222,10 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic
for ((_, item) <- actions) app.profileManager.delProfile(item.id)
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)
if (index >= 0) {
profiles(index) = app.profileManager.getProfile(id).get
......@@ -242,6 +246,7 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic
lazy val profilesAdapter = new ProfilesAdapter
private var undoManager: UndoSnackbarManager[Profile] = _
private var bandwidthProfile: Int = _
private var txTotal: Long = _
private var rxTotal: Long = _
......@@ -292,10 +297,24 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic
}).attachToRecyclerView(profilesList)
}
override def onTrafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit = {
this.txTotal = txTotal
this.rxTotal = rxTotal
profilesAdapter.refreshId(app.profileId)
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.rxTotal = rxTotal
profilesAdapter.refreshId(profileId)
}
def onTrafficPersisted(profileId: Int) {
txTotal = 0
rxTotal = 0
if (bandwidthProfile != profileId) {
onTrafficPersisted(bandwidthProfile)
bandwidthProfile = profileId
}
profilesAdapter.deepRefreshId(profileId)
}
override def onDetach() {
......
......@@ -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 callback = new Stub {
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 rxr = TrafficMonitor.formatTraffic(rxRate)
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
TrafficMonitor.formatTraffic(txTotal), TrafficMonitor.formatTraffic(rxTotal)))
show()
}
override def trafficPersisted(profileId: Int): Unit = ()
}
private var lockReceiver: BroadcastReceiver = _
private var callbackRegistered: Boolean = _
......
......@@ -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 iconConnected = Icon.createWithResource(this, R.drawable.ic_start_connected)
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) {
val tile = getQsTile
if (tile != null) {
......@@ -57,6 +57,7 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext
tile.updateTile()
}
}
override def trafficPersisted(profileId: Int): Unit = ()
}
override def onServiceConnected(): Unit = callback.stateChanged(bgService.getState, bgService.getProfileName, null)
......
......@@ -35,5 +35,5 @@ class ToolbarFragment extends Fragment {
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