TaskRunner.kt 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. package com.example.modifier.service
  2. import android.content.Context
  3. import android.text.TextUtils
  4. import android.util.Base64
  5. import android.util.Log
  6. import android.view.accessibility.AccessibilityNodeInfo
  7. import com.example.modifier.TAG
  8. import com.example.modifier.TraverseResult
  9. import com.example.modifier.constants.CMD_BACK
  10. import com.example.modifier.constants.CMD_CONVERSATION_LIST_ACTIVITY
  11. import com.example.modifier.constants.CMD_MESSAGING_APP
  12. import com.example.modifier.constants.CMD_RCS_SETTINGS_ACTIVITY
  13. import com.example.modifier.constants.PACKAGE_GMS
  14. import com.example.modifier.constants.PACKAGE_MESSAGING
  15. import com.example.modifier.data.AppPreferences
  16. import com.example.modifier.data.AppState
  17. import com.example.modifier.enums.RcsConfigureState
  18. import com.example.modifier.enums.RcsConnectionStatus
  19. import com.example.modifier.enums.RequestNumberState
  20. import com.example.modifier.extension.kill
  21. import com.example.modifier.http.api.DeviceApi
  22. import com.example.modifier.http.api.RcsNumberApi
  23. import com.example.modifier.http.api.SysConfigApi
  24. import com.example.modifier.http.ktorClient
  25. import com.example.modifier.http.request.RcsNumberRequest
  26. import com.example.modifier.http.response.DeviceResponse
  27. import com.example.modifier.http.response.RcsNumberResponse
  28. import com.example.modifier.http.response.SysConfigResponse
  29. import com.example.modifier.model.InstallApkAction
  30. import com.example.modifier.model.RunScriptAction
  31. import com.example.modifier.model.SocketCallback
  32. import com.example.modifier.model.SpoofedSimInfo
  33. import com.example.modifier.model.TaskAction
  34. import com.example.modifier.model.TaskConfig
  35. import com.example.modifier.model.TaskExecutionResult
  36. import com.example.modifier.repo.AppPreferencesRepository
  37. import com.example.modifier.repo.AppStateRepository
  38. import com.example.modifier.repo.BackupRepository
  39. import com.example.modifier.repo.GoogleMessageStateRepository
  40. import com.example.modifier.repo.SpoofedSimInfoRepository
  41. import com.example.modifier.serializer.Json
  42. import com.example.modifier.utils.changeClashProfile
  43. import com.example.modifier.utils.clearConv
  44. import com.example.modifier.utils.genICCID
  45. import com.example.modifier.utils.genIMEI
  46. import com.example.modifier.utils.genIMSI
  47. import com.example.modifier.utils.isClashInstalled
  48. import com.example.modifier.utils.isOldVersion
  49. import com.example.modifier.utils.resetAll
  50. import com.example.modifier.utils.shellRun
  51. import com.example.modifier.utils.smsIntent
  52. import com.example.modifier.utils.spoofSmsIntent
  53. import com.example.modifier.utils.stopClash
  54. import com.example.modifier.utils.uniqueId
  55. import io.ktor.client.HttpClient
  56. import io.ktor.client.call.body
  57. import io.ktor.client.engine.okhttp.OkHttp
  58. import io.ktor.client.plugins.HttpResponseValidator
  59. import io.ktor.client.plugins.ServerResponseException
  60. import io.ktor.client.plugins.resources.get
  61. import io.ktor.client.plugins.resources.post
  62. import io.ktor.client.plugins.resources.put
  63. import io.ktor.client.plugins.timeout
  64. import io.ktor.client.request.prepareGet
  65. import io.ktor.client.request.setBody
  66. import io.ktor.http.ContentType
  67. import io.ktor.http.contentType
  68. import io.ktor.utils.io.ByteReadChannel
  69. import io.ktor.utils.io.core.isEmpty
  70. import io.ktor.utils.io.core.readBytes
  71. import kotlinx.coroutines.CoroutineScope
  72. import kotlinx.coroutines.Dispatchers
  73. import kotlinx.coroutines.delay
  74. import kotlinx.coroutines.flow.StateFlow
  75. import kotlinx.coroutines.launch
  76. import kotlinx.coroutines.withContext
  77. import kotlinx.coroutines.withTimeout
  78. import kotlinx.coroutines.withTimeoutOrNull
  79. import kotlinx.serialization.encodeToString
  80. import org.json.JSONObject
  81. import java.io.File
  82. import java.time.LocalDateTime
  83. import java.time.temporal.ChronoUnit
  84. import kotlin.time.Duration.Companion.days
  85. import kotlin.time.Duration.Companion.hours
  86. import kotlin.time.Duration.Companion.minutes
  87. import kotlin.time.Duration.Companion.seconds
  88. class TaskRunner(
  89. private val context: Context,
  90. private val screenInspector: ScreenInspector,
  91. private val screenController: ScreenController,
  92. private val appStateRepository: AppStateRepository,
  93. private val appPreferencesRepository: AppPreferencesRepository,
  94. private val spoofedSimInfoRepository: SpoofedSimInfoRepository,
  95. private val googleMessageStateRepository: GoogleMessageStateRepository,
  96. private val backupRepository: BackupRepository
  97. ) {
  98. private var lastSend = 0L
  99. private var currentTaskId = 0
  100. private var requestMode = 1
  101. private lateinit var appState: StateFlow<AppState>
  102. private lateinit var appPreferences: StateFlow<AppPreferences>
  103. private lateinit var spoofedSimInfo: StateFlow<SpoofedSimInfo>
  104. init {
  105. CoroutineScope(Dispatchers.IO).launch {
  106. appState = appStateRepository.stateFlow()
  107. appPreferences = appPreferencesRepository.stateFlow()
  108. spoofedSimInfo = spoofedSimInfoRepository.stateFlow()
  109. }
  110. }
  111. suspend fun send(
  112. to: String,
  113. body: String,
  114. taskConfig: TaskConfig
  115. ): Boolean {
  116. Log.i(TAG, "Sending SMS to $to: $body")
  117. context.startActivity(smsIntent(to, body))
  118. try {
  119. Log.i(
  120. TAG,
  121. "Command executed successfully, waiting for app to open..."
  122. )
  123. delay(1000)
  124. var success = false
  125. var traverseResult = TraverseResult()
  126. withTimeoutOrNull(taskConfig.rcsWait) {
  127. while (true) {
  128. traverseResult = TraverseResult()
  129. screenInspector.traverseNode(traverseResult)
  130. if (traverseResult.isRcsCapable && traverseResult.sendBtn != null) {
  131. if (!taskConfig.endToEndEncryption || traverseResult.encrypted) {
  132. break
  133. }
  134. }
  135. delay(200)
  136. }
  137. }
  138. if (traverseResult.isRcsCapable) {
  139. if (traverseResult.sendBtn == null) {
  140. Log.i(TAG, "Send button not found")
  141. } else {
  142. Log.i(TAG, "Clicking send button")
  143. val dt = System.currentTimeMillis() - lastSend
  144. if (taskConfig.rcsInterval > 0 && dt < taskConfig.rcsInterval) {
  145. Log.i(TAG, "Waiting for RCS interval")
  146. delay(taskConfig.rcsInterval - dt)
  147. }
  148. traverseResult.sendBtn!!.performAction(AccessibilityNodeInfo.ACTION_CLICK)
  149. lastSend = System.currentTimeMillis()
  150. success = true
  151. }
  152. } else {
  153. Log.i(TAG, "RCS not detected")
  154. }
  155. appStateRepository.incrementExecutedNum(success)
  156. Log.i(
  157. TAG,
  158. "executedNum: ${appState.value.executedNum}, successNum: ${appState.value.successNum}"
  159. )
  160. delay(1000)
  161. return success
  162. } catch (e: Exception) {
  163. e.printStackTrace()
  164. }
  165. return false
  166. }
  167. suspend fun runTask(
  168. taskAction: TaskAction,
  169. onSuccess: (TaskExecutionResult) -> Unit,
  170. onError: (Exception) -> Unit
  171. ) {
  172. if (appState.value.busy) {
  173. onError(Exception("device busy"))
  174. return
  175. }
  176. try {
  177. val taskConfig = taskAction.data.config
  178. currentTaskId = taskAction.data.taskId
  179. requestMode = if (taskAction.data.config.useBackup) 2 else 1
  180. if (taskAction.data.config.checkConnection) {
  181. appStateRepository.updateRuntimeFlags(checkingConnection = true)
  182. if (!checkRcsAvailability()) {
  183. onError(Exception("RCS not available"))
  184. requestNumber()
  185. appStateRepository.updateRuntimeFlags(checkingConnection = false)
  186. return
  187. }
  188. appStateRepository.updateRuntimeFlags(checkingConnection = false)
  189. }
  190. appStateRepository.updateRuntimeFlags(running = true, checkingConnection = false)
  191. val success = ArrayList<Int>()
  192. val fail = ArrayList<Int>()
  193. for (i in 0 until taskAction.data.tasks.size) {
  194. val taskItem = taskAction.data.tasks[i]
  195. try {
  196. if (send(
  197. taskItem.number,
  198. taskItem.message,
  199. taskConfig
  200. )
  201. ) {
  202. success.add(taskItem.id)
  203. } else {
  204. fail.add(taskItem.id)
  205. }
  206. } catch (e: Exception) {
  207. Log.e(TAG, "runTaskError: ${e.message}", e)
  208. fail.add(taskItem.id)
  209. }
  210. }
  211. shellRun(CMD_BACK)
  212. onSuccess(TaskExecutionResult(success, fail))
  213. if (taskConfig.requestNumberInterval in 1..appState.value.successNum) {
  214. delay(3000)
  215. requestNumber()
  216. } else if (taskConfig.cleanCount in 1..appState.value.executedNum && !appPreferences.value.preventClean) {
  217. delay(3000)
  218. clearConv();
  219. shellRun(CMD_MESSAGING_APP)
  220. delay(3000)
  221. appStateRepository.resetExecutedNum()
  222. } else {
  223. delay(2000)
  224. }
  225. appStateRepository.updateRuntimeFlags(running = false)
  226. } catch (e: Exception) {
  227. Log.e(TAG, "runTaskError: ${e.message}", e)
  228. onError(e)
  229. appStateRepository.updateRuntimeFlags(running = false)
  230. }
  231. }
  232. suspend fun reset() {
  233. if (isOldVersion(context)) {
  234. withTimeout(1.hours) {
  235. while (true) {
  236. delay(100)
  237. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.RESET)
  238. googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
  239. spoofedSimInfoRepository.mock()
  240. resetAll()
  241. var switchAppear = googleMessageStateRepository.waitForRcsState(
  242. arrayOf(RcsConfigureState.WAITING_FOR_TOS),
  243. 2.minutes
  244. )?.let {
  245. it == RcsConfigureState.WAITING_FOR_TOS
  246. }
  247. if (switchAppear != true) {
  248. shellRun(
  249. PACKAGE_GMS.kill(), PACKAGE_MESSAGING.kill(), "sleep 1",
  250. CMD_MESSAGING_APP
  251. )
  252. switchAppear = googleMessageStateRepository.waitForRcsState(
  253. arrayOf(RcsConfigureState.WAITING_FOR_TOS),
  254. 5.minutes
  255. )?.let {
  256. it == RcsConfigureState.WAITING_FOR_TOS
  257. }
  258. if (switchAppear != true) {
  259. Log.e(
  260. TAG,
  261. "RCS not entered default on state, retrying..."
  262. )
  263. continue
  264. }
  265. }
  266. if (!screenController.toggleRcsSwitch(false)) {
  267. Log.e(TAG, "RCS switch not turned off, retrying...")
  268. continue
  269. }
  270. if (!screenController.toggleRcsSwitch(true)) {
  271. Log.e(TAG, "RCS switch not turned on, retrying...")
  272. continue
  273. }
  274. var resetSuccess = googleMessageStateRepository.waitForRcsState(
  275. arrayOf(
  276. RcsConfigureState.READY
  277. ), 30.seconds
  278. ).let { it == RcsConfigureState.READY }
  279. if (!resetSuccess) {
  280. screenController.toggleRcsSwitch(false)
  281. delay(1000)
  282. screenController.toggleRcsSwitch(true)
  283. resetSuccess = googleMessageStateRepository.waitForRcsState(
  284. arrayOf(
  285. RcsConfigureState.READY
  286. ), 1.minutes
  287. ).let { it == RcsConfigureState.READY }
  288. }
  289. Log.i(TAG, "waitForRcsState: $resetSuccess")
  290. appStateRepository.resetRequestedNum()
  291. if (resetSuccess) {
  292. delay(3000)
  293. break
  294. }
  295. }
  296. }
  297. } else {
  298. withTimeout(1.hours) {
  299. while (true) {
  300. delay(100)
  301. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.RESET)
  302. googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
  303. spoofedSimInfoRepository.mock()
  304. resetAll()
  305. var switchAppear = googleMessageStateRepository.waitForRcsState(
  306. arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
  307. 1.minutes
  308. )?.let {
  309. it == RcsConfigureState.WAITING_FOR_DEFAULT_ON
  310. }
  311. if (switchAppear != true) {
  312. shellRun(
  313. PACKAGE_GMS.kill(), PACKAGE_MESSAGING.kill(), "sleep 1",
  314. CMD_MESSAGING_APP
  315. )
  316. switchAppear = googleMessageStateRepository.waitForRcsState(
  317. arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
  318. 2.minutes
  319. )?.let {
  320. it == RcsConfigureState.WAITING_FOR_DEFAULT_ON
  321. }
  322. if (switchAppear != true) {
  323. Log.e(
  324. TAG,
  325. "RCS not entered default on state, retrying..."
  326. )
  327. continue
  328. }
  329. }
  330. val switchOn = screenController.toggleRcsSwitch(true)
  331. if (!switchOn) {
  332. Log.e(TAG, "RCS switch not turned on, retrying...")
  333. continue
  334. }
  335. var resetSuccess = googleMessageStateRepository.waitForRcsState(
  336. arrayOf(
  337. RcsConfigureState.READY
  338. ), 30.seconds
  339. ).let { it == RcsConfigureState.READY }
  340. if (!resetSuccess) {
  341. screenController.toggleRcsSwitch(false)
  342. delay(1000)
  343. screenController.toggleRcsSwitch(true)
  344. resetSuccess = googleMessageStateRepository.waitForRcsState(
  345. arrayOf(
  346. RcsConfigureState.READY
  347. ), 1.minutes
  348. ).let { it == RcsConfigureState.READY }
  349. }
  350. Log.i(TAG, "waitForRcsState: $resetSuccess")
  351. appStateRepository.resetRequestedNum()
  352. if (resetSuccess) {
  353. delay(3000)
  354. break
  355. }
  356. }
  357. }
  358. }
  359. }
  360. suspend fun requestNumber(
  361. reset: Boolean = false,
  362. noBackup: Boolean = false,
  363. fresh: Boolean = false
  364. ) {
  365. appStateRepository.updateRuntimeFlags(suspended = false)
  366. if (appPreferences.value.preventRequest) {
  367. return
  368. }
  369. if (appState.value.requesting) {
  370. return
  371. }
  372. appStateRepository.updateRuntimeFlags(requesting = true)
  373. if (spoofedSimInfo.value.available) {
  374. backupRepository.backup(
  375. spoofedSimInfo = spoofedSimInfo.value,
  376. type = "auto",
  377. sendCount = appState.value.executedNum,
  378. fresh = fresh
  379. )
  380. } else {
  381. clearConv();
  382. }
  383. appStateRepository.incrementRequestedNum()
  384. var requestSuccess = false
  385. var retry = 0
  386. var needRest = reset
  387. withTimeoutOrNull(2.hours) {
  388. while (true) {
  389. delay(200)
  390. needRest = needRest || retry > 2 || appState.value.requestedNum > 5
  391. try {
  392. val device =
  393. ktorClient(appPreferences.value.server).get(DeviceApi.Id(id = uniqueId))
  394. .body<DeviceResponse>()
  395. if (isClashInstalled(context)) {
  396. val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
  397. if (TextUtils.isEmpty(device.clashProfile)) {
  398. prefs.edit()
  399. .remove("clash_profile")
  400. .apply()
  401. stopClash()
  402. } else {
  403. val oldProfile = prefs.getString("clash_profile", "")
  404. if (oldProfile != device.clashProfile) {
  405. prefs.edit()
  406. .putString("clash_profile", device.clashProfile)
  407. .apply()
  408. changeClashProfile(
  409. device.pinCountry!!, Base64.encodeToString(
  410. device.clashProfile!!.toByteArray(),
  411. Base64.DEFAULT
  412. )
  413. )
  414. delay(5000)
  415. }
  416. }
  417. }
  418. if (requestMode == 2 && !noBackup) {
  419. val backup = backupRepository.findBackupForRestore(
  420. spoofedSimInfo.value.number,
  421. System.currentTimeMillis() - 2.days.inWholeMilliseconds
  422. )
  423. if (backup != null) {
  424. if (backupRepository.restore(backup)) {
  425. requestSuccess = true
  426. break
  427. } else {
  428. backupRepository.backup(
  429. spoofedSimInfo = spoofedSimInfo.value,
  430. type = "auto",
  431. sendCount = 0
  432. )
  433. continue
  434. }
  435. }
  436. }
  437. if (needRest && !appPreferences.value.preventReset) {
  438. reset()
  439. retry = 0
  440. needRest = false
  441. }
  442. googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
  443. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.REQUEST)
  444. val req = RcsNumberRequest(
  445. deviceId = uniqueId,
  446. taskId = currentTaskId
  447. )
  448. if (!TextUtils.isEmpty(device.pinCountry)) {
  449. req.country = device.pinCountry
  450. }
  451. val response = ktorClient(appPreferences.value.server).put(
  452. RcsNumberApi()
  453. ) {
  454. contentType(ContentType.Application.Json)
  455. setBody(req)
  456. timeout {
  457. requestTimeoutMillis = 60 * 1000
  458. socketTimeoutMillis = 60 * 1000
  459. }
  460. }
  461. var rcsNumber = response.body<RcsNumberResponse>()
  462. Log.i(TAG, "requestNumber response: $rcsNumber")
  463. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.OTP_1)
  464. spoofedSimInfoRepository.updateSpoofedSimInfo(
  465. SpoofedSimInfo(
  466. number = rcsNumber.number,
  467. mcc = rcsNumber.mcc,
  468. mnc = rcsNumber.mnc,
  469. iccid = genICCID(rcsNumber.mnc, rcsNumber.areaCode),
  470. imsi = genIMSI(rcsNumber.mcc + rcsNumber.mnc),
  471. imei = genIMEI(),
  472. country = rcsNumber.country,
  473. areaCode = rcsNumber.areaCode,
  474. available = false,
  475. carrierId = rcsNumber.carrierId,
  476. carrierName = rcsNumber.carrierName,
  477. )
  478. )
  479. shellRun(CMD_MESSAGING_APP)
  480. if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
  481. Log.e(TAG, "RCS number expired, retrying...")
  482. continue
  483. }
  484. var sendOtpTimeout = ChronoUnit.SECONDS.between(
  485. LocalDateTime.now(),
  486. rcsNumber.expiryTime
  487. ).seconds
  488. if (sendOtpTimeout < 60.seconds) {
  489. Log.e(TAG, "OTP timeout too short, retrying...")
  490. continue
  491. }
  492. if (sendOtpTimeout > 2.minutes) {
  493. sendOtpTimeout = 2.minutes
  494. }
  495. if (googleMessageStateRepository.waitForRcsState(
  496. arrayOf(RcsConfigureState.WAITING_FOR_OTP),
  497. sendOtpTimeout
  498. ) != RcsConfigureState.WAITING_FOR_OTP
  499. ) {
  500. if (!screenController.toggleRcsSwitch(true)) {
  501. needRest = true
  502. }
  503. if (RcsConfigureState.REPLAY_REQUEST == googleMessageStateRepository.rcsConfigureState.value) {
  504. Log.e(TAG, "REPLAY_REQUEST detected, may reset after 3 retry ($retry)")
  505. retry++
  506. }
  507. Log.e(TAG, "RCS not entered waiting for OTP state, retrying...")
  508. continue
  509. }
  510. launch {
  511. try {
  512. ktorClient(appPreferences.value.server).post(
  513. RcsNumberApi.Id.OtpState(
  514. RcsNumberApi.Id(
  515. RcsNumberApi(),
  516. rcsNumber.id
  517. )
  518. )
  519. )
  520. } catch (e: Exception) {
  521. Log.e(TAG, "Send OtpState Error: ${e.message}", e)
  522. }
  523. }
  524. if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
  525. Log.e(TAG, "RCS number expired, retrying...")
  526. continue
  527. }
  528. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.OTP_2)
  529. withTimeoutOrNull(60.seconds) {
  530. while (true) {
  531. try {
  532. rcsNumber =
  533. ktorClient(appPreferences.value.server).get(RcsNumberApi.Id(id = rcsNumber.id))
  534. .body<RcsNumberResponse>()
  535. Log.i(TAG, "wait for otp response: $rcsNumber")
  536. if (rcsNumber.status == RcsNumberResponse.STATUS_SUCCESS || rcsNumber.status == RcsNumberResponse.STATUS_EXPIRED) {
  537. break
  538. }
  539. } catch (exception: Exception) {
  540. Log.e(TAG, "wait for otp Error: ${exception.stackTrace}")
  541. }
  542. delay(2.seconds)
  543. }
  544. }
  545. if (rcsNumber.status != RcsNumberResponse.STATUS_SUCCESS) {
  546. Log.e(TAG, "OTP not received, retrying...")
  547. continue
  548. }
  549. val match =
  550. Regex("Your Messenger verification code is G-(\\d{6})")
  551. .find(rcsNumber.message!!)
  552. if (match != null) {
  553. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.CONFIG)
  554. val otp = match.groupValues[1]
  555. Log.i(TAG, "OTP: $otp")
  556. val sender = "3538"
  557. val msg = "Your Messenger verification code is G-$otp"
  558. val configured = run configuring@{
  559. repeat(2) {
  560. spoofSmsIntent(sender, msg)
  561. val state =
  562. googleMessageStateRepository.waitForRcsState(
  563. arrayOf(
  564. RcsConfigureState.CONFIGURED,
  565. RcsConfigureState.RETRY
  566. ), 60.seconds
  567. )
  568. when (state) {
  569. RcsConfigureState.CONFIGURED -> {
  570. return@configuring true
  571. }
  572. RcsConfigureState.RETRY -> {
  573. googleMessageStateRepository.waitForRcsState(
  574. arrayOf(RcsConfigureState.WAITING_FOR_OTP),
  575. 60.seconds
  576. )
  577. }
  578. else -> {
  579. Log.e(TAG, "verifyOtp fail, retrying...")
  580. }
  581. }
  582. }
  583. false
  584. }
  585. if (!configured) {
  586. Log.e(TAG, "RCS not configured, retrying...")
  587. continue
  588. } else {
  589. launch {
  590. try {
  591. ktorClient(appPreferences.value.server).post(
  592. RcsNumberApi.Id.Configured(
  593. RcsNumberApi.Id(
  594. RcsNumberApi(),
  595. rcsNumber.id
  596. )
  597. )
  598. )
  599. } catch (e: Exception) {
  600. Log.e(
  601. TAG,
  602. "Send ConfiguredState Error: ${e.message}",
  603. e
  604. )
  605. }
  606. }
  607. requestSuccess = true
  608. break
  609. }
  610. }
  611. } catch (e: Exception) {
  612. Log.e(TAG, "requestNumberError: ${e.message}", e)
  613. }
  614. }
  615. }
  616. if (requestSuccess) {
  617. spoofedSimInfoRepository.updateSpoofedSimInfo(
  618. spoofedSimInfo = spoofedSimInfo.value.copy(
  619. available = true
  620. )
  621. )
  622. appStateRepository.resetSuccessNum()
  623. appStateRepository.resetExecutedNum()
  624. Log.i(TAG, "requestNumber success")
  625. delay(5000)
  626. shellRun(PACKAGE_MESSAGING.kill(), "sleep 1", CMD_MESSAGING_APP)
  627. delay(2000)
  628. } else {
  629. Log.e(TAG, "requestNumber failed")
  630. appStateRepository.updateSend(false)
  631. }
  632. appStateRepository.updateRuntimeFlags(
  633. requesting = false,
  634. requestNumberState = RequestNumberState.IDLE,
  635. suspended = !requestSuccess
  636. )
  637. }
  638. private suspend fun checkRcsConnectivity(): Boolean = run checkRcsConnection@{
  639. repeat(3) {
  640. Log.i(TAG, "Checking RCS status...")
  641. shellRun(
  642. CMD_CONVERSATION_LIST_ACTIVITY,
  643. CMD_RCS_SETTINGS_ACTIVITY,
  644. "sleep 1",
  645. )
  646. val res = TraverseResult()
  647. screenInspector.traverseNode(res)
  648. if (res.rcsConnectionStatus == RcsConnectionStatus.CONNECTED) {
  649. Log.i(TAG, "RCS is connected")
  650. shellRun(CMD_BACK)
  651. return@checkRcsConnection true
  652. } else {
  653. Log.i(TAG, "RCS not connected, retrying...")
  654. }
  655. shellRun(CMD_BACK, "sleep ${it * 2}")
  656. }
  657. false
  658. }
  659. suspend fun checkRcsAvailability(): Boolean {
  660. val availability = run checkAvailability@{
  661. val rcsConnected = checkRcsConnectivity()
  662. if (!rcsConnected) {
  663. return@checkAvailability false
  664. }
  665. val checkRcsAvailabilityNumbers = mutableListOf<String>()
  666. try {
  667. val config = ktorClient(appPreferences.value.server).get(
  668. SysConfigApi.Id(
  669. SysConfigApi(),
  670. "check_availability_numbers"
  671. )
  672. )
  673. .body<SysConfigResponse>()
  674. Log.i(TAG, "sysConfig response: $config")
  675. checkRcsAvailabilityNumbers.addAll(
  676. config.value.split(",").map { it.trim() })
  677. } catch (exception: Exception) {
  678. Log.e(
  679. TAG,
  680. "sysConfig Error: ${exception.message}",
  681. exception
  682. )
  683. }
  684. if (checkRcsAvailabilityNumbers.isEmpty()) {
  685. Log.e(TAG, "checkRcsAvailabilityNumbers is empty")
  686. return@checkAvailability true
  687. }
  688. checkRcsAvailabilityNumbers.forEach {
  689. context.startActivity(smsIntent(it, ""))
  690. val s = withTimeoutOrNull(5.seconds) {
  691. while (true) {
  692. val traverseResult = TraverseResult()
  693. screenInspector.traverseNode(traverseResult)
  694. if (traverseResult.isRcsCapable) {
  695. return@withTimeoutOrNull true
  696. } else {
  697. Log.i(
  698. TAG,
  699. "checkRcsAvailability: RCS not detected"
  700. )
  701. }
  702. delay(200)
  703. }
  704. }
  705. if (s == true) {
  706. Log.i(TAG, "checkRcsAvailability: $it success")
  707. delay(1000)
  708. return@checkAvailability true
  709. }
  710. }
  711. false
  712. }
  713. return availability
  714. }
  715. suspend fun installApk(
  716. installApkAction: InstallApkAction,
  717. onSuccess: () -> Unit,
  718. onError: (Exception) -> Unit
  719. ) {
  720. try {
  721. val file = withContext(Dispatchers.IO) {
  722. File.createTempFile("files", ".apk")
  723. }
  724. HttpClient(OkHttp) {
  725. HttpResponseValidator {
  726. validateResponse { response ->
  727. if (response.status.value !in 200..299) {
  728. throw ServerResponseException(
  729. response,
  730. "Error " + response.status.value.toString()
  731. )
  732. }
  733. }
  734. }
  735. }.prepareGet(installApkAction.data.apkUrl)
  736. .execute { httpResponse ->
  737. val channel: ByteReadChannel = httpResponse.body()
  738. while (!channel.isClosedForRead) {
  739. val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
  740. while (!packet.isEmpty) {
  741. val bytes = packet.readBytes()
  742. file.appendBytes(bytes)
  743. }
  744. }
  745. }
  746. Log.i(TAG, "Apk file saved to ${file.path}")
  747. shellRun("pm install -d -r ${file.path}")
  748. onSuccess()
  749. file.delete()
  750. } catch (e: Exception) {
  751. Log.e("Modifier", "Failed to install apk", e)
  752. onError(e)
  753. }
  754. }
  755. suspend fun runScript(
  756. installApkAction: RunScriptAction,
  757. onSuccess: (String, String) -> Unit,
  758. onError: (Exception) -> Unit
  759. ) {
  760. try {
  761. val (out, err) = shellRun(*installApkAction.data.script.split("\n").toTypedArray())
  762. onSuccess(out, err)
  763. } catch (e: Exception) {
  764. Log.e("Modifier", "Failed to install apk", e)
  765. onError(e)
  766. }
  767. }
  768. }