ModifierService.kt 56 KB

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