Skip to content

Commit ebe4beb

Browse files
authored
Merge pull request #15 from shoey63/pr-15
feat: overhaul dynamic CRL fetch logic and enhance status UI Network: Implemented a dynamic cache-busting strategy using randomized floats and 'identity' encoding in HTTP headers. This bypasses aggressive Google CDN edge caching (stale HTTP 200s / 304s) to guarantee fetching the absolute latest X.509 revocation list directly from the origin server. UI: Introduced dual-badge CRL update logic, splitting the network state strings into granular 'Initial list downloaded' and 'New list fetched' states for clearer user feedback. Formatting: Locked the CRL publish time display in AuthorizationList to strict GMT/UTC to eliminate local timezone ambiguity. Credits: CDN cache-busting header logic courtesy of XDA members @TheFreeman193 and @Vagelis1608. New strings
2 parents fbf0ca2 + 82e8bcd commit ebe4beb

4 files changed

Lines changed: 26 additions & 11 deletions

File tree

app/src/main/java/io/github/vvb2060/keyattestation/attestation/AuthorizationList.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,10 @@ private static String joinStrings(Collection<String> collection) {
532532
}
533533

534534
public static String formatDate(Date date) {
535-
return DateFormat.getDateTimeInstance().format(date);
536-
}
535+
java.text.DateFormat df = java.text.DateFormat.getDateTimeInstance();
536+
df.setTimeZone(java.util.TimeZone.getTimeZone("UTC"));
537+
return df.format(date) + " UTC";
538+
}
537539

538540
public static String paddingModesToString(final Set<Integer> paddingModes) {
539541
return joinStrings(transform(paddingModes, forMap(paddingMap, "Unknown")));
@@ -942,4 +944,4 @@ public String toString() {
942944
}
943945
return s.toString();
944946
}
945-
}
947+
}

app/src/main/java/io/github/vvb2060/keyattestation/attestation/RevocationList.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@
2121
import io.github.vvb2060.keyattestation.R;
2222

2323
public record RevocationList(String status, String reason, DataSource source) {
24-
public enum DataSource {
24+
public enum DataSource {
25+
NETWORK_INITIAL,
2526
NETWORK_UPDATE,
2627
NETWORK_UP_TO_DATE,
2728
CACHE,
2829
BUNDLED
2930
}
30-
31+
3132
private static final String TAG = "RevocationList";
3233
private static final String CACHE_FILE = "revocation_cache.json";
3334
private static final String PREFS_NAME = "revocation_prefs";
@@ -83,6 +84,15 @@ private static NetworkResult fetchFromNetwork(String statusUrl, long cachedTime)
8384
connection.setReadTimeout(10000);
8485
connection.setRequestProperty("User-Agent", "KeyAttestation");
8586

87+
double rand = Math.round(Math.random() * 1000.0) / 1000.0;
88+
89+
// Force the CDN to bypass edge caches
90+
connection.setRequestProperty("Cache-Control", "no-cache, no-store, no-transform, max-age=0");
91+
connection.setRequestProperty("Accept", "application/json, */*;q=" + rand);
92+
connection.setRequestProperty("Accept-Encoding", "identity, *;q=" + rand);
93+
connection.setRequestProperty("Accept-Ranges", "bytes");
94+
95+
// Standard conditional GET for bandwidth saving (if the node IS synced)
8696
if (cachedTime != 0) {
8797
connection.setIfModifiedSince(cachedTime);
8898
}
@@ -160,7 +170,8 @@ private static StatusResult getStatus() {
160170
} else if (networkResult != null && networkResult.json() != null) {
161171
saveToCache(networkResult.json());
162172
try {
163-
return new StatusResult(networkResult.json().getJSONObject("entries"), DataSource.NETWORK_UPDATE);
173+
DataSource successState = (cachedTime == 0) ? DataSource.NETWORK_INITIAL : DataSource.NETWORK_UPDATE;
174+
return new StatusResult(networkResult.json().getJSONObject("entries"), successState);
164175
} catch (JSONException ignored) {}
165176
}
166177

@@ -198,7 +209,7 @@ public static void refresh() {
198209

199210
// If we successfully fetched a brand new file this session,
200211
// don't let a subsequent UI refresh overwrite our status with a 304!
201-
if (currentSource == DataSource.NETWORK_UPDATE && result.source() == DataSource.NETWORK_UP_TO_DATE) {
212+
if ((currentSource == DataSource.NETWORK_UPDATE || currentSource == DataSource.NETWORK_INITIAL) && result.source() == DataSource.NETWORK_UP_TO_DATE) {
202213
Log.i(TAG, "Preserving NETWORK_UPDATE status across multiple refreshes");
203214
} else {
204215
currentSource = result.source();
@@ -213,7 +224,7 @@ public static RevocationList get(BigInteger serialNumber) {
213224
StatusResult result = getStatus();
214225
data = result.json();
215226

216-
if (currentSource == DataSource.NETWORK_UPDATE && result.source() == DataSource.NETWORK_UP_TO_DATE) {
227+
if ((currentSource == DataSource.NETWORK_UPDATE || currentSource == DataSource.NETWORK_INITIAL) && result.source() == DataSource.NETWORK_UP_TO_DATE) {
217228
Log.i(TAG, "Preserving NETWORK_UPDATE status in get()");
218229
} else {
219230
currentSource = result.source();
@@ -234,4 +245,4 @@ public static RevocationList get(BigInteger serialNumber) {
234245
public String toString() {
235246
return "status: " + status + ", source: " + source;
236247
}
237-
}
248+
}

app/src/main/java/io/github/vvb2060/keyattestation/home/HomeAdapter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class HomeAdapter(listener: Listener) : IdBasedRecyclerViewAdapter() {
113113
}
114114

115115
val statusLine = when (source) {
116+
RevocationList.DataSource.NETWORK_INITIAL -> context.getString(R.string.revocation_status_initial)
116117
RevocationList.DataSource.NETWORK_UPDATE -> context.getString(R.string.revocation_status_new_fetch)
117118
RevocationList.DataSource.NETWORK_UP_TO_DATE -> context.getString(R.string.revocation_status_up_to_date)
118119
RevocationList.DataSource.CACHE -> context.getString(R.string.revocation_status_offline_cached)
@@ -458,4 +459,4 @@ class HomeAdapter(listener: Listener) : IdBasedRecyclerViewAdapter() {
458459
R.string.authorization_list_moduleHash_description,
459460
)
460461
}
461-
}
462+
}

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@
5757
<string name="revocation_list_publish_time">Revocation list publish time</string>
5858
<string name="revocation_list_description">The revocation list is used to check if certificates have been revoked. This shows the publication time of the currently used revocation list.</string>
5959

60-
<string name="revocation_status_new_fetch">ℹ️ New CRL Fetched!</string>
60+
<string name="revocation_status_initial">⚙️ Initial list downloaded</string>
61+
<string name="revocation_status_new_fetch">✨ New list fetched!</string>
6162
<string name="revocation_status_up_to_date">✅ CRL Up-to-date</string>
6263
<string name="revocation_status_offline_cached">⚠️ Device offline - using cached CRL</string>
6364
<string name="revocation_status_offline_bundled">❌ Offline - CRL Out-of-date</string>

0 commit comments

Comments
 (0)