| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- package com.example.modifier.repo
- import android.annotation.SuppressLint
- import android.content.Context
- import android.util.Log
- import androidx.core.content.ContextCompat
- import com.example.modifier.baseTag
- import com.example.modifier.constants.CMD_MESSAGING_APP
- import com.example.modifier.constants.CMD_RCS_SETTINGS_ACTIVITY
- import com.example.modifier.constants.PACKAGE_GMS
- import com.example.modifier.constants.PACKAGE_GSF
- import com.example.modifier.constants.PACKAGE_MESSAGING
- import com.example.modifier.data.BackupItem
- import com.example.modifier.data.BackupItemDao
- import com.example.modifier.enums.RcsConfigureState
- import com.example.modifier.enums.ReqState
- import com.example.modifier.extension.clear
- import com.example.modifier.extension.disable
- import com.example.modifier.extension.enable
- import com.example.modifier.extension.kill
- import com.example.modifier.http.api.RcsNumberApi
- import com.example.modifier.model.SpoofedInfo
- import com.example.modifier.service.ModifierService
- import com.example.modifier.utils.ROOT_ACCESS
- import com.example.modifier.utils.clearConv
- import com.example.modifier.utils.genAndroidId
- import com.example.modifier.utils.genMacAddress
- import com.example.modifier.utils.genSerialNo
- import com.example.modifier.utils.getContext
- import com.example.modifier.utils.shellRun
- import kotlinx.coroutines.CoroutineScope
- import kotlinx.coroutines.delay
- import kotlinx.coroutines.launch
- import java.io.File
- import java.util.Date
- import java.util.Optional
- import kotlin.coroutines.coroutineContext
- import kotlin.time.Duration.Companion.minutes
- class BackupRepository(
- private val context: Context,
- private val dao: BackupItemDao,
- ) {
- companion object {
- private const val TAG = "$baseTag/BackupRepository"
- }
- suspend fun backup(type: String, sendCount: Int, stock: Int = 0): BackupItem? {
- if (!ROOT_ACCESS) return null
- AppStateRepo.instance.updateRuntimeFlags(reqState = ReqState.BACKUP)
- val spoofedInfoRepo = SpoofedInfoRepo.instance
- clearConv()
- delay(3000)
- // ModifierService.instance!!.toggleRcsSwitch(false)
- val context = getContext()
- val dest = File(
- ContextCompat.getExternalFilesDirs(context, "backup")[0],
- System.currentTimeMillis().toString()
- )
- dest.mkdirs()
- val packages = mutableListOf(
- PACKAGE_MESSAGING,
- PACKAGE_GMS,
- PACKAGE_GSF
- )
- packages.forEach {
- File(dest, it).mkdirs()
- }
- val cmds = mutableListOf<String>()
- for (pkg in packages) {
- if (!shellRun("ls /data/data/$pkg").second
- .contains("No such file or directory")
- ) {
- cmds.add("tar zcpf $dest/$pkg/data.tar.gz -C /data/data $pkg ")
- }
- if (!shellRun("ls /data/user_de/0/$pkg").second
- .contains("No such file or directory")
- ) {
- cmds.add("tar zcpf $dest/$pkg/data_de.tar.gz -C /data/user_de/0 $pkg ")
- }
- if (!shellRun("ls /sdcard/Android/data/$pkg").second
- .contains("No such file or directory")
- ) {
- cmds.add("tar zcpf $dest/$pkg/data_ext.tar.gz -C /sdcard/Android/data $pkg ")
- }
- }
- shellRun(*cmds.toTypedArray())
- val spoofedSimInfo = spoofedInfoRepo.spoofedInfo.value
- val backup = BackupItem(
- createdAt = Date().time,
- numberId = spoofedSimInfo.numberId,
- number = spoofedSimInfo.number,
- code = spoofedSimInfo.areaCode,
- country = spoofedSimInfo.country,
- mcc = spoofedSimInfo.mcc,
- mnc = spoofedSimInfo.mnc,
- imei = spoofedSimInfo.imei,
- imsi = spoofedSimInfo.imsi,
- iccid = spoofedSimInfo.iccid,
- path = dest.path,
- sendCount = sendCount,
- lastUse = Date().time,
- type = type,
- stock = stock,
- carrierId = Optional.ofNullable(spoofedSimInfo.carrierId).orElse("1"),
- carrierName = Optional.ofNullable(spoofedSimInfo.carrierName).orElse("T-Mobile"),
- retry = 0
- )
- dao.findBackupForNumber(spoofedSimInfo.country, spoofedSimInfo.number)?.let {
- File(it.path).deleteRecursively()
- backup.sendCount += it.sendCount
- backup.stock = it.stock
- dao.delete(it)
- }
- backup.id = dao.insert(backup).toInt()
- return backup
- }
- @SuppressLint("SdCardPath")
- suspend fun restore(backup: BackupItem): Boolean {
- val spoofedInfoRepo = SpoofedInfoRepo.instance
- val simInfo = SpoofedInfo(
- numberId = backup.numberId,
- number = backup.number,
- mcc = backup.mcc,
- mnc = backup.mnc,
- country = backup.country,
- areaCode = backup.code,
- iccid = backup.iccid,
- imei = backup.imei,
- imsi = backup.imsi,
- available = false,
- carrierId = backup.carrierId,
- carrierName = backup.carrierName,
- serialNo = genSerialNo(),
- wifiMac = genMacAddress(),
- bssid = genMacAddress(),
- btMac = genMacAddress(),
- ethMac = genMacAddress(),
- androidId = genAndroidId(),
- gmsAid = genAndroidId(),
- rootAid = genAndroidId()
- )
- spoofedInfoRepo.updateSpoofedSimInfo(spoofedInfo = simInfo, suspend = false)
- val packages = mutableListOf(
- PACKAGE_MESSAGING,
- PACKAGE_GMS,
- PACKAGE_GSF
- )
- shellRun(PACKAGE_MESSAGING.clear(), "sleep 2", PACKAGE_MESSAGING.disable())
- for (pkg in packages) {
- for (item in listOf("data.tar.gz", "data_de.tar.gz", "data_ext.tar.gz")) {
- val file = File("${backup.path}/$pkg/$item")
- if (!file.exists()) {
- continue
- }
- val dest = when (item) {
- "data.tar.gz" -> "/data/data"
- "data_de.tar.gz" -> "/data/user_de/0"
- "data_ext.tar.gz" -> "/sdcard/Android/data"
- else -> ""
- }
- shellRun(
- "find $dest/$pkg -type f -delete",
- "tar zxf ${file.path} -C $dest --exclude \"**/AndroidPlatformServices.apk\""
- )
- }
- }
- val taskRunner = ModifierService.instance?.taskRunner
- shellRun(
- // "sed -i 's/<boolean name=\"enable_rcs\" value=\"true\" \\/>/<boolean name=\"enable_rcs\" value=\"false\" \\/>/g' /data/data/com.google.android.apps.messaging/shared_prefs/bugle.xml",
- PACKAGE_GSF.kill(),
- "sleep 1",
- PACKAGE_GMS.kill(),
- "settings put secure location_mode 0",
- "pm revoke com.google.android.gms android.permission.GET_ACCOUNTS",
- "pm revoke com.google.android.gms android.permission.SYSTEM_ALERT_WINDOW",
- "pm revoke com.google.android.gms android.permission.POST_NOTIFICATIONS",
- "pm revoke com.google.android.gms android.permission.READ_CONTACTS",
- "pm revoke com.google.android.gms android.permission.CAMERA",
- "pm revoke com.google.android.gms android.permission.RECEIVE_MMS",
- "pm revoke com.google.android.gms android.permission.GET_APP_OPS_STATS",
- "pm revoke com.google.android.gms android.permission.PROCESS_OUTGOING_CALLS",
- "pm revoke com.google.android.gms android.permission.BLUETOOTH_CONNECT",
- "pm revoke com.google.android.gms android.permission.BLUETOOTH_SCAN",
- "pm revoke com.google.android.gms android.permission.BLUETOOTH_ADVERTISE",
- "pm revoke com.google.android.gms android.permission.NEARBY_WIFI_DEVICES",
- "pm revoke com.google.android.gms android.permission.UWB_RANGING",
- "pm revoke com.google.android.gms android.permission.READ_CALL_LOG",
- "pm revoke com.google.android.gms android.permission.WRITE_CONTACTS",
- "pm revoke com.google.android.gms android.permission.CALL_PHONE",
- "pm revoke com.google.android.gms android.permission.RECORD_AUDIO",
- "pm revoke com.google.android.gms android.permission.READ_LOGS",
- "pm revoke com.google.android.gms android.permission.READ_MEDIA_AUDIO",
- "pm revoke com.google.android.gms android.permission.READ_MEDIA_IMAGES",
- "pm revoke com.google.android.gms android.permission.READ_MEDIA_VIDEO",
- "pm revoke com.google.android.gms android.permission.ACCESS_MEDIA_LOCATION",
- "pm revoke com.google.android.gms android.permission.ACCESS_BROADCAST_RESPONSE_STATS",
- "pm revoke com.google.android.gms android.permission.WRITE_CALL_LOG",
- "pm revoke com.google.android.gms android.permission.BODY_SENSORS",
- "pm revoke com.google.android.gms android.permission.DUMP",
- "sleep 30",
- PACKAGE_MESSAGING.enable(),
- "sleep 1",
- CMD_MESSAGING_APP,
- "sleep 5",
- CMD_RCS_SETTINGS_ACTIVITY,
- "sleep 5",
- PACKAGE_MESSAGING.kill(),
- "sleep 1",
- CMD_MESSAGING_APP,
- "sleep 5",
- )
- var otp = false
- val success = run isSuccess@{
- if (backup.stock != 1) {
- return@isSuccess true
- }
- if (taskRunner == null) return@isSuccess false
- if (!taskRunner.screenController.toggleRcsSwitch(true)) {
- shellRun(
- PACKAGE_GMS.kill(),
- PACKAGE_MESSAGING.kill(),
- "sleep 5",
- CMD_MESSAGING_APP
- )
- delay(5000)
- if (!taskRunner.screenController.toggleRcsSwitch(true)) {
- return@isSuccess false
- }
- }
- val job = CoroutineScope(coroutineContext).launch {
- taskRunner.gmsgStateRepo.rcsConfigureState.collect {
- if (it == RcsConfigureState.RETRY) {
- shellRun(
- PACKAGE_GMS.kill(),
- "sleep 5",
- PACKAGE_MESSAGING.kill(),
- CMD_MESSAGING_APP
- )
- }
- }
- }
- val state = taskRunner.gmsgStateRepo.waitForRcsState(
- arrayOf(RcsConfigureState.CONFIGURED, RcsConfigureState.WAITING_FOR_OTP), 5.minutes
- )
- job.cancel()
- if (state == RcsConfigureState.CONFIGURED) return@isSuccess true
- if (state == RcsConfigureState.WAITING_FOR_OTP) otp = true
- false
- }
- if (success) {
- Log.i(TAG, "restore: success")
- spoofedInfoRepo.updateAvailable(available = true)
- if (backup.stock == 1) {
- backup.stock = 2
- dao.update(backup)
- RcsNumberApi.updateStockFlag(backup.numberId, 2)
- }
- return true
- } else {
- Log.i(TAG, "restore: failed")
- if (backup.stock == 1) {
- backup.retry++
- if (backup.retry >= 3 || otp) {
- RcsNumberApi.updateStockFlag(backup.numberId, 3)
- if (otp) {
- dao.delete(backup)
- } else {
- backup.stock = 3
- dao.update(backup)
- }
- } else {
- dao.update(backup)
- }
- }
- }
- return false
- }
- suspend fun delete(backupItem: BackupItem) {
- dao.delete(backupItem)
- }
- suspend fun findBackupForRestore(number: String): BackupItem? {
- return dao.findBackupForRestore(number)
- }
- suspend fun cleanBackup(start: Long, end: Long) {
- dao.findBackupsBetween(start, end).forEach {
- runCatching {
- File(it.path).deleteRecursively()
- }
- dao.delete(it)
- }
- }
- }
|