package tk.wasdennnoch.androidn_ify.google;
import android.content.Context;
import android.content.SharedPreferences;
import org.json.JSONArray;
import org.json.JSONObject;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XSharedPreferences;
import de.robv.android.xposed.XposedHelpers;
import tk.wasdennnoch.androidn_ify.XposedHook;
import tk.wasdennnoch.androidn_ify.utils.ConfigUtils;
import static de.robv.android.xposed.XposedBridge.hookAllConstructors;
import static de.robv.android.xposed.XposedBridge.log;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static de.robv.android.xposed.XposedHelpers.findClass;
import static de.robv.android.xposed.XposedHelpers.getObjectField;
public class AssistantHooks {
private static final String GSA_PACKAGE = "com.google.android.apps.gsa";
private static final String ASSISTANT_PACKAGE = GSA_PACKAGE + ".assistant";
private static final String KEY_VERSION = "version";
private static final String KEY_ASSISTANT_CLASS = "assistant_class";
private static final String KEY_PREFS = "prefs";
private static final String KEY_SET_PREFS = "set_prefs";
private static final String KEY_FAKE_CONFIG = "fake_config";
private static final String KEY_FAKE_CONFIG_TWO = "fake_config_two";
private static final String KEY_ENABLE_LANGS = "enable_langs";
public static void hook(final ClassLoader classLoader) {
try {
((XSharedPreferences) ConfigUtils.getInstance().getPrefs()).reload();
// #############################################################################
// Thanks to XposedGELSettings for the following snippet (https://git.io/vP2Gw):
Object activityThread = XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentActivityThread");
Context context = (Context) XposedHelpers.callMethod(activityThread, "getSystemContext");
// #############################################################################
String googleVersionName = context.getPackageManager().getPackageInfo(XposedHook.PACKAGE_GOOGLE, 0).versionName;
JSONArray hookConfigs = new JSONArray(ConfigUtils.assistant().google_app_hook_configs);
JSONObject activeHooksTemp = null;
for (int i = 0; i < hookConfigs.length(); i++) {
if (hookConfigs.optInt(i, -1) != -1)
continue;
if (googleVersionName.matches(hookConfigs.getJSONObject(i).optString(KEY_VERSION))) {
activeHooksTemp = hookConfigs.getJSONObject(i);
}
}
if (activeHooksTemp == null) {
return;
}
final JSONObject activeHooks = activeHooksTemp;
Class a = findClass(ASSISTANT_PACKAGE + activeHooks.optString(KEY_ASSISTANT_CLASS, ".shared.h"), classLoader);
hookAllConstructors(a, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
SharedPreferences prefs = (SharedPreferences) getObjectField(param.thisObject, activeHooks.optString(KEY_PREFS, "bhX"));
// Enable all prefs
prefs.edit().putBoolean("key_opa_eligible", true)
.putBoolean("opa_enabled", true)
.putBoolean("opa_hotword_enabled", true)
.putBoolean("opa_hotword_transition_seen", true).apply();
}
});
// Don't allow to disable pref
findAndHookMethod(a, activeHooks.optString(KEY_SET_PREFS, "aG"), boolean.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
param.args[0] = true;
}
});
// Fake config and build.prop item
findAndHookMethod(a, activeHooks.optString(KEY_FAKE_CONFIG, "pa"), new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
return true;
}
});
findAndHookMethod(a, activeHooks.optString(KEY_FAKE_CONFIG_TWO, "oZ"), new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
return true;
}
});
// Enable for all languages, regardless of support from Google
findAndHookMethod(a, activeHooks.optString(KEY_ENABLE_LANGS, "pb"), new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
return true;
}
});
} catch (Throwable t) {
log(t);
}
}
}