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

Commit 50200d18 authored by Abhishek Aggarwal's avatar Abhishek Aggarwal
Browse files

Merge branch '0000-main-4-update_sign_issues' into 'main'

feat(updates): Track faulty installs by failed version

See merge request !818
parents 336eb7a9 a89b8021
Loading
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ import foundation.e.apps.data.parentalcontrol.googleplay.GPlayContentRatingGroup
        FDroidNsfwApp::class,
        GPlayContentRatingGroup::class,
    ],
    version = 5,
    version = 6,
    exportSchema = false
)
@TypeConverters(AppInstallConverter::class)
@@ -46,7 +46,7 @@ abstract class AppDatabase : RoomDatabase() {
                    INSTANCE =
                        Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
                            .fallbackToDestructiveMigration(true)
                            .addMigrations(migration3To4)
                            .addMigrations(migration3To4, migration5To6)
                            .build()
                }
            }
@@ -59,8 +59,17 @@ abstract class AppDatabase : RoomDatabase() {
            }
        }

        private val migration5To6 = object : Migration(VERSION_5, VERSION_6) {
            override fun migrate(db: SupportSQLiteDatabase) {
                db.execSQL("ALTER TABLE FaultyApp ADD COLUMN versionCode INTEGER NOT NULL DEFAULT -1")
                db.execSQL("DELETE FROM FaultyApp")
            }
        }

        private const val VERSION_3 = 3
        private const val VERSION_4 = 4
        private const val VERSION_5 = 5
        private const val VERSION_6 = 6
        private const val DATABASE_NAME = "App_Lounge"
    }
}
+9 −1
Original line number Diff line number Diff line
@@ -24,4 +24,12 @@ import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
data class FaultyApp(@PrimaryKey val packageName: String, val error: String)
data class FaultyApp(
    @PrimaryKey val packageName: String,
    val error: String,
    val versionCode: Long = UNKNOWN_VERSION_CODE,
) {
    companion object {
        const val UNKNOWN_VERSION_CODE = -1L
    }
}
+24 −4
Original line number Diff line number Diff line
@@ -29,8 +29,16 @@ import javax.inject.Singleton
@OpenForTesting
class FaultyAppRepository @Inject constructor(private val faultyAppDao: FaultyAppDao) {

    suspend fun addFaultyApp(packageName: String, error: String) {
        val faultyApp = FaultyApp(packageName, error)
    suspend fun addFaultyApp(
        packageName: String,
        error: String,
        versionCode: Long = FaultyApp.UNKNOWN_VERSION_CODE,
    ) {
        if (versionCode == FaultyApp.UNKNOWN_VERSION_CODE) {
            return
        }

        val faultyApp = FaultyApp(packageName, error, versionCode)
        faultyAppDao.addFaultyApp(faultyApp)
    }

@@ -42,8 +50,20 @@ class FaultyAppRepository @Inject constructor(private val faultyAppDao: FaultyAp
        faultyAppDao.deleteFaultyAppByPackageName(packageName)
    }

    suspend fun getFaultyApp(application: Application): FaultyApp? {
        return getAllFaultyApps().find { it.matches(application) }
    }

    suspend fun removeFaultyApps(applications: List<Application>): List<Application> {
        val faultyAppsPackageNames = getAllFaultyApps().map { it.packageName }
        return applications.filter { !faultyAppsPackageNames.contains(it.package_name) }
        val faultyAppsByPackageName = getAllFaultyApps().associateBy { it.packageName }
        return applications.filter { application ->
            faultyAppsByPackageName[application.package_name]?.matches(application) != true
        }
    }

    private fun FaultyApp.matches(application: Application): Boolean {
        return packageName == application.package_name &&
            versionCode != FaultyApp.UNKNOWN_VERSION_CODE &&
            versionCode == application.latest_version_code
    }
}
+11 −3
Original line number Diff line number Diff line
@@ -29,9 +29,9 @@ import foundation.e.apps.data.application.UpdatesDao
import foundation.e.apps.data.di.qualifiers.IoCoroutineScope
import foundation.e.apps.data.event.AppEvent
import foundation.e.apps.data.event.EventBus
import foundation.e.apps.data.faultyApps.FaultyApp
import foundation.e.apps.data.faultyApps.FaultyAppRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@@ -116,13 +116,21 @@ class InstallerService : Service() {
    }

    private fun handleInstallFailureDueToSignatureMismatch(packageName: String?) {
        MainScope().launch {
        coroutineScope.launch {
            if (packageName.isNullOrEmpty()) {
                Timber.wtf("Installation failure for an app without packagename!")
                return@launch
            }
            EventBus.invokeEvent(AppEvent.SignatureMissMatchError(packageName))
            faultyAppRepository.addFaultyApp(packageName, INSTALL_FAILED_UPDATE_INCOMPATIBLE)
            val failedDownload = appManager.getFusedDownload(packageName = packageName)
            val failedVersionCode = failedDownload.versionCode
                .takeIf { failedDownload.packageName == packageName }
                ?: FaultyApp.UNKNOWN_VERSION_CODE
            faultyAppRepository.addFaultyApp(
                packageName,
                INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                failedVersionCode,
            )
            Timber.e("INSTALL_FAILED_UPDATE_INCOMPATIBLE for $packageName")
        }
    }
+1 −2
Original line number Diff line number Diff line
@@ -57,8 +57,7 @@ class AppInfoFetchViewModel @Inject constructor(
    }

    fun isAppFaulty(application: Application) = liveData {
        val faultyApp = faultyAppRepository.getAllFaultyApps()
            .find { faultyApp -> faultyApp.packageName.contentEquals(application.package_name) }
        val faultyApp = faultyAppRepository.getFaultyApp(application)
        val faultyAppResult = Pair(faultyApp != null, faultyApp?.error ?: "")
        emit(faultyAppResult)
    }
Loading