ModifierService.kt 47 KB

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