Loading app/src/main/java/foundation/e/apps/data/database/AppDatabase.kt +11 −2 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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() } } Loading @@ -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" } } app/src/main/java/foundation/e/apps/data/faultyApps/FaultyApp.kt +9 −1 Original line number Diff line number Diff line Loading @@ -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 } } app/src/main/java/foundation/e/apps/data/faultyApps/FaultyAppRepository.kt +24 −4 Original line number Diff line number Diff line Loading @@ -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) } Loading @@ -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 } } app/src/main/java/foundation/e/apps/data/install/pkg/InstallerService.kt +11 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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") } } Loading app/src/main/java/foundation/e/apps/ui/AppInfoFetchViewModel.kt +1 −2 Original line number Diff line number Diff line Loading @@ -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 Loading
app/src/main/java/foundation/e/apps/data/database/AppDatabase.kt +11 −2 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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() } } Loading @@ -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" } }
app/src/main/java/foundation/e/apps/data/faultyApps/FaultyApp.kt +9 −1 Original line number Diff line number Diff line Loading @@ -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 } }
app/src/main/java/foundation/e/apps/data/faultyApps/FaultyAppRepository.kt +24 −4 Original line number Diff line number Diff line Loading @@ -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) } Loading @@ -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 } }
app/src/main/java/foundation/e/apps/data/install/pkg/InstallerService.kt +11 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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") } } Loading
app/src/main/java/foundation/e/apps/ui/AppInfoFetchViewModel.kt +1 −2 Original line number Diff line number Diff line Loading @@ -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