diff --git a/res/values/evolution_strings.xml b/res/values/evolution_strings.xml
index e08d475..68f5971 100644
--- a/res/values/evolution_strings.xml
+++ b/res/values/evolution_strings.xml
@@ -88,6 +88,31 @@
Status bar tuner
Choose which system icons can be shown
+
+ Spoofing
+
+
+ Component spoofing
+ Bypass app restrictions by spoofing components
+ System-Wide
+ Pixel props
+ Spoof a select group of Google apps to the latest Pixel device
+ Spoof tensor features
+ Unlock tensor/pixel features
+ Storage encryption
+ Spoof the device storage encryption status to \'Encrypted\'
+ App-Specific
+ Google app
+ Spoof the Google app to the latest Pixel device to unlock exclusive features
+ Play Store
+ Spoof the Play Store to the latest Pixel device
+ Google Photos
+ Spoof the Google Photos app as a Pixel XL
+ Snapchat
+ Spoof Snapchat as a Pixel XL to fix possible chat issues
+ Unlock higher FPS in games
+ Spoof your device as different model for specific games to unlock higher FPS
+
Evolution X aims to provide users with a Pixel-like feel at first glance, with additional features at your disposal
Website
diff --git a/res/xml/evolution_settings_miscellaneous.xml b/res/xml/evolution_settings_miscellaneous.xml
index 976b37c..4fcd7ae 100644
--- a/res/xml/evolution_settings_miscellaneous.xml
+++ b/res/xml/evolution_settings_miscellaneous.xml
@@ -9,4 +9,15 @@
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:title="@string/miscellaneous_title">
+
+
+
+
+
diff --git a/res/xml/spoofing.xml b/res/xml/spoofing.xml
new file mode 100644
index 0000000..29980be
--- /dev/null
+++ b/res/xml/spoofing.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/evolution/settings/fragments/miscellaneous/Spoofing.java b/src/org/evolution/settings/fragments/miscellaneous/Spoofing.java
new file mode 100644
index 0000000..bbbb54f
--- /dev/null
+++ b/src/org/evolution/settings/fragments/miscellaneous/Spoofing.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019-2024 The Evolution X Project
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.evolution.settings.fragments.miscellaneous;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.Toast;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.util.android.SystemRestartUtils;
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.evolution.settings.preferences.SystemPropertySwitchPreference;
+import org.evolution.settings.utils.DeviceUtils;
+
+@SearchIndexable
+public class Spoofing extends SettingsPreferenceFragment implements
+ Preference.OnPreferenceChangeListener {
+
+ private static final String TAG = "Spoofing";
+
+ private static final String KEY_SYSTEM_WIDE_CATEGORY = "spoofing_system_wide_category";
+ private static final String SYS_GOOGLE_SPOOF = "persist.sys.pixelprops";
+ private static final String SYS_GAMEPROP_SPOOF = "persist.sys.pixelprops.games";
+ private static final String SYS_GPHOTOS_SPOOF = "persist.sys.pixelprops.gphotos";
+ private static final String SYS_QSB_SPOOF = "persist.sys.pixelprops.qsb";
+ private static final String SYS_SNAP_SPOOF = "persist.sys.pixelprops.snap";
+ private static final String SYS_VENDING_SPOOF = "persist.sys.pixelprops.vending";
+ private static final String SYS_ENABLE_TENSOR_FEATURES = "persist.sys.features.tensor";
+
+ private PreferenceCategory mSystemWideCategory;
+ private SystemPropertySwitchPreference mGoogleSpoof;
+ private SystemPropertySwitchPreference mGamePropsSpoof;
+ private SystemPropertySwitchPreference mGphotosSpoof;
+ private SystemPropertySwitchPreference mQsbSpoof;
+ private SystemPropertySwitchPreference mSnapSpoof;
+ private SystemPropertySwitchPreference mVendingSpoof;
+ private SystemPropertySwitchPreference mTensorFeaturesToggle;
+
+ private Handler mHandler;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mHandler = new Handler();
+ addPreferencesFromResource(R.xml.spoofing);
+
+ final Context context = getContext();
+ final ContentResolver resolver = context.getContentResolver();
+ final PreferenceScreen prefScreen = getPreferenceScreen();
+ final Resources resources = context.getResources();
+
+ mSystemWideCategory = (PreferenceCategory) findPreference(KEY_SYSTEM_WIDE_CATEGORY);
+ mGamePropsSpoof = (SystemPropertySwitchPreference) findPreference(SYS_GAMEPROP_SPOOF);
+ mGphotosSpoof = (SystemPropertySwitchPreference) findPreference(SYS_GPHOTOS_SPOOF);
+ mGoogleSpoof = (SystemPropertySwitchPreference) findPreference(SYS_GOOGLE_SPOOF);
+ mQsbSpoof = (SystemPropertySwitchPreference) findPreference(SYS_QSB_SPOOF);
+ mSnapSpoof = (SystemPropertySwitchPreference) findPreference(SYS_SNAP_SPOOF);
+ mVendingSpoof = (SystemPropertySwitchPreference) findPreference(SYS_VENDING_SPOOF);
+ mTensorFeaturesToggle = (SystemPropertySwitchPreference) findPreference(SYS_ENABLE_TENSOR_FEATURES);
+
+ String model = SystemProperties.get("ro.product.model");
+ boolean isTensorDevice = model.matches("Pixel [6-9][a-zA-Z ]*");
+
+ if (DeviceUtils.isCurrentlySupportedPixel()) {
+ mGoogleSpoof.setDefaultValue(false);
+ if (isMainlineTensorModel(model)) {
+ mSystemWideCategory.removePreference(mGoogleSpoof);
+ }
+ }
+
+ if (isTensorDevice) {
+ mSystemWideCategory.removePreference(mTensorFeaturesToggle);
+ }
+
+ mGoogleSpoof.setOnPreferenceChangeListener(this);
+ mGphotosSpoof.setOnPreferenceChangeListener(this);
+ mGamePropsSpoof.setOnPreferenceChangeListener(this);
+ mQsbSpoof.setOnPreferenceChangeListener(this);
+ mSnapSpoof.setOnPreferenceChangeListener(this);
+ mVendingSpoof.setOnPreferenceChangeListener(this);
+ mTensorFeaturesToggle.setOnPreferenceChangeListener(this);
+ }
+
+ private boolean isMainlineTensorModel(String model) {
+ return model.matches("Pixel [8-9][a-zA-Z ]*");
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final Context context = getContext();
+ final ContentResolver resolver = context.getContentResolver();
+ if (preference == mGoogleSpoof
+ || preference == mGphotosSpoof
+ || preference == mGamePropsSpoof
+ || preference == mQsbSpoof
+ || preference == mSnapSpoof
+ || preference == mVendingSpoof) {
+ SystemRestartUtils.showSystemRestartDialog(getContext());
+ return true;
+ }
+ if (preference == mTensorFeaturesToggle) {
+ boolean enabled = (Boolean) newValue;
+ SystemProperties.set(SYS_ENABLE_TENSOR_FEATURES, enabled ? "true" : "false");
+ SystemRestartUtils.showSystemRestartDialog(getContext());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.EVOLVER;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.spoofing) {
+
+ @Override
+ public List getNonIndexableKeys(Context context) {
+ List keys = super.getNonIndexableKeys(context);
+ final Resources resources = context.getResources();
+
+ return keys;
+ }
+ };
+}
diff --git a/src/org/evolution/settings/utils/DeviceUtils.java b/src/org/evolution/settings/utils/DeviceUtils.java
index 9a026e0..df6439e 100644
--- a/src/org/evolution/settings/utils/DeviceUtils.java
+++ b/src/org/evolution/settings/utils/DeviceUtils.java
@@ -36,6 +36,8 @@ import static org.lineageos.internal.util.DeviceKeysConstants.*;
import androidx.annotation.NonNull;
+import java.util.Arrays;
+
public class DeviceUtils {
/* returns whether the device has a centered display cutout or not. */
@@ -282,4 +284,9 @@ public class DeviceUtils {
return NAV_BAR_MODE_GESTURAL == context.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode);
}
+
+ public static boolean isCurrentlySupportedPixel() {
+ boolean isPixelDevice = SystemProperties.get("ro.product.model").matches("Pixel [3-9][a-zA-Z ]*");
+ return isPixelDevice;
+ }
}