Skip to content

Commit

Permalink
optimize binder usage
Browse files Browse the repository at this point in the history
  • Loading branch information
arm64v8a committed Mar 26, 2023
1 parent 17c6844 commit 962668c
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface ISagerNetService {
int getState();
String getProfileName();

void registerCallback(in ISagerNetServiceCallback cb);
void registerCallback(in ISagerNetServiceCallback cb, int id);
oneway void unregisterCallback(in ISagerNetServiceCallback cb);

int urlTest();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ oneway interface ISagerNetServiceCallback {
void stateChanged(int state, String profileName, String msg);
void missingPlugin(String profileName, String pluginName);
void routeAlert(int type, String routeName);
void updateWakeLockStatus(boolean acquired);
void cbSpeedUpdate(in SpeedDisplayData stats);
void cbTrafficUpdate(in TrafficData stats);
void cbLogUpdate(String str);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import io.nekohasekai.sagernet.database.DataStore

@Suppress("DEPRECATION")
class QuickToggleShortcut : Activity(), SagerConnection.Callback {
private val connection = SagerConnection()
private val connection = SagerConnection(SagerConnection.CONNECTION_ID_SHORTCUT)
private var profileId = -1L

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down
33 changes: 13 additions & 20 deletions app/src/main/java/io/nekohasekai/sagernet/bg/BaseService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import io.nekohasekai.sagernet.aidl.ISagerNetService
import io.nekohasekai.sagernet.aidl.ISagerNetServiceCallback
import io.nekohasekai.sagernet.bg.proto.ProxyInstance
import io.nekohasekai.sagernet.database.DataStore
import io.nekohasekai.sagernet.database.ProxyEntity
import io.nekohasekai.sagernet.database.SagerDatabase
import io.nekohasekai.sagernet.ktx.*
import io.nekohasekai.sagernet.plugin.PluginManager
Expand Down Expand Up @@ -73,20 +72,22 @@ class BaseService {
}
}

val callbackIdMap = mutableMapOf<ISagerNetServiceCallback, Int>()

override val coroutineContext = Dispatchers.Main.immediate + Job()

override fun getState(): Int = (data?.state ?: State.Idle).ordinal
override fun getProfileName(): String = data?.proxy?.profile?.displayName() ?: "Idle"

override fun registerCallback(cb: ISagerNetServiceCallback) {
override fun registerCallback(cb: ISagerNetServiceCallback, id: Int) {
callbacks.register(cb)
cb.updateWakeLockStatus(data?.proxy?.service?.wakeLock != null)
callbackIdMap[cb] = id
}

private val boardcastMutex = Mutex()
private val broadcastMutex = Mutex()

suspend fun broadcast(work: (ISagerNetServiceCallback) -> Unit) {
boardcastMutex.withLock {
broadcastMutex.withLock {
val count = callbacks.beginBroadcast()
try {
repeat(count) {
Expand All @@ -103,6 +104,7 @@ class BaseService {
}

override fun unregisterCallback(cb: ISagerNetServiceCallback) {
callbackIdMap.remove(cb)
callbacks.unregister(cb)
}

Expand Down Expand Up @@ -155,9 +157,8 @@ class BaseService {
val success = data.proxy!!.box.selectOutbound(tag)
if (success) runOnDefaultDispatcher {
data.proxy!!.looper?.selectMain(ent.id)
data.binder.broadcast {
it.stateChanged(-1, ServiceNotification.genTitle(ent), null)
}
val title = ServiceNotification.genTitle(ent)
data.notification?.postNotificationTitle(title)
}
}
return
Expand Down Expand Up @@ -267,14 +268,10 @@ class BaseService {
wakeLock?.apply {
release()
wakeLock = null
data.binder.broadcast {
it.updateWakeLockStatus(false)
}
data.notification?.postNotificationWakeLockStatus(false)
} ?: apply {
acquireWakeLock()
data.binder.broadcast {
it.updateWakeLockStatus(true)
}
data.notification?.postNotificationWakeLockStatus(true)
}
}

Expand All @@ -286,13 +283,9 @@ class BaseService {

if (DataStore.acquireWakeLock) {
acquireWakeLock()
data.binder.broadcast {
it.updateWakeLockStatus(true)
}
data.notification?.postNotificationWakeLockStatus(true)
} else {
data.binder.broadcast {
it.updateWakeLockStatus(false)
}
data.notification?.postNotificationWakeLockStatus(false)
}
}

Expand Down
15 changes: 9 additions & 6 deletions app/src/main/java/io/nekohasekai/sagernet/bg/SagerConnection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ import io.nekohasekai.sagernet.aidl.TrafficData
import io.nekohasekai.sagernet.database.DataStore
import io.nekohasekai.sagernet.ktx.runOnMainDispatcher

class SagerConnection(private var listenForDeath: Boolean = false) : ServiceConnection,
IBinder.DeathRecipient {
class SagerConnection(
private val connectionId: Int,
private var listenForDeath: Boolean = false
) : ServiceConnection, IBinder.DeathRecipient {

companion object {
val serviceClass
Expand All @@ -25,6 +27,10 @@ class SagerConnection(private var listenForDeath: Boolean = false) : ServiceConn
Key.MODE_VPN -> VpnService::class // Key.MODE_TRANS -> TransproxyService::class
else -> throw UnknownError()
}.java

val CONNECTION_ID_SHORTCUT = 0
val CONNECTION_ID_TILE = 1
val CONNECTION_ID_MAINACTIVITY = 2
}

interface Callback {
Expand Down Expand Up @@ -90,9 +96,6 @@ class SagerConnection(private var listenForDeath: Boolean = false) : ServiceConn
}
}

override fun updateWakeLockStatus(acquired: Boolean) {
}

override fun cbLogUpdate(str: String?) {
DataStore.postLogListener?.let {
if (str != null) {
Expand All @@ -114,7 +117,7 @@ class SagerConnection(private var listenForDeath: Boolean = false) : ServiceConn
try {
if (listenForDeath) binder.linkToDeath(this, 0)
check(!callbackRegistered)
service.registerCallback(serviceCallback)
service.registerCallback(serviceCallback, connectionId)
callbackRegistered = true
} catch (e: RemoteException) {
e.printStackTrace()
Expand Down
130 changes: 53 additions & 77 deletions app/src/main/java/io/nekohasekai/sagernet/bg/ServiceNotification.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import androidx.core.app.NotificationManagerCompat
import io.nekohasekai.sagernet.Action
import io.nekohasekai.sagernet.R
import io.nekohasekai.sagernet.SagerNet
import io.nekohasekai.sagernet.aidl.ISagerNetServiceCallback
import io.nekohasekai.sagernet.aidl.SpeedDisplayData
import io.nekohasekai.sagernet.aidl.TrafficData
import io.nekohasekai.sagernet.database.DataStore
import io.nekohasekai.sagernet.database.ProxyEntity
import io.nekohasekai.sagernet.database.SagerDatabase
Expand All @@ -35,7 +33,7 @@ import io.nekohasekai.sagernet.utils.Theme
* See also: https://github.com/aosp-mirror/platform_frameworks_base/commit/070d142993403cc2c42eca808ff3fafcee220ac4
*/
class ServiceNotification(
private val service: BaseService.Interface, profileName: String,
private val service: BaseService.Interface, title: String,
channel: String, visible: Boolean = false,
) : BroadcastReceiver() {
companion object {
Expand All @@ -50,81 +48,63 @@ class ServiceNotification(
}
}

val showDirectSpeed = DataStore.showDirectSpeed

private val callback: ISagerNetServiceCallback by lazy {
object : ISagerNetServiceCallback.Stub() {
override fun cbSpeedUpdate(stats: SpeedDisplayData) {
builder.apply {
if (showDirectSpeed) {
val speedDetail = (service as Context).getString(
R.string.speed_detail, service.getString(
R.string.speed, Formatter.formatFileSize(service, stats.txRateProxy)
), service.getString(
R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy)
), service.getString(
R.string.speed,
Formatter.formatFileSize(service, stats.txRateDirect)
), service.getString(
R.string.speed,
Formatter.formatFileSize(service, stats.rxRateDirect)
)
)
setStyle(NotificationCompat.BigTextStyle().bigText(speedDetail))
setContentText(speedDetail)
} else {
val speedSimple = (service as Context).getString(
R.string.traffic, service.getString(
R.string.speed, Formatter.formatFileSize(service, stats.txRateProxy)
), service.getString(
R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy)
)
)
setContentText(speedSimple)
}
setSubText(
service.getString(
R.string.traffic,
Formatter.formatFileSize(service, stats.txTotal),
Formatter.formatFileSize(service, stats.rxTotal)
)
fun postNotificationSpeedUpdate(stats: SpeedDisplayData) {
builder.apply {
if (showDirectSpeed) {
val speedDetail = (service as Context).getString(
R.string.speed_detail, service.getString(
R.string.speed, Formatter.formatFileSize(service, stats.txRateProxy)
), service.getString(
R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy)
), service.getString(
R.string.speed,
Formatter.formatFileSize(service, stats.txRateDirect)
), service.getString(
R.string.speed,
Formatter.formatFileSize(service, stats.rxRateDirect)
)
}
update()
}

override fun cbTrafficUpdate(stats: TrafficData?) {
}

override fun stateChanged(state: Int, profileName: String?, msg: String?) {
if (state == -1) {
builder.setContentTitle(profileName)
}
}

override fun missingPlugin(profileName: String?, pluginName: String?) {
}

override fun routeAlert(type: Int, routeName: String?) {
)
setStyle(NotificationCompat.BigTextStyle().bigText(speedDetail))
setContentText(speedDetail)
} else {
val speedSimple = (service as Context).getString(
R.string.traffic, service.getString(
R.string.speed, Formatter.formatFileSize(service, stats.txRateProxy)
), service.getString(
R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy)
)
)
setContentText(speedSimple)
}
setSubText(
service.getString(
R.string.traffic,
Formatter.formatFileSize(service, stats.txTotal),
Formatter.formatFileSize(service, stats.rxTotal)
)
)
}
update()
}

override fun updateWakeLockStatus(acquired: Boolean) {
updateActions(acquired)
builder.priority =
if (acquired) NotificationCompat.PRIORITY_HIGH else NotificationCompat.PRIORITY_LOW
update()
}
fun postNotificationTitle(newTitle: String) {
builder.setContentTitle(newTitle)
update()
}

override fun cbLogUpdate(str: String?) {
}
}
fun postNotificationWakeLockStatus(acquired: Boolean) {
updateActions(acquired)
builder.priority =
if (acquired) NotificationCompat.PRIORITY_HIGH else NotificationCompat.PRIORITY_LOW
update()
}
private var callbackRegistered = false

private val showDirectSpeed = DataStore.showDirectSpeed

private val builder = NotificationCompat.Builder(service as Context, channel)
.setWhen(0)
.setTicker(service.getString(R.string.forward_success))
.setContentTitle(profileName)
.setContentTitle(title)
.setOnlyAlertOnce(true)
.setContentIntent(SagerNet.configureIntent(service))
.setSmallIcon(R.drawable.ic_service_active)
Expand All @@ -147,7 +127,7 @@ class ServiceNotification(
show()
}

fun updateActions(wakeLockAcquired: Boolean) {
private fun updateActions(wakeLockAcquired: Boolean) {
service as Context

builder.clearActions()
Expand Down Expand Up @@ -188,15 +168,11 @@ class ServiceNotification(
if (service.data.state == BaseService.State.Connected) updateCallback(intent.action == Intent.ACTION_SCREEN_ON)
}

var listenPostSpeed = false

private fun updateCallback(screenOn: Boolean) {
if (DataStore.speedInterval == 0) return
if (screenOn) {
service.data.binder.registerCallback(callback)
callbackRegistered = true
} else if (callbackRegistered) { // unregister callback to save battery
service.data.binder.unregisterCallback(callback)
callbackRegistered = false
}
listenPostSpeed = screenOn
}

private fun show() = (service as Service).startForeground(notificationId, builder.build())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class TileService : BaseTileService(), SagerConnection.Callback {
}
private var tapPending = false

private val connection = SagerConnection()
private val connection = SagerConnection(SagerConnection.CONNECTION_ID_TILE)
override fun stateChanged(state: BaseService.State, profileName: String?, msg: String?) =
updateTile(state) { profileName }

Expand Down
Loading

0 comments on commit 962668c

Please sign in to comment.