Evolver: Bring back PIF

* Allow users to manually use non-root PIF.

Revert "Evolver: Drop PIF"

This reverts commit d5915369e4263882843d6dc0eedb6147c9528aad.
This commit is contained in:
Joey Huab
2025-06-24 06:27:29 +09:00
parent 7bc56b321c
commit bee645d488
3 changed files with 186 additions and 1 deletions

View File

@@ -555,6 +555,8 @@
<string name="spoofing_pixel_props_summary">Spoof a select group of Google apps to the latest Pixel device</string>
<string name="tensor_spoof_title">Spoof tensor features</string>
<string name="tensor_spoof_summary">Unlock tensor/pixel features</string>
<string name="gms_spoof_title">Play Integrity fix</string>
<string name="gms_spoof_summary">Spoof your device to pass Google Play Attestation</string>
<string name="spoofing_storage_encryption_title">Storage encryption</string>
<string name="spoofing_storage_encryption_summary">Spoof the device storage encryption status to \'Encrypted\'</string>
<string name="spoofing_app_specific_category">App-Specific</string>
@@ -569,6 +571,17 @@
<string name="gameprops_title">Unlock higher FPS in games</string>
<string name="gameprops_summary">Spoof your device as different model for specific games to unlock higher FPS</string>
<!-- Miscellaneous/Spoofing/Play Integrity fix JSON update -->
<string name="toast_spoofing_success">Successfully downloaded pif.json. Spoofing as %1$s for Play Integrity.</string>
<string name="toast_spoofing_failure">Failed to spoof properties.</string>
<string name="update_pif_json_title">Update Play Integrity fix</string>
<string name="update_pif_json_summary">Update PIF spoofing device, requires internet connection.</string>
<string name="show_pif_properties_title">Play Integrity fix properties</string>
<string name="show_pif_properties_summary">Show all currently set PIF properties</string>
<string name="error_loading_properties">Error loading PIF properties</string>
<string name="pif_spoofing_title">Select PIF JSON file</string>
<string name="pif_spoofing_summary">Choose the PIF JSON file to be used to spoof Play Integrity</string>
<!-- About -->
<string name="about_info">Evolution X aims to provide users with a Pixel-like feel at first glance, with additional features at your disposal</string>
<string name="about_website_title">Website</string>

View File

@@ -12,6 +12,31 @@
android:key="spoofing_system_wide_category"
android:title="@string/spoofing_system_wide_category">
<!-- GMS spoof -->
<org.evolution.settings.preferences.SystemPropertySwitchPreference
android:key="persist.sys.pixelprops.gms"
android:title="@string/gms_spoof_title"
android:summary="@string/gms_spoof_summary"
android:defaultValue="false" />
<Preference
android:key="show_pif_properties"
android:title="@string/show_pif_properties_title"
android:summary="@string/show_pif_properties_summary"
android:dependency="persist.sys.pixelprops.gms" />
<Preference
android:key="update_pif_json"
android:title="@string/update_pif_json_title"
android:summary="@string/update_pif_json_summary"
android:dependency="persist.sys.pixelprops.gms" />
<Preference
android:key="pif_json_file_preference"
android:title="@string/pif_spoofing_title"
android:summary="@string/pif_spoofing_summary"
android:dependency="persist.sys.pixelprops.gms" />
<!-- Pixel props -->
<org.evolution.settings.preferences.SystemPropertySwitchPreference
android:key="persist.sys.pixelprops"

View File

@@ -56,13 +56,20 @@ import java.util.stream.Collectors;
import org.evolution.settings.preferences.SystemPropertySwitchPreference;
import org.evolution.settings.utils.DeviceUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@SearchIndexable
public class Spoofing extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener {
private static final String TAG = "Spoofing";
private static final String KEY_PIF_JSON_FILE_PREFERENCE = "pif_json_file_preference";
private static final String KEY_SYSTEM_WIDE_CATEGORY = "spoofing_system_wide_category";
private static final String KEY_UPDATE_JSON_BUTTON = "update_pif_json";
private static final String SYS_GMS_SPOOF = "persist.sys.pixelprops.gms";
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";
@@ -71,7 +78,10 @@ public class Spoofing extends SettingsPreferenceFragment implements
private static final String SYS_VENDING_SPOOF = "persist.sys.pixelprops.vending";
private static final String SYS_ENABLE_TENSOR_FEATURES = "persist.sys.features.tensor";
private Preference mPifJsonFilePreference;
private Preference mUpdateJsonButton;
private PreferenceCategory mSystemWideCategory;
private SystemPropertySwitchPreference mGmsSpoof;
private SystemPropertySwitchPreference mGoogleSpoof;
private SystemPropertySwitchPreference mGamePropsSpoof;
private SystemPropertySwitchPreference mGphotosSpoof;
@@ -96,14 +106,18 @@ public class Spoofing extends SettingsPreferenceFragment implements
mSystemWideCategory = (PreferenceCategory) findPreference(KEY_SYSTEM_WIDE_CATEGORY);
mGamePropsSpoof = (SystemPropertySwitchPreference) findPreference(SYS_GAMEPROP_SPOOF);
mGphotosSpoof = (SystemPropertySwitchPreference) findPreference(SYS_GPHOTOS_SPOOF);
mGmsSpoof = (SystemPropertySwitchPreference) findPreference(SYS_GMS_SPOOF);
mGoogleSpoof = (SystemPropertySwitchPreference) findPreference(SYS_GOOGLE_SPOOF);
mPifJsonFilePreference = findPreference(KEY_PIF_JSON_FILE_PREFERENCE);
mQsbSpoof = (SystemPropertySwitchPreference) findPreference(SYS_QSB_SPOOF);
mSnapSpoof = (SystemPropertySwitchPreference) findPreference(SYS_SNAP_SPOOF);
mVendingSpoof = (SystemPropertySwitchPreference) findPreference(SYS_VENDING_SPOOF);
mUpdateJsonButton = findPreference(KEY_UPDATE_JSON_BUTTON);
mTensorFeaturesToggle = (SystemPropertySwitchPreference) findPreference(SYS_ENABLE_TENSOR_FEATURES);
String model = SystemProperties.get("ro.product.model");
boolean isTensorDevice = model.matches("Pixel [6-9][a-zA-Z ]*");
boolean isPixelGmsEnabled = SystemProperties.getBoolean(SYS_GMS_SPOOF, true); // Default to Pixel GMS
if (DeviceUtils.isCurrentlySupportedPixel()) {
mGoogleSpoof.setDefaultValue(false);
@@ -116,6 +130,7 @@ public class Spoofing extends SettingsPreferenceFragment implements
mSystemWideCategory.removePreference(mTensorFeaturesToggle);
}
mGmsSpoof.setOnPreferenceChangeListener(this);
mGoogleSpoof.setOnPreferenceChangeListener(this);
mGphotosSpoof.setOnPreferenceChangeListener(this);
mGamePropsSpoof.setOnPreferenceChangeListener(this);
@@ -123,17 +138,149 @@ public class Spoofing extends SettingsPreferenceFragment implements
mSnapSpoof.setOnPreferenceChangeListener(this);
mVendingSpoof.setOnPreferenceChangeListener(this);
mTensorFeaturesToggle.setOnPreferenceChangeListener(this);
mPifJsonFilePreference.setOnPreferenceClickListener(preference -> {
openFileSelector(10001);
return true;
});
mUpdateJsonButton.setOnPreferenceClickListener(preference -> {
updatePropertiesFromUrl("https://raw.githubusercontent.com/Evolution-X/.github/refs/heads/main/profile/pif.json");
return true;
});
Preference showPropertiesPref = findPreference("show_pif_properties");
if (showPropertiesPref != null) {
showPropertiesPref.setOnPreferenceClickListener(preference -> {
showPropertiesDialog();
return true;
});
}
}
private boolean isMainlineTensorModel(String model) {
return model.matches("Pixel [8-9][a-zA-Z ]*");
}
private void openFileSelector(int requestCode) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("application/json");
startActivityForResult(intent, requestCode);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && data != null) {
Uri uri = data.getData();
if (uri != null) {
if (requestCode == 10001) {
loadPifJson(uri);
}
}
}
}
private void showPropertiesDialog() {
StringBuilder properties = new StringBuilder();
try {
JSONObject jsonObject = new JSONObject();
String[] keys = {
"persist.sys.pihooks_ID",
"persist.sys.pihooks_BRAND",
"persist.sys.pihooks_DEVICE",
"persist.sys.pihooks_FINGERPRINT",
"persist.sys.pihooks_MANUFACTURER",
"persist.sys.pihooks_MODEL",
"persist.sys.pihooks_PRODUCT",
"persist.sys.pihooks_SECURITY_PATCH",
"persist.sys.pihooks_DEVICE_INITIAL_SDK_INT",
"persist.sys.pihooks_RELEASE",
"persist.sys.pihooks_SDK_INT"
};
for (String key : keys) {
String value = SystemProperties.get(key, null);
if (value != null) {
String buildKey = key.replace("persist.sys.pihooks_", "");
jsonObject.put(buildKey, value);
}
}
properties.append(jsonObject.toString(4));
} catch (JSONException e) {
Log.e(TAG, "Error creating JSON from properties", e);
properties.append(getString(R.string.error_loading_properties));
}
new AlertDialog.Builder(getContext())
.setTitle(R.string.show_pif_properties_title)
.setMessage(properties.toString())
.setPositiveButton(android.R.string.ok, null)
.show();
}
private void updatePropertiesFromUrl(String urlString) {
new Thread(() -> {
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try (InputStream inputStream = urlConnection.getInputStream()) {
String json = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
Log.d(TAG, "Downloaded JSON data: " + json);
JSONObject jsonObject = new JSONObject(json);
String spoofedModel = jsonObject.optString("MODEL", "Unknown model");
for (Iterator<String> it = jsonObject.keys(); it.hasNext(); ) {
String key = it.next();
String value = jsonObject.getString(key);
Log.d(TAG, "Setting property: persist.sys.pihooks_" + key + " = " + value);
SystemProperties.set("persist.sys.pihooks_" + key, value);
}
mHandler.post(() -> {
String toastMessage = getString(R.string.toast_spoofing_success, spoofedModel);
Toast.makeText(getContext(), toastMessage, Toast.LENGTH_LONG).show();
});
} finally {
urlConnection.disconnect();
}
} catch (Exception e) {
Log.e(TAG, "Error downloading JSON or setting properties", e);
mHandler.post(() -> {
Toast.makeText(getContext(), R.string.toast_spoofing_failure, Toast.LENGTH_LONG).show();
});
}
mHandler.postDelayed(() -> {
SystemRestartUtils.showSystemRestartDialog(getContext());
}, 1250);
}).start();
}
private void loadPifJson(Uri uri) {
Log.d(TAG, "Loading PIF JSON from URI: " + uri.toString());
try (InputStream inputStream = getActivity().getContentResolver().openInputStream(uri)) {
if (inputStream != null) {
String json = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
Log.d(TAG, "PIF JSON data: " + json);
JSONObject jsonObject = new JSONObject(json);
for (Iterator<String> it = jsonObject.keys(); it.hasNext(); ) {
String key = it.next();
String value = jsonObject.getString(key);
Log.d(TAG, "Setting PIF property: persist.sys.pihooks_" + key + " = " + value);
SystemProperties.set("persist.sys.pihooks_" + key, value);
}
}
} catch (Exception e) {
Log.e(TAG, "Error reading PIF JSON or setting properties", e);
}
mHandler.postDelayed(() -> {
SystemRestartUtils.showSystemRestartDialog(getContext());
}, 1250);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final Context context = getContext();
final ContentResolver resolver = context.getContentResolver();
if (preference == mGoogleSpoof
if (preference == mGmsSpoof
|| preference == mGoogleSpoof
|| preference == mGphotosSpoof
|| preference == mGamePropsSpoof
|| preference == mQsbSpoof