ModifierService.kt 55 KB

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