|
|
@@ -26,6 +26,7 @@ import androidx.datastore.preferences.core.Preferences
|
|
|
import androidx.datastore.preferences.preferencesDataStore
|
|
|
import androidx.lifecycle.MediatorLiveData
|
|
|
import androidx.lifecycle.MutableLiveData
|
|
|
+import androidx.lifecycle.Observer
|
|
|
import androidx.lifecycle.liveData
|
|
|
import com.example.modifier.BuildConfig
|
|
|
import com.example.modifier.Global
|
|
|
@@ -36,6 +37,7 @@ import com.example.modifier.TraverseResult
|
|
|
import com.example.modifier.Utils
|
|
|
import com.example.modifier.databinding.FloatingWindowBinding
|
|
|
import com.example.modifier.enums.RcsConfigureState
|
|
|
+import com.example.modifier.extension.waitUntilValueIs
|
|
|
import com.example.modifier.http.KtorClient
|
|
|
import com.example.modifier.http.RcsNumberApi
|
|
|
import com.example.modifier.http.request.RcsNumberRequest
|
|
|
@@ -56,8 +58,10 @@ import kotlinx.coroutines.Dispatchers
|
|
|
import kotlinx.coroutines.delay
|
|
|
import kotlinx.coroutines.launch
|
|
|
import kotlinx.coroutines.runBlocking
|
|
|
+import kotlinx.coroutines.suspendCancellableCoroutine
|
|
|
import kotlinx.coroutines.withContext
|
|
|
import kotlinx.coroutines.withTimeoutOrNull
|
|
|
+import org.apache.commons.collections4.queue.CircularFifoQueue
|
|
|
import org.apache.commons.lang3.RandomStringUtils
|
|
|
import org.apache.commons.lang3.StringUtils
|
|
|
import org.json.JSONArray
|
|
|
@@ -68,6 +72,7 @@ import java.util.concurrent.ScheduledExecutorService
|
|
|
import java.util.concurrent.ScheduledThreadPoolExecutor
|
|
|
import java.util.concurrent.TimeUnit
|
|
|
import java.util.concurrent.atomic.AtomicReference
|
|
|
+import kotlin.coroutines.resume
|
|
|
import kotlin.math.max
|
|
|
import kotlin.math.min
|
|
|
import kotlin.time.Duration.Companion.hours
|
|
|
@@ -152,12 +157,13 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
|
|
|
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 tag")
|
|
|
+ writer.write("logcat BugleRcsEngine:D *:S -v time")
|
|
|
writer.newLine()
|
|
|
writer.flush()
|
|
|
}
|
|
|
@@ -166,7 +172,6 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
.useLines { lines ->
|
|
|
Log.d(TAG, "logcat new lines")
|
|
|
lines.forEach { line ->
|
|
|
- emit(line)
|
|
|
if (line.contains("destState=CheckPreconditionsState")) {
|
|
|
rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
|
|
|
} else if (line.contains("destState=WaitingForOtpState")) {
|
|
|
@@ -178,6 +183,22 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
} else if (line.contains("destState=WaitingForRcsDefaultOnState")) {
|
|
|
rcsConfigureState.postValue(RcsConfigureState.WAITING_FOR_DEFAULT_ON)
|
|
|
}
|
|
|
+ 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"))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
} catch (e: Exception) {
|
|
|
@@ -252,7 +273,6 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
} else if ("task" == action) {
|
|
|
val data = json.optJSONObject("data")
|
|
|
val id = json.optString("id")
|
|
|
- currentTaskId = json.optInt("id", 0)
|
|
|
if (data != null && StringUtils.isNoneBlank(id)) {
|
|
|
runTask(id, data)
|
|
|
}
|
|
|
@@ -270,6 +290,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
rcsInterval = config.optLong("rcsInterval", 0)
|
|
|
requestNumberInterval = config.optInt("requestNumberInterval", 0)
|
|
|
val tasks = data.optJSONArray("tasks")!!
|
|
|
+ currentTaskId = data.optInt("taskId", 0)
|
|
|
mExecutor.submit {
|
|
|
running.postValue(true)
|
|
|
|
|
|
@@ -524,8 +545,8 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
}
|
|
|
|
|
|
logcat.observeForever {
|
|
|
- if (it.contains("destState="))
|
|
|
- binding.tvLog.text = it
|
|
|
+ binding.tvLog.text = it
|
|
|
+ binding.scroll.fullScroll(View.FOCUS_DOWN)
|
|
|
}
|
|
|
requesting.observeForever {
|
|
|
binding.btnReq.isEnabled = !it
|
|
|
@@ -578,6 +599,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
withContext(Dispatchers.Main) {
|
|
|
binding.tvLog.text = "Waiting for logs..."
|
|
|
}
|
|
|
+ rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
|
|
|
resetAll()
|
|
|
val switchAppear = withTimeoutOrNull(60.seconds) {
|
|
|
while (true) {
|
|
|
@@ -626,7 +648,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
setBody(
|
|
|
RcsNumberRequest(
|
|
|
deviceId = Utils.getUniqueID(),
|
|
|
- taskId = currentTaskId.toString()
|
|
|
+ taskId = currentTaskId
|
|
|
)
|
|
|
)
|
|
|
}
|
|
|
@@ -709,8 +731,66 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
|
|
|
"message",
|
|
|
"Your Messenger verification code is G-$otp"
|
|
|
)
|
|
|
- sendBroadcast(intent)
|
|
|
- break
|
|
|
+
|
|
|
+ suspend fun waitForConfigured(): Boolean {
|
|
|
+ sendBroadcast(intent)
|
|
|
+ val configured = withTimeoutOrNull(30.seconds) {
|
|
|
+ while (true) {
|
|
|
+ if (rcsConfigureState.value == RcsConfigureState.CONFIGURED) {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ delay(1000)
|
|
|
+ }
|
|
|
+ true
|
|
|
+ } ?: false
|
|
|
+ if (configured) {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ Log.e(TAG, "verifyOtp fail, retrying...")
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+// suspendCancellableCoroutine<Unit> { continuation ->
|
|
|
+// val observer = Observer<RcsConfigureState> { value ->
|
|
|
+// if (value == expectedValue) {
|
|
|
+// continuation.resume(Unit)
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// observeForever(observer)
|
|
|
+//
|
|
|
+// continuation.invokeOnCancellation {
|
|
|
+// removeObserver(observer)
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+ val configured = run a@{
|
|
|
+ repeat(2) {
|
|
|
+ sendBroadcast(intent)
|
|
|
+ val configured = withTimeoutOrNull(30.seconds) {
|
|
|
+ while (true) {
|
|
|
+ if (rcsConfigureState.value == RcsConfigureState.CONFIGURED) {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ delay(1000)
|
|
|
+ }
|
|
|
+ true
|
|
|
+ } ?: false
|
|
|
+ if (configured) {
|
|
|
+ return@a true
|
|
|
+ } else {
|
|
|
+ Log.e(TAG, "verifyOtp fail, retrying...")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ false
|
|
|
+ }
|
|
|
+ if (!configured) {
|
|
|
+ Log.e(TAG, "RCS not configured, retrying...")
|
|
|
+ continue
|
|
|
+ } else {
|
|
|
+ break
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
true
|