diff --git a/res/values/evolution_strings.xml b/res/values/evolution_strings.xml
index b271e12..5980734 100644
--- a/res/values/evolution_strings.xml
+++ b/res/values/evolution_strings.xml
@@ -555,6 +555,8 @@
Spoof a select group of Google apps to the latest Pixel device
Spoof tensor features
Unlock tensor/pixel features
+ Play Integrity fix
+ Spoof your device to pass Google Play Attestation
Storage encryption
Spoof the device storage encryption status to \'Encrypted\'
App-Specific
@@ -569,6 +571,17 @@
Unlock higher FPS in games
Spoof your device as different model for specific games to unlock higher FPS
+
+ Successfully downloaded pif.json. Spoofing as %1$s for Play Integrity.
+ Failed to spoof properties.
+ Update Play Integrity fix
+ Update PIF spoofing device, requires internet connection.
+ Play Integrity fix properties
+ Show all currently set PIF properties
+ Error loading PIF properties
+ Select PIF JSON file
+ Choose the PIF JSON file to be used to spoof Play Integrity
+
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/spoofing.xml b/res/xml/spoofing.xml
index 29980be..60a1bb4 100644
--- a/res/xml/spoofing.xml
+++ b/res/xml/spoofing.xml
@@ -12,6 +12,31 @@
android:key="spoofing_system_wide_category"
android:title="@string/spoofing_system_wide_category">
+
+
+
+
+
+
+
+
+
{
+ 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 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 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