ModifierService.kt 31 KB

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