ModifierService.kt 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  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.Context
  6. import android.content.Intent
  7. import android.graphics.PixelFormat
  8. import android.graphics.Rect
  9. import android.net.Uri
  10. import android.os.Build
  11. import android.os.Handler
  12. import android.os.Looper
  13. import android.util.DisplayMetrics
  14. import android.util.Log
  15. import android.view.Gravity
  16. import android.view.LayoutInflater
  17. import android.view.MotionEvent
  18. import android.view.View
  19. import android.view.View.OnTouchListener
  20. import android.view.WindowManager
  21. import android.view.accessibility.AccessibilityEvent
  22. import android.view.accessibility.AccessibilityNodeInfo
  23. import android.widget.CompoundButton
  24. import android.widget.FrameLayout
  25. import androidx.datastore.core.DataStore
  26. import androidx.datastore.preferences.core.Preferences
  27. import androidx.datastore.preferences.preferencesDataStore
  28. import androidx.lifecycle.MediatorLiveData
  29. import androidx.lifecycle.MutableLiveData
  30. import androidx.lifecycle.Observer
  31. import androidx.lifecycle.liveData
  32. import com.example.modifier.BuildConfig
  33. import com.example.modifier.Global
  34. import com.example.modifier.Global.load
  35. import com.example.modifier.Global.resetAll
  36. import com.example.modifier.R
  37. import com.example.modifier.TraverseResult
  38. import com.example.modifier.Utils
  39. import com.example.modifier.databinding.FloatingWindowBinding
  40. import com.example.modifier.enums.RcsConfigureState
  41. import com.example.modifier.extension.waitUntilValueIs
  42. import com.example.modifier.http.KtorClient
  43. import com.example.modifier.http.RcsNumberApi
  44. import com.example.modifier.http.request.RcsNumberRequest
  45. import com.example.modifier.http.response.RcsNumberResponse
  46. import com.example.modifier.model.TelephonyConfig
  47. import com.google.android.material.color.DynamicColors
  48. import io.ktor.client.call.body
  49. import io.ktor.client.plugins.resources.get
  50. import io.ktor.client.plugins.resources.put
  51. import io.ktor.client.request.setBody
  52. import io.ktor.http.ContentType
  53. import io.ktor.http.contentType
  54. import io.socket.client.IO
  55. import io.socket.client.Socket
  56. import io.socket.emitter.Emitter
  57. import kotlinx.coroutines.CoroutineScope
  58. import kotlinx.coroutines.Dispatchers
  59. import kotlinx.coroutines.delay
  60. import kotlinx.coroutines.isActive
  61. import kotlinx.coroutines.launch
  62. import kotlinx.coroutines.runBlocking
  63. import kotlinx.coroutines.suspendCancellableCoroutine
  64. import kotlinx.coroutines.withContext
  65. import kotlinx.coroutines.withTimeout
  66. import kotlinx.coroutines.withTimeoutOrNull
  67. import org.apache.commons.collections4.queue.CircularFifoQueue
  68. import org.apache.commons.lang3.RandomStringUtils
  69. import org.apache.commons.lang3.StringUtils
  70. import org.json.JSONArray
  71. import org.json.JSONException
  72. import org.json.JSONObject
  73. import java.util.Optional
  74. import java.util.concurrent.ScheduledExecutorService
  75. import java.util.concurrent.ScheduledThreadPoolExecutor
  76. import java.util.concurrent.TimeUnit
  77. import java.util.concurrent.atomic.AtomicReference
  78. import kotlin.coroutines.coroutineContext
  79. import kotlin.coroutines.resume
  80. import kotlin.math.max
  81. import kotlin.math.min
  82. import kotlin.time.Duration
  83. import kotlin.time.Duration.Companion.hours
  84. import kotlin.time.Duration.Companion.minutes
  85. import kotlin.time.Duration.Companion.seconds
  86. val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "serverConfig")
  87. @SuppressLint("SetTextI18n")
  88. class ModifierService : AccessibilityService(), Emitter.Listener {
  89. companion object {
  90. private const val TAG = "ModifierService"
  91. const val NAME: String = BuildConfig.APPLICATION_ID + ".service.ModifierService"
  92. @JvmStatic
  93. var instance: ModifierService? = null
  94. private set
  95. }
  96. private val handler = Handler(Looper.getMainLooper())
  97. private val mExecutor: ScheduledExecutorService = ScheduledThreadPoolExecutor(8)
  98. private val mSocketOpts = IO.Options()
  99. private lateinit var mSocket: Socket
  100. private lateinit var binding: FloatingWindowBinding
  101. private var canSend: Boolean
  102. get() {
  103. return getSharedPreferences(
  104. BuildConfig.APPLICATION_ID,
  105. MODE_PRIVATE
  106. ).getBoolean("canSend", false)
  107. }
  108. set(value) {
  109. getSharedPreferences(BuildConfig.APPLICATION_ID, MODE_PRIVATE).edit()
  110. .putBoolean("canSend", value).apply()
  111. reportDeviceStatues()
  112. }
  113. private var counter = 0
  114. private var cleanCount = 0
  115. private var lastSend = 0L
  116. private var rcsInterval = 0L
  117. private var requestNumberInterval = 0
  118. private val running = MutableLiveData(false)
  119. private val requesting = MutableLiveData(false)
  120. private var currentTaskId = 0
  121. private var busy = MediatorLiveData<Boolean>().apply {
  122. addSource(running) {
  123. value = it || requesting.value!!
  124. }
  125. addSource(requesting) {
  126. value = it || running.value!!
  127. }
  128. value = requesting.value!! || running.value!!
  129. }
  130. private val rcsConfigureState = MutableLiveData(RcsConfigureState.CONFIGURED)
  131. private var sendCount: Int
  132. get() {
  133. return getSharedPreferences(
  134. BuildConfig.APPLICATION_ID,
  135. MODE_PRIVATE
  136. ).getInt("sendCount", 0)
  137. }
  138. set(value) {
  139. getSharedPreferences(BuildConfig.APPLICATION_ID, MODE_PRIVATE).edit()
  140. .putInt("sendCount", value).apply()
  141. }
  142. private var requestNumberCount: Int
  143. get() {
  144. return getSharedPreferences(
  145. BuildConfig.APPLICATION_ID,
  146. MODE_PRIVATE
  147. ).getInt("requestNumberCount", 0)
  148. }
  149. set(value) {
  150. getSharedPreferences(BuildConfig.APPLICATION_ID, MODE_PRIVATE).edit()
  151. .putInt("requestNumberCount", value).apply()
  152. }
  153. private val logcat = liveData(Dispatchers.IO) {
  154. try {
  155. val logs = CircularFifoQueue<String>(128)
  156. val p = Runtime.getRuntime().exec("su")
  157. p.outputStream.bufferedWriter().use { writer ->
  158. writer.write("logcat -c")
  159. writer.newLine()
  160. writer.flush()
  161. writer.write("logcat BugleRcsEngine:D *:S -v time")
  162. writer.newLine()
  163. writer.flush()
  164. }
  165. p.inputStream
  166. .bufferedReader()
  167. .useLines { lines ->
  168. lines.forEach { line ->
  169. if (line.contains("destState=CheckPreconditionsState")) {
  170. rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
  171. } else if (line.contains("destState=ReadyState")) {
  172. rcsConfigureState.postValue(RcsConfigureState.READY)
  173. } else if (line.contains("destState=WaitingForOtpState")) {
  174. rcsConfigureState.postValue(RcsConfigureState.WAITING_FOR_OTP)
  175. } else if (line.contains("destState=VerifyOtpState")) {
  176. rcsConfigureState.postValue(RcsConfigureState.VERIFYING_OTP)
  177. } else if (line.contains("destState=ConfiguredState")) {
  178. rcsConfigureState.postValue(RcsConfigureState.CONFIGURED)
  179. } else if (line.contains("destState=WaitingForRcsDefaultOnState")) {
  180. rcsConfigureState.postValue(RcsConfigureState.WAITING_FOR_DEFAULT_ON)
  181. } else if (line.contains("destState=RetryState")) {
  182. rcsConfigureState.postValue(RcsConfigureState.RETRY)
  183. }
  184. Regex("(?<time>\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3}) I/BugleRcsEngine\\(\\W*\\d+\\): (?<log>.*)").matchEntire(
  185. line
  186. )?.apply {
  187. val time = groups["time"]?.value?.dropLast(4)
  188. val log = groups["log"]?.value
  189. ?.replace(Regex("\\[\\w+-\\w+-\\w+-\\w+-\\w+]"), "")
  190. ?.replace(Regex("\\[CONTEXT.*]"), "")
  191. ?.trim()
  192. if (time != null && log != null) {
  193. if (log.contains("destState=")) {
  194. logs.add("$time: $log")
  195. emit(logs.joinToString("\n"))
  196. delay(100)
  197. emit(logs.joinToString("\n"))
  198. }
  199. }
  200. }
  201. }
  202. }
  203. } catch (e: Exception) {
  204. e.printStackTrace()
  205. }
  206. }
  207. fun connect() {
  208. try {
  209. load()
  210. if (this@ModifierService::binding.isInitialized) {
  211. binding.swSend.text = Global.name
  212. }
  213. if (this@ModifierService::mSocket.isInitialized) {
  214. mSocket.disconnect()
  215. }
  216. mSocketOpts.query =
  217. "model=${Build.MANUFACTURER} ${Build.MODEL}&name=${Global.name}&id=${Utils.getUniqueID()}"
  218. mSocketOpts.transports = arrayOf("websocket")
  219. Log.i(TAG, "Connection query: ${mSocketOpts.query}")
  220. mSocket = IO.socket(Global.serverUrl, mSocketOpts)
  221. mSocket.on("message", this@ModifierService)
  222. mSocket.on(Socket.EVENT_CONNECT) {
  223. Log.i(TAG, "Connected to server")
  224. CoroutineScope(Dispatchers.IO).launch {
  225. delay(500)
  226. reportDeviceStatues()
  227. }
  228. }
  229. mSocket.on(Socket.EVENT_DISCONNECT) {
  230. Log.i(TAG, "Disconnected from server")
  231. }
  232. mSocket.on(Socket.EVENT_CONNECT_ERROR) { args ->
  233. Log.i(TAG, "Connection error: " + args[0])
  234. if (args[0] is Exception) {
  235. val e = args[0] as Exception
  236. e.printStackTrace()
  237. }
  238. }
  239. mSocket.connect()
  240. } catch (e: Exception) {
  241. e.printStackTrace()
  242. }
  243. }
  244. override fun onCreate() {
  245. super.onCreate()
  246. Log.i(TAG, "Starting ModifierService")
  247. connect()
  248. }
  249. override fun onAccessibilityEvent(event: AccessibilityEvent) {
  250. // traverseNode(getRootInActiveWindow(), new TraverseResult());
  251. }
  252. override fun onInterrupt() {
  253. }
  254. override fun call(vararg args: Any) {
  255. if (args.isNotEmpty()) {
  256. Log.i(TAG, "Received message: " + args[0])
  257. if (args[0] is JSONObject) {
  258. val json = args[0] as JSONObject
  259. val action = json.optString("action")
  260. if ("send" == action) {
  261. val data = json.optJSONObject("data")
  262. if (data != null) {
  263. val to = data.optString("to")
  264. val body = data.optString("body")
  265. send(to, body, 2000)
  266. }
  267. } else if ("task" == action) {
  268. val data = json.optJSONObject("data")
  269. val id = json.optString("id")
  270. if (data != null && StringUtils.isNoneBlank(id)) {
  271. runTask(id, data)
  272. }
  273. } else if ("changeNumber" == action) {
  274. }
  275. }
  276. }
  277. }
  278. private fun runTask(id: String, data: JSONObject) {
  279. val config = data.optJSONObject("config")
  280. config!!
  281. val rcsWait = config.optLong("rcsWait", 2000)
  282. cleanCount = config.optInt("cleanCount", 20)
  283. rcsInterval = config.optLong("rcsInterval", 0)
  284. requestNumberInterval = config.optInt("requestNumberInterval", 0)
  285. val tasks = data.optJSONArray("tasks")!!
  286. currentTaskId = data.optInt("taskId", 0)
  287. mExecutor.submit {
  288. running.postValue(true)
  289. val success = JSONArray()
  290. val fail = JSONArray()
  291. for (i in 0 until tasks.length()) {
  292. val task = tasks.optJSONObject(i)
  293. val to = task.optString("number")
  294. val body = task.optString("message")
  295. val taskId = task.optInt("id")
  296. try {
  297. if (send(to, body, rcsWait)) {
  298. success.put(taskId)
  299. } else {
  300. fail.put(taskId)
  301. }
  302. } catch (e: Exception) {
  303. e.printStackTrace()
  304. fail.put(taskId)
  305. }
  306. }
  307. val res = JSONObject()
  308. try {
  309. res.put("id", id)
  310. res.put("status", 0)
  311. res.put(
  312. "data", JSONObject()
  313. .put("success", success)
  314. .put("fail", fail)
  315. )
  316. } catch (e: JSONException) {
  317. }
  318. mSocket.emit("callback", res)
  319. if (requestNumberInterval in 1..sendCount) {
  320. runBlocking {
  321. requestNumber()
  322. }
  323. }
  324. running.postValue(false)
  325. }
  326. }
  327. private fun send(to: String, body: String, rcsWait: Long): Boolean {
  328. Log.i(TAG, "Sending SMS to $to: $body")
  329. val intent = Intent(Intent.ACTION_SENDTO)
  330. intent.setData(Uri.parse("sms:$to"))
  331. intent.putExtra("sms_body", body)
  332. intent.putExtra("exit_on_sent", true)
  333. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
  334. startActivity(intent)
  335. try {
  336. Log.i(TAG, "Command executed successfully, waiting for app to open...")
  337. val f = mExecutor.schedule<Boolean>(
  338. {
  339. var success = false
  340. val ts = System.currentTimeMillis()
  341. while (System.currentTimeMillis() - ts < rcsWait) {
  342. val root = rootInActiveWindow
  343. val packageName = root.packageName.toString()
  344. val traverseResult = TraverseResult()
  345. traverseNode(root, traverseResult)
  346. if (traverseResult.isRcsCapable) {
  347. if (traverseResult.sendBtn == null) {
  348. Log.i(TAG, "Send button not found")
  349. } else {
  350. Log.i(TAG, "Clicking send button")
  351. val dt = System.currentTimeMillis() - lastSend
  352. if (rcsInterval > 0 && dt < rcsInterval) {
  353. Log.i(TAG, "Waiting for RCS interval")
  354. Thread.sleep(rcsInterval - dt)
  355. }
  356. traverseResult.sendBtn.performAction(AccessibilityNodeInfo.ACTION_CLICK)
  357. lastSend = System.currentTimeMillis()
  358. success = true
  359. sendCount++
  360. break
  361. }
  362. } else {
  363. Log.i(TAG, "RCS not detected")
  364. }
  365. try {
  366. Thread.sleep(500)
  367. } catch (e: InterruptedException) {
  368. e.printStackTrace()
  369. }
  370. }
  371. counter++
  372. Log.i(
  373. TAG,
  374. "sendCount: $sendCount, Counter: $counter, cleanCount: $cleanCount, requestNumberInterval: $requestNumberInterval"
  375. )
  376. if (cleanCount in 1..counter) {
  377. counter = 0
  378. Thread.sleep(2000)
  379. Global.clearConv();
  380. Thread.sleep(2000)
  381. }
  382. success
  383. }, 1000, TimeUnit.MILLISECONDS
  384. )
  385. synchronized(f) {
  386. Log.i(TAG, "Waiting for task to complete...")
  387. return f.get()
  388. }
  389. } catch (e: Exception) {
  390. e.printStackTrace()
  391. }
  392. return false
  393. }
  394. private fun traverseNode(node: AccessibilityNodeInfo?, result: TraverseResult) {
  395. if (node == null) {
  396. return
  397. }
  398. val className = node.className.toString()
  399. val name = node.viewIdResourceName
  400. val text = Optional.ofNullable(node.text).map { obj: CharSequence -> obj.toString() }
  401. .orElse(null)
  402. val id = node.viewIdResourceName
  403. Log.d(TAG, "Node: class=$className, text=$text, name=$name, id=$id")
  404. if ("Compose:Draft:Send" == name) {
  405. result.sendBtn = node
  406. }
  407. if ("com.google.android.apps.messaging:id/send_message_button_icon" == id) {
  408. result.sendBtn = node
  409. }
  410. if (text != null && (text.contains("RCS 聊天") || text.contains("RCS chat"))) {
  411. result.isRcsCapable = true
  412. }
  413. if (text != null && (text.contains("Turn on RCS chats") || text.contains("开启 RCS 聊天功能"))) {
  414. fun findSwitch(node: AccessibilityNodeInfo): Boolean {
  415. if ("com.google.android.apps.messaging:id/switchWidget" == node.viewIdResourceName) {
  416. result.rcsSwitch = node
  417. return true
  418. }
  419. for (i in 0 until node.childCount) {
  420. val child = node.getChild(i)
  421. if (findSwitch(child)) {
  422. return true
  423. }
  424. }
  425. return false
  426. }
  427. findSwitch(node.parent.parent)
  428. }
  429. if (node.childCount != 0) {
  430. for (i in 0 until node.childCount) {
  431. traverseNode(node.getChild(i), result)
  432. }
  433. }
  434. }
  435. @SuppressLint("ClickableViewAccessibility")
  436. override fun onServiceConnected() {
  437. super.onServiceConnected()
  438. instance = this
  439. val info = AccessibilityServiceInfo()
  440. info.flags =
  441. AccessibilityServiceInfo.DEFAULT or AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS
  442. info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
  443. info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN
  444. info.notificationTimeout = 100
  445. this.serviceInfo = info
  446. val displayMetrics = DisplayMetrics()
  447. val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
  448. windowManager.defaultDisplay.getMetrics(displayMetrics)
  449. val height = displayMetrics.heightPixels
  450. val width = displayMetrics.widthPixels
  451. val mLayout = FrameLayout(this)
  452. val layoutParams = WindowManager.LayoutParams()
  453. layoutParams.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
  454. layoutParams.format = PixelFormat.TRANSLUCENT
  455. layoutParams.flags = layoutParams.flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
  456. layoutParams.flags = layoutParams.flags or WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
  457. layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT
  458. layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
  459. layoutParams.x = 0
  460. layoutParams.y = 800
  461. layoutParams.gravity = Gravity.START or Gravity.TOP
  462. val newContext = DynamicColors.wrapContextIfAvailable(applicationContext, R.style.AppTheme)
  463. val inflater = LayoutInflater.from(newContext)
  464. binding = FloatingWindowBinding.inflate(inflater, mLayout, true)
  465. binding.swSend.text = Global.name
  466. windowManager.addView(mLayout, layoutParams)
  467. val maxX = width - binding.root.measuredWidth
  468. val maxY = height - binding.root.measuredHeight
  469. val downX = AtomicReference(0f)
  470. val downY = AtomicReference(0f)
  471. val downParamX = AtomicReference(0)
  472. val downParamY = AtomicReference(0)
  473. val touchListener = OnTouchListener { v, event ->
  474. when (event.action) {
  475. MotionEvent.ACTION_DOWN -> {
  476. downX.set(event.rawX)
  477. downY.set(event.rawY)
  478. downParamX.set(layoutParams.x)
  479. downParamY.set(layoutParams.y)
  480. }
  481. MotionEvent.ACTION_MOVE -> {
  482. layoutParams.x = min(
  483. max((downParamX.get() + (event.rawX - downX.get())).toDouble(), 0.0),
  484. maxX.toDouble()
  485. )
  486. .toInt()
  487. layoutParams.y = min(
  488. max((downParamY.get() + (event.rawY - downY.get())).toDouble(), 0.0),
  489. maxY.toDouble()
  490. )
  491. .toInt()
  492. windowManager.updateViewLayout(mLayout, layoutParams)
  493. }
  494. MotionEvent.ACTION_UP -> {
  495. return@OnTouchListener event.eventTime - event.downTime >= 200
  496. }
  497. }
  498. false
  499. }
  500. binding.swSend.setOnTouchListener(touchListener)
  501. binding.swConnect.isChecked = true
  502. binding.swConnect.setOnCheckedChangeListener { buttonView: CompoundButton?, isChecked: Boolean ->
  503. if (isChecked) {
  504. connect()
  505. } else {
  506. if (this::mSocket.isInitialized) {
  507. mSocket.disconnect()
  508. }
  509. }
  510. }
  511. binding.swSend.isChecked = canSend
  512. binding.swSend.setOnCheckedChangeListener { buttonView: CompoundButton?, isChecked: Boolean ->
  513. canSend = isChecked
  514. }
  515. logcat.observeForever {
  516. binding.tvLog.text = it
  517. binding.scroll.fullScroll(View.FOCUS_DOWN)
  518. }
  519. requesting.observeForever {
  520. binding.btnReq.isEnabled = !it
  521. }
  522. binding.btnReq.setOnClickListener {
  523. requestNumberCount = 6
  524. CoroutineScope(Dispatchers.IO).launch {
  525. requestNumber()
  526. }
  527. }
  528. binding.btnInspect.setOnClickListener {
  529. CoroutineScope(Dispatchers.IO).launch {
  530. traverseNode(rootInActiveWindow, TraverseResult())
  531. }
  532. }
  533. busy.observeForever {
  534. reportDeviceStatues()
  535. }
  536. }
  537. private fun reportDeviceStatues() {
  538. if (this::mSocket.isInitialized) {
  539. val data = JSONObject()
  540. try {
  541. data.put("action", "updateDevice")
  542. val dataObj = JSONObject()
  543. dataObj.put("canSend", canSend)
  544. dataObj.put("busy", busy.value)
  545. data.put("data", dataObj)
  546. mSocket.emit("message", data)
  547. } catch (e: JSONException) {
  548. e.printStackTrace()
  549. }
  550. }
  551. }
  552. private suspend fun waitForRcsState(
  553. states: Array<RcsConfigureState>,
  554. timeout: Duration
  555. ): RcsConfigureState? {
  556. var state: RcsConfigureState? = null
  557. withTimeoutOrNull(timeout) {
  558. withContext(Dispatchers.Main) {
  559. suspendCancellableCoroutine { continuation ->
  560. val observer = Observer<RcsConfigureState> { value ->
  561. if (states.contains(value)) {
  562. state = value
  563. if (isActive)
  564. continuation.resume(Unit)
  565. }
  566. }
  567. rcsConfigureState.observeForever(observer)
  568. continuation.invokeOnCancellation {
  569. handler.post {
  570. Log.i(TAG, "removeObserver")
  571. rcsConfigureState.removeObserver(observer)
  572. }
  573. }
  574. }
  575. }
  576. false
  577. }
  578. return state
  579. }
  580. private suspend fun requestNumber() {
  581. requestNumberCount++
  582. requesting.postValue(true)
  583. val result = withTimeoutOrNull(1.hours) {
  584. while (true) {
  585. withContext(Dispatchers.Main) {
  586. binding.tvLog.text = "Waiting for logs..."
  587. }
  588. var rcsRes: RcsNumberResponse? = null
  589. rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
  590. withTimeoutOrNull(10.minutes) {
  591. while (true) {
  592. try {
  593. val response = KtorClient.put(
  594. RcsNumberApi()
  595. ) {
  596. contentType(ContentType.Application.Json)
  597. setBody(
  598. RcsNumberRequest(
  599. deviceId = Utils.getUniqueID(),
  600. taskId = currentTaskId
  601. )
  602. )
  603. }
  604. rcsRes = response.body<RcsNumberResponse>()
  605. Log.i(TAG, "requestNumber response: $rcsRes")
  606. break
  607. } catch (exception: Exception) {
  608. exception.printStackTrace()
  609. delay(2000)
  610. }
  611. }
  612. }
  613. if (rcsRes == null) {
  614. Log.e(TAG, "requestNumber fail, retrying...")
  615. continue
  616. }
  617. Global.save(
  618. TelephonyConfig(
  619. rcsRes!!.number,
  620. rcsRes!!.mcc,
  621. rcsRes!!.mnc,
  622. RandomStringUtils.randomNumeric(20),
  623. rcsRes!!.mcc + rcsRes!!.mnc + RandomStringUtils.randomNumeric(
  624. 15 - rcsRes!!.mcc.length - rcsRes!!.mnc.length
  625. ),
  626. Utils.generateIMEI(),
  627. rcsRes!!.country
  628. )
  629. )
  630. var otpTimeout = 60.seconds
  631. if (requestNumberCount > 5) {
  632. otpTimeout = 60.seconds
  633. val resetSuccess = withTimeoutOrNull(5.minutes) {
  634. while (true) {
  635. withContext(Dispatchers.Main) {
  636. binding.tvLog.text = "Waiting for logs..."
  637. }
  638. rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
  639. resetAll()
  640. val switchAppear = withTimeoutOrNull(60.seconds) {
  641. while (true) {
  642. if (rcsConfigureState.value == RcsConfigureState.WAITING_FOR_DEFAULT_ON) {
  643. break
  644. }
  645. delay(1.seconds)
  646. }
  647. true
  648. } ?: false
  649. if (!switchAppear) {
  650. Log.e(TAG, "RCS not entered default on state, retrying...")
  651. continue
  652. }
  653. Utils.runAsRoot(
  654. "am start com.google.android.apps.messaging/com.google.android.apps.messaging.ui.appsettings.RcsSettingsActivity",
  655. "sleep 1"
  656. )
  657. val res = TraverseResult()
  658. traverseNode(rootInActiveWindow, res)
  659. if (res.rcsSwitch == null) {
  660. Log.e(TAG, "RCS switch not found, retrying...")
  661. continue
  662. }
  663. val rect = Rect()
  664. res.rcsSwitch.getBoundsInScreen(rect)
  665. Utils.runAsRoot(
  666. "input tap ${rect.centerX()} ${rect.centerY()}",
  667. "sleep 1",
  668. "input keyevent KEYCODE_BACK",
  669. "am start com.google.android.apps.messaging/com.google.android.apps.messaging.ui.appsettings.RcsSettingsActivity",
  670. )
  671. Log.i(TAG, "RCS switch turned on, waiting for state change...")
  672. val resetSuccess = waitForRcsState(
  673. arrayOf(
  674. RcsConfigureState.READY,
  675. RcsConfigureState.RETRY
  676. ), 60.seconds
  677. )
  678. Log.i(TAG, "waitForRcsState: $resetSuccess")
  679. requestNumberCount = 0
  680. break
  681. }
  682. true
  683. } ?: false
  684. if (!resetSuccess) {
  685. Log.e(TAG, "RCS reset failed, retrying...")
  686. continue
  687. }
  688. } else {
  689. Global.revealMessaging()
  690. }
  691. if (waitForRcsState(
  692. arrayOf(RcsConfigureState.WAITING_FOR_OTP),
  693. otpTimeout
  694. ) != RcsConfigureState.WAITING_FOR_OTP
  695. ) {
  696. Log.e(TAG, "RCS not entered waiting for OTP state, retrying...")
  697. continue
  698. }
  699. withTimeoutOrNull(60.seconds) {
  700. while (true) {
  701. try {
  702. rcsRes = KtorClient.get(RcsNumberApi.Id(id = rcsRes!!.id))
  703. .body<RcsNumberResponse>()
  704. Log.i(TAG, "wait for otp response: $rcsRes")
  705. if (rcsRes!!.status == RcsNumberResponse.STATUS_SUCCESS) {
  706. break
  707. }
  708. } catch (exception: Exception) {
  709. Log.e(TAG, "wait for otp Error: ${exception.stackTrace}")
  710. }
  711. delay(2.seconds)
  712. }
  713. }
  714. if (rcsRes!!.status != RcsNumberResponse.STATUS_SUCCESS) {
  715. Log.e(TAG, "OTP not received, retrying...")
  716. continue
  717. }
  718. val match =
  719. Regex("Your Messenger verification code is G-(\\d{6})")
  720. .matchEntire(rcsRes!!.message!!)
  721. if (match != null) {
  722. val otp = match.groupValues[1]
  723. Log.i(TAG, "OTP: $otp")
  724. val intent = Intent()
  725. intent.setAction("com.example.modifier.sms")
  726. intent.putExtra("sender", "3538")
  727. intent.putExtra(
  728. "message",
  729. "Your Messenger verification code is G-$otp"
  730. )
  731. val configured = run a@{
  732. repeat(2) {
  733. sendBroadcast(intent)
  734. val state =
  735. waitForRcsState(
  736. arrayOf(
  737. RcsConfigureState.CONFIGURED,
  738. RcsConfigureState.RETRY
  739. ), 60.seconds
  740. )
  741. if (state == RcsConfigureState.CONFIGURED) {
  742. return@a true
  743. } else if (state == RcsConfigureState.RETRY) {
  744. waitForRcsState(
  745. arrayOf(RcsConfigureState.WAITING_FOR_OTP),
  746. 60.seconds
  747. )
  748. } else {
  749. Log.e(TAG, "verifyOtp fail, retrying...")
  750. }
  751. }
  752. false
  753. }
  754. if (!configured) {
  755. Log.e(TAG, "RCS not configured, retrying...")
  756. continue
  757. } else {
  758. break
  759. }
  760. }
  761. }
  762. true
  763. } ?: false
  764. requesting.postValue(false)
  765. if (result) {
  766. sendCount = 0
  767. counter = 0
  768. Log.i(TAG, "requestNumber success")
  769. } else {
  770. Log.e(TAG, "requestNumber failed")
  771. }
  772. }
  773. }