package com.example.modifier.repo import android.Manifest import android.annotation.SuppressLint import android.content.Context import android.telephony.SubscriptionManager import android.util.Log import androidx.core.content.ContextCompat import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import com.example.modifier.BuildConfig import com.example.modifier.Utils import com.example.modifier.constants.PACKAGE_GMS import com.example.modifier.constants.PACKAGE_MESSAGING import com.example.modifier.model.SpoofedSimInfo import com.example.modifier.serializer.Json import com.example.modifier.utils.genICCID import com.example.modifier.utils.genIMEI import com.example.modifier.utils.genIMSI import com.example.modifier.utils.hasPermission import com.example.modifier.utils.isOldVersion import com.example.modifier.utils.resumePackage import com.example.modifier.utils.shellRun import com.example.modifier.utils.suspendPackage import com.google.gson.Gson import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.serialization.decodeFromString import org.apache.commons.io.FileUtils import java.io.File import kotlin.coroutines.coroutineContext val Context.simInfoDataStore by preferencesDataStore(name = "${BuildConfig.APPLICATION_ID}.simInfo") class SpoofedSimInfoRepository(private val context: Context) { private object PreferencesKeys { val NUMBER = stringPreferencesKey("number") val MCC = stringPreferencesKey("mcc") val MNC = stringPreferencesKey("mnc") val ICCID = stringPreferencesKey("iccid") val IMSI = stringPreferencesKey("imsi") val IMEI = stringPreferencesKey("imei") val COUNTRY = stringPreferencesKey("country") val AREA_CODE = stringPreferencesKey("area_code") val AVAILABLE = booleanPreferencesKey("available") val CARRIER_ID = stringPreferencesKey("carrier_id") val CARRIER_NAME = stringPreferencesKey("carrier_name") } val simInfoFlow = context.simInfoDataStore.data.map { val file = File(ContextCompat.getDataDir(context), "config.json") val old = file.exists().let { if (it) { try { return@let Json.decodeFromString( FileUtils.readFileToString( file, "UTF-8" ) ) } catch (e: Exception) { e.printStackTrace() } } null } val number = it[PreferencesKeys.NUMBER] ?: old?.number ?: "" val mcc = it[PreferencesKeys.MCC] ?: old?.mcc ?: "" val mnc = it[PreferencesKeys.MNC] ?: old?.mnc ?: "" val iccid = it[PreferencesKeys.ICCID] ?: old?.iccid ?: "" val imsi = it[PreferencesKeys.IMSI] ?: old?.imsi ?: "" val imei = it[PreferencesKeys.IMEI] ?: old?.imei ?: "" val country = it[PreferencesKeys.COUNTRY] ?: old?.country ?: "" val areaCode = it[PreferencesKeys.AREA_CODE] ?: old?.areaCode ?: "" val available = it[PreferencesKeys.AVAILABLE] ?: old?.available ?: false val carrierId = it[PreferencesKeys.CARRIER_ID] ?: old?.carrierId ?: "" val carrierName = it[PreferencesKeys.CARRIER_NAME] ?: old?.carrierName ?: "" SpoofedSimInfo( number = number, mcc = mcc, mnc = mnc, iccid = iccid, imsi = imsi, imei = imei, country = country, areaCode = areaCode, available = available, carrierId = carrierId, carrierName = carrierName ) } suspend fun stateFlow() = simInfoFlow.stateIn(CoroutineScope(coroutineContext)) suspend fun value() { } @SuppressLint("MissingPermission") suspend fun updateSpoofedSimInfo(spoofedSimInfo: SpoofedSimInfo, suspend: Boolean? = true) { context.simInfoDataStore.edit { it[PreferencesKeys.NUMBER] = spoofedSimInfo.number it[PreferencesKeys.MCC] = spoofedSimInfo.mcc it[PreferencesKeys.MNC] = spoofedSimInfo.mnc it[PreferencesKeys.ICCID] = spoofedSimInfo.iccid it[PreferencesKeys.IMSI] = spoofedSimInfo.imsi it[PreferencesKeys.IMEI] = spoofedSimInfo.imei it[PreferencesKeys.COUNTRY] = spoofedSimInfo.country it[PreferencesKeys.AREA_CODE] = spoofedSimInfo.areaCode it[PreferencesKeys.AVAILABLE] = spoofedSimInfo.available it[PreferencesKeys.CARRIER_ID] = spoofedSimInfo.carrierId it[PreferencesKeys.CARRIER_NAME] = spoofedSimInfo.carrierName } try { if (suspend == true) { suspendPackage(PACKAGE_GMS, PACKAGE_MESSAGING) } shellRun( "setprop persist.spoof.number ${spoofedSimInfo.number}", "setprop persist.spoof.mcc ${spoofedSimInfo.mcc}", "setprop persist.spoof.mnc ${spoofedSimInfo.mnc}", "setprop persist.spoof.iccid ${spoofedSimInfo.iccid}", "setprop persist.spoof.imsi ${spoofedSimInfo.imsi}", "setprop persist.spoof.imei ${spoofedSimInfo.imei}", "setprop persist.spoof.country ${spoofedSimInfo.country}", "setprop persist.spoof.carrier.id ${ spoofedSimInfo.carrierId.replace( "^\\W*\$".toRegex(), "''" ) }", "setprop persist.spoof.carrier.name ${ spoofedSimInfo.carrierName.replace( "^\\W*\$".toRegex(), "''" ) }", ) val context = Utils.getContext() val subscriptionManager: SubscriptionManager = context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager if (hasPermission(Manifest.permission.READ_PHONE_STATE)) { val simCount = subscriptionManager.activeSubscriptionInfoCountMax for (i in 0 until simCount) { val info = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(i) if (info != null) { val mcc = info.mccString val mnc = info.mncString Log.i(com.example.modifier.TAG, "mccmnc spoofed: $mcc$mnc") } } } if (suspend == true) { resumePackage(PACKAGE_GMS, PACKAGE_MESSAGING) } } catch (e: Exception) { e.printStackTrace() } } suspend fun mock() { if (isOldVersion(context)) { val content = Utils.getContext().assets.open("us_numbers.txt").bufferedReader().use { it.readText() } // get random number content.split("\n") .filter { it.isNotBlank() } .shuffled() .firstOrNull() ?.let { updateSpoofedSimInfo( SpoofedSimInfo( number = it, mcc = "310", mnc = "150", iccid = genICCID("310", "1"), imsi = genIMSI("310150"), imei = genIMEI(), country = "us", areaCode = "1", available = false, carrierId = "1779", carrierName = "Cricket Wireless" ) ) } } else { val content = Utils.getContext().assets.open("us_numbers.txt").bufferedReader().use { it.readText() } // get random number content.split("\n") .filter { it.isNotBlank() } .shuffled() .firstOrNull() ?.let { updateSpoofedSimInfo( SpoofedSimInfo( number = it, mcc = "310", mnc = "240", iccid = genICCID("310", "1"), imsi = genIMSI("310240"), imei = genIMEI(), country = "us", areaCode = "1", available = false, carrierId = "1", carrierName = "T-Mobile" ) ) } } } }