Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ebcb55e authored by Sayantan Roychowdhury's avatar Sayantan Roychowdhury
Browse files

AgeRatingProvider - separation of concerns

parent 952e34f0
Loading
Loading
Loading
Loading
+54 −24
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import timber.log.Timber

class AgeRatingProvider : ContentProvider() {

@@ -101,41 +102,70 @@ class AgeRatingProvider : ContentProvider() {

    private fun getAgeRatings(): Cursor {
        val cursor = MatrixCursor(arrayOf(COLUMN_PACKAGE_NAME))
        val packagesNames = appLoungePackageManager.getAllUserApps().map { it.packageName }
        val packageNames = appLoungePackageManager.getAllUserApps().map { it.packageName }
        runBlocking {
            withContext(IO) {
                try {
                    if (packageNames.isEmpty()) return@withContext cursor

                    ensureAgeGroupDataExists()

                    val ageValidityDeferred = packageNames.map { packageName ->
                        async {
                            if (!setupAuthDataIfExists()) return@async null
                            getAppAgeValidity(packageName)
                        }
                    }
                    val validityList = ageValidityDeferred.awaitAll()
                    compileAppBlockList(cursor, validityList, packageNames)
                } catch (e: Exception) {
                    Timber.e("AgeRatingProvider", "Error fetching age ratings", e)
                }
            }
        }
        return cursor
    }

    private suspend fun ensureAgeGroupDataExists() {
        if (contentRatingsRepository.contentRatingGroups.isEmpty()) {
            contentRatingsRepository.fetchContentRatingData()
        }
    }

                val contentRatingsDeferred = packagesNames.map { packageName ->
                    async {
    /**
     * Return true if valid AuthData could be fetched from data store, false otherwise.
     */
    private fun setupAuthDataIfExists(): Boolean {
        val authData = dataStoreManager.getAuthData()
                        if (authData.email.isBlank() && authData.aasToken.isBlank()) {
                            return@async null
                        } else {
        if (authData.email.isNotBlank() || authData.aasToken.isNotBlank()) {
            authenticatorRepository.gplayAuth = authData
            return true
        }
        Timber.e("Blank AuthData, cannot fetch ratings from provider.")
        return false
    }

    private suspend fun getAppAgeValidity(packageName: String): Boolean {
        val fakeAppInstall = AppInstall(
            packageName = packageName,
            origin = Origin.GPLAY
        )
        val validateResult = validateAppAgeLimitUseCase(fakeAppInstall)
                        validateResult.data ?: false
        return validateResult.data ?: false
    }
                }
                val contentsRatings = contentRatingsDeferred.awaitAll()
                contentsRatings.forEachIndexed { index: Int, isValid: Boolean? ->
                    if (isValid == false) {

    private fun compileAppBlockList(
        cursor: MatrixCursor,
        validityList: List<Boolean?>,
        packageNames: List<String>,
    ) {
        validityList.forEachIndexed { index: Int, isValid: Boolean? ->
            if (isValid != true) {
                // Collect package names for blocklist
                        cursor.addRow(arrayOf(packagesNames[index]))
                    }
                cursor.addRow(arrayOf(packageNames[index]))
            }
        }
    }
        return cursor
    }

    override fun onCreate(): Boolean {
        val appContext = context?.applicationContext ?: error("Null context in ${this::class.java.name}")