package com.example.modifier.utils import android.accessibilityservice.AccessibilityServiceInfo import android.annotation.SuppressLint import android.content.Context import android.content.pm.PackageManager import android.provider.Settings import android.text.TextUtils import android.util.Log import android.view.accessibility.AccessibilityManager import androidx.core.app.ActivityCompat import com.example.modifier.BuildConfig import com.example.modifier.Utils import com.example.modifier.http.ktorClient import com.example.modifier.service.ModifierService import io.ktor.client.request.head import org.apache.commons.lang3.StringUtils import java.time.ZoneId import java.time.ZonedDateTime import java.time.format.DateTimeFormatter import java.util.Locale import java.util.Objects import java.util.UUID val uniqueId: String @SuppressLint("HardwareIds") get() { val context = Utils.getContext() Objects.requireNonNull(context) val sharedPrefs = context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE) var uniqueID = sharedPrefs.getString("unique_id", "")!! if (uniqueID.isBlank()) { try { uniqueID = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) } catch (e: java.lang.Exception) { e.printStackTrace() } } if (StringUtils.isBlank(uniqueID)) { uniqueID = UUID.randomUUID().toString() } sharedPrefs.edit().putString("unique_id", uniqueID).apply() return uniqueID } @SuppressLint("PrivateApi") fun getContext(): Context? { try { val activityThreadClass = Class.forName("android.app.ActivityThread") val currentActivityThreadMethod = activityThreadClass.getMethod("currentActivityThread") currentActivityThreadMethod.isAccessible = true val currentActivityThread = currentActivityThreadMethod.invoke(null) val getApplicationMethod = activityThreadClass.getMethod("getApplication") getApplicationMethod.isAccessible = true return getApplicationMethod.invoke(currentActivityThread) as Context } catch (e: java.lang.Exception) { e.printStackTrace() } return null } suspend fun hasRootAccess(): Boolean { var rootAccess = false try { val (output, _) = shellRun("echo \"imrooted\"") if (output.contains("imrooted")) { rootAccess = true } } catch (e: Exception) { e.printStackTrace() } return rootAccess } fun hasPermission(permission: String): Boolean { return ActivityCompat.checkSelfPermission( getContext()!!, permission ) == PackageManager.PERMISSION_GRANTED } fun isAccessibilityEnabled(): Boolean { val context = getContext()!! val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager val enabledServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK) for (enabledService in enabledServices) { Log.i( com.example.modifier.TAG, "Enabled service: " + enabledService.resolveInfo.serviceInfo.packageName + "/" + enabledService.resolveInfo.serviceInfo.name ) val enabledServiceInfo = enabledService.resolveInfo.serviceInfo if (enabledServiceInfo.packageName == context.packageName && enabledServiceInfo.name == ModifierService.NAME) return true } return false } suspend fun enableAccessibility(): Boolean { if (isAccessibilityEnabled()) return true val context = getContext()!! val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager val enabledServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK) val names: MutableList = ArrayList() for (enabledService in enabledServices) { names.add(enabledService.resolveInfo.serviceInfo.packageName + "/" + enabledService.resolveInfo.serviceInfo.name) } names.add(context.packageName + "/" + ModifierService.NAME) try { shellRun( "settings put secure enabled_accessibility_services " + TextUtils.join(":", names), "settings put secure accessibility_enabled 1" ) return true } catch (e: java.lang.Exception) { e.printStackTrace() } return false } suspend fun enableOverlay() { try { shellRun("appops set " + BuildConfig.APPLICATION_ID + " SYSTEM_ALERT_WINDOW allow") } catch (e: java.lang.Exception) { e.printStackTrace() } } suspend fun optimize() { val context = Utils.getContext() val packageManager = context.packageManager val info = packageManager.getApplicationInfo("com.google.android.gms", 0) shellRun( "dumpsys deviceidle whitelist +com.google.android.apps.messaging", "dumpsys deviceidle whitelist +${BuildConfig.APPLICATION_ID}", "cmd netpolicy add restrict-background-blacklist ${info.uid}", "settings put global window_animation_scale 0", "settings put global transition_animation_scale 0", "settings put global animator_duration_scale 0" ) } suspend fun syncTime() { try { Log.i("Modifier", "syncTime: start") val response = ktorClient("").head("http://www.baidu.com") val dateHeader = response.headers["Date"] val date = ZonedDateTime.parse( dateHeader, DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH) ) // convert to Asia/Shanghai val dateInZone = date.withZoneSameInstant(ZoneId.of("Asia/Shanghai")) Log.i( com.example.modifier.TAG, "CurrentTime from Baidu: ${dateInZone.format(DateTimeFormatter.ISO_DATE_TIME)}" ) shellRun( "settings put system time_12_24 24", "settings put global auto_time 0", "settings put global auto_time_zone 0", "setprop persist.sys.timezone Asia/Shanghai", "date \"${dateInZone.format(DateTimeFormatter.ofPattern("MMddHHmmyyyy.ss"))}\"" ) } catch (e: Exception) { Log.e(com.example.modifier.TAG, "Error SyncTime", e) } } suspend fun isRebooted(): Boolean { if (shellRun("getprop rebooted").component1().contains("yes")) { return false } shellRun("setprop rebooted yes") return true } suspend fun setBatteryLevel(level: Int) { shellRun("dumpsys battery set level $level") }