|
|
@@ -27,9 +27,6 @@ import android.widget.FrameLayout
|
|
|
import androidx.annotation.MenuRes
|
|
|
import androidx.appcompat.widget.PopupMenu
|
|
|
import androidx.core.content.ContextCompat
|
|
|
-import androidx.lifecycle.MutableLiveData
|
|
|
-import androidx.lifecycle.Observer
|
|
|
-import androidx.lifecycle.liveData
|
|
|
import com.example.modifier.BuildConfig
|
|
|
import com.example.modifier.Global
|
|
|
import com.example.modifier.Global.backup
|
|
|
@@ -49,33 +46,36 @@ import com.example.modifier.data.AppPreferencesRepository
|
|
|
import com.example.modifier.data.AppState
|
|
|
import com.example.modifier.data.AppStateRepository
|
|
|
import com.example.modifier.data.BackupItemDao
|
|
|
+import com.example.modifier.data.GoogleMessageStateRepository
|
|
|
import com.example.modifier.databinding.FloatingWindowBinding
|
|
|
import com.example.modifier.enums.RcsConfigureState
|
|
|
import com.example.modifier.enums.RcsConnectionStatus
|
|
|
import com.example.modifier.extension.kill
|
|
|
-import com.example.modifier.utils.hasRootAccess
|
|
|
-import com.example.modifier.http.ktorClient
|
|
|
import com.example.modifier.http.api.DeviceApi
|
|
|
import com.example.modifier.http.api.RcsNumberApi
|
|
|
import com.example.modifier.http.api.SysConfigApi
|
|
|
+import com.example.modifier.http.ktorClient
|
|
|
import com.example.modifier.http.request.RcsNumberRequest
|
|
|
import com.example.modifier.http.response.DeviceResponse
|
|
|
import com.example.modifier.http.response.RcsNumberResponse
|
|
|
import com.example.modifier.http.response.SysConfigResponse
|
|
|
import com.example.modifier.model.InstallApkAction
|
|
|
+import com.example.modifier.model.SimInfo
|
|
|
import com.example.modifier.model.SocketCallback
|
|
|
import com.example.modifier.model.TaskAction
|
|
|
import com.example.modifier.model.TaskConfig
|
|
|
import com.example.modifier.model.TaskExecutionResult
|
|
|
-import com.example.modifier.model.SimInfo
|
|
|
import com.example.modifier.serializer.Json
|
|
|
import com.example.modifier.utils.changeClashProfile
|
|
|
import com.example.modifier.utils.clearConv
|
|
|
+import com.example.modifier.utils.hasRootAccess
|
|
|
import com.example.modifier.utils.isClashInstalled
|
|
|
import com.example.modifier.utils.isOldVersion
|
|
|
import com.example.modifier.utils.isRebooted
|
|
|
+import com.example.modifier.utils.killPhoneProcess
|
|
|
import com.example.modifier.utils.optimize
|
|
|
import com.example.modifier.utils.resetAll
|
|
|
+import com.example.modifier.utils.setBatteryLevel
|
|
|
import com.example.modifier.utils.shellRun
|
|
|
import com.example.modifier.utils.smsIntent
|
|
|
import com.example.modifier.utils.stopClash
|
|
|
@@ -105,14 +105,11 @@ import kotlinx.coroutines.CoroutineScope
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
import kotlinx.coroutines.delay
|
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
|
-import kotlinx.coroutines.isActive
|
|
|
import kotlinx.coroutines.launch
|
|
|
-import kotlinx.coroutines.suspendCancellableCoroutine
|
|
|
import kotlinx.coroutines.withContext
|
|
|
import kotlinx.coroutines.withTimeout
|
|
|
import kotlinx.coroutines.withTimeoutOrNull
|
|
|
import kotlinx.serialization.encodeToString
|
|
|
-import org.apache.commons.collections4.queue.CircularFifoQueue
|
|
|
import org.apache.commons.lang3.RandomStringUtils
|
|
|
import org.json.JSONException
|
|
|
import org.json.JSONObject
|
|
|
@@ -123,10 +120,8 @@ import java.util.Optional
|
|
|
import java.util.Timer
|
|
|
import java.util.TimerTask
|
|
|
import java.util.concurrent.atomic.AtomicReference
|
|
|
-import kotlin.coroutines.resume
|
|
|
import kotlin.math.max
|
|
|
import kotlin.math.min
|
|
|
-import kotlin.time.Duration
|
|
|
import kotlin.time.Duration.Companion.hours
|
|
|
import kotlin.time.Duration.Companion.minutes
|
|
|
import kotlin.time.Duration.Companion.seconds
|
|
|
@@ -150,67 +145,6 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
private var currentTaskId = 0
|
|
|
private var lastSend = 0L
|
|
|
|
|
|
- private val rcsConfigureState = MutableLiveData(RcsConfigureState.CONFIGURED)
|
|
|
- private val logcat = liveData(Dispatchers.IO) {
|
|
|
- try {
|
|
|
- val logs = CircularFifoQueue<String>(128)
|
|
|
- val p = Runtime.getRuntime().exec("su")
|
|
|
- p.outputStream.bufferedWriter().use { writer ->
|
|
|
- writer.write("logcat -c")
|
|
|
- writer.newLine()
|
|
|
- writer.flush()
|
|
|
- writer.write("logcat BugleRcsEngine:D *:S -v time")
|
|
|
- writer.newLine()
|
|
|
- writer.flush()
|
|
|
- }
|
|
|
- p.inputStream
|
|
|
- .bufferedReader()
|
|
|
- .useLines { lines ->
|
|
|
- lines.forEach { line ->
|
|
|
- if (line.contains("destState=CheckPreconditionsState")) {
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
|
|
|
- } else if (line.contains("destState=ReadyState")) {
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.READY)
|
|
|
- } else if (line.contains("destState=WaitingForOtpState")) {
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.WAITING_FOR_OTP)
|
|
|
- } else if (line.contains("destState=VerifyOtpState")) {
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.VERIFYING_OTP)
|
|
|
- } else if (line.contains("destState=ConfiguredState")) {
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.CONFIGURED)
|
|
|
- } else if (line.contains("destState=WaitingForRcsDefaultOnState")) {
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.WAITING_FOR_DEFAULT_ON)
|
|
|
- } else if (line.contains("destState=WaitingForGoogleTosState")) {
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.WAITING_FOR_TOS)
|
|
|
- } else if (line.contains("destState=RetryState")) {
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.RETRY)
|
|
|
- } else if (line.contains("destState=ReplayRequestState")) {
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.REPLAY_REQUEST)
|
|
|
- }
|
|
|
- Regex("(?<time>\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3}) I/BugleRcsEngine\\(\\W*\\d+\\): (?<log>.*)")
|
|
|
- .matchEntire(line)
|
|
|
- ?.apply {
|
|
|
- val time = groups["time"]?.value?.dropLast(4)
|
|
|
- val log = groups["log"]?.value
|
|
|
- ?.replace(Regex("\\[\\w+-\\w+-\\w+-\\w+-\\w+]"), "")
|
|
|
- ?.replace(Regex("\\[CONTEXT.*]"), "")
|
|
|
- ?.trim()
|
|
|
-
|
|
|
- if (time != null && log != null) {
|
|
|
- if (log.contains("destState=")) {
|
|
|
- logs.add("$time: $log")
|
|
|
- emit(logs.joinToString("\n"))
|
|
|
- delay(100)
|
|
|
- emit(logs.joinToString("\n"))
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (e: Exception) {
|
|
|
- e.printStackTrace()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private val backupItemDao: BackupItemDao by lazy {
|
|
|
AppDatabase.getDatabase(this).itemDao()
|
|
|
}
|
|
|
@@ -222,8 +156,17 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
AppStateRepository(this)
|
|
|
}
|
|
|
private lateinit var appState: StateFlow<AppState>
|
|
|
+ private val googleMessageStateRepository: GoogleMessageStateRepository by lazy {
|
|
|
+ GoogleMessageStateRepository(this)
|
|
|
+ }
|
|
|
private var requestMode = 1;
|
|
|
private var currentActivity = ""
|
|
|
+ private val screenInspector: ScreenInspector by lazy {
|
|
|
+ ScreenInspector(this)
|
|
|
+ }
|
|
|
+ private val screenController: ScreenController by lazy {
|
|
|
+ ScreenController(this, screenInspector)
|
|
|
+ }
|
|
|
|
|
|
fun connect() {
|
|
|
try {
|
|
|
@@ -278,6 +221,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
if (!hasRoot) {
|
|
|
System.exit(0)
|
|
|
}
|
|
|
+ googleMessageStateRepository.startLogging()
|
|
|
if (isRebooted()) {
|
|
|
delay(2.minutes)
|
|
|
} else {
|
|
|
@@ -286,7 +230,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
optimize()
|
|
|
syncTime()
|
|
|
if (Build.MODEL.startsWith("SM-F707") || Build.MODEL.startsWith("SM-F711")) {
|
|
|
- Global.killPhoneProcess(force = false)
|
|
|
+ killPhoneProcess(force = false)
|
|
|
}
|
|
|
appStateRepository.updateRuntimeFlags(preparing = false)
|
|
|
|
|
|
@@ -297,11 +241,19 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
reportDeviceStatues()
|
|
|
}
|
|
|
}, 0, 3.seconds.inWholeMilliseconds)
|
|
|
- timer.schedule(object : TimerTask() {
|
|
|
- override fun run() {
|
|
|
-
|
|
|
- }
|
|
|
- }, 0, 30.minutes.inWholeMilliseconds)
|
|
|
+ if (Build.MODEL.startsWith("SM-F707") || Build.MODEL.startsWith("SM-F711")) {
|
|
|
+ timer.schedule(object : TimerTask() {
|
|
|
+ override fun run() {
|
|
|
+ CoroutineScope(Dispatchers.IO).launch {
|
|
|
+ try {
|
|
|
+ setBatteryLevel(100)
|
|
|
+ } catch (e: Exception) {
|
|
|
+ e.printStackTrace()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, 0, 30.minutes.inWholeMilliseconds)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -556,18 +508,11 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
var traverseResult = TraverseResult()
|
|
|
withTimeoutOrNull(taskConfig.rcsWait) {
|
|
|
while (true) {
|
|
|
- val root = rootInActiveWindow
|
|
|
traverseResult = TraverseResult()
|
|
|
- traverseNode(root, traverseResult)
|
|
|
- if (traverseResult.isRcsCapable) {
|
|
|
- if (traverseResult.sendBtn != null) {
|
|
|
- if (taskConfig.endToEndEncryption) {
|
|
|
- if (traverseResult.encrypted) {
|
|
|
- break
|
|
|
- }
|
|
|
- } else {
|
|
|
- break
|
|
|
- }
|
|
|
+ screenInspector.traverseNode(traverseResult)
|
|
|
+ if (traverseResult.isRcsCapable && traverseResult.sendBtn != null) {
|
|
|
+ if (!taskConfig.endToEndEncryption || traverseResult.encrypted) {
|
|
|
+ break
|
|
|
}
|
|
|
}
|
|
|
delay(200)
|
|
|
@@ -604,110 +549,12 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
- fun getNodes(node: AccessibilityNodeInfo? = null): List<AccessibilityNodeInfo> {
|
|
|
- fun traverseChildren(node: AccessibilityNodeInfo): List<AccessibilityNodeInfo> {
|
|
|
- val result = mutableListOf<AccessibilityNodeInfo>()
|
|
|
- for (i in 0 until node.childCount) {
|
|
|
- val child = node.getChild(i)
|
|
|
- result.add(child)
|
|
|
- result.addAll(traverseChildren(child))
|
|
|
- }
|
|
|
- return result
|
|
|
- }
|
|
|
- return traverseChildren(node ?: rootInActiveWindow)
|
|
|
- }
|
|
|
-
|
|
|
- private fun traverseNode(node: AccessibilityNodeInfo?, result: TraverseResult) {
|
|
|
- if (node == null) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- val packageInfo = packageManager.getPackageInfo(
|
|
|
- node.packageName.toString(), 0
|
|
|
- )
|
|
|
-
|
|
|
- val className = node.className.toString()
|
|
|
- val name = node.viewIdResourceName
|
|
|
- val text = Optional.ofNullable(node.text).map { obj: CharSequence -> obj.toString() }
|
|
|
- .orElse(null)
|
|
|
- val id = node.viewIdResourceName
|
|
|
-
|
|
|
- Log.d(com.example.modifier.TAG, "Node: class=$className, text=$text, name=$name, id=$id")
|
|
|
-
|
|
|
- if ("Compose:Draft:Send" == name) {
|
|
|
- result.sendBtn = node
|
|
|
- }
|
|
|
-
|
|
|
- if ("com.google.android.apps.messaging:id/send_message_button_icon" == id) {
|
|
|
- result.sendBtn = node
|
|
|
- }
|
|
|
-
|
|
|
- if (text != null && (text.contains("RCS 聊天") || text.contains("RCS chat"))) {
|
|
|
- result.isRcsCapable = true
|
|
|
- }
|
|
|
-
|
|
|
- if ("com.google.android.apps.messaging:id/tombstone_message" == id) {
|
|
|
- result.isRcsCapable = text.contains("聊天") || text.contains("Chatting with")
|
|
|
- }
|
|
|
-
|
|
|
- if (text != null && (text.contains("Turn on RCS chats") || text.contains("开启 RCS 聊天功能")
|
|
|
- || text.contains("Enable chat features") || text.contains("启用聊天功能"))
|
|
|
- ) {
|
|
|
- fun findSwitch(node: AccessibilityNodeInfo): Boolean {
|
|
|
- if ("com.google.android.apps.messaging:id/switchWidget" == node.viewIdResourceName) {
|
|
|
- result.rcsSwitch = node
|
|
|
- return true
|
|
|
- }
|
|
|
- for (i in 0 until node.childCount) {
|
|
|
- val child = node.getChild(i)
|
|
|
- if (findSwitch(child)) {
|
|
|
- return true
|
|
|
- }
|
|
|
- }
|
|
|
- return false
|
|
|
- }
|
|
|
- findSwitch(node.parent.parent)
|
|
|
- }
|
|
|
-
|
|
|
- if ("com.google.android.apps.messaging:id/rcs_sim_status_status_text" == id) {
|
|
|
- if (text.lowercase().contains("connected") || text.lowercase().contains("已连接")) {
|
|
|
- result.rcsConnectionStatus = RcsConnectionStatus.CONNECTED
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if ("android:id/title" == id) {
|
|
|
- when (text) {
|
|
|
- "状态:已连接" -> result.rcsConnectionStatus = RcsConnectionStatus.CONNECTED
|
|
|
- "Status: Connected" -> result.rcsConnectionStatus = RcsConnectionStatus.CONNECTED
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (text != null && (text.contains("end-to-end encrypted") || text.contains("已经过端到端加密"))) {
|
|
|
- result.encrypted = true
|
|
|
- }
|
|
|
-
|
|
|
- if (node.childCount != 0) {
|
|
|
- for (i in 0 until node.childCount) {
|
|
|
- traverseNode(node.getChild(i), result)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
@SuppressLint("ClickableViewAccessibility")
|
|
|
override fun onServiceConnected() {
|
|
|
super.onServiceConnected()
|
|
|
|
|
|
instance = this
|
|
|
|
|
|
- val info = AccessibilityServiceInfo()
|
|
|
- info.flags = AccessibilityServiceInfo.DEFAULT or
|
|
|
- AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS or
|
|
|
- AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
|
|
|
- info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
|
|
- info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN
|
|
|
- info.notificationTimeout = 100
|
|
|
- this.serviceInfo = info
|
|
|
-
|
|
|
val displayMetrics = DisplayMetrics()
|
|
|
val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
|
|
|
windowManager.defaultDisplay.getMetrics(displayMetrics)
|
|
|
@@ -801,7 +648,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- logcat.observeForever {
|
|
|
+ googleMessageStateRepository.logs.observeForever {
|
|
|
binding.tvLog.text = it
|
|
|
binding.scroll.fullScroll(View.FOCUS_DOWN)
|
|
|
}
|
|
|
@@ -835,7 +682,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
when (item.itemId) {
|
|
|
R.id.inspect -> {
|
|
|
delay(1500)
|
|
|
- traverseNode(rootInActiveWindow, TraverseResult())
|
|
|
+ screenInspector.traverseNode(TraverseResult())
|
|
|
}
|
|
|
|
|
|
R.id.check_availability -> {
|
|
|
@@ -843,11 +690,11 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
}
|
|
|
|
|
|
R.id.toggle_on -> {
|
|
|
- toggleRcsSwitch(true)
|
|
|
+ screenController.toggleRcsSwitch(true)
|
|
|
}
|
|
|
|
|
|
R.id.toggle_off -> {
|
|
|
- toggleRcsSwitch(false)
|
|
|
+ screenController.toggleRcsSwitch(false)
|
|
|
}
|
|
|
|
|
|
R.id.clear_conv -> {
|
|
|
@@ -905,104 +752,6 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- suspend fun waitForRcsState(
|
|
|
- states: Array<RcsConfigureState>,
|
|
|
- timeout: Duration
|
|
|
- ): RcsConfigureState? {
|
|
|
- var state: RcsConfigureState? = null
|
|
|
- withTimeoutOrNull(timeout) {
|
|
|
- withContext(Dispatchers.Main) {
|
|
|
- suspendCancellableCoroutine { continuation ->
|
|
|
- val observer = Observer<RcsConfigureState> { value ->
|
|
|
- if (states.contains(value)) {
|
|
|
- state = value
|
|
|
- if (isActive)
|
|
|
- continuation.resume(Unit)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- rcsConfigureState.observeForever(observer)
|
|
|
-
|
|
|
- continuation.invokeOnCancellation {
|
|
|
- handler.post {
|
|
|
- Log.i(com.example.modifier.TAG, "removeObserver")
|
|
|
- rcsConfigureState.removeObserver(observer)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- false
|
|
|
- }
|
|
|
- return state
|
|
|
- }
|
|
|
-
|
|
|
- suspend fun toggleRcsSwitch(state: Boolean, retry: Int = 3): Boolean {
|
|
|
- val res = TraverseResult()
|
|
|
-
|
|
|
- shellRun(CMD_RCS_SETTINGS_ACTIVITY, "sleep 2")
|
|
|
- val success = run repeatBlock@{
|
|
|
- repeat(retry) {
|
|
|
- res.rcsSwitch = null
|
|
|
- traverseNode(rootInActiveWindow, res)
|
|
|
- if (res.rcsSwitch == null) {
|
|
|
- shellRun(CMD_BACK, "sleep 0.5", CMD_RCS_SETTINGS_ACTIVITY, "sleep 0.5")
|
|
|
- } else {
|
|
|
- if (res.rcsSwitch!!.isChecked == state) {
|
|
|
- return@repeatBlock true
|
|
|
- }
|
|
|
- val rect = Rect()
|
|
|
- res.rcsSwitch!!.getBoundsInScreen(rect)
|
|
|
- if (state) {
|
|
|
- shellRun(
|
|
|
- "input tap ${rect.centerX()} ${rect.centerY()}", "sleep 1",
|
|
|
- )
|
|
|
- val btn =
|
|
|
- rootInActiveWindow.findAccessibilityNodeInfosByViewId("android:id/button1")
|
|
|
- .firstOrNull()
|
|
|
- if (btn != null) {
|
|
|
- btn.performAction(AccessibilityNodeInfo.ACTION_CLICK)
|
|
|
- delay(1000)
|
|
|
- }
|
|
|
- while (shellRun("dumpsys activity activities | grep topResumedActivity")
|
|
|
- .first.contains("RcsSettingsActivity")
|
|
|
- ) {
|
|
|
- shellRun(CMD_BACK)
|
|
|
- delay(500)
|
|
|
- }
|
|
|
- shellRun(CMD_RCS_SETTINGS_ACTIVITY, "sleep 1")
|
|
|
- } else {
|
|
|
- shellRun(
|
|
|
- "input tap ${rect.centerX()} ${rect.centerY()}", "sleep 1",
|
|
|
- )
|
|
|
- rootInActiveWindow.findAccessibilityNodeInfosByViewId("android:id/button1")
|
|
|
- .firstOrNull()?.performAction(AccessibilityNodeInfo.ACTION_CLICK)
|
|
|
- delay(1000)
|
|
|
- while (shellRun("dumpsys activity activities | grep topResumedActivity")
|
|
|
- .first.contains("RcsSettingsActivity")
|
|
|
- ) {
|
|
|
- shellRun(CMD_BACK)
|
|
|
- delay(500)
|
|
|
- }
|
|
|
- shellRun(CMD_RCS_SETTINGS_ACTIVITY, "sleep 1")
|
|
|
- }
|
|
|
- res.rcsSwitch = null
|
|
|
- traverseNode(rootInActiveWindow, res)
|
|
|
- if (res.rcsSwitch?.isChecked == state) {
|
|
|
- return@repeatBlock true
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- false
|
|
|
- }
|
|
|
- while (shellRun("dumpsys activity activities | grep topResumedActivity")
|
|
|
- .first.contains("RcsSettingsActivity")
|
|
|
- ) {
|
|
|
- shellRun(CMD_BACK)
|
|
|
- delay(500)
|
|
|
- }
|
|
|
- return success
|
|
|
- }
|
|
|
-
|
|
|
private suspend fun reset() {
|
|
|
if (isOldVersion(this)) {
|
|
|
withTimeout(1.hours) {
|
|
|
@@ -1011,10 +760,10 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
withContext(Dispatchers.Main) {
|
|
|
binding.tvLog.text = "Waiting for RCS switch on..."
|
|
|
}
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
|
|
|
+ googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
|
|
|
Global.saveMock()
|
|
|
resetAll()
|
|
|
- var switchAppear = waitForRcsState(
|
|
|
+ var switchAppear = googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(RcsConfigureState.WAITING_FOR_TOS),
|
|
|
2.minutes
|
|
|
)?.let {
|
|
|
@@ -1025,7 +774,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
PACKAGE_GMS.kill(), PACKAGE_MESSAGING.kill(), "sleep 1",
|
|
|
CMD_MESSAGING_APP
|
|
|
)
|
|
|
- switchAppear = waitForRcsState(
|
|
|
+ switchAppear = googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(RcsConfigureState.WAITING_FOR_TOS),
|
|
|
5.minutes
|
|
|
)?.let {
|
|
|
@@ -1039,24 +788,24 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
- if (!toggleRcsSwitch(false)) {
|
|
|
+ if (!screenController.toggleRcsSwitch(false)) {
|
|
|
Log.e(com.example.modifier.TAG, "RCS switch not turned off, retrying...")
|
|
|
continue
|
|
|
}
|
|
|
- if (!toggleRcsSwitch(true)) {
|
|
|
+ if (!screenController.toggleRcsSwitch(true)) {
|
|
|
Log.e(com.example.modifier.TAG, "RCS switch not turned on, retrying...")
|
|
|
continue
|
|
|
}
|
|
|
- var resetSuccess = waitForRcsState(
|
|
|
+ var resetSuccess = googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(
|
|
|
RcsConfigureState.READY
|
|
|
), 30.seconds
|
|
|
).let { it == RcsConfigureState.READY }
|
|
|
if (!resetSuccess) {
|
|
|
- toggleRcsSwitch(false)
|
|
|
+ screenController.toggleRcsSwitch(false)
|
|
|
delay(1000)
|
|
|
- toggleRcsSwitch(true)
|
|
|
- resetSuccess = waitForRcsState(
|
|
|
+ screenController.toggleRcsSwitch(true)
|
|
|
+ resetSuccess = googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(
|
|
|
RcsConfigureState.READY
|
|
|
), 1.minutes
|
|
|
@@ -1077,10 +826,10 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
withContext(Dispatchers.Main) {
|
|
|
binding.tvLog.text = "Waiting for RCS switch on..."
|
|
|
}
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
|
|
|
+ googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
|
|
|
Global.saveMock()
|
|
|
resetAll()
|
|
|
- var switchAppear = waitForRcsState(
|
|
|
+ var switchAppear = googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
|
|
|
1.minutes
|
|
|
)?.let {
|
|
|
@@ -1091,7 +840,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
PACKAGE_GMS.kill(), PACKAGE_MESSAGING.kill(), "sleep 1",
|
|
|
CMD_MESSAGING_APP
|
|
|
)
|
|
|
- switchAppear = waitForRcsState(
|
|
|
+ switchAppear = googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
|
|
|
2.minutes
|
|
|
)?.let {
|
|
|
@@ -1105,21 +854,21 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
- val switchOn = toggleRcsSwitch(true)
|
|
|
+ val switchOn = screenController.toggleRcsSwitch(true)
|
|
|
if (!switchOn) {
|
|
|
Log.e(com.example.modifier.TAG, "RCS switch not turned on, retrying...")
|
|
|
continue
|
|
|
}
|
|
|
- var resetSuccess = waitForRcsState(
|
|
|
+ var resetSuccess = googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(
|
|
|
RcsConfigureState.READY
|
|
|
), 30.seconds
|
|
|
).let { it == RcsConfigureState.READY }
|
|
|
if (!resetSuccess) {
|
|
|
- toggleRcsSwitch(false)
|
|
|
+ screenController.toggleRcsSwitch(false)
|
|
|
delay(1000)
|
|
|
- toggleRcsSwitch(true)
|
|
|
- resetSuccess = waitForRcsState(
|
|
|
+ screenController.toggleRcsSwitch(true)
|
|
|
+ resetSuccess = googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(
|
|
|
RcsConfigureState.READY
|
|
|
), 1.minutes
|
|
|
@@ -1222,7 +971,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
needRest = false
|
|
|
}
|
|
|
|
|
|
- rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
|
|
|
+ googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
|
|
|
withContext(Dispatchers.Main) {
|
|
|
binding.tvLog.text = "Requesting number..."
|
|
|
}
|
|
|
@@ -1289,15 +1038,15 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
if (sendOtpTimeout > 2.minutes) {
|
|
|
sendOtpTimeout = 2.minutes
|
|
|
}
|
|
|
- if (waitForRcsState(
|
|
|
+ if (googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(RcsConfigureState.WAITING_FOR_OTP),
|
|
|
sendOtpTimeout
|
|
|
) != RcsConfigureState.WAITING_FOR_OTP
|
|
|
) {
|
|
|
- if (!toggleRcsSwitch(true)) {
|
|
|
+ if (!screenController.toggleRcsSwitch(true)) {
|
|
|
needRest = true
|
|
|
}
|
|
|
- if (RcsConfigureState.REPLAY_REQUEST == rcsConfigureState.value) {
|
|
|
+ if (RcsConfigureState.REPLAY_REQUEST == googleMessageStateRepository.rcsConfigureState.value) {
|
|
|
Log.e(
|
|
|
com.example.modifier.TAG,
|
|
|
"REPLAY_REQUEST detected, may reset after 3 retry ($retry)"
|
|
|
@@ -1369,7 +1118,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
repeat(2) {
|
|
|
Global.sendSmsIntent(sender, msg)
|
|
|
val state =
|
|
|
- waitForRcsState(
|
|
|
+ googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(
|
|
|
RcsConfigureState.CONFIGURED,
|
|
|
RcsConfigureState.RETRY
|
|
|
@@ -1381,7 +1130,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
}
|
|
|
|
|
|
RcsConfigureState.RETRY -> {
|
|
|
- waitForRcsState(
|
|
|
+ googleMessageStateRepository.waitForRcsState(
|
|
|
arrayOf(RcsConfigureState.WAITING_FOR_OTP),
|
|
|
60.seconds
|
|
|
)
|
|
|
@@ -1458,7 +1207,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
"sleep 1",
|
|
|
)
|
|
|
val res = TraverseResult()
|
|
|
- traverseNode(rootInActiveWindow, res)
|
|
|
+ screenInspector.traverseNode(res)
|
|
|
if (res.rcsConnectionStatus == RcsConnectionStatus.CONNECTED) {
|
|
|
Log.i(com.example.modifier.TAG, "RCS is connected")
|
|
|
shellRun(CMD_BACK)
|
|
|
@@ -1512,9 +1261,8 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
startActivity(smsIntent(it, ""))
|
|
|
val s = withTimeoutOrNull(5.seconds) {
|
|
|
while (true) {
|
|
|
- val root = rootInActiveWindow
|
|
|
val traverseResult = TraverseResult()
|
|
|
- traverseNode(root, traverseResult)
|
|
|
+ screenInspector.traverseNode(traverseResult)
|
|
|
if (traverseResult.isRcsCapable) {
|
|
|
return@withTimeoutOrNull true
|
|
|
} else {
|