ModifierService.kt 59 KB

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