|
@@ -31,7 +31,12 @@ import androidx.lifecycle.MutableLiveData
|
|
|
import androidx.lifecycle.Observer
|
|
import androidx.lifecycle.Observer
|
|
|
import androidx.lifecycle.liveData
|
|
import androidx.lifecycle.liveData
|
|
|
import com.example.modifier.BuildConfig
|
|
import com.example.modifier.BuildConfig
|
|
|
-import com.example.modifier.Frida
|
|
|
|
|
|
|
+import com.example.modifier.CMD_BACK
|
|
|
|
|
+import com.example.modifier.CMD_CONVERSATION_LIST_ACTIVITY
|
|
|
|
|
+import com.example.modifier.CMD_HOME
|
|
|
|
|
+import com.example.modifier.CMD_MESSAGING_APP
|
|
|
|
|
+import com.example.modifier.CMD_MSG_SETTINGS_ACTIVITY
|
|
|
|
|
+import com.example.modifier.CMD_RCS_SETTINGS_ACTIVITY
|
|
|
import com.example.modifier.Global
|
|
import com.example.modifier.Global
|
|
|
import com.example.modifier.Global.load
|
|
import com.example.modifier.Global.load
|
|
|
import com.example.modifier.Global.resetAll
|
|
import com.example.modifier.Global.resetAll
|
|
@@ -42,8 +47,10 @@ import com.example.modifier.databinding.FloatingWindowBinding
|
|
|
import com.example.modifier.enums.RcsConfigureState
|
|
import com.example.modifier.enums.RcsConfigureState
|
|
|
import com.example.modifier.http.KtorClient
|
|
import com.example.modifier.http.KtorClient
|
|
|
import com.example.modifier.http.api.RcsNumberApi
|
|
import com.example.modifier.http.api.RcsNumberApi
|
|
|
|
|
+import com.example.modifier.http.api.SysConfigApi
|
|
|
import com.example.modifier.http.request.RcsNumberRequest
|
|
import com.example.modifier.http.request.RcsNumberRequest
|
|
|
import com.example.modifier.http.response.RcsNumberResponse
|
|
import com.example.modifier.http.response.RcsNumberResponse
|
|
|
|
|
+import com.example.modifier.http.response.SysConfigResponse
|
|
|
import com.example.modifier.model.TelephonyConfig
|
|
import com.example.modifier.model.TelephonyConfig
|
|
|
import com.google.android.material.color.DynamicColors
|
|
import com.google.android.material.color.DynamicColors
|
|
|
import io.ktor.client.call.body
|
|
import io.ktor.client.call.body
|
|
@@ -57,9 +64,6 @@ import io.socket.client.Socket
|
|
|
import io.socket.emitter.Emitter
|
|
import io.socket.emitter.Emitter
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.CoroutineScope
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
-import kotlinx.coroutines.GlobalScope
|
|
|
|
|
-import kotlinx.coroutines.async
|
|
|
|
|
-import kotlinx.coroutines.coroutineScope
|
|
|
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.delay
|
|
|
import kotlinx.coroutines.isActive
|
|
import kotlinx.coroutines.isActive
|
|
|
import kotlinx.coroutines.launch
|
|
import kotlinx.coroutines.launch
|
|
@@ -347,14 +351,18 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private fun send(to: String, body: String, rcsWait: Long): Boolean {
|
|
|
|
|
- Log.i(TAG, "Sending SMS to $to: $body")
|
|
|
|
|
|
|
+ private fun smsIntent(to: String, body: String): Intent {
|
|
|
val intent = Intent(Intent.ACTION_SENDTO)
|
|
val intent = Intent(Intent.ACTION_SENDTO)
|
|
|
- intent.setData(Uri.parse("sms:$to"))
|
|
|
|
|
|
|
+ intent.data = Uri.parse("sms:$to")
|
|
|
intent.putExtra("sms_body", body)
|
|
intent.putExtra("sms_body", body)
|
|
|
intent.putExtra("exit_on_sent", true)
|
|
intent.putExtra("exit_on_sent", true)
|
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
|
- startActivity(intent)
|
|
|
|
|
|
|
+ return intent
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private fun send(to: String, body: String, rcsWait: Long): Boolean {
|
|
|
|
|
+ Log.i(TAG, "Sending SMS to $to: $body")
|
|
|
|
|
+ startActivity(smsIntent(to, body))
|
|
|
try {
|
|
try {
|
|
|
Log.i(TAG, "Command executed successfully, waiting for app to open...")
|
|
Log.i(TAG, "Command executed successfully, waiting for app to open...")
|
|
|
val f = mExecutor.schedule<Boolean>(
|
|
val f = mExecutor.schedule<Boolean>(
|
|
@@ -363,7 +371,6 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
val ts = System.currentTimeMillis()
|
|
val ts = System.currentTimeMillis()
|
|
|
while (System.currentTimeMillis() - ts < rcsWait) {
|
|
while (System.currentTimeMillis() - ts < rcsWait) {
|
|
|
val root = rootInActiveWindow
|
|
val root = rootInActiveWindow
|
|
|
- val packageName = root.packageName.toString()
|
|
|
|
|
val traverseResult = TraverseResult()
|
|
val traverseResult = TraverseResult()
|
|
|
traverseNode(root, traverseResult)
|
|
traverseNode(root, traverseResult)
|
|
|
if (traverseResult.isRcsCapable) {
|
|
if (traverseResult.isRcsCapable) {
|
|
@@ -458,6 +465,12 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
findSwitch(node.parent.parent)
|
|
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.isRcsConnected = true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (node.childCount != 0) {
|
|
if (node.childCount != 0) {
|
|
|
for (i in 0 until node.childCount) {
|
|
for (i in 0 until node.childCount) {
|
|
|
traverseNode(node.getChild(i), result)
|
|
traverseNode(node.getChild(i), result)
|
|
@@ -573,7 +586,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
}
|
|
}
|
|
|
binding.btnInspect.setOnClickListener {
|
|
binding.btnInspect.setOnClickListener {
|
|
|
CoroutineScope(Dispatchers.IO).launch {
|
|
CoroutineScope(Dispatchers.IO).launch {
|
|
|
- traverseNode(rootInActiveWindow, TraverseResult())
|
|
|
|
|
|
|
+ checkRcsAvailability()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -630,9 +643,6 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private suspend fun requestNumber() {
|
|
private suspend fun requestNumber() {
|
|
|
- CoroutineScope(Dispatchers.IO).async {
|
|
|
|
|
- Frida.start()
|
|
|
|
|
- }
|
|
|
|
|
requestNumberCount++
|
|
requestNumberCount++
|
|
|
requesting.postValue(true)
|
|
requesting.postValue(true)
|
|
|
val result = withTimeoutOrNull(1.hours) {
|
|
val result = withTimeoutOrNull(1.hours) {
|
|
@@ -786,17 +796,12 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
if (match != null) {
|
|
if (match != null) {
|
|
|
val otp = match.groupValues[1]
|
|
val otp = match.groupValues[1]
|
|
|
Log.i(TAG, "OTP: $otp")
|
|
Log.i(TAG, "OTP: $otp")
|
|
|
- Global.sendSms(
|
|
|
|
|
- "3538",
|
|
|
|
|
- "Your Messenger verification code is G-$otp"
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ val sender = "3538"
|
|
|
|
|
+ val msg = "Your Messenger verification code is G-$otp"
|
|
|
|
|
|
|
|
val configured = run a@{
|
|
val configured = run a@{
|
|
|
repeat(2) {
|
|
repeat(2) {
|
|
|
- Global.sendSms(
|
|
|
|
|
- "3538",
|
|
|
|
|
- "Your Messenger verification code is G-$otp"
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ Global.sendSmsIntent(sender, msg)
|
|
|
val state =
|
|
val state =
|
|
|
waitForRcsState(
|
|
waitForRcsState(
|
|
|
arrayOf(
|
|
arrayOf(
|
|
@@ -835,10 +840,75 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
} else {
|
|
} else {
|
|
|
Log.e(TAG, "requestNumber failed")
|
|
Log.e(TAG, "requestNumber failed")
|
|
|
}
|
|
}
|
|
|
- try {
|
|
|
|
|
- Frida.stop()
|
|
|
|
|
- } catch (e: Exception) {
|
|
|
|
|
- Log.wtf(TAG, "stop frida failed", e)
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ suspend fun checkRcsAvailability(): Boolean {
|
|
|
|
|
+ var rcsConnected = false
|
|
|
|
|
+ repeat(3) {
|
|
|
|
|
+ Utils.runAsRoot(
|
|
|
|
|
+ CMD_CONVERSATION_LIST_ACTIVITY,
|
|
|
|
|
+ "sleep 2",
|
|
|
|
|
+ CMD_RCS_SETTINGS_ACTIVITY,
|
|
|
|
|
+ "sleep 1",
|
|
|
|
|
+ )
|
|
|
|
|
+ val res = TraverseResult()
|
|
|
|
|
+ traverseNode(rootInActiveWindow, res)
|
|
|
|
|
+ if (res.isRcsConnected) {
|
|
|
|
|
+ rcsConnected = true
|
|
|
|
|
+ return@repeat
|
|
|
|
|
+ }
|
|
|
|
|
+ Utils.runAsRoot(CMD_HOME, "sleep 1")
|
|
|
}
|
|
}
|
|
|
|
|
+ if (!rcsConnected) {
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var config: SysConfigResponse
|
|
|
|
|
+ val checkRcsAvailabilityNumbers = mutableListOf<String>()
|
|
|
|
|
+ withTimeoutOrNull(60.seconds) {
|
|
|
|
|
+ while (true) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ config = KtorClient.get(
|
|
|
|
|
+ SysConfigApi.Id(
|
|
|
|
|
+ SysConfigApi(),
|
|
|
|
|
+ "check_availability_numbers"
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
|
|
+ .body<SysConfigResponse>()
|
|
|
|
|
+ Log.i(TAG, "sysConfig response: $config")
|
|
|
|
|
+ checkRcsAvailabilityNumbers.addAll(config.value.split(",").map { it.trim() })
|
|
|
|
|
+ break
|
|
|
|
|
+ } catch (exception: Exception) {
|
|
|
|
|
+ Log.e(TAG, "sysConfig Error: ${exception.message}", exception)
|
|
|
|
|
+ }
|
|
|
|
|
+ delay(1.seconds)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ checkRcsAvailabilityNumbers.forEach {
|
|
|
|
|
+ startActivity(smsIntent(it, ""))
|
|
|
|
|
+ val s = withTimeoutOrNull(3.seconds) {
|
|
|
|
|
+ while (true) {
|
|
|
|
|
+ val root = rootInActiveWindow
|
|
|
|
|
+ val traverseResult = TraverseResult()
|
|
|
|
|
+ traverseNode(root, traverseResult)
|
|
|
|
|
+ if (traverseResult.isRcsCapable) {
|
|
|
|
|
+ return@withTimeoutOrNull true
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Log.i(TAG, "RCS not detected")
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ delay(200)
|
|
|
|
|
+ } catch (e: InterruptedException) {
|
|
|
|
|
+ e.printStackTrace()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (s == true) {
|
|
|
|
|
+ Log.i(TAG, "checkRcsAvailability: $it success")
|
|
|
|
|
+ return true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return false
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|