xiongzhu 1 سال پیش
والد
کامیت
300a78e3fe

+ 27 - 13
app/src/main/java/com/example/modifier/Global.kt

@@ -140,6 +140,21 @@ object Global {
         }
     }
 
+    fun saveMock() {
+        save(
+            TelephonyConfig(
+                number = "9043351752",
+                mcc = "310",
+                mnc = "240",
+                iccid = genICCID("310", "1"),
+                "310240" + RandomStringUtils.randomNumeric(9),
+                Utils.generateIMEI(),
+                "us",
+                "1"
+            )
+        )
+    }
+
     @JvmStatic
     fun clear(gsf: Boolean, gms: Boolean, sms: Boolean) {
         try {
@@ -320,30 +335,29 @@ object Global {
     }
 
     @JvmStatic
-    fun resetAll() {
+    suspend fun resetAll() {
         val context = Utils.getContext()
         try {
             val dataDir = ContextCompat.getDataDir(context)
             Utils.copyAssetFolder(context.assets, "providerDB", File(dataDir, "providerDB").path)
             val providerDBPath = File(dataDir, "providerDB/mmssms.db").path
 
-            Utils.runAsRoot(
+            shellRun(
                 "cp $providerDBPath /data/data/com.android.providers.telephony/databases/mmssms.db",
                 "chmod 660 /data/data/com.android.providers.telephony/databases/mmssms.db",
-                "pm suspend com.google.android.apps.messaging",
-                "am force-stop com.google.android.apps.messaging",
-                "pm clear com.google.android.apps.messaging",
-                "pm clear com.google.android.gsf",
-                "pm clear com.google.android.gms",
+                CMD_SUSPEND_MESSAGING_APP,
+                CMD_KILL_MESSAGING_APP,
+                CMD_CLEAR_MESSAGING_APP,
+                CMD_CLEAR_GSF,
+                CMD_CLEAR_GMS,
                 "sleep 1",
-                "am start com.android.vending",
+                CMD_START_PLAY_STORE,
                 "sleep 1",
-                "input keyevent KEYCODE_HOME",
-                "sleep 10",
-                "pm clear com.google.android.gms",
-                "pm unsuspend com.google.android.apps.messaging",
+                CMD_HOME,
                 "sleep 1",
-                "am start com.google.android.apps.messaging"
+                CMD_CLEAR_GMS,
+                CMD_RESUME_MESSAGING_APP,
+                CMD_MESSAGING_APP
             )
         } catch (e: Exception) {
             e.printStackTrace()

+ 26 - 0
app/src/main/java/com/example/modifier/ShellCommands.kt

@@ -16,3 +16,29 @@ const val CMD_BACK = "input keyevent KEYCODE_BACK"
 const val CMD_HOME = "input keyevent KEYCODE_HOME"
 
 const val CMD_BACK_APP = "am start ${BuildConfig.APPLICATION_ID}/.MainActivity"
+
+const val CMD_CLEAR_MESSAGING_APP = "pm clear com.google.android.apps.messaging"
+
+const val CMD_CLEAR_GMS = "pm clear com.google.android.gms"
+
+const val CMD_CLEAR_GSF = "pm clear com.google.android.gsf"
+
+const val CMD_SUSPEND_MESSAGING_APP = "pm suspend com.google.android.apps.messaging"
+
+const val CMD_SUSPEND_GMS = "pm suspend com.google.android.gms"
+
+const val CMD_SUSPEND_GSF = "pm suspend com.google.android.gsf"
+
+const val CMD_RESUME_MESSAGING_APP = "pm unsuspend com.google.android.apps.messaging"
+
+const val CMD_RESUME_GMS = "pm unsuspend com.google.android.gms"
+
+const val CMD_RESUME_GSF = "pm unsuspend com.google.android.gsf"
+
+const val CMD_KILL_MESSAGING_APP = "am force-stop com.google.android.apps.messaging"
+
+const val CMD_KILL_GMS = "am force-stop com.google.android.gms"
+
+const val CMD_KILL_GSF = "am force-stop com.google.android.gsf"
+
+const val CMD_START_PLAY_STORE = "am start com.android.vending"

+ 35 - 0
app/src/main/java/com/example/modifier/Utils.java

@@ -16,6 +16,7 @@ import com.google.android.material.progressindicator.CircularProgressIndicatorSp
 import com.google.android.material.progressindicator.IndeterminateDrawable;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import java.io.DataOutputStream;
@@ -28,6 +29,7 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
@@ -165,6 +167,39 @@ public class Utils {
     }
 
     public static String generateIMEI() {
+        int pos;
+        int[] str = Arrays.stream(("35684610" + RandomStringUtils.randomNumeric(7)).split("")).mapToInt(Integer::parseInt).toArray();
+        int sum = 0;
+        int final_digit;
+        int t;
+        int len_offset;
+        int len = 15;
+        String imei = "";
+
+        len_offset = (len + 1) % 2;
+        for (pos = 0; pos < len - 1; pos++) {
+            if ((pos + len_offset) % 2 != 0) {
+                t = str[pos] * 2;
+                if (t > 9) {
+                    t -= 9;
+                }
+                sum += t;
+            } else {
+                sum += str[pos];
+            }
+        }
+
+        final_digit = (10 - (sum % 10)) % 10;
+        str[len - 1] = final_digit;
+
+        for (int d : str) {
+            imei += String.valueOf(d);
+        }
+
+        return imei;
+    }
+
+    public static String generateIMEI1() {
         int pos;
         int[] str = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
         int sum = 0;

+ 100 - 16
app/src/main/java/com/example/modifier/service/ModifierService.kt

@@ -34,8 +34,14 @@ import androidx.lifecycle.liveData
 import com.example.modifier.BuildConfig
 import com.example.modifier.CMD_BACK
 import com.example.modifier.CMD_CONVERSATION_LIST_ACTIVITY
+import com.example.modifier.CMD_KILL_GMS
+import com.example.modifier.CMD_KILL_MESSAGING_APP
 import com.example.modifier.CMD_MESSAGING_APP
 import com.example.modifier.CMD_RCS_SETTINGS_ACTIVITY
+import com.example.modifier.CMD_RESUME_GMS
+import com.example.modifier.CMD_RESUME_MESSAGING_APP
+import com.example.modifier.CMD_SUSPEND_GMS
+import com.example.modifier.CMD_SUSPEND_MESSAGING_APP
 import com.example.modifier.Global
 import com.example.modifier.Global.load
 import com.example.modifier.Global.resetAll
@@ -75,6 +81,7 @@ 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 kotlinx.serialization.json.Json
@@ -693,8 +700,15 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
             }
         }
         binding.btnInspect.setOnClickListener {
-           CoroutineScope(Dispatchers.IO).launch {
-               toggleRcsSwitch(false)
+            traverseNode(rootInActiveWindow, TraverseResult())
+        }
+        binding.btnReset.setOnClickListener {
+            binding.btnReset.isEnabled = false
+            CoroutineScope(Dispatchers.IO).launch {
+                reset()
+                withContext(Dispatchers.Main) {
+                    binding.btnReset.isEnabled = true
+                }
             }
         }
         binding.btnCheck.setOnClickListener {
@@ -707,6 +721,24 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                 storeNumbers()
             }
         }
+        binding.btnToggleOn.setOnClickListener {
+            binding.btnToggleOn.isEnabled = false
+            CoroutineScope(Dispatchers.IO).launch {
+                toggleRcsSwitch(true)
+                withContext(Dispatchers.Main) {
+                    binding.btnToggleOn.isEnabled = true
+                }
+            }
+        }
+        binding.btnToggleOff.setOnClickListener {
+            binding.btnToggleOff.isEnabled = false
+            CoroutineScope(Dispatchers.IO).launch {
+                toggleRcsSwitch(false)
+                withContext(Dispatchers.Main) {
+                    binding.btnToggleOff.isEnabled = true
+                }
+            }
+        }
         busy.observeForever {
             reportDeviceStatues()
         }
@@ -762,23 +794,24 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
     private suspend fun toggleRcsSwitch(on: Boolean, retry: Int = 3): Boolean {
         val res = TraverseResult()
 
-        val success = run {
-            shellRun(CMD_RCS_SETTINGS_ACTIVITY, "sleep 1")
+        shellRun(CMD_RCS_SETTINGS_ACTIVITY, "sleep 0.5")
+        val success = run repeatBlock@{
+
             repeat(retry) {
                 res.rcsSwitch = null
                 traverseNode(rootInActiveWindow, res)
                 if (res.rcsSwitch == null) {
-                    shellRun(CMD_BACK, "sleep 2", CMD_RCS_SETTINGS_ACTIVITY, "sleep 1")
+                    shellRun(CMD_BACK, "sleep 0.5", CMD_RCS_SETTINGS_ACTIVITY, "sleep 0.5")
                 } else {
                     if (res.rcsSwitch!!.isChecked == on) {
-                        return true
+                        return@repeatBlock true
                     }
                     val rect = Rect()
                     res.rcsSwitch!!.getBoundsInScreen(rect)
                     if (on) {
                         shellRun(
-                            "input tap ${rect.centerX()} ${rect.centerY()}",
-                            "sleep 1", CMD_BACK, "sleep 1",
+                            "input tap ${rect.centerX()} ${rect.centerY()}", "sleep 1",
+                            CMD_BACK, "sleep 0.5",
                             CMD_RCS_SETTINGS_ACTIVITY, "sleep 1",
                         )
                     } else {
@@ -788,22 +821,72 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                         rootInActiveWindow.findAccessibilityNodeInfosByViewId("android:id/button1")
                             .firstOrNull()?.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                         shellRun(
-                            "sleep 1", CMD_BACK, "sleep 1",
-                            CMD_RCS_SETTINGS_ACTIVITY, "sleep 1",
+                            "sleep 0.5", CMD_BACK, "sleep 0.5",
+                            CMD_RCS_SETTINGS_ACTIVITY, "sleep 0.5",
                         )
                     }
+                    res.rcsSwitch = null
                     traverseNode(rootInActiveWindow, res)
-                    if (res.rcsSwitch!!.isChecked == on) {
-                        return true
+                    if (res.rcsSwitch?.isChecked == on) {
+                        return@repeatBlock true
                     }
                 }
             }
             false
         }
-        shellRun(CMD_BACK, "sleep 1")
+        shellRun(CMD_BACK, "sleep 0.5")
         return success
     }
 
+    private suspend fun reset() {
+        withTimeout(1.hours) {
+            while (true) {
+                delay(100)
+                withContext(Dispatchers.Main) {
+                    binding.tvLog.text = "Waiting for RCS switch on..."
+                }
+                rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
+                Global.saveMock()
+                resetAll()
+                var switchAppear = waitForRcsState(
+                    arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
+                    1.minutes
+                )?.let {
+                    it == RcsConfigureState.WAITING_FOR_DEFAULT_ON
+                }
+                if (switchAppear != true) {
+                    shellRun(
+                        CMD_KILL_GMS, CMD_KILL_MESSAGING_APP, "sleep 1",
+                        CMD_MESSAGING_APP
+                    )
+                    switchAppear = waitForRcsState(
+                        arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
+                        2.minutes
+                    )?.let {
+                        it == RcsConfigureState.WAITING_FOR_DEFAULT_ON
+                    }
+                    if (switchAppear != true) {
+                        Log.e(TAG, "RCS not entered default on state, retrying...")
+                        continue
+                    }
+                }
+                val switchOn = toggleRcsSwitch(true)
+                if (!switchOn) {
+                    Log.e(TAG, "RCS switch not turned on, retrying...")
+                    continue
+                }
+                val resetSuccess = waitForRcsState(
+                    arrayOf(
+                        RcsConfigureState.READY
+                    ), 3.minutes
+                )
+                Log.i(TAG, "waitForRcsState: $resetSuccess")
+                requestNumberCount = 0
+                break
+            }
+        }
+    }
+
     private suspend fun requestNumber() {
         val color = ContextCompat.getColorStateList(binding.root.context, R.color.btn_color)
         binding.btnReq.backgroundTintList = color
@@ -863,7 +946,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                         )
                     )
 
-                    if (needRest &&
+                    if (requestNumberCount > 5 &&
                         !getSharedPreferences("settings", Context.MODE_PRIVATE)
                             .getBoolean("do_not_reset", false)
                     ) {
@@ -896,8 +979,9 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                                     ), 3.minutes
                                 )
                                 Log.i(TAG, "waitForRcsState: $resetSuccess")
-                                Global.suspend(gms = true, sms = true)
-                                Global.unsuspend(gms = true, sms = true)
+                                toggleRcsSwitch(false)
+                                delay(500)
+                                toggleRcsSwitch(true)
                                 requestNumberCount = 0
                                 break
                             }

+ 11 - 11
app/src/main/java/com/example/modifier/ui/utils/UtilsFragment.kt

@@ -261,26 +261,26 @@ class UtilsFragment : Fragment() {
     private fun onClear() {
         binding.btnClear.isEnabled = false
         Utils.makeLoadingButton(context, binding.btnClear)
-        executor.execute {
-            val all = binding.cbAll.isChecked
-            val gsf = binding.cbGsf.isChecked
-            val gms = binding.cbGms.isChecked
-            val sms = binding.cbSms.isChecked
+        val all = binding.cbAll.isChecked
+        val gsf = binding.cbGsf.isChecked
+        val gms = binding.cbGms.isChecked
+        val sms = binding.cbSms.isChecked
+        CoroutineScope(Dispatchers.IO).launch {
             if (all) {
                 resetAll()
             } else {
                 clear(gsf, gms, sms)
             }
-            handler.post {
+            withContext(Dispatchers.Main) {
                 binding.btnClear.setIconResource(R.drawable.ic_done)
                 binding.btnClear.text = "OK"
-                handler.postDelayed({
-                    binding.btnClear.isEnabled = true
-                    binding.btnClear.icon = null
-                    binding.btnClear.text = "Clear"
-                }, 1500)
+                delay(1500)
+                binding.btnClear.isEnabled = true
+                binding.btnClear.icon = null
+                binding.btnClear.text = "Clear"
             }
         }
+
     }
 
     private fun onStopClick() {

+ 10 - 0
app/src/main/res/drawable/ic_toggle_off.xml

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M280,720Q180,720 110,650Q40,580 40,480Q40,380 110,310Q180,240 280,240L680,240Q780,240 850,310Q920,380 920,480Q920,580 850,650Q780,720 680,720L280,720ZM280,640L680,640Q746,640 793,593Q840,546 840,480Q840,414 793,367Q746,320 680,320L280,320Q214,320 167,367Q120,414 120,480Q120,546 167,593Q214,640 280,640ZM280,600Q330,600 365,565Q400,530 400,480Q400,430 365,395Q330,360 280,360Q230,360 195,395Q160,430 160,480Q160,530 195,565Q230,600 280,600ZM480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
+</vector>

+ 10 - 0
app/src/main/res/drawable/ic_toggle_on.xml

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M280,720Q180,720 110,650Q40,580 40,480Q40,380 110,310Q180,240 280,240L680,240Q780,240 850,310Q920,380 920,480Q920,580 850,650Q780,720 680,720L280,720ZM280,640L680,640Q746,640 793,593Q840,546 840,480Q840,414 793,367Q746,320 680,320L280,320Q214,320 167,367Q120,414 120,480Q120,546 167,593Q214,640 280,640ZM680,600Q730,600 765,565Q800,530 800,480Q800,430 765,395Q730,360 680,360Q630,360 595,395Q560,430 560,480Q560,530 595,565Q630,600 680,600ZM480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
+</vector>

+ 35 - 7
app/src/main/res/layout/floating_window.xml

@@ -74,17 +74,19 @@
                         android:textSize="12sp" />
                 </ScrollView>
 
-                <LinearLayout
+                <GridLayout
+
                     android:id="@+id/btns"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:orientation="horizontal"
+                    android:columnCount="3"
                     app:layout_constraintBottom_toBottomOf="parent"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent">
 
                     <com.google.android.material.button.MaterialButton
                         android:id="@+id/btn_req"
+                        style="?attr/materialIconButtonFilledStyle"
                         android:layout_width="50dp"
                         android:layout_height="34dp"
                         android:backgroundTint="@color/btn_color"
@@ -93,12 +95,22 @@
                         app:iconGravity="textStart"
                         app:iconPadding="0dp" />
 
+                    <com.google.android.material.button.MaterialButton
+                        android:id="@+id/btn_reset"
+                        style="?attr/materialIconButtonOutlinedStyle"
+                        android:layout_width="50dp"
+                        android:layout_height="34dp"
+                        android:layout_marginHorizontal="4dp"
+                        android:padding="0dp"
+                        app:icon="@drawable/ic_refresh"
+                        app:iconGravity="textStart"
+                        app:iconPadding="0dp" />
+
                     <com.google.android.material.button.MaterialButton
                         android:id="@+id/btn_inspect"
                         style="?attr/materialIconButtonOutlinedStyle"
                         android:layout_width="50dp"
                         android:layout_height="34dp"
-                        android:layout_marginLeft="8dp"
                         android:padding="0dp"
                         app:icon="@drawable/ic_manage_search"
                         app:iconGravity="textStart"
@@ -109,7 +121,7 @@
                         style="?attr/materialIconButtonFilledTonalStyle"
                         android:layout_width="50dp"
                         android:layout_height="34dp"
-                        android:layout_marginLeft="8dp"
+                        android:layout_marginTop="-7dp"
                         android:padding="0dp"
                         app:icon="@drawable/ic_ecg_heart"
                         app:iconGravity="textStart"
@@ -120,12 +132,28 @@
                         style="?attr/materialIconButtonFilledTonalStyle"
                         android:layout_width="50dp"
                         android:layout_height="34dp"
-                        android:layout_marginLeft="8dp"
-                        android:padding="0dp"
                         app:icon="@drawable/ic_archive"
                         app:iconGravity="textStart"
                         app:iconPadding="0dp" />
-                </LinearLayout>
+
+                    <com.google.android.material.button.MaterialButton
+                        android:id="@+id/btn_toggle_on"
+                        style="?attr/materialIconButtonFilledTonalStyle"
+                        android:layout_width="50dp"
+                        android:layout_height="34dp"
+                        app:icon="@drawable/ic_toggle_on"
+                        app:iconGravity="textStart"
+                        app:iconPadding="0dp" />
+
+                    <com.google.android.material.button.MaterialButton
+                        android:id="@+id/btn_toggle_off"
+                        style="?attr/materialIconButtonFilledTonalStyle"
+                        android:layout_width="50dp"
+                        android:layout_height="34dp"
+                        app:icon="@drawable/ic_toggle_off"
+                        app:iconGravity="textStart"
+                        app:iconPadding="0dp" />
+                </GridLayout>
             </androidx.constraintlayout.widget.ConstraintLayout>
         </com.google.android.material.card.MaterialCardView>
     </FrameLayout>

+ 4 - 1
app/src/test/java/com/example/modifier/ExampleUnitTest.kt

@@ -1,5 +1,7 @@
 package com.example.asdfasdfawf
 
+import com.example.modifier.Global
+import com.example.modifier.Utils
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.coroutineScope
@@ -23,7 +25,8 @@ import java.time.format.DateTimeFormatter
 class ExampleUnitTest {
     @Test
     fun test1() {
-        println(String.format("%02d", "1".toInt()))
+        println(Utils.generateIMEI())
+        println(Utils.generateIMEI1())
     }