Refactor ServiceClient

This commit is contained in:
Nullptr 2022-12-29 20:11:53 +08:00
commit 1d250bb9fb
No known key found for this signature in database
6 changed files with 99 additions and 65 deletions

View file

@ -35,7 +35,7 @@ object ConfigManager {
private fun saveConfig() {
val text = config.toString()
configFile.writeText(text)
ServiceHelper.submitConfig(text)
ServiceClient.syncConfig(text)
}
var detailLog: Boolean

View file

@ -0,0 +1,85 @@
package icu.nullptr.hidemyapplist.service
import android.os.IBinder.DeathRecipient
import android.os.Parcel
import android.os.RemoteException
import android.os.ServiceManager
import android.util.Log
import icu.nullptr.hidemyapplist.common.Constants
import icu.nullptr.hidemyapplist.common.IHMAService
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
object ServiceClient : IHMAService, DeathRecipient {
private const val TAG = "ServiceHelper"
private class ServiceProxy(private val obj: IHMAService) : InvocationHandler {
override fun invoke(proxy: Any?, method: Method, args: Array<out Any?>?): Any? {
val result = method.invoke(obj, *args.orEmpty())
if (result == null) Log.i(TAG, "Call service method ${method.name}")
else Log.i(TAG, "Call service method ${method.name} with result " + result.toString().take(20))
return result
}
}
@Volatile
private var service: IHMAService? = null
override fun binderDied() {
service = null
Log.e(TAG, "Binder died")
}
override fun asBinder() = service?.asBinder()
private fun getService(): IHMAService? {
if (service != null) return service
val pm = ServiceManager.getService("package")
val data = Parcel.obtain()
val reply = Parcel.obtain()
val remote = try {
data.writeInterfaceToken(Constants.DESCRIPTOR)
data.writeInt(Constants.ACTION_GET_BINDER)
pm.transact(Constants.TRANSACTION, data, reply, 0)
reply.readException()
val binder = reply.readStrongBinder()
binder.linkToDeath(this, 0)
IHMAService.Stub.asInterface(binder)
} catch (e: RemoteException) {
Log.d(TAG, "Failed to get binder")
null
} finally {
data.recycle()
reply.recycle()
}
if (remote != null) {
Log.i(TAG, "Binder acquired")
service = Proxy.newProxyInstance(
javaClass.classLoader,
arrayOf(IHMAService::class.java),
ServiceProxy(remote)
) as IHMAService
}
return service
}
override fun getServiceVersion() = getService()?.serviceVersion ?: 0
override fun getFilterCount() = getService()?.filterCount ?: 0
override fun getLogs() = getService()?.logs
override fun clearLogs() {
getService()?.clearLogs()
}
override fun syncConfig(json: String) {
getService()?.syncConfig(json)
}
override fun stopService(cleanEnv: Boolean) {
getService()?.stopService(cleanEnv)
}
}

View file

@ -1,51 +0,0 @@
package icu.nullptr.hidemyapplist.service
import android.os.Parcel
import android.os.RemoteException
import android.os.ServiceManager
import android.util.Log
import icu.nullptr.hidemyapplist.common.Constants
import icu.nullptr.hidemyapplist.common.IHMAService
object ServiceHelper {
private const val TAG = "ServiceHelper"
private fun getService(): IHMAService? {
val pm = ServiceManager.getService("package")
val data = Parcel.obtain()
val reply = Parcel.obtain()
return try {
data.writeInterfaceToken(Constants.DESCRIPTOR)
data.writeInt(Constants.ACTION_GET_BINDER)
pm.transact(Constants.TRANSACTION, data, reply, 0)
reply.readException()
val binder = reply.readStrongBinder()
IHMAService.Stub.asInterface(binder)
} catch (e: RemoteException) {
Log.d(TAG, "Failed to get binder")
null
} finally {
data.recycle()
reply.recycle()
}
}
fun getServiceVersion() = getService()?.serviceVersion ?: 0
fun getFilterCount() = getService()?.filterCount ?: 0
fun getLogs() = getService()?.logs
fun cleanLogs() {
getService()?.clearLogs()
}
fun submitConfig(json: String) {
getService()?.syncConfig(json)
}
fun stopSystemService(cleanEnv: Boolean) {
getService()?.stopService(cleanEnv)
}
}

View file

@ -23,7 +23,7 @@ import icu.nullptr.hidemyapplist.data.fetchLatestUpdate
import icu.nullptr.hidemyapplist.hmaApp
import icu.nullptr.hidemyapplist.service.ConfigManager
import icu.nullptr.hidemyapplist.service.PrefManager
import icu.nullptr.hidemyapplist.service.ServiceHelper
import icu.nullptr.hidemyapplist.service.ServiceClient
import icu.nullptr.hidemyapplist.ui.activity.AboutActivity
import icu.nullptr.hidemyapplist.ui.util.ThemeUtils.getColor
import icu.nullptr.hidemyapplist.ui.util.ThemeUtils.themeColor
@ -132,7 +132,7 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
override fun onStart() {
super.onStart()
val serviceVersion = ServiceHelper.getServiceVersion()
val serviceVersion = ServiceClient.serviceVersion
val color = when {
!hmaApp.isHooked -> getColor(R.color.gray)
serviceVersion == 0 -> getColor(R.color.invalid)
@ -146,19 +146,19 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
if (hmaApp.isHooked) {
binding.moduleStatusIcon.setImageResource(R.drawable.outline_done_all_24)
val versionNameSimple = BuildConfig.VERSION_NAME.substringBefore(".r")
binding.moduleStatus.text = String.format(getString(R.string.home_xposed_activated), versionNameSimple, BuildConfig.VERSION_CODE)
binding.moduleStatus.text = getString(R.string.home_xposed_activated, versionNameSimple, BuildConfig.VERSION_CODE)
} else {
binding.moduleStatusIcon.setImageResource(R.drawable.outline_extension_off_24)
binding.moduleStatus.setText(R.string.home_xposed_not_activated)
}
if (serviceVersion != 0) {
if (serviceVersion < icu.nullptr.hidemyapplist.common.BuildConfig.SERVICE_VERSION) {
binding.serviceStatus.text = String.format(getString(R.string.home_xposed_service_old))
binding.serviceStatus.text = getString(R.string.home_xposed_service_old)
} else {
binding.serviceStatus.text = String.format(getString(R.string.home_xposed_service_on), serviceVersion)
binding.serviceStatus.text = getString(R.string.home_xposed_service_on, serviceVersion)
}
binding.filterCount.visibility = View.VISIBLE
binding.filterCount.text = String.format(getString(R.string.home_xposed_filter_count), ServiceHelper.getFilterCount())
binding.filterCount.text = getString(R.string.home_xposed_filter_count, ServiceClient.filterCount)
} else {
binding.serviceStatus.setText(R.string.home_xposed_service_off)
binding.filterCount.visibility = View.GONE

View file

@ -13,7 +13,7 @@ import com.tsng.hidemyapplist.R
import com.tsng.hidemyapplist.databinding.FragmentLogsBinding
import icu.nullptr.hidemyapplist.hmaApp
import icu.nullptr.hidemyapplist.service.PrefManager
import icu.nullptr.hidemyapplist.service.ServiceHelper
import icu.nullptr.hidemyapplist.service.ServiceClient
import icu.nullptr.hidemyapplist.ui.adapter.LogAdapter
import icu.nullptr.hidemyapplist.ui.util.makeToast
import icu.nullptr.hidemyapplist.ui.util.setupToolbar
@ -44,7 +44,7 @@ class LogsFragment : Fragment(R.layout.fragment_logs) {
private fun updateLogs() {
lifecycleScope.launch {
logCache = ServiceHelper.getLogs()
logCache = ServiceClient.logs
val raw = logCache?.split("\n")
if (raw == null) {
binding.serviceOff.visibility = View.VISIBLE
@ -80,7 +80,7 @@ class LogsFragment : Fragment(R.layout.fragment_logs) {
saveSAFLauncher.launch("hma_logs_$date.log")
}
R.id.menu_delete -> {
ServiceHelper.cleanLogs()
ServiceClient.clearLogs()
updateLogs()
}
R.id.menu_filter_debug -> {

View file

@ -21,7 +21,7 @@ import icu.nullptr.hidemyapplist.common.Constants
import icu.nullptr.hidemyapplist.hmaApp
import icu.nullptr.hidemyapplist.service.ConfigManager
import icu.nullptr.hidemyapplist.service.PrefManager
import icu.nullptr.hidemyapplist.service.ServiceHelper
import icu.nullptr.hidemyapplist.service.ServiceClient
import icu.nullptr.hidemyapplist.ui.util.makeToast
import icu.nullptr.hidemyapplist.ui.util.setupToolbar
import icu.nullptr.hidemyapplist.util.LangList
@ -164,16 +164,16 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
?.isEnabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
findPreference<Preference>("stopSystemService")?.setOnPreferenceClickListener {
if (ServiceHelper.getServiceVersion() != 0) {
if (ServiceClient.serviceVersion != 0) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.settings_is_clean_env)
.setMessage(R.string.settings_is_clean_env_summary)
.setPositiveButton(R.string.yes) { _, _ ->
ServiceHelper.stopSystemService(true)
ServiceClient.stopService(true)
makeToast(R.string.settings_stop_system_service)
}
.setNegativeButton(R.string.no) { _, _ ->
ServiceHelper.stopSystemService(false)
ServiceClient.stopService(false)
makeToast(R.string.settings_stop_system_service)
}
.setNeutralButton(android.R.string.cancel, null)