From e279045cfe02dd4a571df98f596b8a9af9b9d24c Mon Sep 17 00:00:00 2001
From: Guillaume Jacquart <guillaume.jacquart@hoodbrains.com>
Date: Mon, 6 Mar 2023 10:41:06 +0000
Subject: 842: Create dummy-app apps compatibility leaking system components

---
 .../data/repositories/AppListsRepository.kt        | 94 ++++++++++++++++++----
 .../domain/usecases/IpScramblingStateUseCase.kt    |  9 +++
 .../domain/usecases/TrackersStateUseCase.kt        | 36 ++-------
 .../domain/usecases/TrackersStatisticsUseCase.kt   | 28 ++++++-
 4 files changed, 119 insertions(+), 48 deletions(-)

(limited to 'app/src/main/java/foundation/e/privacycentralapp')

diff --git a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt
index 65ae478..a97888f 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt
@@ -41,6 +41,12 @@ class AppListsRepository(
     companion object {
         private const val PNAME_SETTINGS = "com.android.settings"
         private const val PNAME_PWAPLAYER = "foundation.e.pwaplayer"
+        private const val PNAME_INTENT_VERIFICATION = "com.android.statementservice"
+        private const val PNAME_MICROG_SERVICES_CORE = "com.google.android.gms"
+
+        val appsCompatibiltyPNames = setOf(
+            PNAME_PWAPLAYER, PNAME_INTENT_VERIFICATION, PNAME_MICROG_SERVICES_CORE
+        )
     }
 
     val dummySystemApp = ApplicationDescription(
@@ -50,6 +56,13 @@ class AppListsRepository(
         icon = context.getDrawable(R.drawable.ic_e_app_logo)
     )
 
+    val dummyAppsCompatibilityApp = ApplicationDescription(
+        packageName = "foundation.e.dummyappscompatibilityapp",
+        uid = -2,
+        label = context.getString(R.string.dummy_apps_compatibility_app_label),
+        icon = context.getDrawable(R.drawable.ic_apps_compatibility_components)
+    )
+
     private suspend fun fetchAppDescriptions() {
         val launcherPackageNames = pm.queryIntentActivities(
             Intent(Intent.ACTION_MAIN, null).apply { addCategory(Intent.CATEGORY_LAUNCHER) },
@@ -58,25 +71,32 @@ class AppListsRepository(
 
         val visibleAppsFilter = { packageInfo: PackageInfo ->
             hasInternetPermission(packageInfo) &&
-                isNotHiddenSystemApp(packageInfo.applicationInfo, launcherPackageNames)
+                isStandardApp(packageInfo.applicationInfo, launcherPackageNames)
         }
 
         val hiddenAppsFilter = { packageInfo: PackageInfo ->
             hasInternetPermission(packageInfo) &&
-                !isNotHiddenSystemApp(packageInfo.applicationInfo, launcherPackageNames)
+                isHiddenSystemApp(packageInfo.applicationInfo, launcherPackageNames)
+        }
+
+        val aCFilter = { packageInfo: PackageInfo ->
+            packageInfo.packageName in appsCompatibiltyPNames
         }
 
         val visibleApps = permissionsModule.getApplications(visibleAppsFilter, true)
         val hiddenApps = permissionsModule.getApplications(hiddenAppsFilter, false)
+        val aCApps = permissionsModule.getApplications(aCFilter, false)
 
         val workProfileVisibleApps = permissionsModule.getWorkProfileApplications(visibleAppsFilter, true)
         val workProfileHiddenApps = permissionsModule.getWorkProfileApplications(hiddenAppsFilter, false)
-
-        appDescriptions.emit((visibleApps + dummySystemApp) to hiddenApps)
-        allProfilesAppDescriptions.emit(
-            (visibleApps + workProfileVisibleApps + dummySystemApp)
-                to (hiddenApps + workProfileHiddenApps)
-        )
+        val workProfileACApps = permissionsModule.getApplications(aCFilter, false)
+
+        appDescriptions.emit((visibleApps + dummySystemApp + dummyAppsCompatibilityApp) to hiddenApps)
+        allProfilesAppDescriptions.emit(Triple(
+            (visibleApps + workProfileVisibleApps + dummySystemApp + dummyAppsCompatibilityApp),
+            (hiddenApps + workProfileHiddenApps),
+            (aCApps + workProfileACApps)
+        ))
     }
 
     private var refreshAppJob: Job? = null
@@ -109,26 +129,47 @@ class AppListsRepository(
         return allProfilesAppDescriptions.value.second
     }
 
-    fun getAllApps(): Flow<List<ApplicationDescription>> = getAllProfilesVisibleApps()
-        .map { it + getAllProfilesHiddenSystemApps() }
-
-    fun getApplicationDescription(packageName: String): ApplicationDescription? {
-        return appDescriptions.value.first.find { it.packageName == packageName }
+    fun getAllProfilesACApps(): List<ApplicationDescription> {
+        return allProfilesAppDescriptions.value.third
     }
 
+    fun getAllApps(): Flow<List<ApplicationDescription>> = getAllProfilesVisibleApps()
+        .map { it + getAllProfilesHiddenSystemApps() + getAllProfilesACApps()}
+
     fun getApplicationDescription(appUid: Int): ApplicationDescription? {
-        return appDescriptions.value.first.find { it.uid == appUid }
+        return allProfilesAppDescriptions.value.first.find { it.uid == appUid }
     }
 
-    fun foldForHiddenSystemApp(appUid: Int, appValueGetter: (Int) -> Int): Int {
+    fun foldForHiddenApp(appUid: Int, appValueGetter: (Int) -> Int): Int {
         return if (appUid == dummySystemApp.uid) {
             getAllProfilesHiddenSystemApps().fold(0) { acc, app ->
                 acc + appValueGetter(app.uid)
             }
+        } else if (appUid == dummyAppsCompatibilityApp.uid) {
+            getAllProfilesACApps().fold(0) { acc, app ->
+                acc + appValueGetter(app.uid)
+            }
         } else appValueGetter(appUid)
     }
 
-    private val pm get() = context.packageManager
+    fun anyForHiddenApps(appUid: Int, test: (Int) -> Boolean): Boolean {
+        return if (appUid == dummySystemApp.uid) {
+            getAllProfilesHiddenSystemApps().any { test(it.uid) }
+        } else if (appUid == dummyAppsCompatibilityApp.uid) {
+            getAllProfilesACApps().any { test(it.uid) }
+        } else test(appUid)
+    }
+
+    fun applyForHiddenApps(appUid: Int, action: (Int) -> Unit) {
+        if (appUid == dummySystemApp.uid) {
+            getAllProfilesHiddenSystemApps().forEach { action(it.uid) }
+        } else if (appUid == dummyAppsCompatibilityApp.uid) {
+            getAllProfilesACApps().forEach { action(it.uid) }
+        } else action(appUid)
+    }
+
+
+        private val pm get() = context.packageManager
 
     private val appDescriptions = MutableStateFlow(
         Pair(
@@ -138,7 +179,8 @@ class AppListsRepository(
     )
 
     private val allProfilesAppDescriptions = MutableStateFlow(
-        Pair(
+        Triple(
+            emptyList<ApplicationDescription>(),
             emptyList<ApplicationDescription>(),
             emptyList<ApplicationDescription>()
         )
@@ -164,5 +206,23 @@ class AppListsRepository(
         return false
     }
 
+    private fun isStandardApp(app: ApplicationInfo, launcherApps: List<String>): Boolean {
+        return when {
+            app.packageName == PNAME_SETTINGS -> false
+            app.packageName in appsCompatibiltyPNames -> false
+            app.hasFlag(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) -> true
+            !app.hasFlag(ApplicationInfo.FLAG_SYSTEM) -> true
+            launcherApps.contains(app.packageName) -> true
+            else -> false
+        }
+    }
+
+    private fun isHiddenSystemApp(app: ApplicationInfo, launcherApps: List<String>): Boolean {
+        return when {
+            app.packageName in appsCompatibiltyPNames -> false
+            else -> !isNotHiddenSystemApp(app, launcherApps)
+        }
+    }
+
     private fun ApplicationInfo.hasFlag(flag: Int) = (flags and flag) == 1
 }
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt
index 9216233..e753d7b 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt
@@ -97,6 +97,11 @@ class IpScramblingStateUseCase(
             mutable.removeAll(getHiddenPackageNames())
             mutable.add(appListsRepository.dummySystemApp.packageName)
             whitelist = mutable
+        } else if (AppListsRepository.appsCompatibiltyPNames.any { it in whitelist }) {
+            val mutable = whitelist.toMutableSet()
+            mutable.removeAll(AppListsRepository.appsCompatibiltyPNames)
+            mutable.add(appListsRepository.dummyAppsCompatibilityApp.packageName)
+            whitelist = mutable
         }
 
         return whitelist
@@ -109,12 +114,16 @@ class IpScramblingStateUseCase(
         if (visibleList.contains(packageName)) {
             if (packageName == appListsRepository.dummySystemApp.packageName) {
                 rawList.removeAll(getHiddenPackageNames())
+            } else if (packageName == appListsRepository.dummyAppsCompatibilityApp.packageName) {
+                rawList.removeAll(AppListsRepository.appsCompatibiltyPNames)
             } else {
                 rawList.remove(packageName)
             }
         } else {
             if (packageName == appListsRepository.dummySystemApp.packageName) {
                 rawList.addAll(getHiddenPackageNames())
+            } else if (packageName == appListsRepository.dummyAppsCompatibilityApp.packageName) {
+                rawList.addAll(AppListsRepository.appsCompatibiltyPNames)
             } else {
                 rawList.add(packageName)
             }
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt
index 11f0466..820073b 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt
@@ -54,10 +54,6 @@ class TrackersStateUseCase(
             blockTrackersPrivacyModule.isWhiteListEmpty()
     }
 
-    fun getApplicationDescription(packageName: String): ApplicationDescription? {
-        return appListsRepository.getApplicationDescription(packageName)
-    }
-
     fun getApplicationDescription(appUid: Int): ApplicationDescription? {
         return appListsRepository.getApplicationDescription(appUid)
     }
@@ -66,32 +62,18 @@ class TrackersStateUseCase(
         return isWhitelisted(appUid, appListsRepository, blockTrackersPrivacyModule)
     }
 
-    fun getTrackersWhitelistIds(appUid: Int): List<String> {
-        return if (appUid == appListsRepository.dummySystemApp.uid) {
-            appListsRepository.getAllProfilesHiddenSystemApps().fold(mutableSetOf<String>()) { acc, app ->
-                acc.addAll(blockTrackersPrivacyModule.getWhiteList(app.uid).map { it.id })
-                acc
-            }.toList()
-        } else blockTrackersPrivacyModule.getWhiteList(appUid).map { it.id }
-    }
-
     fun toggleAppWhitelist(appUid: Int, isWhitelisted: Boolean) {
-        if (appUid == appListsRepository.dummySystemApp.uid) {
-            appListsRepository.getAllProfilesHiddenSystemApps().forEach {
-                blockTrackersPrivacyModule.setWhiteListed(it.uid, isWhitelisted)
-            }
-        } else blockTrackersPrivacyModule.setWhiteListed(appUid, isWhitelisted)
+        appListsRepository.applyForHiddenApps(appUid) { uid ->
+            blockTrackersPrivacyModule.setWhiteListed(uid, isWhitelisted)
+        }
 
         updateAllTrackersBlockedState()
     }
 
     fun blockTracker(appUid: Int, tracker: Tracker, isBlocked: Boolean) {
-        if (appUid == appListsRepository.dummySystemApp.uid) {
-            appListsRepository.getAllProfilesHiddenSystemApps().forEach {
-                blockTrackersPrivacyModule.setWhiteListed(tracker, it.uid, !isBlocked)
-            }
-        } else blockTrackersPrivacyModule.setWhiteListed(tracker, appUid, !isBlocked)
-
+        appListsRepository.applyForHiddenApps(appUid) { uid ->
+            blockTrackersPrivacyModule.setWhiteListed(tracker, uid, !isBlocked)
+        }
         updateAllTrackersBlockedState()
     }
 
@@ -106,9 +88,5 @@ fun isWhitelisted(
     appListsRepository: AppListsRepository,
     blockTrackersPrivacyModule: IBlockTrackersPrivacyModule
 ): Boolean {
-    return if (appUid == appListsRepository.dummySystemApp.uid) {
-        appListsRepository.getAllProfilesHiddenSystemApps().any {
-            blockTrackersPrivacyModule.isWhitelisted(it.uid)
-        }
-    } else blockTrackersPrivacyModule.isWhitelisted(appUid)
+    return appListsRepository.anyForHiddenApps(appUid, blockTrackersPrivacyModule::isWhitelisted)
 }
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt
index 404032b..cc6ec45 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt
@@ -166,6 +166,10 @@ class TrackersStatisticsUseCase(
             appListsRepository.getAllProfilesHiddenSystemApps().map {
                 trackTrackersPrivacyModule.getTrackersForApp(it.uid)
             }.flatten().distinctBy { it.id }
+        } else if (appUid == appListsRepository.dummyAppsCompatibilityApp.uid) {
+            appListsRepository.getAllProfilesACApps().map {
+                trackTrackersPrivacyModule.getTrackersForApp(it.uid)
+            }.flatten().distinctBy { it.id }
         } else trackTrackersPrivacyModule.getTrackersForApp(appUid)
 
         return trackers.sortedBy { it.label.lowercase() }
@@ -182,6 +186,14 @@ class TrackersStatisticsUseCase(
                 acc.addAll(blockTrackersPrivacyModule.getWhiteList(app.uid).map { it.id })
                 acc
             }
+        } else if (appUid == appListsRepository.dummyAppsCompatibilityApp.uid) {
+            val acApps = appListsRepository.getAllProfilesACApps()
+            trackers = trackTrackersPrivacyModule.getTrackers(acApps.map { it.uid })
+
+            whiteListedTrackersIds = acApps.fold(HashSet<String>()) { acc, app ->
+                acc.addAll(blockTrackersPrivacyModule.getWhiteList(app.uid).map { it.id })
+                acc
+            }
         } else {
             trackers = trackTrackersPrivacyModule.getTrackersForApp(appUid)
             whiteListedTrackersIds = blockTrackersPrivacyModule.getWhiteList(appUid)
@@ -198,6 +210,12 @@ class TrackersStatisticsUseCase(
             }.reduce { (accBlocked, accLeaked), (blocked, leaked) ->
                 accBlocked + blocked to accLeaked + leaked
             }
+        } else if (appUid == appListsRepository.dummyAppsCompatibilityApp.uid) {
+            appListsRepository.getAllProfilesACApps().map {
+                trackTrackersPrivacyModule.getPastDayTrackersCallsForApp(it.uid)
+            }.reduce { (accBlocked, accLeaked), (blocked, leaked) ->
+                accBlocked + blocked to accLeaked + leaked
+            }
         } else trackTrackersPrivacyModule.getPastDayTrackersCallsForApp(appUid)
     }
 
@@ -205,6 +223,8 @@ class TrackersStatisticsUseCase(
         val trackersCounts = trackTrackersPrivacyModule.getTrackersCountByApp()
         val hiddenAppsTrackersWithWhiteList =
             getTrackersWithWhiteList(appListsRepository.dummySystemApp.uid)
+        val acAppsTrackersWithWhiteList =
+            getTrackersWithWhiteList(appListsRepository.dummyAppsCompatibilityApp.uid)
 
         return appListsRepository.getAllProfilesVisibleApps()
             .map { apps ->
@@ -216,19 +236,23 @@ class TrackersStatisticsUseCase(
                             isWhitelisted(app.uid, appListsRepository, blockTrackersPrivacyModule),
                         trackersCount = if (app.uid == appListsRepository.dummySystemApp.uid) {
                             hiddenAppsTrackersWithWhiteList.size
+                        } else if (app.uid == appListsRepository.dummyAppsCompatibilityApp.uid) {
+                            acAppsTrackersWithWhiteList.size
                         } else {
                             trackersCounts.getOrDefault(app.uid, 0)
                         },
                         whiteListedTrackersCount = if (app.uid == appListsRepository.dummySystemApp.uid) {
                             hiddenAppsTrackersWithWhiteList.count { it.second }
+                        } else if (app.uid == appListsRepository.dummyAppsCompatibilityApp.uid) {
+                            acAppsTrackersWithWhiteList.count { it.second }
                         } else {
                             blockTrackersPrivacyModule.getWhiteList(app.uid).size
                         },
-                        blockedLeaks = appListsRepository.foldForHiddenSystemApp(app.uid) {
+                        blockedLeaks = appListsRepository.foldForHiddenApp(app.uid) {
                             appUid ->
                             callsByApp.getOrDefault(appUid, 0 to 0).first
                         },
-                        leaks = appListsRepository.foldForHiddenSystemApp(app.uid) {
+                        leaks = appListsRepository.foldForHiddenApp(app.uid) {
                             appUid ->
                             callsByApp.getOrDefault(appUid, 0 to 0).second
                         }
-- 
cgit v1.2.1