TaskRunner.kt 34 KB

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