Skip to content

Commit 136e2e6

Browse files
Add sort by most recent tracker detection (#537)
* Add option in menu page to sort in order of app last detected with tracking * Resolve naming issue for sorting apps with recent trackers detected, fix tiebreaking so that it is done in alphabetical order if both apps have the same last tracker detected time * Improve readability, add comments
1 parent 3dafe04 commit 136e2e6

5 files changed

Lines changed: 59 additions & 0 deletions

File tree

app/src/main/java/eu/faircode/netguard/ActivityMain.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,8 @@ else if ("name".equals(sort))
933933
menu.findItem(R.id.menu_sort_name).setChecked(true);
934934
else if ("trackers_all".equals(sort))
935935
menu.findItem(R.id.menu_sort_trackers_all).setChecked(true);
936+
else if ("trackers_recent".equals(sort))
937+
menu.findItem(R.id.menu_sort_by_latest_detected_tracker).setChecked(true);
936938
else
937939
menu.findItem(R.id.menu_sort_trackers_week).setChecked(true);
938940

@@ -974,6 +976,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
974976
item.setChecked(true);
975977
prefs.edit().putString("sort", "trackers_all").apply();
976978
return true;
979+
} else if (itemId == R.id.menu_sort_by_latest_detected_tracker) {
980+
item.setChecked(true);
981+
prefs.edit().putString("sort", "trackers_recent").apply();
982+
return true;
977983
} else if (itemId == R.id.menu_sort_uid) {
978984
item.setChecked(true);
979985
prefs.edit().putString("sort", "uid").apply();

app/src/main/java/eu/faircode/netguard/Rule.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,12 @@ public class Rule {
9999
private static Map<String, Boolean> cacheSystem = new HashMap<>();
100100
private static Map<String, Boolean> cacheInternet = new HashMap<>();
101101
private static Map<PackageInfo, Boolean> cacheEnabled = new HashMap<>();
102+
private static Map<Integer, Long> trackerRecent = new HashMap<>();
102103

104+
public long getLastTrackerTime() {
105+
Long time = trackerRecent.get(uid);
106+
return time == null ? 0L : time;
107+
}
103108
static List<PackageInfo> getPackages(Context context) {
104109
if (cachePackageInfo == null) {
105110
PackageManager pm = context.getPackageManager();
@@ -455,6 +460,7 @@ public static List<Rule> getRules(final boolean all, boolean self, Context conte
455460

456461
trackerCounts = trackerCountsAndTotalAll.first();
457462
trackerCountsPastWeek = trackerCountsAndTotalPastWeek.first();
463+
trackerRecent = trackerList.getLastTrackerTimes();
458464
int trackerTotal = trackerCountsAndTotalAll.second();
459465

460466
if (trackerTotal == 0
@@ -500,6 +506,17 @@ public int compare(Rule rule, Rule other) {
500506
return (rule.changed ? -1 : 1);
501507
}
502508
});
509+
else if ("trackers_recent".equals(sort)) {
510+
Collections.sort(listRules, (a, b) -> {
511+
// Most recent tracker contact first
512+
int timeCmp = Long.compare(b.getLastTrackerTime(), a.getLastTrackerTime());
513+
if (timeCmp != 0) return timeCmp;
514+
515+
// Tiebreak: alphabetical by app name, then package name
516+
int nameCmp = collator.compare(a.name, b.name);
517+
return nameCmp != 0 ? nameCmp : a.packageName.compareTo(b.packageName);
518+
});
519+
}
503520
else
504521
Collections.sort(listRules, new Comparator<Rule>() {
505522
@Override

app/src/main/java/net/kollnig/missioncontrol/data/TrackerList.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,38 @@ private Pair<Map<Integer, Integer>, Integer> countTrackers(Map<Integer, Set<Stri
258258
return new Pair<>(trackerCounts, totalTracker);
259259
}
260260

261+
/**
262+
* Iterate through all recorded host contacts and identify those that belong to known trackers,
263+
* For each app, only the most recent tracker contact time is stored in the hashmap. Used to
264+
* sort by most recent tracker detection in the main app list.
265+
*
266+
* @return A map of app UIDs to their most recent tracker contact timestamp in milliseconds
267+
* since epoch. Apps with no tracker contacts are not included in the map.
268+
*/
269+
public synchronized Map<Integer, Long> getLastTrackerTimes() {
270+
Map<Integer, Long> result = new HashMap<>();
271+
272+
try (Cursor cursor = databaseHelper.getHosts()) {
273+
if (cursor.moveToFirst()) {
274+
do {
275+
int uid = cursor.getInt(cursor.getColumnIndexOrThrow("uid"));
276+
String hostname = cursor.getString(cursor.getColumnIndexOrThrow("daddr"));
277+
long time = cursor.getLong(cursor.getColumnIndexOrThrow("time"));
278+
279+
Tracker tracker = findTracker(hostname);
280+
if (tracker == null)
281+
continue;
282+
283+
Long existing = result.get(uid);
284+
if (existing == null || time > existing)
285+
result.put(uid, time);
286+
287+
} while (cursor.moveToNext());
288+
}
289+
}
290+
291+
return result;
292+
}
261293
/**
262294
* Retrieve info for CSV export
263295
*

app/src/main/res/menu/main.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
<item
4444
android:id="@+id/menu_sort_name"
4545
android:title="@string/menu_sort_name"/>
46+
<item
47+
android:id="@+id/menu_sort_by_latest_detected_tracker"
48+
android:title="@string/menu_sort_by_latest_detected_tracker"/>
4649
<item
4750
android:visible="false"
4851
android:id="@+id/menu_sort_uid"

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<string name="menu_sort_uid">Sort by uid</string>
2222
<string name="menu_sort_companies_week">Sort by companies (week)</string>
2323
<string name="menu_sort_companies">Sort by companies</string>
24+
<string name="menu_sort_by_latest_detected_tracker">Sort by latest detected tracker</string>
2425
<string name="menu_log">Traffic log</string>
2526
<string name="menu_settings">Settings</string>
2627
<string name="menu_invite">Invite</string>

0 commit comments

Comments
 (0)