package com.example.modifier; import android.content.Context; import android.content.SharedPreferences; import android.os.Build; import android.util.Log; import androidx.core.content.ContextCompat; import com.android.volley.RequestQueue; import com.android.volley.toolbox.JsonObjectRequest; import com.android.volley.toolbox.RequestFuture; import com.android.volley.toolbox.Volley; import com.google.gson.Gson; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; import java.io.File; import java.io.FileWriter; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class Global { public static String serverUrl = ""; public static long rcsTimeout = 2000; public static Config config = new Config("", "", "", "", "", "", ""); ExecutorService executor = Executors.newFixedThreadPool(8); public static void load() { Context context = Utils.getContext(); serverUrl = context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE).getString("server", "http://192.168.6.215:3000"); RequestQueue queue = Volley.newRequestQueue(context); RequestFuture future = RequestFuture.newFuture(); JsonObjectRequest request = new JsonObjectRequest(serverUrl + "/api/sys-config/rcs_wait", future, future); queue.add(request); try { JSONObject jsonObject = future.get(60, TimeUnit.SECONDS); rcsTimeout = Long.parseLong(jsonObject.optString("value")); } catch (Exception e) { e.printStackTrace(); } try { File file = new File(ContextCompat.getDataDir(context), "config.json"); if (file.exists()) { Gson gson = new Gson(); String json = FileUtils.readFileToString(file, "UTF-8"); config = gson.fromJson(json, Config.class); } } catch (Exception e) { e.printStackTrace(); } } public static Set getServers() { Context context = Utils.getContext(); Set defServers = new HashSet<>(); defServers.add("http://192.168.6.215:3000"); defServers.add("http://192.168.50.135:3000"); SharedPreferences prefs = context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE); return new HashSet<>(prefs.getStringSet("servers", defServers)); } public static void saveServer(String server) { serverUrl = server; Context context = Utils.getContext(); SharedPreferences prefs = context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE); Set servers = getServers(); servers.add(server); prefs.edit().putStringSet("servers", servers) .putString("server", server) .apply(); } public static void save(Config config) { Context context = Utils.getContext(); try { File file = new File(ContextCompat.getDataDir(context), "config.json"); Gson gson = new Gson(); String json = gson.toJson(config); try { FileWriter writer = new FileWriter(file); writer.write(json); writer.close(); } catch (Exception e) { e.printStackTrace(); } Utils.runAsRoot( "cp " + file.getPath() + " /data/data/com.android.phone/rcsConfig.json", "echo 'copied to phone'", "chmod 777 /data/data/com.android.phone/rcsConfig.json"); } catch (Exception e) { e.printStackTrace(); } } public static void clear(boolean gsf, boolean gms, boolean sms) { try { List cmds = new ArrayList<>(); if (gsf) { cmds.add("pm clear com.google.android.gsf"); cmds.add("echo 'cleared gsf'"); } if (gms) { cmds.add("pm clear com.google.android.gms"); cmds.add("echo 'cleared gms'"); } if (sms) { cmds.add("pm clear com.google.android.apps.messaging"); cmds.add("echo 'cleared sms'"); } Utils.runAsRoot(cmds.toArray(new String[0])); } catch (Exception e) { e.printStackTrace(); } } public static void stop(boolean gsf, boolean gms, boolean sms) { try { List cmds = new ArrayList<>(); if (gsf) { cmds.add("am force-stop com.google.android.gsf"); cmds.add("echo 'stopped gsf'"); } if (gms) { cmds.add("am force-stop com.google.android.gms"); cmds.add("echo 'stopped gms'"); } if (sms) { cmds.add("am force-stop com.google.android.apps.messaging"); cmds.add("echo 'stopped sms'"); } Utils.runAsRoot(cmds.toArray(new String[0])); } catch (Exception e) { e.printStackTrace(); } } public static void clearConv() { Context context = Utils.getContext(); try { File dataDir = ContextCompat.getDataDir(context); Utils.copyAssetFolder(context.getAssets(), "bin", new File(dataDir, "bin").getPath()); // Utils.runAsRoot("su -c \"\""); Log.i("Modifier", "arch: " + StringUtils.join(Build.SUPPORTED_ABIS, ", ")); String arch = null; for (String supportedAbi : Build.SUPPORTED_ABIS) { if ("x86".equals(supportedAbi)) { arch = "x86"; } else if ("x86_64".equals(supportedAbi)) { arch = "x64"; } else if ("arm64-v8a".equals(supportedAbi)) { arch = "arm64"; } else if ("armeabi-v7a".equals(supportedAbi)) { arch = "arm"; } if (StringUtils.isNoneBlank(arch)) { String binPath = new File(dataDir, "bin/sqlite3." + arch).getPath(); Log.i("Modifier", "sqlite3 binPath: " + binPath); Utils.runAsRoot("chmod +x " + binPath, binPath + " /data/data/com.google.android.apps.messaging/databases/bugle_db \"DELETE FROM conversations;\"", binPath + " /data/data/com.google.android.apps.messaging/databases/bugle_db \"DELETE FROM messages;\"", "echo ok"); Global.stop(false, false, true); Utils.runAsRoot("am start com.google.android.apps.messaging"); break; } } } catch (Exception e) { e.printStackTrace(); } } }