From a1d910c260ef4c024a2ebd552f2d1814a8abcea2 Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Thu, 21 Aug 2025 18:30:48 +0530 Subject: [PATCH] Evolver: Fix and improve keybox data preference * Add space for icon * Use linear layout throughout * Make toasts translatable * Dynamically update summary when XML loaded/cleared * Improve checks and XML loading Signed-off-by: Pranav Vashi --- res/layout/keybox_data_pref.xml | 48 +++++++++++--- res/values/evolution_strings.xml | 10 ++- res/xml/spoofing.xml | 4 +- .../preferences/KeyboxDataPreference.java | 66 +++++++++++++------ 4 files changed, 95 insertions(+), 33 deletions(-) diff --git a/res/layout/keybox_data_pref.xml b/res/layout/keybox_data_pref.xml index 6848b9a..622cd33 100644 --- a/res/layout/keybox_data_pref.xml +++ b/res/layout/keybox_data_pref.xml @@ -1,10 +1,35 @@ - + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" + android:clipToPadding="false" + android:baselineAligned="false"> + + + + + + android:textAppearance="?android:attr/textAppearanceListItem" /> + android:maxLines="5" + android:ellipsize="end" /> diff --git a/res/values/evolution_strings.xml b/res/values/evolution_strings.xml index 40c4a3e..bfe31ff 100644 --- a/res/values/evolution_strings.xml +++ b/res/values/evolution_strings.xml @@ -566,8 +566,14 @@ Choose the PIF JSON file to be used to spoof Play Integrity - Select keybox XML to spoof - Select the keybox XML used for system-wide key attestation spoofing. Click delete to reset keybox data. + Keybox attestation override + Load a custom keybox XML to override device key attestation + Custom keybox XML loaded. Delete to clear. + Clear keybox data + Not an XML file. Choose a valid keybox XML. + Invalid keybox XML: required fields missing + Keybox loaded + Keybox cleared Evolution X is a custom Android ROM that aims to replicate the Google Pixel experience, with added customization. Based on the LineageOS Project. diff --git a/res/xml/spoofing.xml b/res/xml/spoofing.xml index 3e08cf5..a01a76c 100644 --- a/res/xml/spoofing.xml +++ b/res/xml/spoofing.xml @@ -15,9 +15,7 @@ + android:title="@string/keybox_data_title" /> { if (mFilePickerLauncher != null) { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); - intent.setType("text/xml"); + intent.setType("*/*"); + intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"text/xml", "application/xml"}); intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); mFilePickerLauncher.launch(intent); } }); deleteButton.setOnClickListener(v -> { - Settings.Secure.putString(getContext().getContentResolver(), - Settings.Secure.KEYBOX_DATA, null); - Toast.makeText(getContext(), "XML data cleared", Toast.LENGTH_SHORT).show(); - callChangeListener(null); + if (!callChangeListener(Boolean.FALSE)) return; + Settings.Secure.putString(cr, Settings.Secure.KEYBOX_DATA, null); + Toast.makeText(ctx, ctx.getString(R.string.keybox_toast_file_cleared), Toast.LENGTH_SHORT).show(); + notifyChanged(); }); } + public void handleFileSelected(Uri uri) { - if (uri == null || - (!uri.toString().endsWith(".xml") && - !"text/xml".equals(getContext().getContentResolver().getType(uri)))) { - Toast.makeText(getContext(), "Invalid file selected", Toast.LENGTH_SHORT).show(); + final Context ctx = getContext(); + final ContentResolver cr = ctx.getContentResolver(); + + if (uri == null) { + Toast.makeText(ctx, + ctx.getString(R.string.keybox_toast_invalid_file_selected), Toast.LENGTH_SHORT).show(); return; } - try (InputStream inputStream = getContext().getContentResolver().openInputStream(uri); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { + final String type = cr.getType(uri); + boolean isXmlMime = "text/xml".equals(type) || "application/xml".equals(type); + boolean hasXmlExt = (uri.getPath() != null && uri.getPath().toLowerCase().endsWith(".xml")); + if (!isXmlMime && !hasXmlExt) { + Toast.makeText(ctx, + ctx.getString(R.string.keybox_toast_invalid_file_selected), Toast.LENGTH_SHORT).show(); + return; + } + try (InputStream inputStream = cr.openInputStream(uri); + BufferedReader reader = new BufferedReader( + new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8))) { StringBuilder xmlContent = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { @@ -86,18 +112,20 @@ public class KeyboxDataPreference extends Preference { String xml = xmlContent.toString(); if (!validateXml(xml)) { - Toast.makeText(getContext(), "Invalid XML: missing required data", Toast.LENGTH_SHORT).show(); + Toast.makeText(ctx, + ctx.getString(R.string.keybox_toast_missing_data), Toast.LENGTH_SHORT).show(); return; } - Settings.Secure.putString(getContext().getContentResolver(), - Settings.Secure.KEYBOX_DATA, xml); - Toast.makeText(getContext(), "XML file loaded", Toast.LENGTH_SHORT).show(); - callChangeListener(xml); - + if (!callChangeListener(Boolean.TRUE)) return; + Settings.Secure.putString(cr, Settings.Secure.KEYBOX_DATA, xml); + Toast.makeText(ctx, + ctx.getString(R.string.keybox_toast_file_loaded), Toast.LENGTH_SHORT).show(); + notifyChanged(); } catch (IOException e) { Log.e(TAG, "Failed to read XML file", e); - Toast.makeText(getContext(), "Failed to read XML", Toast.LENGTH_SHORT).show(); + Toast.makeText(ctx, + ctx.getString(R.string.keybox_toast_invalid_file_selected), Toast.LENGTH_SHORT).show(); } }