System.kt 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package com.example.modifier.utils
  2. import android.accessibilityservice.AccessibilityServiceInfo
  3. import android.annotation.SuppressLint
  4. import android.content.Context
  5. import android.content.pm.PackageManager
  6. import android.provider.Settings
  7. import android.text.TextUtils
  8. import android.util.Log
  9. import android.view.accessibility.AccessibilityManager
  10. import androidx.core.app.ActivityCompat
  11. import com.example.modifier.BuildConfig
  12. import com.example.modifier.Utils
  13. import com.example.modifier.http.ktorClient
  14. import com.example.modifier.service.ModifierService
  15. import io.ktor.client.request.head
  16. import org.apache.commons.lang3.StringUtils
  17. import java.time.ZoneId
  18. import java.time.ZonedDateTime
  19. import java.time.format.DateTimeFormatter
  20. import java.util.Locale
  21. import java.util.Objects
  22. import java.util.UUID
  23. val uniqueId: String
  24. @SuppressLint("HardwareIds")
  25. get() {
  26. val context = Utils.getContext()
  27. Objects.requireNonNull(context)
  28. val sharedPrefs =
  29. context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE)
  30. var uniqueID = sharedPrefs.getString("unique_id", "")!!
  31. if (uniqueID.isBlank()) {
  32. try {
  33. uniqueID =
  34. Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
  35. } catch (e: java.lang.Exception) {
  36. e.printStackTrace()
  37. }
  38. }
  39. if (StringUtils.isBlank(uniqueID)) {
  40. uniqueID = UUID.randomUUID().toString()
  41. }
  42. sharedPrefs.edit().putString("unique_id", uniqueID).apply()
  43. return uniqueID
  44. }
  45. @SuppressLint("PrivateApi")
  46. fun getContext(): Context? {
  47. try {
  48. val activityThreadClass = Class.forName("android.app.ActivityThread")
  49. val currentActivityThreadMethod = activityThreadClass.getMethod("currentActivityThread")
  50. currentActivityThreadMethod.isAccessible = true
  51. val currentActivityThread = currentActivityThreadMethod.invoke(null)
  52. val getApplicationMethod = activityThreadClass.getMethod("getApplication")
  53. getApplicationMethod.isAccessible = true
  54. return getApplicationMethod.invoke(currentActivityThread) as Context
  55. } catch (e: java.lang.Exception) {
  56. e.printStackTrace()
  57. }
  58. return null
  59. }
  60. suspend fun hasRootAccess(): Boolean {
  61. var rootAccess = false
  62. try {
  63. val (output, _) = shellRun("echo \"imrooted\"")
  64. if (output.contains("imrooted")) {
  65. rootAccess = true
  66. }
  67. } catch (e: Exception) {
  68. e.printStackTrace()
  69. }
  70. return rootAccess
  71. }
  72. fun hasPermission(permission: String): Boolean {
  73. return ActivityCompat.checkSelfPermission(
  74. getContext()!!,
  75. permission
  76. ) == PackageManager.PERMISSION_GRANTED
  77. }
  78. fun isAccessibilityEnabled(): Boolean {
  79. val context = getContext()!!
  80. val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
  81. val enabledServices =
  82. am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
  83. for (enabledService in enabledServices) {
  84. Log.i(
  85. com.example.modifier.TAG,
  86. "Enabled service: " + enabledService.resolveInfo.serviceInfo.packageName + "/" + enabledService.resolveInfo.serviceInfo.name
  87. )
  88. val enabledServiceInfo = enabledService.resolveInfo.serviceInfo
  89. if (enabledServiceInfo.packageName == context.packageName && enabledServiceInfo.name == ModifierService.NAME) return true
  90. }
  91. return false
  92. }
  93. suspend fun enableAccessibility(): Boolean {
  94. if (isAccessibilityEnabled()) return true
  95. val context = getContext()!!
  96. val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
  97. val enabledServices =
  98. am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
  99. val names: MutableList<String?> = ArrayList()
  100. for (enabledService in enabledServices) {
  101. names.add(enabledService.resolveInfo.serviceInfo.packageName + "/" + enabledService.resolveInfo.serviceInfo.name)
  102. }
  103. names.add(context.packageName + "/" + ModifierService.NAME)
  104. try {
  105. shellRun(
  106. "settings put secure enabled_accessibility_services " + TextUtils.join(":", names),
  107. "settings put secure accessibility_enabled 1"
  108. )
  109. return true
  110. } catch (e: java.lang.Exception) {
  111. e.printStackTrace()
  112. }
  113. return false
  114. }
  115. suspend fun enableOverlay() {
  116. try {
  117. shellRun("appops set " + BuildConfig.APPLICATION_ID + " SYSTEM_ALERT_WINDOW allow")
  118. } catch (e: java.lang.Exception) {
  119. e.printStackTrace()
  120. }
  121. }
  122. suspend fun optimize() {
  123. val context = Utils.getContext()
  124. val packageManager = context.packageManager
  125. val info = packageManager.getApplicationInfo("com.google.android.gms", 0)
  126. shellRun(
  127. "dumpsys deviceidle whitelist +com.google.android.apps.messaging",
  128. "dumpsys deviceidle whitelist +${BuildConfig.APPLICATION_ID}",
  129. "cmd netpolicy add restrict-background-blacklist ${info.uid}",
  130. "settings put global window_animation_scale 0",
  131. "settings put global transition_animation_scale 0",
  132. "settings put global animator_duration_scale 0"
  133. )
  134. }
  135. suspend fun syncTime() {
  136. try {
  137. Log.i("Modifier", "syncTime: start")
  138. val response = ktorClient("").head("http://www.baidu.com")
  139. val dateHeader = response.headers["Date"]
  140. val date = ZonedDateTime.parse(
  141. dateHeader,
  142. DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH)
  143. )
  144. // convert to Asia/Shanghai
  145. val dateInZone = date.withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
  146. Log.i(
  147. com.example.modifier.TAG,
  148. "CurrentTime from Baidu: ${dateInZone.format(DateTimeFormatter.ISO_DATE_TIME)}"
  149. )
  150. shellRun(
  151. "settings put system time_12_24 24",
  152. "settings put global auto_time 0",
  153. "settings put global auto_time_zone 0",
  154. "setprop persist.sys.timezone Asia/Shanghai",
  155. "date \"${dateInZone.format(DateTimeFormatter.ofPattern("MMddHHmmyyyy.ss"))}\""
  156. )
  157. } catch (e: Exception) {
  158. Log.e(com.example.modifier.TAG, "Error SyncTime", e)
  159. }
  160. }
  161. suspend fun isRebooted(): Boolean {
  162. if (shellRun("getprop rebooted").component1().contains("yes")) {
  163. return false
  164. }
  165. shellRun("setprop rebooted yes")
  166. return true
  167. }
  168. suspend fun setBatteryLevel(level: Int) {
  169. shellRun("dumpsys battery set level $level")
  170. }