From 840a6070b58e52242ecf1914a276a25b67fcdff7 Mon Sep 17 00:00:00 2001 From: Jacopo Tediosi Date: Wed, 7 Dec 2022 02:56:45 +0100 Subject: [PATCH] Improved queries performance --- .../googledialermod/DBFlagsSingleton.java | 231 +++++++++++------- .../com/jacopomii/googledialermod/Utils.java | 39 +-- 2 files changed, 148 insertions(+), 122 deletions(-) diff --git a/app/src/main/java/com/jacopomii/googledialermod/DBFlagsSingleton.java b/app/src/main/java/com/jacopomii/googledialermod/DBFlagsSingleton.java index d734db6..c222144 100644 --- a/app/src/main/java/com/jacopomii/googledialermod/DBFlagsSingleton.java +++ b/app/src/main/java/com/jacopomii/googledialermod/DBFlagsSingleton.java @@ -1,12 +1,14 @@ package com.jacopomii.googledialermod; import static com.jacopomii.googledialermod.Constants.DIALER_PACKAGE_NAME; +import static com.jacopomii.googledialermod.Constants.DIALER_PHENOTYPE_CACHE; +import static com.jacopomii.googledialermod.Constants.PHENOTYPE_DB; import static com.jacopomii.googledialermod.Utils.byteArrayToHexString; -import static com.jacopomii.googledialermod.Utils.execPhenotypeQuery; -import static com.jacopomii.googledialermod.Utils.killDialerAndDeletePhenotypeCache; import android.content.Context; +import com.topjohnwu.superuser.Shell; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -74,48 +76,52 @@ private void reloadDBUsers() { } } - public void reloadDBBooleanFlags() { + private void reloadDBBooleanFlags() { mDBBooleanFlags.clear(); - String[] tables = {"Flags", "FlagOverrides"}; - for (String table : tables) { - JSONArray queryResult = execPhenotypeQuery( - mContext, - String.format( - "SELECT DISTINCT name, boolVal FROM %s WHERE packageName = '%s' AND user = '' AND boolVal != 'NULL'", - table, - DIALER_PACKAGE_NAME - ) - ); - for (int i=0; i < queryResult.length(); i++) { - try { - JSONObject flag = queryResult.getJSONObject(i); - mDBBooleanFlags.put(flag.getString("name"), flag.getInt("boolVal")!=0); - } catch (JSONException e) { - e.printStackTrace(); - } + JSONArray queryResult = execPhenotypeQuery( + mContext, + String.format( + "SELECT DISTINCT name, boolVal " + + "FROM Flags " + + "WHERE packageName = '%s' AND user = '' AND boolVal != 'NULL' AND name NOT IN (SELECT name FROM FlagOverrides) " + + "UNION ALL " + + "SELECT DISTINCT name, boolVal FROM FlagOverrides " + + "WHERE packageName = '%s' AND user = '' AND boolVal != 'NULL'", + DIALER_PACKAGE_NAME, + DIALER_PACKAGE_NAME + ) + ); + for (int i=0; i < queryResult.length(); i++) { + try { + JSONObject flag = queryResult.getJSONObject(i); + mDBBooleanFlags.put(flag.getString("name"), flag.getInt("boolVal")!=0); + } catch (JSONException e) { + e.printStackTrace(); } } } - public void reloadDBStringFlags() { + private void reloadDBStringFlags() { mDBStringFlags.clear(); - String[] tables = {"Flags", "FlagOverrides"}; - for (String table : tables) { - JSONArray queryResult = execPhenotypeQuery( - mContext, - String.format( - "SELECT DISTINCT name, stringVal FROM %s WHERE packageName = '%s' AND user = '' AND stringVal != 'NULL'", - table, - DIALER_PACKAGE_NAME - ) - ); - for (int i=0; i < queryResult.length(); i++) { - try { - JSONObject flag = queryResult.getJSONObject(i); - mDBStringFlags.put(flag.getString("name"), flag.getString("stringVal")); - } catch (JSONException e) { - e.printStackTrace(); - } + JSONArray queryResult = execPhenotypeQuery( + mContext, + String.format( + "SELECT DISTINCT name, stringVal " + + "FROM Flags " + + "WHERE packageName = '%s' AND user = '' AND stringVal != 'NULL' AND name NOT IN (SELECT name FROM FlagOverrides) " + + "UNION ALL " + + "SELECT DISTINCT name, stringVal FROM FlagOverrides " + + "WHERE packageName = '%s' AND user = '' AND stringVal != 'NULL'", + DIALER_PACKAGE_NAME, + DIALER_PACKAGE_NAME + ) + ); + for (int i=0; i < queryResult.length(); i++) { + try { + JSONObject flag = queryResult.getJSONObject(i); + mDBStringFlags.put(flag.getString("name"), flag.getString("stringVal")); + } catch (JSONException e) { + e.printStackTrace(); } } } @@ -131,17 +137,22 @@ public void updateDBFlag(String flag, boolean value) { flag.replace("'", "\\'") ) ); + + ArrayList queryValues = new ArrayList<>(); for (String user : mDBUsers) - execPhenotypeQuery( - mContext, + queryValues.add( String.format( - "INSERT OR REPLACE INTO FlagOverrides (packageName, flagType, name, user, boolVal, committed) VALUES ('%s', 0, '%s', '%s', '%s', 0)", + "('%s', 0, '%s', '%s', '%s', 0)", DIALER_PACKAGE_NAME, flag.replace("'", "\\'"), user.replace("'", "\\'"), (value ? '1' : '0') ) ); + execPhenotypeQuery( + mContext, + "INSERT OR REPLACE INTO FlagOverrides (packageName, flagType, name, user, boolVal, committed) VALUES " + String.join(",", queryValues) + ); } public void updateDBFlag(String flag, String value) { @@ -151,20 +162,26 @@ public void updateDBFlag(String flag, String value) { mContext, String.format( "DELETE FROM FlagOverrides WHERE packageName = '%s' AND name = '%s'", - DIALER_PACKAGE_NAME,flag.replace("'", "\\'") + DIALER_PACKAGE_NAME, + flag.replace("'", "\\'") ) ); + + ArrayList queryValues = new ArrayList<>(); for (String user : mDBUsers) - execPhenotypeQuery( - mContext, + queryValues.add( String.format( - "INSERT OR REPLACE INTO FlagOverrides (packageName, flagType, name, user, stringVal, committed) VALUES ('%s', 0, '%s', '%s', '%s', 0)", + "('%s', 0, '%s', '%s', '%s', 0)", DIALER_PACKAGE_NAME, flag.replace("'", "\\'"), user.replace("'", "\\'"), value.replace("'", "\\'") ) ); + execPhenotypeQuery( + mContext, + "INSERT OR REPLACE INTO FlagOverrides (packageName, flagType, name, user, stringVal, committed) VALUES " + String.join(",", queryValues) + ); } public void updateDBFlag(String flag, byte[] value) { @@ -178,49 +195,58 @@ public void updateDBFlag(String flag, byte[] value) { flag.replace("'", "\\'") ) ); + + ArrayList queryValues = new ArrayList<>(); for (String user : mDBUsers) - execPhenotypeQuery( - mContext, + queryValues.add( String.format( - "INSERT OR REPLACE INTO FlagOverrides (packageName, flagType, name, user, extensionVal, committed) VALUES ('%s', 0, '%s', '%s', X'%s', 0)", + "('%s', 0, '%s', '%s', '%s', 0)", DIALER_PACKAGE_NAME, flag.replace("'", "\\'"), user.replace("'", "\\'"), byteArrayToHexString(value) ) ); + execPhenotypeQuery( + mContext, + "INSERT OR REPLACE INTO FlagOverrides (packageName, flagType, name, user, extensionVal, committed) VALUES " + String.join(",", queryValues) + ); } public void deleteFlagOverrides(String... flags) { - for (String flag : flags) { - execPhenotypeQuery( - mContext, - String.format( - "DELETE FROM FlagOverrides WHERE packageName = '%s' AND name = '%s'", - DIALER_PACKAGE_NAME, - flag.replace("'", "\\'") - ) - ); - // Updating internal singleton cached flags - try { - JSONArray queryResult = execPhenotypeQuery( - mContext, - String.format( - "SELECT boolVal, stringVal FROM Flags WHERE packageName = '%s' AND user = '' AND name = '%s'", - DIALER_PACKAGE_NAME, - flag.replace("'", "\\'") - ) - ); - if (queryResult.length() > 0) { - JSONObject flagValues = queryResult.getJSONObject(0); - if (!flagValues.isNull("boolVal")) - mDBBooleanFlags.put(flag, flagValues.getBoolean(flag)); - else if (!flagValues.isNull("stringVal")) - mDBStringFlags.put(flag, flagValues.getString(flag)); - } - } catch (JSONException e) { - e.printStackTrace(); + killDialerAndDeletePhenotypeCache(); + + ArrayList queryValues = new ArrayList<>(); + for (String flag : flags) + queryValues.add("'" + flag.replace("'", "\\'") + "'"); + + execPhenotypeQuery( + mContext, + String.format( + "DELETE FROM FlagOverrides WHERE packageName = '%s' AND name IN (%s)", + DIALER_PACKAGE_NAME, + String.join(",", queryValues) + ) + ); + + JSONArray queryResult = execPhenotypeQuery( + mContext, + String.format( + "SELECT name, boolVal, stringVal FROM Flags WHERE packageName = '%s' AND user = '' AND name IN (%s)", + DIALER_PACKAGE_NAME, + String.join(",", queryValues) + ) + ); + try { + for (int i=0; i queryValues = new ArrayList<>(); + for (String flag : flags) + queryValues.add("'" + flag.replace("'", "\\'") + "'"); + + JSONArray queryResult = execPhenotypeQuery( + mContext, + String.format( + "SELECT DISTINCT name FROM Flags WHERE packageName = '%s' AND name IN (%s)", + DIALER_PACKAGE_NAME, + String.join(",", queryValues) + ) + ); + + return queryResult.length() == flags.length; + } + + private JSONArray execPhenotypeQuery(Context context, String query) { + JSONArray result = null; + try { + String query_result = String.join("", Shell.cmd( String.format( - "SELECT name FROM FlagOverrides WHERE packageName = '%s' AND name = '%s'", - DIALER_PACKAGE_NAME, - flag.replace("'", "\\'") + "%s/sqlite3 -batch -json %s \"%s;\"", + context.getApplicationInfo().dataDir, + PHENOTYPE_DB, + query ) - ); - if (queryResult.length() < 1) - return false; + ).exec().getOut()); + if (query_result.equals("")) { + result = new JSONArray("[]"); + } else { + result = new JSONArray(query_result); + } + } catch (JSONException e) { + e.printStackTrace(); } - return true; + return result; + } + + private void killDialerAndDeletePhenotypeCache() { + Shell.cmd( + String.format( + "am kill all %s; rm -rf %s", + DIALER_PACKAGE_NAME, + DIALER_PHENOTYPE_CACHE + ) + ).exec(); } } \ No newline at end of file diff --git a/app/src/main/java/com/jacopomii/googledialermod/Utils.java b/app/src/main/java/com/jacopomii/googledialermod/Utils.java index 57a93b1..d5b1315 100644 --- a/app/src/main/java/com/jacopomii/googledialermod/Utils.java +++ b/app/src/main/java/com/jacopomii/googledialermod/Utils.java @@ -3,7 +3,6 @@ import static com.jacopomii.googledialermod.Constants.DIALER_CALLRECORDINGPROMPT; import static com.jacopomii.googledialermod.Constants.DIALER_DATA_DATA; import static com.jacopomii.googledialermod.Constants.DIALER_PACKAGE_NAME; -import static com.jacopomii.googledialermod.Constants.DIALER_PHENOTYPE_CACHE; import static com.jacopomii.googledialermod.Constants.PHENOTYPE_DB; import android.content.Context; @@ -20,7 +19,6 @@ import com.android.volley.toolbox.Volley; import com.topjohnwu.superuser.Shell; -import org.json.JSONArray; import org.json.JSONException; import java.io.IOException; @@ -62,35 +60,9 @@ public static String byteArrayToHexString(byte[] byteArray) { return formatter.toString(); } - public static JSONArray execPhenotypeQuery(Context context, String query) { - JSONArray result = null; - try { - String query_result = String.join("", Shell.cmd( - String.format( - "%s/sqlite3 -batch -json %s \"%s;\"", - context.getApplicationInfo().dataDir, - PHENOTYPE_DB, - query - ) - ).exec().getOut()); - if (query_result.equals("")) { - result = new JSONArray("[]"); - } else { - result = new JSONArray(query_result); - } - } catch (JSONException e) { - e.printStackTrace(); - } - return result; - } - - public static void killDialerAndDeletePhenotypeCache() { - Shell.cmd( - String.format( - "am kill all com.google.android.dialer; rm -rf %s", - DIALER_PHENOTYPE_CACHE - ) - ).exec(); + public static void revertAllMods(Context context) { + DBFlagsSingleton.getInstance(context).deleteAllFlagOverrides(); + deleteCallrecordingpromptFolder(); } public static void deleteCallrecordingpromptFolder() { @@ -102,11 +74,6 @@ public static void deleteCallrecordingpromptFolder() { ).exec(); } - public static void revertAllMods(Context context) { - DBFlagsSingleton.getInstance(context).deleteAllFlagOverrides(); - deleteCallrecordingpromptFolder(); - } - public static void checkIsLatestGithubVersion(Context context) { RequestQueue requestQueue = Volley.newRequestQueue(context); requestQueue.add(