ModifierService.kt 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312
  1. package com.example.modifier.service
  2. import android.accessibilityservice.AccessibilityService
  3. import android.annotation.SuppressLint
  4. import android.content.ComponentName
  5. import android.content.Context
  6. import android.graphics.PixelFormat
  7. import android.os.Build
  8. import android.os.Handler
  9. import android.os.Looper
  10. import android.text.TextUtils
  11. import android.util.Base64
  12. import android.util.DisplayMetrics
  13. import android.util.Log
  14. import android.view.Gravity
  15. import android.view.LayoutInflater
  16. import android.view.MotionEvent
  17. import android.view.View
  18. import android.view.View.OnTouchListener
  19. import android.view.WindowManager
  20. import android.view.accessibility.AccessibilityEvent
  21. import android.view.accessibility.AccessibilityNodeInfo
  22. import android.widget.CompoundButton
  23. import android.widget.FrameLayout
  24. import androidx.annotation.MenuRes
  25. import androidx.appcompat.widget.PopupMenu
  26. import androidx.core.content.ContextCompat
  27. import com.example.modifier.BuildConfig
  28. import com.example.modifier.Global
  29. import com.example.modifier.Global.restartModifier
  30. import com.example.modifier.R
  31. import com.example.modifier.TraverseResult
  32. import com.example.modifier.Utils
  33. import com.example.modifier.constants.CMD_BACK
  34. import com.example.modifier.constants.CMD_CONVERSATION_LIST_ACTIVITY
  35. import com.example.modifier.constants.CMD_MESSAGING_APP
  36. import com.example.modifier.constants.CMD_RCS_SETTINGS_ACTIVITY
  37. import com.example.modifier.constants.PACKAGE_GMS
  38. import com.example.modifier.constants.PACKAGE_MESSAGING
  39. import com.example.modifier.data.AppDatabase
  40. import com.example.modifier.data.AppPreferences
  41. import com.example.modifier.repo.AppPreferencesRepository
  42. import com.example.modifier.data.AppState
  43. import com.example.modifier.repo.AppStateRepository
  44. import com.example.modifier.data.BackupItemDao
  45. import com.example.modifier.repo.GoogleMessageStateRepository
  46. import com.example.modifier.databinding.FloatingWindowBinding
  47. import com.example.modifier.enums.RcsConfigureState
  48. import com.example.modifier.enums.RcsConnectionStatus
  49. import com.example.modifier.extension.kill
  50. import com.example.modifier.http.api.DeviceApi
  51. import com.example.modifier.http.api.RcsNumberApi
  52. import com.example.modifier.http.api.SysConfigApi
  53. import com.example.modifier.http.ktorClient
  54. import com.example.modifier.http.request.RcsNumberRequest
  55. import com.example.modifier.http.response.DeviceResponse
  56. import com.example.modifier.http.response.RcsNumberResponse
  57. import com.example.modifier.http.response.SysConfigResponse
  58. import com.example.modifier.model.InstallApkAction
  59. import com.example.modifier.model.SpoofedSimInfo
  60. import com.example.modifier.model.SocketCallback
  61. import com.example.modifier.model.TaskAction
  62. import com.example.modifier.model.TaskConfig
  63. import com.example.modifier.model.TaskExecutionResult
  64. import com.example.modifier.repo.BackupRepository
  65. import com.example.modifier.repo.SpoofedSimInfoRepository
  66. import com.example.modifier.serializer.Json
  67. import com.example.modifier.utils.changeClashProfile
  68. import com.example.modifier.utils.clearConv
  69. import com.example.modifier.utils.genICCID
  70. import com.example.modifier.utils.genIMEI
  71. import com.example.modifier.utils.genIMSI
  72. import com.example.modifier.utils.hasRootAccess
  73. import com.example.modifier.utils.isClashInstalled
  74. import com.example.modifier.utils.isOldVersion
  75. import com.example.modifier.utils.isRebooted
  76. import com.example.modifier.utils.killPhoneProcess
  77. import com.example.modifier.utils.optimize
  78. import com.example.modifier.utils.resetAll
  79. import com.example.modifier.utils.setBatteryLevel
  80. import com.example.modifier.utils.shellRun
  81. import com.example.modifier.utils.smsIntent
  82. import com.example.modifier.utils.stopClash
  83. import com.example.modifier.utils.syncTime
  84. import com.example.modifier.utils.uniqueId
  85. import com.google.android.material.color.DynamicColors
  86. import io.ktor.client.HttpClient
  87. import io.ktor.client.call.body
  88. import io.ktor.client.engine.okhttp.OkHttp
  89. import io.ktor.client.plugins.HttpResponseValidator
  90. import io.ktor.client.plugins.ServerResponseException
  91. import io.ktor.client.plugins.resources.get
  92. import io.ktor.client.plugins.resources.post
  93. import io.ktor.client.plugins.resources.put
  94. import io.ktor.client.plugins.timeout
  95. import io.ktor.client.request.prepareGet
  96. import io.ktor.client.request.setBody
  97. import io.ktor.http.ContentType
  98. import io.ktor.http.contentType
  99. import io.ktor.utils.io.ByteReadChannel
  100. import io.ktor.utils.io.core.isEmpty
  101. import io.ktor.utils.io.core.readBytes
  102. import io.socket.client.IO
  103. import io.socket.client.Socket
  104. import io.socket.emitter.Emitter
  105. import kotlinx.coroutines.CoroutineScope
  106. import kotlinx.coroutines.Dispatchers
  107. import kotlinx.coroutines.delay
  108. import kotlinx.coroutines.flow.StateFlow
  109. import kotlinx.coroutines.launch
  110. import kotlinx.coroutines.withContext
  111. import kotlinx.coroutines.withTimeout
  112. import kotlinx.coroutines.withTimeoutOrNull
  113. import kotlinx.serialization.encodeToString
  114. import org.apache.commons.lang3.RandomStringUtils
  115. import org.json.JSONException
  116. import org.json.JSONObject
  117. import java.io.File
  118. import java.time.LocalDateTime
  119. import java.time.temporal.ChronoUnit
  120. import java.util.Timer
  121. import java.util.TimerTask
  122. import java.util.concurrent.atomic.AtomicReference
  123. import kotlin.math.max
  124. import kotlin.math.min
  125. import kotlin.time.Duration.Companion.hours
  126. import kotlin.time.Duration.Companion.minutes
  127. import kotlin.time.Duration.Companion.seconds
  128. @SuppressLint("SetTextI18n")
  129. class ModifierService : AccessibilityService(), Emitter.Listener {
  130. companion object {
  131. const val NAME: String = BuildConfig.APPLICATION_ID + ".service.ModifierService"
  132. @JvmStatic
  133. var instance: ModifierService? = null
  134. private set
  135. }
  136. private val handler = Handler(Looper.getMainLooper())
  137. private val mSocketOpts = IO.Options()
  138. private lateinit var mSocket: Socket
  139. private lateinit var binding: FloatingWindowBinding
  140. private var currentTaskId = 0
  141. private var lastSend = 0L
  142. private val backupItemDao by lazy {
  143. AppDatabase.getDatabase(this).itemDao()
  144. }
  145. private val appPreferencesRepository by lazy {
  146. AppPreferencesRepository(this)
  147. }
  148. private lateinit var appPreferences: StateFlow<AppPreferences>
  149. private val appStateRepository: AppStateRepository by lazy {
  150. AppStateRepository(this)
  151. }
  152. private lateinit var appState: StateFlow<AppState>
  153. private val googleMessageStateRepository by lazy {
  154. GoogleMessageStateRepository(this)
  155. }
  156. private var requestMode = 1;
  157. private var currentActivity = ""
  158. private val screenInspector by lazy {
  159. ScreenInspector(this)
  160. }
  161. private val screenController by lazy {
  162. ScreenController(this, screenInspector)
  163. }
  164. private val spoofedSimInfoRepository by lazy {
  165. SpoofedSimInfoRepository(this)
  166. }
  167. private lateinit var spoofedSimInfo: StateFlow<SpoofedSimInfo>
  168. private val backupRepository by lazy {
  169. BackupRepository(this, backupItemDao, spoofedSimInfoRepository)
  170. }
  171. fun connect() {
  172. try {
  173. if (this@ModifierService::mSocket.isInitialized) {
  174. mSocket.disconnect()
  175. }
  176. mSocketOpts.query =
  177. "model=${Build.MODEL}&name=${appPreferences.value.name}&id=${uniqueId}&version=${BuildConfig.VERSION_CODE}"
  178. mSocketOpts.transports = arrayOf("websocket")
  179. Log.i(com.example.modifier.TAG, "Connection query: ${mSocketOpts.query}")
  180. mSocket = IO.socket(appPreferences.value.server, mSocketOpts)
  181. mSocket.on("message", this@ModifierService)
  182. mSocket.on(Socket.EVENT_CONNECT) {
  183. Log.i(com.example.modifier.TAG, "Connected to server")
  184. CoroutineScope(Dispatchers.IO).launch {
  185. delay(500)
  186. reportDeviceStatues()
  187. }
  188. }
  189. mSocket.on(Socket.EVENT_DISCONNECT) {
  190. Log.i(com.example.modifier.TAG, "Disconnected from server")
  191. }
  192. mSocket.on(Socket.EVENT_CONNECT_ERROR) { args ->
  193. Log.i(com.example.modifier.TAG, "Connection error: " + args[0])
  194. if (args[0] is Exception) {
  195. val e = args[0] as Exception
  196. e.printStackTrace()
  197. }
  198. }
  199. mSocket.connect()
  200. } catch (e: Exception) {
  201. e.printStackTrace()
  202. }
  203. }
  204. override fun onCreate() {
  205. super.onCreate()
  206. Log.i(com.example.modifier.TAG, "Starting ModifierService")
  207. CoroutineScope(Dispatchers.IO).launch {
  208. appState = appStateRepository.getAppState()
  209. appPreferences = appPreferencesRepository.getAppPreferences()
  210. spoofedSimInfo = spoofedSimInfoRepository.stateFlow()
  211. appStateRepository.updateRuntimeFlags(preparing = true)
  212. val hasRoot = run checkRoot@{
  213. repeat(30) {
  214. if (hasRootAccess()) {
  215. return@checkRoot true
  216. }
  217. delay(1000)
  218. }
  219. false
  220. }
  221. if (!hasRoot) {
  222. System.exit(0)
  223. }
  224. launch {
  225. googleMessageStateRepository.startLogging()
  226. }
  227. if (isRebooted()) {
  228. delay(2.minutes)
  229. } else {
  230. delay(5000)
  231. }
  232. optimize()
  233. syncTime()
  234. if (Build.MODEL.startsWith("SM-F707") || Build.MODEL.startsWith("SM-F711")) {
  235. killPhoneProcess(force = false)
  236. }
  237. appStateRepository.updateRuntimeFlags(preparing = false)
  238. connect()
  239. val timer = Timer()
  240. timer.schedule(object : TimerTask() {
  241. override fun run() {
  242. reportDeviceStatues()
  243. }
  244. }, 0, 3.seconds.inWholeMilliseconds)
  245. if (Build.MODEL.startsWith("SM-F707") || Build.MODEL.startsWith("SM-F711")) {
  246. timer.schedule(object : TimerTask() {
  247. override fun run() {
  248. CoroutineScope(Dispatchers.IO).launch {
  249. try {
  250. setBatteryLevel(100)
  251. } catch (e: Exception) {
  252. e.printStackTrace()
  253. }
  254. }
  255. }
  256. }, 0, 30.minutes.inWholeMilliseconds)
  257. }
  258. }
  259. }
  260. override fun onAccessibilityEvent(event: AccessibilityEvent) {
  261. Log.d(
  262. com.example.modifier.TAG,
  263. "eventType: ${event.eventType}, packageName: ${event.packageName}, className: ${event.className}"
  264. )
  265. if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
  266. if (event.packageName != null && event.className != null) {
  267. val componentName = ComponentName(
  268. event.packageName.toString(),
  269. event.className.toString()
  270. )
  271. try {
  272. packageManager.getActivityInfo(componentName, 0)
  273. currentActivity = componentName.flattenToShortString()
  274. Log.d(com.example.modifier.TAG, "Activity: $currentActivity")
  275. } catch (_: Exception) {
  276. }
  277. }
  278. }
  279. }
  280. override fun onInterrupt() {
  281. }
  282. override fun call(vararg args: Any) {
  283. if (args.isNotEmpty()) {
  284. Log.i(com.example.modifier.TAG, "Received message: " + args[0])
  285. if (args[0] is JSONObject) {
  286. val json = args[0] as JSONObject
  287. val action = json.optString("action")
  288. if ("send" == action) {
  289. val data = json.optJSONObject("data")
  290. if (data != null) {
  291. val to = data.optString("to")
  292. val body = data.optString("body")
  293. CoroutineScope(Dispatchers.IO).launch {
  294. send(
  295. to, body, TaskConfig(
  296. rcsWait = 3000,
  297. rcsInterval = 1000,
  298. cleanCount = 10,
  299. requestNumberInterval = 50,
  300. checkConnection = true,
  301. useBackup = false,
  302. endToEndEncryption = true
  303. )
  304. )
  305. }
  306. }
  307. } else if ("task" == action) {
  308. val taskAction = Json.decodeFromString<TaskAction>(json.toString())
  309. CoroutineScope(Dispatchers.IO).launch {
  310. runTask(taskAction)
  311. }
  312. } else if ("installApk" == action) {
  313. val installApkAction = Json.decodeFromString<InstallApkAction>(json.toString())
  314. CoroutineScope(Dispatchers.IO).launch {
  315. installApk(installApkAction)
  316. }
  317. }
  318. }
  319. }
  320. }
  321. private suspend fun installApk(installApkAction: InstallApkAction) {
  322. try {
  323. val file = withContext(Dispatchers.IO) {
  324. File.createTempFile("files", ".apk")
  325. }
  326. HttpClient(OkHttp) {
  327. HttpResponseValidator {
  328. validateResponse { response ->
  329. if (response.status.value !in 200..299) {
  330. throw ServerResponseException(
  331. response,
  332. "Error " + response.status.value.toString()
  333. )
  334. }
  335. }
  336. }
  337. }.prepareGet(installApkAction.data.apkUrl)
  338. .execute { httpResponse ->
  339. val channel: ByteReadChannel = httpResponse.body()
  340. while (!channel.isClosedForRead) {
  341. val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
  342. while (!packet.isEmpty) {
  343. val bytes = packet.readBytes()
  344. file.appendBytes(bytes)
  345. }
  346. }
  347. }
  348. Log.i(com.example.modifier.TAG, "Apk file saved to ${file.path}")
  349. shellRun("pm install -d -r ${file.path}")
  350. mSocket.emit(
  351. "callback",
  352. JSONObject(
  353. Json.encodeToString(
  354. SocketCallback<String>(
  355. id = installApkAction.id,
  356. status = 0,
  357. )
  358. )
  359. )
  360. )
  361. } catch (e: Exception) {
  362. Log.e("Modifier", "Failed to install apk", e)
  363. mSocket.emit(
  364. "callback",
  365. JSONObject(
  366. Json.encodeToString(
  367. SocketCallback<String>(
  368. id = installApkAction.id,
  369. status = -1,
  370. error = e.message
  371. )
  372. )
  373. )
  374. )
  375. }
  376. }
  377. private suspend fun runTask(taskAction: TaskAction) {
  378. if (appState.value.busy) {
  379. mSocket.emit(
  380. "callback",
  381. JSONObject(
  382. Json.encodeToString(
  383. SocketCallback<String>(
  384. id = taskAction.id,
  385. status = -1,
  386. error = "another task is running"
  387. )
  388. )
  389. )
  390. )
  391. return
  392. }
  393. try {
  394. val taskConfig = taskAction.data.config
  395. currentTaskId = taskAction.data.taskId
  396. requestMode = if (taskAction.data.config.useBackup) 2 else 1
  397. if (taskAction.data.config.checkConnection) {
  398. appStateRepository.updateRuntimeFlags(checkingConnection = true)
  399. if (!checkRcsAvailability()) {
  400. mSocket.emit(
  401. "callback",
  402. JSONObject(
  403. Json.encodeToString(
  404. SocketCallback<String>(
  405. id = taskAction.id,
  406. status = -1,
  407. error = "RCS not available"
  408. )
  409. )
  410. )
  411. )
  412. requestNumber()
  413. appStateRepository.updateRuntimeFlags(checkingConnection = false)
  414. return
  415. }
  416. appStateRepository.updateRuntimeFlags(checkingConnection = false)
  417. }
  418. appStateRepository.updateRuntimeFlags(running = true)
  419. val success = ArrayList<Int>()
  420. val fail = ArrayList<Int>()
  421. for (i in 0 until taskAction.data.tasks.size) {
  422. val taskItem = taskAction.data.tasks[i]
  423. try {
  424. if (send(
  425. taskItem.number,
  426. taskItem.message,
  427. taskConfig
  428. )
  429. ) {
  430. success.add(taskItem.id)
  431. } else {
  432. fail.add(taskItem.id)
  433. }
  434. } catch (e: Exception) {
  435. Log.e(com.example.modifier.TAG, "runTaskError: ${e.message}", e)
  436. fail.add(taskItem.id)
  437. }
  438. }
  439. shellRun(CMD_BACK)
  440. mSocket.emit(
  441. "callback",
  442. JSONObject(
  443. Json.encodeToString(
  444. SocketCallback(
  445. id = taskAction.id,
  446. status = 0,
  447. data = TaskExecutionResult(success, fail)
  448. )
  449. )
  450. )
  451. )
  452. if (taskConfig.requestNumberInterval in 1..appState.value.successNum) {
  453. delay(3000)
  454. requestNumber()
  455. } else if (taskConfig.cleanCount in 1..appState.value.executedNum && !appPreferences.value.preventClean) {
  456. delay(3000)
  457. clearConv();
  458. shellRun(CMD_MESSAGING_APP)
  459. delay(3000)
  460. appStateRepository.resetExecutedNum()
  461. } else {
  462. delay(2000)
  463. }
  464. appStateRepository.updateRuntimeFlags(running = false)
  465. } catch (e: Exception) {
  466. Log.e(com.example.modifier.TAG, "runTaskError: ${e.message}", e)
  467. mSocket.emit(
  468. "callback",
  469. JSONObject(
  470. Json.encodeToString(
  471. SocketCallback<String>(
  472. id = taskAction.id,
  473. status = -1,
  474. error = e.message
  475. )
  476. )
  477. )
  478. )
  479. appStateRepository.updateRuntimeFlags(running = false)
  480. }
  481. }
  482. private suspend fun send(
  483. to: String,
  484. body: String,
  485. taskConfig: TaskConfig
  486. ): Boolean {
  487. Log.i(com.example.modifier.TAG, "Sending SMS to $to: $body")
  488. startActivity(smsIntent(to, body))
  489. try {
  490. Log.i(
  491. com.example.modifier.TAG,
  492. "Command executed successfully, waiting for app to open..."
  493. )
  494. delay(1000)
  495. var success = false
  496. var traverseResult = TraverseResult()
  497. withTimeoutOrNull(taskConfig.rcsWait) {
  498. while (true) {
  499. traverseResult = TraverseResult()
  500. screenInspector.traverseNode(traverseResult)
  501. if (traverseResult.isRcsCapable && traverseResult.sendBtn != null) {
  502. if (!taskConfig.endToEndEncryption || traverseResult.encrypted) {
  503. break
  504. }
  505. }
  506. delay(200)
  507. }
  508. }
  509. if (traverseResult.isRcsCapable) {
  510. if (traverseResult.sendBtn == null) {
  511. Log.i(com.example.modifier.TAG, "Send button not found")
  512. } else {
  513. Log.i(com.example.modifier.TAG, "Clicking send button")
  514. val dt = System.currentTimeMillis() - lastSend
  515. if (taskConfig.rcsInterval > 0 && dt < taskConfig.rcsInterval) {
  516. Log.i(com.example.modifier.TAG, "Waiting for RCS interval")
  517. delay(taskConfig.rcsInterval - dt)
  518. }
  519. traverseResult.sendBtn!!.performAction(AccessibilityNodeInfo.ACTION_CLICK)
  520. lastSend = System.currentTimeMillis()
  521. success = true
  522. }
  523. } else {
  524. Log.i(com.example.modifier.TAG, "RCS not detected")
  525. }
  526. appStateRepository.incrementExecutedNum(success)
  527. Log.i(
  528. com.example.modifier.TAG,
  529. "executedNum: ${appState.value.executedNum}, successNum: ${appState.value.successNum}"
  530. )
  531. delay(1000)
  532. return success
  533. } catch (e: Exception) {
  534. e.printStackTrace()
  535. }
  536. return false
  537. }
  538. @SuppressLint("ClickableViewAccessibility")
  539. override fun onServiceConnected() {
  540. super.onServiceConnected()
  541. instance = this
  542. val displayMetrics = DisplayMetrics()
  543. val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
  544. windowManager.defaultDisplay.getMetrics(displayMetrics)
  545. val height = displayMetrics.heightPixels
  546. val width = displayMetrics.widthPixels
  547. val mLayout = FrameLayout(this)
  548. val layoutParams = WindowManager.LayoutParams()
  549. layoutParams.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
  550. layoutParams.format = PixelFormat.TRANSLUCENT
  551. layoutParams.flags = layoutParams.flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
  552. layoutParams.flags = layoutParams.flags or WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
  553. layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT
  554. layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
  555. layoutParams.x = 0
  556. layoutParams.y = 800
  557. layoutParams.gravity = Gravity.START or Gravity.TOP
  558. val newContext = DynamicColors.wrapContextIfAvailable(applicationContext, R.style.AppTheme)
  559. val inflater = LayoutInflater.from(newContext)
  560. binding = FloatingWindowBinding.inflate(inflater, mLayout, true)
  561. binding.tvVersion.text = "v${BuildConfig.VERSION_CODE}"
  562. windowManager.addView(mLayout, layoutParams)
  563. var maxX = 0
  564. var maxY = 0
  565. binding.root.measure(View.MeasureSpec.EXACTLY, View.MeasureSpec.EXACTLY)
  566. binding.root.post {
  567. maxX = width - binding.root.measuredWidth
  568. maxY = height - binding.root.measuredHeight
  569. Log.i(com.example.modifier.TAG, "measured: $maxX, $maxY")
  570. layoutParams.x = maxX
  571. windowManager.updateViewLayout(mLayout, layoutParams)
  572. }
  573. val downX = AtomicReference(0f)
  574. val downY = AtomicReference(0f)
  575. val downParamX = AtomicReference(0)
  576. val downParamY = AtomicReference(0)
  577. val touchListener = OnTouchListener { v, event ->
  578. when (event.action) {
  579. MotionEvent.ACTION_DOWN -> {
  580. downX.set(event.rawX)
  581. downY.set(event.rawY)
  582. downParamX.set(layoutParams.x)
  583. downParamY.set(layoutParams.y)
  584. }
  585. MotionEvent.ACTION_MOVE -> {
  586. layoutParams.x = min(
  587. max((downParamX.get() + (event.rawX - downX.get())).toDouble(), 0.0),
  588. maxX.toDouble()
  589. )
  590. .toInt()
  591. layoutParams.y = min(
  592. max((downParamY.get() + (event.rawY - downY.get())).toDouble(), 0.0),
  593. maxY.toDouble()
  594. )
  595. .toInt()
  596. windowManager.updateViewLayout(mLayout, layoutParams)
  597. }
  598. MotionEvent.ACTION_UP -> {
  599. return@OnTouchListener event.eventTime - event.downTime >= 200
  600. }
  601. }
  602. false
  603. }
  604. CoroutineScope(Dispatchers.Main).launch {
  605. appState.collect {
  606. binding.swSend.isChecked = it.send
  607. binding.btnReq.isEnabled = !it.requesting
  608. binding.tvCount.text = "${it.successNum} / ${it.executedNum}"
  609. withContext(Dispatchers.IO) {
  610. reportDeviceStatues()
  611. }
  612. }
  613. }
  614. CoroutineScope(Dispatchers.Main).launch {
  615. appPreferences.collect {
  616. binding.swSend.text = it.name
  617. }
  618. }
  619. binding.swSend.setOnTouchListener(touchListener)
  620. binding.swSend.setOnCheckedChangeListener { buttonView: CompoundButton?, isChecked: Boolean ->
  621. CoroutineScope(Dispatchers.IO).launch {
  622. appStateRepository.updateSend(isChecked)
  623. }
  624. }
  625. googleMessageStateRepository.logs.observeForever {
  626. binding.tvLog.text = it
  627. binding.scroll.fullScroll(View.FOCUS_DOWN)
  628. }
  629. binding.btnReq.setOnClickListener {
  630. CoroutineScope(Dispatchers.IO).launch {
  631. requestNumber(reset = false, noBackup = true)
  632. }
  633. }
  634. binding.btnReset.setOnClickListener {
  635. binding.btnReset.isEnabled = false
  636. CoroutineScope(Dispatchers.IO).launch {
  637. reset()
  638. withContext(Dispatchers.Main) {
  639. binding.btnReset.isEnabled = true
  640. }
  641. }
  642. }
  643. binding.btnMore.setOnClickListener {
  644. showMenu(newContext, binding.btnMore, R.menu.more)
  645. }
  646. }
  647. private fun showMenu(context: Context, v: View, @MenuRes menuRes: Int) {
  648. val popup = PopupMenu(context, v)
  649. popup.menuInflater.inflate(menuRes, popup.menu)
  650. popup.setOnMenuItemClickListener { item ->
  651. binding.btnMore.isEnabled = false
  652. CoroutineScope(Dispatchers.IO).launch {
  653. when (item.itemId) {
  654. R.id.inspect -> {
  655. delay(1500)
  656. screenInspector.traverseNode(TraverseResult())
  657. }
  658. R.id.check_availability -> {
  659. checkRcsAvailability()
  660. }
  661. R.id.toggle_on -> {
  662. screenController.toggleRcsSwitch(true)
  663. }
  664. R.id.toggle_off -> {
  665. screenController.toggleRcsSwitch(false)
  666. }
  667. R.id.clear_conv -> {
  668. clearConv()
  669. }
  670. R.id.store_numbers -> {
  671. storeNumbers()
  672. }
  673. R.id.change_profile -> {
  674. }
  675. R.id.restart_modifier -> {
  676. restartModifier()
  677. }
  678. R.id.reset_counter -> {
  679. CoroutineScope(Dispatchers.IO).launch {
  680. appStateRepository.resetExecutedNum()
  681. appStateRepository.resetSuccessNum()
  682. appStateRepository.resetRequestedNum()
  683. }
  684. }
  685. }
  686. withContext(Dispatchers.Main) {
  687. binding.btnMore.isEnabled = true
  688. }
  689. }
  690. true
  691. }
  692. popup.setOnDismissListener {
  693. // Respond to popup being dismissed.
  694. }
  695. // Show the popup menu.
  696. popup.show()
  697. }
  698. private fun reportDeviceStatues() {
  699. if (this::mSocket.isInitialized) {
  700. val data = JSONObject()
  701. try {
  702. data.put("action", "updateDevice")
  703. val dataObj = JSONObject()
  704. dataObj.put("canSend", appState.value.send)
  705. dataObj.put("busy", appState.value.busy)
  706. dataObj.put("currentCountry", spoofedSimInfo.value.country)
  707. data.put("data", dataObj)
  708. mSocket.emit("message", data)
  709. } catch (e: JSONException) {
  710. e.printStackTrace()
  711. }
  712. }
  713. }
  714. private suspend fun reset() {
  715. if (isOldVersion(this)) {
  716. withTimeout(1.hours) {
  717. while (true) {
  718. delay(100)
  719. withContext(Dispatchers.Main) {
  720. binding.tvLog.text = "Waiting for RCS switch on..."
  721. }
  722. googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
  723. spoofedSimInfoRepository.mock()
  724. resetAll()
  725. var switchAppear = googleMessageStateRepository.waitForRcsState(
  726. arrayOf(RcsConfigureState.WAITING_FOR_TOS),
  727. 2.minutes
  728. )?.let {
  729. it == RcsConfigureState.WAITING_FOR_TOS
  730. }
  731. if (switchAppear != true) {
  732. shellRun(
  733. PACKAGE_GMS.kill(), PACKAGE_MESSAGING.kill(), "sleep 1",
  734. CMD_MESSAGING_APP
  735. )
  736. switchAppear = googleMessageStateRepository.waitForRcsState(
  737. arrayOf(RcsConfigureState.WAITING_FOR_TOS),
  738. 5.minutes
  739. )?.let {
  740. it == RcsConfigureState.WAITING_FOR_TOS
  741. }
  742. if (switchAppear != true) {
  743. Log.e(
  744. com.example.modifier.TAG,
  745. "RCS not entered default on state, retrying..."
  746. )
  747. continue
  748. }
  749. }
  750. if (!screenController.toggleRcsSwitch(false)) {
  751. Log.e(com.example.modifier.TAG, "RCS switch not turned off, retrying...")
  752. continue
  753. }
  754. if (!screenController.toggleRcsSwitch(true)) {
  755. Log.e(com.example.modifier.TAG, "RCS switch not turned on, retrying...")
  756. continue
  757. }
  758. var resetSuccess = googleMessageStateRepository.waitForRcsState(
  759. arrayOf(
  760. RcsConfigureState.READY
  761. ), 30.seconds
  762. ).let { it == RcsConfigureState.READY }
  763. if (!resetSuccess) {
  764. screenController.toggleRcsSwitch(false)
  765. delay(1000)
  766. screenController.toggleRcsSwitch(true)
  767. resetSuccess = googleMessageStateRepository.waitForRcsState(
  768. arrayOf(
  769. RcsConfigureState.READY
  770. ), 1.minutes
  771. ).let { it == RcsConfigureState.READY }
  772. }
  773. Log.i(com.example.modifier.TAG, "waitForRcsState: $resetSuccess")
  774. appStateRepository.resetRequestedNum()
  775. if (resetSuccess) {
  776. delay(3000)
  777. break
  778. }
  779. }
  780. }
  781. } else {
  782. withTimeout(1.hours) {
  783. while (true) {
  784. delay(100)
  785. withContext(Dispatchers.Main) {
  786. binding.tvLog.text = "Waiting for RCS switch on..."
  787. }
  788. googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
  789. spoofedSimInfoRepository.mock()
  790. resetAll()
  791. var switchAppear = googleMessageStateRepository.waitForRcsState(
  792. arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
  793. 1.minutes
  794. )?.let {
  795. it == RcsConfigureState.WAITING_FOR_DEFAULT_ON
  796. }
  797. if (switchAppear != true) {
  798. shellRun(
  799. PACKAGE_GMS.kill(), PACKAGE_MESSAGING.kill(), "sleep 1",
  800. CMD_MESSAGING_APP
  801. )
  802. switchAppear = googleMessageStateRepository.waitForRcsState(
  803. arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
  804. 2.minutes
  805. )?.let {
  806. it == RcsConfigureState.WAITING_FOR_DEFAULT_ON
  807. }
  808. if (switchAppear != true) {
  809. Log.e(
  810. com.example.modifier.TAG,
  811. "RCS not entered default on state, retrying..."
  812. )
  813. continue
  814. }
  815. }
  816. val switchOn = screenController.toggleRcsSwitch(true)
  817. if (!switchOn) {
  818. Log.e(com.example.modifier.TAG, "RCS switch not turned on, retrying...")
  819. continue
  820. }
  821. var resetSuccess = googleMessageStateRepository.waitForRcsState(
  822. arrayOf(
  823. RcsConfigureState.READY
  824. ), 30.seconds
  825. ).let { it == RcsConfigureState.READY }
  826. if (!resetSuccess) {
  827. screenController.toggleRcsSwitch(false)
  828. delay(1000)
  829. screenController.toggleRcsSwitch(true)
  830. resetSuccess = googleMessageStateRepository.waitForRcsState(
  831. arrayOf(
  832. RcsConfigureState.READY
  833. ), 1.minutes
  834. ).let { it == RcsConfigureState.READY }
  835. }
  836. Log.i(com.example.modifier.TAG, "waitForRcsState: $resetSuccess")
  837. appStateRepository.resetRequestedNum()
  838. if (resetSuccess) {
  839. delay(3000)
  840. break
  841. }
  842. }
  843. }
  844. }
  845. }
  846. private suspend fun requestNumber(
  847. reset: Boolean = false,
  848. noBackup: Boolean = false,
  849. fresh: Boolean = false
  850. ) {
  851. val color = ContextCompat.getColorStateList(binding.root.context, R.color.btn_color)
  852. binding.btnReq.backgroundTintList = color
  853. if (appPreferences.value.preventRequest) {
  854. return
  855. }
  856. if (appState.value.requesting) {
  857. return
  858. }
  859. appStateRepository.updateRuntimeFlags(requesting = true)
  860. if (spoofedSimInfo.value.available) {
  861. backupRepository.backup(
  862. spoofedSimInfo = spoofedSimInfo.value,
  863. type = "auto",
  864. sendCount = appState.value.executedNum,
  865. fresh = fresh
  866. )
  867. } else {
  868. clearConv();
  869. }
  870. appStateRepository.incrementRequestedNum()
  871. var requestSuccess = false
  872. var retry = 0
  873. var needRest = reset
  874. withTimeoutOrNull(1.hours) {
  875. while (true) {
  876. delay(200)
  877. needRest = needRest || retry > 2 || appState.value.requestedNum > 5
  878. try {
  879. val device =
  880. ktorClient(appPreferences.value.server).get(DeviceApi.Id(id = uniqueId))
  881. .body<DeviceResponse>()
  882. if (isClashInstalled(applicationContext)) {
  883. val prefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
  884. if (TextUtils.isEmpty(device.clashProfile)) {
  885. prefs.edit()
  886. .remove("clash_profile")
  887. .apply()
  888. stopClash()
  889. } else {
  890. val oldProfile = prefs.getString("clash_profile", "")
  891. if (oldProfile != device.clashProfile) {
  892. prefs.edit()
  893. .putString("clash_profile", device.clashProfile)
  894. .apply()
  895. changeClashProfile(
  896. device.pinCountry!!, Base64.encodeToString(
  897. device.clashProfile!!.toByteArray(),
  898. Base64.DEFAULT
  899. )
  900. )
  901. delay(5000)
  902. }
  903. }
  904. }
  905. if (requestMode == 2 && !noBackup) {
  906. val backup = backupItemDao.findBackupForRestore(
  907. spoofedSimInfo.value.number,
  908. System.currentTimeMillis() - 2 * 24 * 60 * 60 * 1000
  909. )
  910. if (backup != null) {
  911. if (backupRepository.restore(backup)) {
  912. requestSuccess = true
  913. break
  914. } else {
  915. backupRepository.backup(
  916. spoofedSimInfo = spoofedSimInfo.value,
  917. type = "auto",
  918. sendCount = 0
  919. )
  920. continue
  921. }
  922. }
  923. }
  924. if (needRest && !appPreferences.value.preventReset) {
  925. reset()
  926. retry = 0
  927. needRest = false
  928. }
  929. googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
  930. withContext(Dispatchers.Main) {
  931. binding.tvLog.text = "Requesting number..."
  932. }
  933. val req = RcsNumberRequest(
  934. deviceId = uniqueId,
  935. taskId = currentTaskId
  936. )
  937. if (!TextUtils.isEmpty(device.pinCountry)) {
  938. req.country = device.pinCountry
  939. }
  940. val response = ktorClient(appPreferences.value.server).put(
  941. RcsNumberApi()
  942. ) {
  943. contentType(ContentType.Application.Json)
  944. setBody(req)
  945. timeout {
  946. requestTimeoutMillis = 60 * 1000
  947. socketTimeoutMillis = 60 * 1000
  948. }
  949. }
  950. var rcsNumber = response.body<RcsNumberResponse>()
  951. Log.i(com.example.modifier.TAG, "requestNumber response: $rcsNumber")
  952. withContext(Dispatchers.Main) {
  953. binding.tvLog.text = "Requesting success, waiting for logs..."
  954. }
  955. spoofedSimInfoRepository.updateSpoofedSimInfo(
  956. SpoofedSimInfo(
  957. number = rcsNumber.number,
  958. mcc = rcsNumber.mcc,
  959. mnc = rcsNumber.mnc,
  960. iccid = genICCID(rcsNumber.mnc, rcsNumber.areaCode),
  961. imsi = genIMSI(rcsNumber.mcc + rcsNumber.mnc),
  962. imei = genIMEI(),
  963. country = rcsNumber.country,
  964. areaCode = rcsNumber.areaCode,
  965. available = false,
  966. carrierId = rcsNumber.carrierId,
  967. carrierName = rcsNumber.carrierName,
  968. )
  969. )
  970. shellRun(CMD_MESSAGING_APP)
  971. withContext(Dispatchers.Main) {
  972. binding.tvLog.text = "Waiting for logs..."
  973. }
  974. if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
  975. Log.e(com.example.modifier.TAG, "RCS number expired, retrying...")
  976. continue
  977. }
  978. var sendOtpTimeout = ChronoUnit.SECONDS.between(
  979. LocalDateTime.now(),
  980. rcsNumber.expiryTime
  981. ).seconds
  982. if (sendOtpTimeout < 60.seconds) {
  983. Log.e(com.example.modifier.TAG, "OTP timeout too short, retrying...")
  984. continue
  985. }
  986. if (sendOtpTimeout > 2.minutes) {
  987. sendOtpTimeout = 2.minutes
  988. }
  989. if (googleMessageStateRepository.waitForRcsState(
  990. arrayOf(RcsConfigureState.WAITING_FOR_OTP),
  991. sendOtpTimeout
  992. ) != RcsConfigureState.WAITING_FOR_OTP
  993. ) {
  994. if (!screenController.toggleRcsSwitch(true)) {
  995. needRest = true
  996. }
  997. if (RcsConfigureState.REPLAY_REQUEST == googleMessageStateRepository.rcsConfigureState.value) {
  998. Log.e(
  999. com.example.modifier.TAG,
  1000. "REPLAY_REQUEST detected, may reset after 3 retry ($retry)"
  1001. )
  1002. retry++
  1003. }
  1004. Log.e(
  1005. com.example.modifier.TAG,
  1006. "RCS not entered waiting for OTP state, retrying..."
  1007. )
  1008. continue
  1009. }
  1010. launch {
  1011. try {
  1012. ktorClient(appPreferences.value.server).post(
  1013. RcsNumberApi.Id.OtpState(
  1014. RcsNumberApi.Id(
  1015. RcsNumberApi(),
  1016. rcsNumber.id
  1017. )
  1018. )
  1019. )
  1020. } catch (e: Exception) {
  1021. Log.e(com.example.modifier.TAG, "Send OtpState Error: ${e.message}", e)
  1022. }
  1023. }
  1024. if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
  1025. Log.e(com.example.modifier.TAG, "RCS number expired, retrying...")
  1026. continue
  1027. }
  1028. withTimeoutOrNull(60.seconds) {
  1029. while (true) {
  1030. try {
  1031. rcsNumber =
  1032. ktorClient(appPreferences.value.server).get(RcsNumberApi.Id(id = rcsNumber.id))
  1033. .body<RcsNumberResponse>()
  1034. Log.i(com.example.modifier.TAG, "wait for otp response: $rcsNumber")
  1035. if (rcsNumber.status == RcsNumberResponse.STATUS_SUCCESS || rcsNumber.status == RcsNumberResponse.STATUS_EXPIRED) {
  1036. break
  1037. }
  1038. } catch (exception: Exception) {
  1039. Log.e(
  1040. com.example.modifier.TAG,
  1041. "wait for otp Error: ${exception.stackTrace}"
  1042. )
  1043. }
  1044. delay(2.seconds)
  1045. }
  1046. }
  1047. if (rcsNumber.status != RcsNumberResponse.STATUS_SUCCESS) {
  1048. Log.e(com.example.modifier.TAG, "OTP not received, retrying...")
  1049. continue
  1050. }
  1051. val match =
  1052. Regex("Your Messenger verification code is G-(\\d{6})")
  1053. .find(rcsNumber.message!!)
  1054. if (match != null) {
  1055. val otp = match.groupValues[1]
  1056. Log.i(com.example.modifier.TAG, "OTP: $otp")
  1057. val sender = "3538"
  1058. val msg = "Your Messenger verification code is G-$otp"
  1059. val configured = run configuring@{
  1060. repeat(2) {
  1061. Global.sendSmsIntent(sender, msg)
  1062. val state =
  1063. googleMessageStateRepository.waitForRcsState(
  1064. arrayOf(
  1065. RcsConfigureState.CONFIGURED,
  1066. RcsConfigureState.RETRY
  1067. ), 60.seconds
  1068. )
  1069. when (state) {
  1070. RcsConfigureState.CONFIGURED -> {
  1071. return@configuring true
  1072. }
  1073. RcsConfigureState.RETRY -> {
  1074. googleMessageStateRepository.waitForRcsState(
  1075. arrayOf(RcsConfigureState.WAITING_FOR_OTP),
  1076. 60.seconds
  1077. )
  1078. }
  1079. else -> {
  1080. Log.e(
  1081. com.example.modifier.TAG,
  1082. "verifyOtp fail, retrying..."
  1083. )
  1084. }
  1085. }
  1086. }
  1087. false
  1088. }
  1089. if (!configured) {
  1090. Log.e(com.example.modifier.TAG, "RCS not configured, retrying...")
  1091. continue
  1092. } else {
  1093. launch {
  1094. try {
  1095. ktorClient(appPreferences.value.server).post(
  1096. RcsNumberApi.Id.Configured(
  1097. RcsNumberApi.Id(
  1098. RcsNumberApi(),
  1099. rcsNumber.id
  1100. )
  1101. )
  1102. )
  1103. } catch (e: Exception) {
  1104. Log.e(
  1105. com.example.modifier.TAG,
  1106. "Send ConfiguredState Error: ${e.message}",
  1107. e
  1108. )
  1109. }
  1110. }
  1111. requestSuccess = true
  1112. break
  1113. }
  1114. }
  1115. } catch (e: Exception) {
  1116. Log.e(com.example.modifier.TAG, "requestNumberError: ${e.message}", e)
  1117. }
  1118. }
  1119. }
  1120. if (requestSuccess) {
  1121. spoofedSimInfoRepository.updateSpoofedSimInfo(
  1122. spoofedSimInfo = spoofedSimInfo.value.copy(
  1123. available = true
  1124. )
  1125. )
  1126. appStateRepository.resetSuccessNum()
  1127. appStateRepository.resetExecutedNum()
  1128. Log.i(com.example.modifier.TAG, "requestNumber success")
  1129. delay(5000)
  1130. shellRun(PACKAGE_MESSAGING.kill(), "sleep 1", CMD_MESSAGING_APP)
  1131. delay(2000)
  1132. } else {
  1133. Log.e(com.example.modifier.TAG, "requestNumber failed")
  1134. appStateRepository.updateSend(false)
  1135. withContext(Dispatchers.Main) {
  1136. binding.swSend.isChecked = false
  1137. binding.btnReq.backgroundTintList =
  1138. ContextCompat.getColorStateList(binding.root.context, R.color.btn_color_error)
  1139. }
  1140. }
  1141. appStateRepository.updateRuntimeFlags(requesting = false)
  1142. }
  1143. private suspend fun checkRcsConnectivity(): Boolean = run checkRcsConnection@{
  1144. repeat(3) {
  1145. Log.i(com.example.modifier.TAG, "Checking RCS status...")
  1146. shellRun(
  1147. CMD_CONVERSATION_LIST_ACTIVITY,
  1148. CMD_RCS_SETTINGS_ACTIVITY,
  1149. "sleep 1",
  1150. )
  1151. val res = TraverseResult()
  1152. screenInspector.traverseNode(res)
  1153. if (res.rcsConnectionStatus == RcsConnectionStatus.CONNECTED) {
  1154. Log.i(com.example.modifier.TAG, "RCS is connected")
  1155. shellRun(CMD_BACK)
  1156. return@checkRcsConnection true
  1157. } else {
  1158. Log.i(com.example.modifier.TAG, "RCS not connected, retrying...")
  1159. }
  1160. shellRun(CMD_BACK, "sleep ${it * 2}")
  1161. }
  1162. false
  1163. }
  1164. suspend fun checkRcsAvailability(): Boolean {
  1165. appStateRepository.updateRuntimeFlags(checkingConnection = true)
  1166. val availability = run checkAvailability@{
  1167. val rcsConnected = checkRcsConnectivity()
  1168. if (!rcsConnected) {
  1169. return@checkAvailability false
  1170. }
  1171. var config: SysConfigResponse
  1172. val checkRcsAvailabilityNumbers = mutableListOf<String>()
  1173. withTimeoutOrNull(60.seconds) {
  1174. try {
  1175. config = ktorClient(appPreferences.value.server).get(
  1176. SysConfigApi.Id(
  1177. SysConfigApi(),
  1178. "check_availability_numbers"
  1179. )
  1180. )
  1181. .body<SysConfigResponse>()
  1182. Log.i(com.example.modifier.TAG, "sysConfig response: $config")
  1183. checkRcsAvailabilityNumbers.addAll(
  1184. config.value.split(",").map { it.trim() })
  1185. } catch (exception: Exception) {
  1186. Log.e(
  1187. com.example.modifier.TAG,
  1188. "sysConfig Error: ${exception.message}",
  1189. exception
  1190. )
  1191. }
  1192. }
  1193. if (checkRcsAvailabilityNumbers.isEmpty()) {
  1194. Log.e(com.example.modifier.TAG, "checkRcsAvailabilityNumbers is empty")
  1195. return true
  1196. }
  1197. checkRcsAvailabilityNumbers.forEach {
  1198. startActivity(smsIntent(it, ""))
  1199. val s = withTimeoutOrNull(5.seconds) {
  1200. while (true) {
  1201. val traverseResult = TraverseResult()
  1202. screenInspector.traverseNode(traverseResult)
  1203. if (traverseResult.isRcsCapable) {
  1204. return@withTimeoutOrNull true
  1205. } else {
  1206. Log.i(
  1207. com.example.modifier.TAG,
  1208. "checkRcsAvailability: RCS not detected"
  1209. )
  1210. }
  1211. delay(200)
  1212. }
  1213. }
  1214. if (s == true) {
  1215. Log.i(com.example.modifier.TAG, "checkRcsAvailability: $it success")
  1216. delay(1000)
  1217. return@checkAvailability true
  1218. }
  1219. }
  1220. false
  1221. }
  1222. appStateRepository.updateRuntimeFlags(checkingConnection = false)
  1223. return availability
  1224. }
  1225. private suspend fun storeNumbers() {
  1226. repeat(100) {
  1227. requestNumber(reset = true, fresh = it > 0)
  1228. delay(5000)
  1229. }
  1230. }
  1231. }