xiongzhu 11 месяцев назад
Родитель
Сommit
67bc6d79d0

+ 1 - 1
app/build.gradle

@@ -24,7 +24,7 @@ android {
         applicationId "com.example.modifier"
         minSdk 33
         targetSdk 34
-        versionCode 162
+        versionCode 163
         versionName "1.0.1"
         archivesBaseName = "modifier-${versionCode}"
 

+ 47 - 1
app/src/main/AndroidManifest.xml

@@ -76,6 +76,20 @@
 
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <action android:name="android.intent.action.SENDTO" />
+
+                <category android:name="android.intent.category.DEFAULT" />
+
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.SENDTO" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="smsto" />
+            </intent-filter>
         </activity>
 
         <service
@@ -106,6 +120,38 @@
                 android:name="android.support.FILE_PROVIDER_PATHS"
                 android:resource="@xml/file_paths" />
         </provider>
-    </application>
 
+        <service
+            android:name=".sms.SmsService"
+            android:exported="true"
+            android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
+            <intent-filter>
+                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="smsto" />
+            </intent-filter>
+        </service>
+
+        <receiver
+            android:name=".sms.SmsReceiver"
+            android:exported="true"
+            android:permission="android.permission.BROADCAST_SMS">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.SMS_DELIVER" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
+            </intent-filter>
+        </receiver>
+
+        <receiver
+            android:name=".sms.MmsReceiver"
+            android:exported="true"
+            android:permission="android.permission.BROADCAST_WAP_PUSH">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
+                <data android:mimeType="application/vnd.wap.mms-message" />
+            </intent-filter>
+        </receiver>
+    </application>
 </manifest>

+ 64 - 21
app/src/main/java/com/example/modifier/MainActivity.kt

@@ -1,12 +1,13 @@
 package com.example.modifier
 
-import android.content.Context
+import android.app.role.RoleManager
 import android.content.DialogInterface
 import android.content.Intent
 import android.net.Uri
 import android.os.Bundle
 import android.provider.Settings
 import android.util.Log
+import android.widget.Toast
 import androidx.activity.enableEdgeToEdge
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.appcompat.app.AppCompatActivity
@@ -27,13 +28,30 @@ import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 
 class MainActivity : AppCompatActivity() {
+    companion object {
+        const val TAG = "MainActivity"
+        const val CODE_CLEAN = 100
+    }
+
     private lateinit var mBinding: ActivityMainBinding
+    private var mTmpCallback: ((success: Boolean) -> Unit)? = null
+    var a11yRegister = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+        if (it.resultCode == RESULT_OK) {
+
+        } else {
 
-    var r = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
-        requestSystemAlertWindowPermission()
+        }
+    }
+    var smsRegister = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+        if (it.resultCode == RESULT_OK) {
+            deleteAllSms(mTmpCallback)
+        } else {
+            mTmpCallback?.invoke(false)
+        }
     }
 
     override fun onCreate(savedInstanceState: Bundle?) {
+        Log.i(TAG, "onCreate")
         super.onCreate(savedInstanceState)
         enableEdgeToEdge()
         mBinding = ActivityMainBinding.inflate(layoutInflater)
@@ -66,27 +84,28 @@ class MainActivity : AppCompatActivity() {
             }
             Log.i("getIPAddress", getIPAddress().joinToString())
         }
+        checkCleanIntent(intent)
     }
 
-    private fun requestSystemAlertWindowPermission(): Boolean {
-        if (!Settings.canDrawOverlays(this)) {
-            MaterialAlertDialogBuilder(this)
-                .setTitle("Operation Needed")
-                .setMessage("Enable System Alert Window Permission")
-                .setCancelable(false)
-                .setPositiveButton("OK") { _: DialogInterface?, _: Int ->
-                    val intent = Intent(
-                        Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
-                        Uri.parse("package:$packageName")
-                    )
-                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-                    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
-                    r.launch(intent)
+    override fun onNewIntent(intent: Intent) {
+        super.onNewIntent(intent)
+        Log.i(TAG, "onNewIntent")
+        checkCleanIntent(intent)
+    }
+
+    fun checkCleanIntent(intent: Intent) {
+        if (intent.getBooleanExtra("clean", false)) {
+            intent.removeExtra("clean")
+            checkPermissionAndClean {
+                if (it) {
+                    Log.i(TAG, "SMS Cleaned")
+                    Toast.makeText(this, "SMS Cleaned", Toast.LENGTH_SHORT).show()
+                } else {
+                    Log.e(TAG, "Failed to clean SMS")
+                    Toast.makeText(this, "Failed to clean SMS", Toast.LENGTH_SHORT).show()
                 }
-                .show()
-            return false
+            }
         }
-        return true
     }
 
     private fun requestAccessibilityPermission(): Boolean {
@@ -99,11 +118,35 @@ class MainActivity : AppCompatActivity() {
                     val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
                     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                     intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
-                    r.launch(intent)
+                    a11yRegister.launch(intent)
                 }
                 .show()
             return false
         }
         return true
     }
+
+    private fun checkPermissionAndClean(callback: (success: Boolean) -> Unit) {
+        mTmpCallback = callback
+        val roleManager = applicationContext.getSystemService(RoleManager::class.java)
+        if (roleManager.isRoleAvailable(RoleManager.ROLE_SMS)) {
+            if (roleManager.isRoleHeld(RoleManager.ROLE_SMS)) {
+                deleteAllSms(callback)
+            } else {
+                val roleRequestIntent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS)
+                smsRegister.launch(roleRequestIntent)
+            }
+        }
+    }
+
+    private fun deleteAllSms(callback: ((success: Boolean) -> Unit)?) {
+        try {
+            val cr = contentResolver
+            cr.delete(Uri.parse("content://sms/"), null, null)
+            callback?.invoke(true)
+        } catch (e: Exception) {
+            Log.wtf(TAG, "Error: " + e.message, e)
+            callback?.invoke(false)
+        }
+    }
 }

+ 1 - 1
app/src/main/java/com/example/modifier/constants/SIMView.kt

@@ -4,7 +4,7 @@ object SIMView {
 
     const val AID_CUSTOM = "D07002CA44900101"
 
-    const val AID_USIM = "A0000000871002FF86FFFF89FFFFFFFF00"
+    const val AID_USIM = "A0000000871002FF86FFFF89FFFFFFFF"
 
     // ------------------------------- Constants ------------------------------
     /** File identifier : MF = "3F00"                                         */

+ 50 - 50
app/src/main/java/com/example/modifier/repo/SpoofedSimInfoRepo.kt

@@ -174,74 +174,74 @@ class SpoofedSimInfoRepo private constructor(private val context: Context) {
                         PACKAGE_GMS.kill(),
                         PACKAGE_MESSAGING.kill()
                     )
-                }
 
-                val plmn = spoofedSimInfo.mcc + spoofedSimInfo.mnc
-                val plmnHex = SimEncoder.encPLMN(spoofedSimInfo.mcc + spoofedSimInfo.mnc)
-                val plmnwactHex = SimEncoder.encPLMNwAcT("$plmn:4000,$plmn:8000,$plmn:0080")
-                val fplmn =
-                    SimEncoder.encPLMN("46000,46001,46002,46006,46007,46011,46012,46015,46020")
-                val telephonyManager =
-                    context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
-                val apduChannel = ApduChannel(telephonyManager, SIMView.AID_CUSTOM)
-                apduChannel.select(SIMView.FID_MF)
-                apduChannel.select(SIMView.FID_EF_ICCID)
-                apduChannel.writeBinary(SimEncoder.encICCID(spoofedSimInfo.iccid))
 
-                apduChannel.select(SIMView.FID_MF)
-                apduChannel.select(SIMView.FID_DF_TELECOM)
-                apduChannel.select(SIMView.FID_EF_MSISDN)
-                apduChannel.writeRecord(
-                    1, SimEncoder.encMSISDN(spoofedSimInfo.number)
-                        .padStart(56, 'F')
-                )
+                    val plmn = spoofedSimInfo.mcc + spoofedSimInfo.mnc
+                    val plmnHex = SimEncoder.encPLMN(spoofedSimInfo.mcc + spoofedSimInfo.mnc)
+                    val plmnwactHex = SimEncoder.encPLMNwAcT("$plmn:4000,$plmn:8000,$plmn:0080")
+                    val fplmn =
+                        SimEncoder.encPLMN("46000,46001,46002,46006,46007,46011,46012,46015,46020")
+                    val telephonyManager =
+                        context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+                    val apduChannel = ApduChannel(telephonyManager, SIMView.AID_CUSTOM)
+                    apduChannel.select(SIMView.FID_MF)
+                    apduChannel.select(SIMView.FID_EF_ICCID)
+                    apduChannel.writeBinary(SimEncoder.encICCID(spoofedSimInfo.iccid))
+
+                    apduChannel.select(SIMView.FID_MF)
+                    apduChannel.select(SIMView.FID_DF_TELECOM)
+                    apduChannel.select(SIMView.FID_EF_MSISDN)
+                    apduChannel.writeRecord(
+                        1, SimEncoder.encMSISDN(spoofedSimInfo.number)
+                            .padStart(56, 'F')
+                    )
 
-                apduChannel.select(SIMView.FID_MF)
-                apduChannel.select(SIMView.FID_DF_GSM)
-                apduChannel.select(SIMView.FID_EF_IMSI)
-                apduChannel.writeBinary(SimEncoder.encIMSI(spoofedSimInfo.imsi))
+                    apduChannel.select(SIMView.FID_MF)
+                    apduChannel.select(SIMView.FID_DF_GSM)
+                    apduChannel.select(SIMView.FID_EF_IMSI)
+                    apduChannel.writeBinary(SimEncoder.encIMSI(spoofedSimInfo.imsi))
 
-                apduChannel.select(SIMView.FID_EF_PLMNSEL)
-                apduChannel.writeBinary(plmnHex.padEnd(120, 'f'))
+                    apduChannel.select(SIMView.FID_EF_PLMNSEL)
+                    apduChannel.writeBinary(plmnHex.padEnd(120, 'f'))
 
-                apduChannel.select(SIMView.FID_EF_EHPLMN)
-                apduChannel.writeBinary(plmnHex.padEnd(24, 'f'))
+                    apduChannel.select(SIMView.FID_EF_EHPLMN)
+                    apduChannel.writeBinary(plmnHex.padEnd(24, 'f'))
 
-                apduChannel.select(SIMView.FID_EF_PLMNWACT)
-                apduChannel.writeBinary(plmnwactHex.padEnd(240, 'f'))
+                    apduChannel.select(SIMView.FID_EF_PLMNWACT)
+                    apduChannel.writeBinary(plmnwactHex.padEnd(240, 'f'))
 
-                apduChannel.select(SIMView.FID_EF_OPLMNWACT)
-                apduChannel.writeBinary(plmnwactHex.padEnd(120, 'f'))
+                    apduChannel.select(SIMView.FID_EF_OPLMNWACT)
+                    apduChannel.writeBinary(plmnwactHex.padEnd(120, 'f'))
 
-                apduChannel.select(SIMView.FID_EF_HPLMNWACT)
-                apduChannel.writeBinary(plmnwactHex.padEnd(40, 'f'))
+                    apduChannel.select(SIMView.FID_EF_HPLMNWACT)
+                    apduChannel.writeBinary(plmnwactHex.padEnd(40, 'f'))
 
-                apduChannel.select(SIMView.FID_EF_FPLMN)
-                apduChannel.writeBinary(fplmn.padEnd(60, 'f'))
+                    apduChannel.select(SIMView.FID_EF_FPLMN)
+                    apduChannel.writeBinary(fplmn.padEnd(60, 'f'))
 
-                if (plmn.isNotEmpty()) {
-                    if (plmn.length == 5) {
-                        apduChannel.select(SIMView.FID_EF_AD)
-                        apduChannel.writeBinary("00000102")
-                    } else if (plmn.length == 6) {
-                        apduChannel.select(SIMView.FID_EF_AD)
-                        apduChannel.writeBinary("00000103")
+                    if (plmn.isNotEmpty()) {
+                        if (plmn.length == 5) {
+                            apduChannel.select(SIMView.FID_EF_AD)
+                            apduChannel.writeBinary("00000102")
+                        } else if (plmn.length == 6) {
+                            apduChannel.select(SIMView.FID_EF_AD)
+                            apduChannel.writeBinary("00000103")
+                        }
                     }
-                }
-                apduChannel.close()
+                    apduChannel.close()
 
-                val apduChannel1 = ApduChannel(telephonyManager, SIMView.AID_USIM)
-                apduChannel1.writeMSISDN_USIM(spoofedSimInfo.number)
-                apduChannel.close()
+                    val apduChannel1 = ApduChannel(telephonyManager, SIMView.AID_USIM)
+                    apduChannel1.writeMSISDN_USIM(spoofedSimInfo.number)
+                    apduChannel.close()
 
-                telephonyManager.rebootModem()
-                delay(5000)
+                    telephonyManager.rebootModem()
+                    delay(5000)
 
-                if (suspend == true) {
                     shellRun(
                         PACKAGE_GMS.kill(),
                         PACKAGE_MESSAGING.kill()
                     )
+                    delay(1000)
                     resumePackage(PACKAGE_GMS, PACKAGE_MESSAGING)
                 }
             }

+ 5 - 8
app/src/main/java/com/example/modifier/service/ModifierService.kt

@@ -21,6 +21,7 @@ import android.view.View.OnTouchListener
 import android.view.View.VISIBLE
 import android.view.WindowManager
 import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityNodeInfo
 import android.widget.CompoundButton
 import android.widget.FrameLayout
 import androidx.annotation.MenuRes
@@ -49,6 +50,7 @@ import com.example.modifier.utils.killPhoneProcess
 import com.example.modifier.utils.optimize
 import com.example.modifier.utils.restartSelf
 import com.example.modifier.utils.setBatteryLevel
+import com.example.modifier.utils.smsIntent
 import com.example.modifier.utils.syncTime
 import com.google.android.material.color.DynamicColors
 import kotlinx.coroutines.CoroutineScope
@@ -91,7 +93,7 @@ class ModifierService : AccessibilityService() {
     private lateinit var uiContext: Context
 
     override fun onAccessibilityEvent(event: AccessibilityEvent) {
-//        Log.w(TAG, "AccessibilityEvent: type=${event.eventType} text=${event.text}")
+        Log.w(TAG, "AccessibilityEvent: type=${event.eventType} text=${event.text}")
         if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
             if (event.text.any { it.contains("允许 USB 调试吗?") || it.contains("Allow USB debugging?") }) {
                 CoroutineScope(Dispatchers.IO).launch {
@@ -407,13 +409,8 @@ class ModifierService : AccessibilityService() {
                         }
                     }
 
-                    R.id.settings -> {
-                        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
-                        val uri: Uri =
-                            Uri.fromParts("package", "com.google.android.apps.messaging", null)
-                        intent.setData(uri)
-                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-                        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                    R.id.set_default -> {
+                        val intent = smsIntent("10086", "test", null)
                         startActivity(intent)
                     }
 

+ 26 - 4
app/src/main/java/com/example/modifier/service/ScreenController.kt

@@ -8,6 +8,8 @@ import android.graphics.Rect
 import android.provider.Settings
 import android.util.Log
 import android.view.accessibility.AccessibilityNodeInfo
+import androidx.core.content.ContextCompat
+import com.example.modifier.R
 import com.example.modifier.TraverseResult
 import com.example.modifier.constants.CMD_BACK
 import com.example.modifier.constants.CMD_RCS_SETTINGS_ACTIVITY
@@ -165,7 +167,7 @@ class ScreenController(val context: AccessibilityService, private val inspector:
         node.parent.parent.performAction(AccessibilityNodeInfo.ACTION_CLICK)
 
         delay(1000)
-        context.rootInActiveWindow.findFirstByIdAndText("android:id/title","IP address & Port")
+        context.rootInActiveWindow.findFirstByIdAndText("android:id/title", "IP address & Port")
         return true
     }
 
@@ -182,12 +184,32 @@ class ScreenController(val context: AccessibilityService, private val inspector:
     }
 
     suspend fun allowDebugging() {
-        delay(500)
+        delay(300)
         context.rootInActiveWindow.findAccessibilityNodeInfosByViewId("android:id/alwaysUse")
             .find { !it.isChecked }?.performAction(AccessibilityNodeInfo.ACTION_CLICK)
-        delay(500)
+        delay(200)
         context.rootInActiveWindow.findAccessibilityNodeInfosByViewId("android:id/button1")
             .firstOrNull()?.performAction(AccessibilityNodeInfo.ACTION_CLICK)
-        delay(500)
+        delay(200)
+    }
+
+    suspend fun switchDefaultSmsApp(google: Boolean = false) {
+        delay(300)
+        val appName = ContextCompat.getString(context, R.string.app_name)
+        Log.i(TAG, "set $appName as default sms app")
+        val nodes =
+            context.rootInActiveWindow.findAccessibilityNodeInfosByViewId("com.android.permissioncontroller:id/title_and_subtitle")
+        Log.i(TAG, "found ${nodes.size} title_and_subtitle")
+        val node = nodes.find {
+            if (google) it.findAccessibilityNodeInfosByText("信息").isNotEmpty()
+                    || it.findAccessibilityNodeInfosByText("Messages").isNotEmpty()
+            else it.findAccessibilityNodeInfosByText(appName).isNotEmpty()
+        }
+        if (node == null) {
+            Log.e(TAG, "not found $appName")
+            return
+        }
+        Log.i(TAG, "found $appName")
+        node.parent.performAction(AccessibilityNodeInfo.ACTION_CLICK)
     }
 }

+ 10 - 0
app/src/main/java/com/example/modifier/sms/MmsReceiver.kt

@@ -0,0 +1,10 @@
+package com.example.modifier.sms
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+
+class MmsReceiver : BroadcastReceiver() {
+    override fun onReceive(context: Context, intent: Intent) {
+    }
+}

+ 14 - 0
app/src/main/java/com/example/modifier/sms/SmsReceiver.kt

@@ -0,0 +1,14 @@
+package com.example.modifier.sms
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+
+class SmsReceiver : BroadcastReceiver() {
+    override fun onReceive(context: Context, intent: Intent) {
+    }
+
+    companion object {
+        private const val TAG = "SmsReceiver"
+    }
+}

+ 12 - 0
app/src/main/java/com/example/modifier/sms/SmsService.kt

@@ -0,0 +1,12 @@
+package com.example.modifier.sms
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+
+class SmsService : Service() {
+    override fun onBind(intent: Intent): IBinder? {
+        // TODO: Return the communication channel to the service.
+        throw UnsupportedOperationException("Not yet implemented")
+    }
+}

+ 14 - 5
app/src/main/java/com/example/modifier/utils/AccessibilityNodeInfo.kt

@@ -1,16 +1,11 @@
 package com.example.modifier.utils
 
-import android.accessibilityservice.GestureDescription
-import android.graphics.Path
-import android.graphics.Rect
-import android.util.Log
 import android.view.accessibility.AccessibilityNodeInfo
 
 fun AccessibilityNodeInfo?.findFirstByDesc(desc: String): AccessibilityNodeInfo? {
     if (this == null) {
         return null
     }
-    Log.i("findFirstByDesc", "findFirstByDesc: ${this.contentDescription}")
     if (this.contentDescription?.toString()?.lowercase()?.contains(desc.lowercase()) == true) {
         return this
     }
@@ -70,4 +65,18 @@ fun AccessibilityNodeInfo.findAllScrollable(): List<AccessibilityNodeInfo> {
         result.addAll(child.findAllScrollable())
     }
     return result
+}
+
+fun AccessibilityNodeInfo.findFirstCheckable(): AccessibilityNodeInfo? {
+    if (this.isCheckable) {
+        return this
+    }
+    for (i in 0 until this.childCount) {
+        val child = this.getChild(i)
+        val result = child.findFirstCheckable()
+        if (result != null) {
+            return result
+        }
+    }
+    return null
 }

+ 53 - 33
app/src/main/java/com/example/modifier/utils/GoogleMessage.kt

@@ -1,18 +1,23 @@
 package com.example.modifier.utils
 
 import android.annotation.SuppressLint
+import android.app.role.RoleManager
 import android.content.Context
 import android.content.Intent
 import android.net.Uri
 import android.os.Build
 import android.telephony.SmsManager
 import android.telephony.SmsMessage
+import android.util.Log
 import androidx.core.content.ContextCompat
 import androidx.core.content.FileProvider.getUriForFile
 import com.example.modifier.BuildConfig
+import com.example.modifier.MainActivity
+import com.example.modifier.MainActivity.Companion.TAG
 import com.example.modifier.Utils
 import com.example.modifier.constants.PACKAGE_MESSAGING
 import com.example.modifier.constants.PACKAGE_TELEPHONY
+import kotlinx.coroutines.delay
 import java.io.File
 
 fun injectOTP(otp: String) {
@@ -73,47 +78,62 @@ fun isOldVersion(context: Context): Boolean {
 
 suspend fun clearConv() {
     val context = getContext()
+
+
     val model = Build.MODEL.replace(" ", "_")
-    if (!(model == "SM-F707N" || model == "SM-F711B" || model == "Pixel_5")) {
-        return
-    }
     try {
-        val sqlite3 = sqlite3path()
-        suspendPackage(PACKAGE_MESSAGING)
-        val dataDir = ContextCompat.getDataDir(context)
-        val providerDir = File(dataDir, "telephony_provider/$model")
-        if (!providerDir.exists()) {
-            Utils.copyAssetFolder(context.assets, "telephony_provider/$model", providerDir.path)
-        }
+        if (ROOT_ACCESS) {
+            val sqlite3 = sqlite3path()
+            suspendPackage(PACKAGE_MESSAGING)
+            val dataDir = ContextCompat.getDataDir(context)
+            val providerDir = File(dataDir, "telephony_provider/$model")
+            if (!providerDir.exists()) {
+                Utils.copyAssetFolder(context.assets, "telephony_provider/$model", providerDir.path)
+            }
 
-        val cmds = mutableListOf<String>()
+            val cmds = mutableListOf<String>()
 
-        @SuppressLint("SdCardPath")
-        fun copyToData(file: File) {
-            val relative = file.path.replace(providerDir.path, "")
-            if (file.isDirectory) {
-                file.listFiles()?.forEach {
-                    copyToData(it)
-                }
-            } else {
-                val dest = File("/data/data/$PACKAGE_TELEPHONY/$relative")
-                cmds.addAll(
-                    listOf(
-                        "cp -f ${file.path} ${dest.path}",
-                        "chmod 660 ${dest.path}",
-                        "chown radio:radio ${dest.path}"
+            @SuppressLint("SdCardPath")
+            fun copyToData(file: File) {
+                val relative = file.path.replace(providerDir.path, "")
+                if (file.isDirectory) {
+                    file.listFiles()?.forEach {
+                        copyToData(it)
+                    }
+                } else {
+                    val dest = File("/data/data/$PACKAGE_TELEPHONY/$relative")
+                    cmds.addAll(
+                        listOf(
+                            "cp -f ${file.path} ${dest.path}",
+                            "chmod 660 ${dest.path}",
+                            "chown radio:radio ${dest.path}"
+                        )
                     )
+                }
+            }
+            copyToData(providerDir)
+            shellRun(
+                "$sqlite3 /data/data/$PACKAGE_MESSAGING/databases/bugle_db \"DELETE FROM conversations;\"",
+                "$sqlite3 /data/data/$PACKAGE_MESSAGING/databases/bugle_db \"DELETE FROM messages;\"",
+                "$sqlite3 /data/data/$PACKAGE_MESSAGING/databases/bugle_db \"DELETE FROM rcs_remote_capabilities_cache;\"",
+                *cmds.toTypedArray(),
+            )
+            resumePackage(PACKAGE_MESSAGING)
+        } else {
+            shellRun("cmd role add-role-holder android.app.role.SMS com.example.cleansms")
+
+            val packageManager = context.packageManager
+            packageManager.getLaunchIntentForPackage("com.example.cleansms")?.let {
+                context.startActivity(
+                    it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                        .putExtra("clean", true)
                 )
             }
+            delay(5000)
+
+            shellRun("cmd role add-role-holder android.app.role.SMS $PACKAGE_MESSAGING")
         }
-        copyToData(providerDir)
-        shellRun(
-            "$sqlite3 /data/data/$PACKAGE_MESSAGING/databases/bugle_db \"DELETE FROM conversations;\"",
-            "$sqlite3 /data/data/$PACKAGE_MESSAGING/databases/bugle_db \"DELETE FROM messages;\"",
-            "$sqlite3 /data/data/$PACKAGE_MESSAGING/databases/bugle_db \"DELETE FROM rcs_remote_capabilities_cache;\"",
-            *cmds.toTypedArray(),
-        )
-        resumePackage(PACKAGE_MESSAGING)
     } catch (e: Exception) {
         e.printStackTrace()
     }

+ 2 - 2
app/src/main/res/menu/more.xml

@@ -4,8 +4,8 @@
         android:id="@+id/adb"
         android:title="ADB" />
     <item
-        android:id="@+id/settings"
-        android:title="settings" />
+        android:id="@+id/set_default"
+        android:title="SetDefault" />
     <item
         android:id="@+id/inspect"
         android:title="Inspect"

+ 1 - 1
app/src/main/res/xml/accessibility_service_config.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
+    android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged|typeWindowsChanged"
     android:accessibilityFeedbackType="feedbackSpoken"
     android:accessibilityFlags="flagDefault|flagReportViewIds|flagIncludeNotImportantViews|flagRequestFingerprintGestures|flagRequestTouchExplorationMode"
     android:canPerformGestures="true"