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();
}
}