xiongzhu 1 an în urmă
părinte
comite
a81834ee19

+ 2 - 0
app/src/main/java/com/example/modifier/TraverseResult.kt

@@ -15,4 +15,6 @@ class TraverseResult {
     var rcsConnectionStatus = RcsConnectionStatus.UNKNOWN
     var rcsConnectionStatus = RcsConnectionStatus.UNKNOWN
 
 
     var encrypted: Boolean = false
     var encrypted: Boolean = false
+
+    var tosAgreeBtn: AccessibilityNodeInfo? = null
 }
 }

+ 0 - 1
app/src/main/java/com/example/modifier/adapter/BackupAdapter.kt

@@ -46,7 +46,6 @@ class BackupAdapter(
 
 
     @SuppressLint("DefaultLocale")
     @SuppressLint("DefaultLocale")
     override fun onBindViewHolder(holder: BackupViewHolder, position: Int) {
     override fun onBindViewHolder(holder: BackupViewHolder, position: Int) {
-        Log.i(tag, "onBindViewHolder")
         val backup = backups[position]
         val backup = backups[position]
         holder.binding.tvNumber.text = "+${backup.code} ${backup.number}"
         holder.binding.tvNumber.text = "+${backup.code} ${backup.number}"
         holder.binding.tvTime.text =
         holder.binding.tvTime.text =

+ 1 - 0
app/src/main/java/com/example/modifier/data/AppRuntimeFlags.kt

@@ -9,4 +9,5 @@ data class AppRuntimeFlags(
     val checkingConnection: Boolean = false,
     val checkingConnection: Boolean = false,
     val suspended: Boolean = false,
     val suspended: Boolean = false,
     val requestNumberState: RequestNumberState = RequestNumberState.IDLE,
     val requestNumberState: RequestNumberState = RequestNumberState.IDLE,
+    val storing: Boolean = false,
 )
 )

+ 6 - 4
app/src/main/java/com/example/modifier/repo/AppStateRepo.kt

@@ -35,7 +35,7 @@ class AppStateRepo private constructor(private val context: Context) {
         val REQUESTED_NUM = intPreferencesKey("requested_num")
         val REQUESTED_NUM = intPreferencesKey("requested_num")
     }
     }
 
 
-    private val appRuntimeFlags = MutableStateFlow(AppRuntimeFlags())
+    val appRuntimeFlags = MutableStateFlow(AppRuntimeFlags())
 
 
     val appState = MutableStateFlow(
     val appState = MutableStateFlow(
         AppState(
         AppState(
@@ -70,7 +70,7 @@ class AppStateRepo private constructor(private val context: Context) {
                 requesting = runtimeFlags.requesting,
                 requesting = runtimeFlags.requesting,
                 preparing = runtimeFlags.preparing,
                 preparing = runtimeFlags.preparing,
                 checkingConnection = runtimeFlags.checkingConnection,
                 checkingConnection = runtimeFlags.checkingConnection,
-                busy = runtimeFlags.running || runtimeFlags.requesting || runtimeFlags.preparing || runtimeFlags.checkingConnection,
+                busy = runtimeFlags.running || runtimeFlags.requesting || runtimeFlags.preparing || runtimeFlags.checkingConnection || runtimeFlags.storing,
                 suspended = runtimeFlags.suspended,
                 suspended = runtimeFlags.suspended,
                 requestNumberState = runtimeFlags.requestNumberState
                 requestNumberState = runtimeFlags.requestNumberState
             )
             )
@@ -132,7 +132,8 @@ class AppStateRepo private constructor(private val context: Context) {
         preparing: Boolean? = null,
         preparing: Boolean? = null,
         checkingConnection: Boolean? = null,
         checkingConnection: Boolean? = null,
         suspended: Boolean? = null,
         suspended: Boolean? = null,
-        requestNumberState: RequestNumberState? = null
+        requestNumberState: RequestNumberState? = null,
+        storing: Boolean? = null
     ) {
     ) {
         val value = appRuntimeFlags.value
         val value = appRuntimeFlags.value
         appRuntimeFlags.update {
         appRuntimeFlags.update {
@@ -142,7 +143,8 @@ class AppStateRepo private constructor(private val context: Context) {
                 preparing = preparing ?: value.preparing,
                 preparing = preparing ?: value.preparing,
                 checkingConnection = checkingConnection ?: value.checkingConnection,
                 checkingConnection = checkingConnection ?: value.checkingConnection,
                 suspended = suspended ?: value.suspended,
                 suspended = suspended ?: value.suspended,
-                requestNumberState = requestNumberState ?: value.requestNumberState
+                requestNumberState = requestNumberState ?: value.requestNumberState,
+                storing = storing ?: value.storing
             )
             )
         }
         }
     }
     }

+ 48 - 6
app/src/main/java/com/example/modifier/service/ModifierService.kt

@@ -42,6 +42,7 @@ import com.example.modifier.utils.hasRootAccess
 import com.example.modifier.utils.isRebooted
 import com.example.modifier.utils.isRebooted
 import com.example.modifier.utils.killPhoneProcess
 import com.example.modifier.utils.killPhoneProcess
 import com.example.modifier.utils.optimize
 import com.example.modifier.utils.optimize
+import com.example.modifier.utils.resetAll
 import com.example.modifier.utils.restartSelf
 import com.example.modifier.utils.restartSelf
 import com.example.modifier.utils.setBatteryLevel
 import com.example.modifier.utils.setBatteryLevel
 import com.example.modifier.utils.syncTime
 import com.example.modifier.utils.syncTime
@@ -130,7 +131,6 @@ class ModifierService : AccessibilityService() {
         binding.root.post {
         binding.root.post {
             maxX = width - binding.root.measuredWidth
             maxX = width - binding.root.measuredWidth
             maxY = height - binding.root.measuredHeight
             maxY = height - binding.root.measuredHeight
-            Log.i(TAG, "measured: $maxX, $maxY")
             layoutParams.x = maxX
             layoutParams.x = maxX
             windowManager.updateViewLayout(mLayout, layoutParams)
             windowManager.updateViewLayout(mLayout, layoutParams)
         }
         }
@@ -349,13 +349,15 @@ class ModifierService : AccessibilityService() {
     private fun showMenu(context: Context, v: View, @MenuRes menuRes: Int) {
     private fun showMenu(context: Context, v: View, @MenuRes menuRes: Int) {
         val popup = PopupMenu(context, v)
         val popup = PopupMenu(context, v)
         popup.menuInflater.inflate(menuRes, popup.menu)
         popup.menuInflater.inflate(menuRes, popup.menu)
+        popup.menu.findItem(R.id.store_numbers).isEnabled =
+            !appStateRepo.appRuntimeFlags.value.storing
         popup.setOnMenuItemClickListener { item ->
         popup.setOnMenuItemClickListener { item ->
             binding.btnMore.isEnabled = false
             binding.btnMore.isEnabled = false
             CoroutineScope(Dispatchers.IO).launch {
             CoroutineScope(Dispatchers.IO).launch {
                 when (item.itemId) {
                 when (item.itemId) {
                     R.id.inspect -> {
                     R.id.inspect -> {
                         delay(1500)
                         delay(1500)
-                        screenInspector.traverseNode(TraverseResult())
+                        screenInspector.traverseNode(TraverseResult(), true)
                     }
                     }
 
 
                     R.id.check_availability -> {
                     R.id.check_availability -> {
@@ -376,7 +378,11 @@ class ModifierService : AccessibilityService() {
                     }
                     }
 
 
                     R.id.store_numbers -> {
                     R.id.store_numbers -> {
-                        storeNumbers()
+                        if (!appStateRepo.appRuntimeFlags.value.storing) {
+                            launch {
+                                storeNumbers()
+                            }
+                        }
                     }
                     }
 
 
                     R.id.change_profile -> {
                     R.id.change_profile -> {
@@ -420,9 +426,45 @@ class ModifierService : AccessibilityService() {
     }
     }
 
 
     private suspend fun storeNumbers() {
     private suspend fun storeNumbers() {
-        withContext(Dispatchers.Main) {
-
-
+        appStateRepo.updateRuntimeFlags(storing = true)
+        var success = true
+        var retry = 0
+        val num = 5
+        repeat(num) {
+            Log.i(TAG, "storeNumbers: $it")
+            try {
+                if (success || retry > 3) {
+                    taskRunner.reset()
+                }
+                appStateRepo.updateRuntimeFlags(requesting = true)
+                taskRunner.requestNumberAtomic()
+                spoofedSimInfoRepo.updateSpoofedSimInfo(
+                    spoofedSimInfo = spoofedSimInfoRepo.spoofedSimInfo.value.copy(
+                        available = true
+                    ),
+                    suspend = false
+                )
+                appStateRepo.updateRuntimeFlags(requesting = false)
+                if (it < num - 1) {
+                    backupRepository.backup(
+                        spoofedSimInfo = spoofedSimInfoRepo.spoofedSimInfo.value,
+                        type = "auto",
+                        sendCount = 0,
+                        stock = true
+                    )
+                }
+                success = true
+                retry = 0
+            } catch (e: Exception) {
+                appStateRepo.updateRuntimeFlags(requesting = false)
+                success = false
+                retry++
+                Log.i(TAG, "Error store number, retry: $retry", e)
+            }
         }
         }
+        appStateRepo.updateRuntimeFlags(
+            requestNumberState = RequestNumberState.IDLE,
+            storing = false
+        )
     }
     }
 }
 }

+ 19 - 8
app/src/main/java/com/example/modifier/service/ScreenInspector.kt

@@ -4,27 +4,34 @@ import android.accessibilityservice.AccessibilityService
 import android.util.Log
 import android.util.Log
 import android.view.accessibility.AccessibilityNodeInfo
 import android.view.accessibility.AccessibilityNodeInfo
 import com.example.modifier.TraverseResult
 import com.example.modifier.TraverseResult
+import com.example.modifier.baseTag
 import com.example.modifier.enums.RcsConnectionStatus
 import com.example.modifier.enums.RcsConnectionStatus
 import java.util.Optional
 import java.util.Optional
 
 
 class ScreenInspector(val context: AccessibilityService) {
 class ScreenInspector(val context: AccessibilityService) {
 
 
-    private fun traverse(node: AccessibilityNodeInfo?, result: TraverseResult) {
+    companion object {
+        private const val TAG = "$baseTag/Inspector"
+    }
+
+    private fun traverse(
+        node: AccessibilityNodeInfo?,
+        result: TraverseResult,
+        log: Boolean = false
+    ) {
         if (node == null) {
         if (node == null) {
             return
             return
         }
         }
 
 
-        val packageInfo = context.packageManager.getPackageInfo(
-            node.packageName.toString(), 0
-        )
-
         val className = node.className.toString()
         val className = node.className.toString()
         val name = node.viewIdResourceName
         val name = node.viewIdResourceName
         val text = Optional.ofNullable(node.text).map { obj: CharSequence -> obj.toString() }
         val text = Optional.ofNullable(node.text).map { obj: CharSequence -> obj.toString() }
             .orElse(null)
             .orElse(null)
         val id = node.viewIdResourceName
         val id = node.viewIdResourceName
 
 
-        Log.d(com.example.modifier.baseTag, "Node: class=$className, text=$text, name=$name, id=$id")
+        if (log) {
+            Log.d(TAG, "Node: class=$className, text=$text, name=$name, id=$id")
+        }
 
 
         if ("Compose:Draft:Send" == name) {
         if ("Compose:Draft:Send" == name) {
             result.sendBtn = node
             result.sendBtn = node
@@ -78,6 +85,10 @@ class ScreenInspector(val context: AccessibilityService) {
             result.encrypted = true
             result.encrypted = true
         }
         }
 
 
+        if ("com.google.android.apps.messaging:id/conversation_list_google_tos_popup_positive_button" == id) {
+            result.tosAgreeBtn = node
+        }
+
         if (node.childCount != 0) {
         if (node.childCount != 0) {
             for (i in 0 until node.childCount) {
             for (i in 0 until node.childCount) {
                 traverse(node.getChild(i), result)
                 traverse(node.getChild(i), result)
@@ -85,7 +96,7 @@ class ScreenInspector(val context: AccessibilityService) {
         }
         }
     }
     }
 
 
-    fun traverseNode(result: TraverseResult) {
-        traverse(context.rootInActiveWindow, result)
+    fun traverseNode(result: TraverseResult, log: Boolean = false) {
+        traverse(context.rootInActiveWindow, result, log)
     }
     }
 }
 }

+ 29 - 14
app/src/main/java/com/example/modifier/service/TaskRunner.kt

@@ -57,14 +57,19 @@ import io.ktor.client.request.prepareGet
 import io.ktor.utils.io.ByteReadChannel
 import io.ktor.utils.io.ByteReadChannel
 import io.ktor.utils.io.core.isEmpty
 import io.ktor.utils.io.core.isEmpty
 import io.ktor.utils.io.core.readBytes
 import io.ktor.utils.io.core.readBytes
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import kotlinx.coroutines.withContext
 import kotlinx.coroutines.withTimeout
 import kotlinx.coroutines.withTimeout
 import kotlinx.coroutines.withTimeoutOrNull
 import kotlinx.coroutines.withTimeoutOrNull
 import java.io.File
 import java.io.File
 import java.time.LocalDateTime
 import java.time.LocalDateTime
 import java.time.temporal.ChronoUnit
 import java.time.temporal.ChronoUnit
+import kotlin.coroutines.coroutineContext
 import kotlin.time.Duration.Companion.days
 import kotlin.time.Duration.Companion.days
 import kotlin.time.Duration.Companion.hours
 import kotlin.time.Duration.Companion.hours
 import kotlin.time.Duration.Companion.minutes
 import kotlin.time.Duration.Companion.minutes
@@ -184,12 +189,7 @@ class TaskRunner(
             for (i in 0 until taskAction.data.tasks.size) {
             for (i in 0 until taskAction.data.tasks.size) {
                 val taskItem = taskAction.data.tasks[i]
                 val taskItem = taskAction.data.tasks[i]
                 try {
                 try {
-                    if (send(
-                            taskItem.number,
-                            taskItem.message,
-                            taskConfig
-                        )
-                    ) {
+                    if (send(taskItem.number, taskItem.message, taskConfig)) {
                         success.add(taskItem.id)
                         success.add(taskItem.id)
                     } else {
                     } else {
                         fail.add(taskItem.id)
                         fail.add(taskItem.id)
@@ -387,10 +387,24 @@ class TaskRunner(
         if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
         if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
             throw RequestNumberException(ErrorCode.CODE_NUMBER_EXPIRED)
             throw RequestNumberException(ErrorCode.CODE_NUMBER_EXPIRED)
         }
         }
-        var sendOtpTimeout = ChronoUnit.SECONDS.between(
-            LocalDateTime.now(),
-            rcsNumber.expiryTime
-        ).seconds
+        var tosAgreeJob: Job? = null
+        if (rcsNumber.country.lowercase() == "af") {
+            tosAgreeJob = CoroutineScope(coroutineContext).launch {
+                run tos@{
+                    repeat(60 * 1000 / 200) {
+                        delay(200)
+                        val traverseResult = TraverseResult()
+                        screenInspector.traverseNode(traverseResult)
+                        if (traverseResult.tosAgreeBtn != null) {
+                            traverseResult.tosAgreeBtn!!.performAction(AccessibilityNodeInfo.ACTION_CLICK)
+                            return@tos
+                        }
+                    }
+                }
+            }
+        }
+        var sendOtpTimeout =
+            ChronoUnit.SECONDS.between(LocalDateTime.now(), rcsNumber.expiryTime).seconds
         if (sendOtpTimeout < 5.seconds) {
         if (sendOtpTimeout < 5.seconds) {
             throw RequestNumberException(ErrorCode.CODE_TIMEOUT_TOO_SHORT)
             throw RequestNumberException(ErrorCode.CODE_TIMEOUT_TOO_SHORT)
         }
         }
@@ -402,6 +416,7 @@ class TaskRunner(
                 sendOtpTimeout
                 sendOtpTimeout
             ) != RcsConfigureState.WAITING_FOR_OTP
             ) != RcsConfigureState.WAITING_FOR_OTP
         ) {
         ) {
+            tosAgreeJob?.cancel()
             if (!screenController.toggleRcsSwitch(true)) {
             if (!screenController.toggleRcsSwitch(true)) {
                 throw RequestNumberException(ErrorCode.CODE_RCS_TOGGLED_OFF)
                 throw RequestNumberException(ErrorCode.CODE_RCS_TOGGLED_OFF)
             }
             }
@@ -410,7 +425,7 @@ class TaskRunner(
             }
             }
             throw RequestNumberException(ErrorCode.CODE_OTP_NOT_SENT)
             throw RequestNumberException(ErrorCode.CODE_OTP_NOT_SENT)
         }
         }
-
+        tosAgreeJob?.cancel()
         RcsNumberApi.notifyOtpState(rcsNumber.id)
         RcsNumberApi.notifyOtpState(rcsNumber.id)
 
 
         if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
         if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
@@ -455,6 +470,9 @@ class TaskRunner(
             throw RequestNumberException(ErrorCode.CODE_OTP_VERIFY_FAILED)
             throw RequestNumberException(ErrorCode.CODE_OTP_VERIFY_FAILED)
         } else {
         } else {
             RcsNumberApi.notifyConfigured(rcsNumber.id)
             RcsNumberApi.notifyConfigured(rcsNumber.id)
+            delay(5000)
+            shellRun(PACKAGE_MESSAGING.kill(), "sleep 1", CMD_MESSAGING_APP)
+            delay(2000)
         }
         }
     }
     }
 
 
@@ -537,9 +555,6 @@ class TaskRunner(
             appStateRepo.resetSuccessNum()
             appStateRepo.resetSuccessNum()
             appStateRepo.resetExecutedNum()
             appStateRepo.resetExecutedNum()
             Log.i(tag, "requestNumber success")
             Log.i(tag, "requestNumber success")
-            delay(5000)
-            shellRun(PACKAGE_MESSAGING.kill(), "sleep 1", CMD_MESSAGING_APP)
-            delay(2000)
         } else {
         } else {
             Log.e(tag, "requestNumber failed")
             Log.e(tag, "requestNumber failed")
             appStateRepo.updateSend(false)
             appStateRepo.updateSend(false)

+ 0 - 2
app/src/main/java/com/example/modifier/ui/settings/SettingsFragment.kt

@@ -91,7 +91,6 @@ class SettingsFragment : Fragment() {
         inflater: LayoutInflater, container: ViewGroup?,
         inflater: LayoutInflater, container: ViewGroup?,
         savedInstanceState: Bundle?
         savedInstanceState: Bundle?
     ): View {
     ): View {
-        Log.i(tag, "SettingsFragment.onCreateView")
         if (!this::binding.isInitialized) {
         if (!this::binding.isInitialized) {
             binding = FragmentSettingsBinding.inflate(inflater, container, false)
             binding = FragmentSettingsBinding.inflate(inflater, container, false)
             binding.tlIccid.setEndIconOnClickListener {
             binding.tlIccid.setEndIconOnClickListener {
@@ -307,7 +306,6 @@ class SettingsFragment : Fragment() {
         viewLifecycleOwner.lifecycleScope.launch {
         viewLifecycleOwner.lifecycleScope.launch {
             launch {
             launch {
                 appPrefsRepo.appPrefs.collect {
                 appPrefsRepo.appPrefs.collect {
-                    Log.i(tag, "appPreferencesRepository.collect")
                     binding.etServer.setText(it.server)
                     binding.etServer.setText(it.server)
                     binding.etDeviceLabel.setText(it.name)
                     binding.etDeviceLabel.setText(it.name)
                     binding.switchClean.isChecked = it.preventClean
                     binding.switchClean.isChecked = it.preventClean