DataStore.kt 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /******************************************************************************
  2. * *
  3. * Copyright (C) 2021 by nekohasekai <[email protected]> *
  4. * Copyright (C) 2021 by Max Lv <[email protected]> *
  5. * Copyright (C) 2021 by Mygod Studio <[email protected]> *
  6. * *
  7. * This program is free software: you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation, either version 3 of the License, or *
  10. * (at your option) any later version. *
  11. * *
  12. * This program is distributed in the hope that it will be useful, *
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15. * GNU General Public License for more details. *
  16. * *
  17. * You should have received a copy of the GNU General Public License *
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  19. * *
  20. ******************************************************************************/
  21. package io.nekohasekai.sagernet.database
  22. import android.os.Binder
  23. import android.os.Build
  24. import androidx.preference.PreferenceDataStore
  25. import io.nekohasekai.sagernet.Key
  26. import io.nekohasekai.sagernet.RouteMode
  27. import io.nekohasekai.sagernet.SagerNet
  28. import io.nekohasekai.sagernet.database.preference.OnPreferenceDataStoreChangeListener
  29. import io.nekohasekai.sagernet.database.preference.PublicDatabase
  30. import io.nekohasekai.sagernet.database.preference.RoomPreferenceDataStore
  31. import io.nekohasekai.sagernet.ktx.boolean
  32. import io.nekohasekai.sagernet.ktx.long
  33. import io.nekohasekai.sagernet.ktx.parsePort
  34. import io.nekohasekai.sagernet.ktx.string
  35. import io.nekohasekai.sagernet.utils.DirectBoot
  36. object DataStore : OnPreferenceDataStoreChangeListener {
  37. val configurationStore = RoomPreferenceDataStore(PublicDatabase.kvPairDao)
  38. val profileCacheStore = RoomPreferenceDataStore(SagerDatabase.profileCacheDao)
  39. fun init() {
  40. if (Build.VERSION.SDK_INT >= 24) {
  41. SagerNet.deviceStorage.moveDatabaseFrom(SagerNet.application, Key.DB_PUBLIC)
  42. }
  43. if (Build.VERSION.SDK_INT >= 24 && directBootAware && SagerNet.user.isUserUnlocked) {
  44. DirectBoot.flushTrafficStats()
  45. }
  46. }
  47. var selectedProxy by configurationStore.long(Key.PROFILE_ID)
  48. var selectedGroup by configurationStore.long(Key.PROFILE_GROUP) {
  49. SagerNet.currentProfile?.groupId ?: 0L
  50. }
  51. var serviceMode by configurationStore.string(Key.SERVICE_MODE) { Key.MODE_VPN }
  52. var routeMode by configurationStore.string(Key.ROUTE_MODE) { RouteMode.ALL }
  53. var allowAccess by configurationStore.boolean(Key.ALLOW_ACCESS)
  54. var enableLocalDNS by configurationStore.boolean(Key.ENABLE_LOCAL_DNS) { true }
  55. var remoteDNS by configurationStore.string(Key.REMOTE_DNS) { "1.1.1.1" }
  56. var domesticDns by configurationStore.string(Key.DOMESTIC_DNS) { "9.9.9.11" }
  57. // hopefully hashCode = mHandle doesn't change, currently this is true from KitKat to Nougat
  58. private val userIndex by lazy { Binder.getCallingUserHandle().hashCode() }
  59. var socksPort: Int
  60. get() = getLocalPort(Key.SOCKS_PORT, 2080)
  61. set(value) = saveLocalPort(Key.SOCKS_PORT, value)
  62. var localDNSPort: Int
  63. get() = getLocalPort(Key.LOCAL_DNS_PORT, 6450)
  64. set(value) {
  65. saveLocalPort(Key.LOCAL_DNS_PORT, value)
  66. }
  67. var httpPort: Int
  68. get() = getLocalPort(Key.HTTP_PORT, 9080)
  69. set(value) = saveLocalPort(Key.HTTP_PORT, value)
  70. fun initGlobal() {
  71. persistAcrossReboot
  72. if (configurationStore.getString(Key.SOCKS_PORT) == null) socksPort = socksPort
  73. if (configurationStore.getString(Key.LOCAL_DNS_PORT) == null) localDNSPort = localDNSPort
  74. if (configurationStore.getString(Key.HTTP_PORT) == null) httpPort = httpPort
  75. }
  76. private fun getLocalPort(key: String, default: Int): Int {
  77. return parsePort(configurationStore.getString(key), default + userIndex)
  78. }
  79. private fun saveLocalPort(key: String, value: Int) {
  80. configurationStore.putString(key, "$value")
  81. }
  82. var ipv6Route by configurationStore.boolean(Key.IPV6_ROUTE) { true }
  83. var preferIpv6 by configurationStore.boolean(Key.PREFER_IPV6)
  84. var meteredNetwork by configurationStore.boolean(Key.METERED_NETWORK)
  85. var proxyApps by configurationStore.boolean(Key.PROXY_APPS)
  86. var bypass by configurationStore.boolean(Key.BYPASS_MODE)
  87. var individual by configurationStore.string("individual")
  88. var forceShadowsocksRust by configurationStore.boolean(Key.FORCE_SHADOWSOCKS_RUST)
  89. var requireHttp by configurationStore.boolean(Key.REQUIRE_HTTP)
  90. val persistAcrossReboot by configurationStore.boolean(Key.PERSIST_ACROSS_REBOOT) { true }
  91. val canToggleLocked: Boolean get() = configurationStore.getBoolean(Key.DIRECT_BOOT_AWARE) == true
  92. val directBootAware: Boolean get() = SagerNet.directBootSupported && canToggleLocked
  93. // cache
  94. var dirty by profileCacheStore.boolean(Key.PROFILE_DIRTY)
  95. var editingId by profileCacheStore.long(Key.PROFILE_ID)
  96. var editingGroup by profileCacheStore.long(Key.PROFILE_GROUP)
  97. var profileName by profileCacheStore.string(Key.PROFILE_NAME)
  98. var serverAddress by profileCacheStore.string(Key.SERVER_ADDRESS)
  99. var serverPort by profileCacheStore.string(Key.SERVER_PORT)
  100. var serverUsername by profileCacheStore.string(Key.SERVER_USERNAME)
  101. var serverPassword by profileCacheStore.string(Key.SERVER_PASSWORD)
  102. var serverUdp by profileCacheStore.boolean(Key.SERVER_UDP)
  103. var serverMethod by profileCacheStore.string(Key.SERVER_METHOD)
  104. var serverPlugin by profileCacheStore.string(Key.SERVER_PLUGIN)
  105. override fun onPreferenceDataStoreChanged(store: PreferenceDataStore, key: String) {
  106. when (key) {
  107. Key.PROFILE_ID -> if (directBootAware) DirectBoot.update()
  108. }
  109. }
  110. }